Преглед на файлове

Started camera example (not working correctly yet)

Former-commit-id: f3a746446bceb951ab04ff159a0a19a443c94677
Alec Jacobson (jalec преди 11 години
родител
ревизия
0f69e26554
променени са 5 файла, в които са добавени 866 реда и са изтрити 80 реда
  1. 56 0
      examples/camera/Makefile
  2. 503 0
      examples/camera/example.cpp
  3. 304 78
      examples/shadow-mapping/example.cpp
  4. 2 2
      include/igl/active_set.cpp
  5. 1 0
      include/igl/jet.cpp

+ 56 - 0
examples/camera/Makefile

@@ -0,0 +1,56 @@
+
+.PHONY: all
+
+# Shared flags etc.
+include ../../Makefile.conf
+
+all: obj example
+
+.PHONY: example
+
+LIBIGL=../../
+LIBIGL_INC=-I$(LIBIGL)/include
+LIBIGL_LIB=-L$(LIBIGL)/lib -ligl
+
+EIGEN3_INC=-I/opt/local/include/eigen3 -I/opt/local/include/eigen3/unsupported
+
+ANTTWEAKBAR_INC=-I$(LIBIGL)/external/AntTweakBar/include
+ANTTWEAKBAR_LIB=-L$(LIBIGL)/external/AntTweakBar/lib -lAntTweakBar -framework AppKit
+
+MATLAB_INC=-I$(MATLAB)/extern/include/
+MATLAB_LIB=-L$(MATLAB)/bin/maci64 -lmx -lmat -lmex -lstdc++
+
+CARBON_LIB=-framework Carbon
+
+## Use free glut for mouse scrolling
+#FREE_GLUT=/opt/local/
+#FREE_GLUT_INC=-I$(FREE_GLUT)/include
+#FREE_GLUT_LIB=-L$(FREE_GLUT)/lib -lglut
+#GLUT_LIB=$(FREE_GLUT_LIB)
+#GLUT_INC=$(FREE_GLUT_INC)
+GLUT_LIB=-framework GLUT
+GLUT_INC=
+
+INC=$(LIBIGL_INC) $(ANTTWEAKBAR_INC) $(EIGEN3_INC) $(MATLAB_INC) $(GLUT_INC)
+LIB=$(OPENGL_LIB) $(GLUT_LIB) $(ANTTWEAKBAR_LIB) $(LIBIGL_LIB) $(MATLAB_LIB) $(CARBON_LIB)
+
+CPP_FILES=$(wildcard ./*.cpp)
+OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o))) 
+
+CFLAGS+=-std=c++11 -g -O0
+
+example: obj $(OBJ_FILES)
+	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -o example $(OBJ_FILES) $(LIB)
+
+obj:
+	mkdir -p obj
+
+obj/%.o: %.cpp
+	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -c $< -o $@ $(INC)
+
+obj/%.o: %.cpp %.h
+	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -c $< -o $@ $(INC)
+
+clean:
+	rm -f $(OBJ_FILES)
+	rm -f example

+ 503 - 0
examples/camera/example.cpp

@@ -0,0 +1,503 @@
+#include <igl/Viewport.h>
+#include <igl/report_gl_error.h>
+#include <igl/ReAntTweakBar.h>
+#include <igl/trackball.h>
+#include <igl/PI.h>
+#include <igl/EPS.h>
+#include <igl/get_seconds.h>
+
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+
+#ifdef WIN32
+#include <GL/glut.h>
+#else
+#include <GLUT/glut.h>
+#endif
+
+#include <vector>
+#include <stack>
+#include <iostream>
+
+class Camera
+{
+  public:
+    //  m_zoom   Zoom of camera lens {1}
+    //  m_angle  Field of view angle in degrees {15}
+    //  m_aspect  Aspect ratio {1}
+    //  m_near  near clipping plane {1e-2}
+    //  m_far  far clipping plane {100}
+    //  m_rotation  Rotation part of rigid transformation of camera {identity}
+    //  m_translation  Translation part of rigid transformation of camera
+    //    {(0,0,1)}
+    double m_zoom, m_angle, m_aspect, m_near, m_far;
+    Eigen::Quaterniond m_rotation;
+    Eigen::Vector3d m_translation;
+    Camera():
+      m_zoom(1), m_angle(15.0), m_aspect(1), m_near(1e-2), m_far(100),
+      m_rotation(1,0,0,0),
+      m_translation(0,0,1)
+    {
+    }
+
+    Eigen::Vector3d eye() const
+    {
+      using namespace Eigen;
+      Affine3d t = Affine3d::Identity();
+      t.rotate(m_rotation);
+      t.translate(m_translation);
+      return t * Vector3d(0,0,0);
+    }
+
+    Eigen::Vector3d at() const
+    {
+      using namespace Eigen;
+      Affine3d t = Affine3d::Identity();
+      t.rotate(m_rotation);
+      t.translate(m_translation);
+      return t * Vector3d(0,0,-1);
+    }
+
+    Eigen::Vector3d up() const
+    {
+      using namespace Eigen;
+      Affine3d t = Affine3d::Identity();
+      t.rotate(m_rotation);
+      return t * Vector3d(0,1,0);
+    }
+
+    void dolly(const double d)
+    {
+      using namespace Eigen;
+      Vector3d dv(0,0,d);
+      m_translation += m_rotation.conjugate() * dv;
+    }
+
+    void look_at(
+      const Eigen::Vector3d & eye,
+      const Eigen::Vector3d & at,
+      const Eigen::Vector3d & up)
+    {
+      using namespace Eigen;
+      using namespace std;
+      using namespace igl;
+      // http://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
+      // Normalize vector from at to eye
+      const Vector3d F = (eye-at).normalized();
+      // Project up onto plane orthogonal to F and normalize
+      const Vector3d proj_up = (up-(up.dot(F))*F).normalized();
+      Quaterniond a,b;
+      a.setFromTwoVectors(Vector3d(0,0,-1),-F);
+      b.setFromTwoVectors(a*Vector3d(0,1,0),proj_up);
+      m_rotation = a*b;
+      m_translation = m_rotation.conjugate() * eye;
+      assert(           (eye-this->eye()).squaredNorm() < DOUBLE_EPS);
+      assert((F-(this->eye()-this->at())).squaredNorm() < DOUBLE_EPS);
+      assert(        (proj_up-this->up()).squaredNorm() < DOUBLE_EPS);
+    }
+
+};
+
+enum RotationType
+{
+  ROTATION_TYPE_IGL_TRACKBALL = 0,
+  ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP = 1,
+  NUM_ROTATION_TYPES = 2,
+} rotation_type = ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP;
+
+int width,height;
+#define REBAR_NAME "temp.rbr"
+igl::ReTwBar rebar;
+struct State
+{
+  int viewing_camera;
+  std::vector<Camera> cameras;
+  State():viewing_camera(0),cameras(2){}
+} s;
+std::stack<State> undo_stack;
+bool is_rotating = false;
+Camera down_camera;
+int down_x,down_y;
+std::stack<State> redo_stack;
+
+void push_undo()
+{
+  undo_stack.push(s);
+  // Clear
+  redo_stack = std::stack<State>();
+}
+
+void undo()
+{
+  if(!undo_stack.empty())
+  {
+    redo_stack.push(s);
+    s = undo_stack.top();
+    undo_stack.pop();
+  }
+}
+
+void redo()
+{
+  if(!redo_stack.empty())
+  {
+    undo_stack.push(s);
+    s = redo_stack.top();
+    redo_stack.pop();
+  }
+}
+
+void print(const Camera & camera)
+{
+  using namespace std;
+  cout<<
+    "rotation:    "<<camera.m_rotation.coeffs().transpose()<<endl<<
+    "translation: "<<camera.m_translation.transpose()<<endl<<
+    "eye:         "<<camera.eye().transpose()<<endl<<
+    "at:          "<<camera.at().transpose()<<endl<<
+    "up:          "<<camera.up().transpose()<<endl<<
+    endl;
+}
+
+void init_cameras()
+{
+  using namespace Eigen;
+  using namespace std;
+  s.cameras[0].look_at(
+    Vector3d(0,0,1),
+    Vector3d(0,0,0),
+    Vector3d(0,1,0));
+  print(s.cameras[0]);
+  //s.cameras[1].look_at(
+  //  Vector3d(0,0,-1),
+  //  Vector3d(0,0,0),
+  //  Vector3d(0,1,0));
+}
+
+void reshape(int width, int height)
+{
+  ::width = width;
+  ::height = height;
+  glViewport(0,0,width,height);
+  // Send the new window size to AntTweakBar
+  TwWindowSize(width, height);
+}
+
+
+void display()
+{
+  using namespace igl;
+  using namespace std;
+  using namespace Eigen;
+  glClearColor(1,1,1,0);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  // Update aspect ratios (may have changed since undo/redo)
+  const double aspect = (double)width/(double)height;
+  for(auto & camera : s.cameras)
+  {
+    camera.m_aspect = aspect;
+  }
+
+  //camera.m_rotation *= Quaterniond(AngleAxisd(0.01,Vector3d(0,1,0)));
+
+  auto & camera = s.cameras[s.viewing_camera];
+  const double theta = cos(2.0*PI*get_seconds()*0.1)*PI*0.05;
+  const Quaterniond R(AngleAxisd(theta,Vector3d(0,1,0)));
+  //// Orbit
+  //camera.look_at(
+  //    R*Vector3d(0,0,1),
+  //    Vector3d(0,0,0),
+  //    Vector3d(0,1,0));
+  // First person, head rotate
+  //camera.look_at(
+  //    Vector3d(0,0,1),
+  //    Vector3d(0,0,1)-R*Vector3d(0,0,1),
+  //    Vector3d(0,1,0));
+
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix();
+  glLoadIdentity();
+  gluPerspective(camera.m_angle,camera.m_aspect,camera.m_near,camera.m_far);
+  glMatrixMode(GL_MODELVIEW);
+  glPushMatrix();
+  glLoadIdentity();
+  gluLookAt(
+    camera.eye()(0), camera.eye()(1), camera.eye()(2),
+    camera.at()(0), camera.at()(1), camera.at()(2),
+    camera.up()(0), camera.up()(1), camera.up()(2));
+
+  for(int c = 0;c<(int)s.cameras.size();c++)
+  {
+    // draw camera
+  }
+
+  glDisable(GL_LIGHTING);
+  glEnable(GL_COLOR_MATERIAL);
+  glLineWidth(3.f);
+  glColor4f(0,0,0,1);
+  glutWireCube(0.25);
+  glColor4f(1,0.5,0.5,1);
+  glutWireSphere(0.125,20,20);
+  // Axes
+  for(int d = 0;d<3;d++)
+  {
+    glColor4f(d==0,d==1,d==2,1);
+    glBegin(GL_LINES);
+    glVertex3f(0,0,0);
+    glVertex3f(d==0,d==1,d==2);
+    glEnd();
+  }
+
+  glMatrixMode(GL_PROJECTION);
+  glPopMatrix();
+  glMatrixMode(GL_MODELVIEW);
+  glPopMatrix();
+
+  report_gl_error();
+  TwDraw();
+  glutSwapBuffers();
+  glutPostRedisplay();
+}
+
+void mouse_wheel(int wheel, int direction, int mouse_x, int mouse_y)
+{
+  using namespace std;
+  if(wheel == 0)
+  {
+    static double mouse_scroll_y = 0;
+    const double delta_y = 0.125*direction;
+    mouse_scroll_y += delta_y;
+    // absolute scale difference when changing zooms (+1)
+    const double z_diff = 0.01;
+    GLint viewport[4];
+    glGetIntegerv(GL_VIEWPORT,viewport);
+    if(TwMouseMotion(mouse_x, viewport[3] - mouse_y))
+    {
+      TwMouseWheel(mouse_scroll_y);
+    }else
+    {
+      auto & camera = s.cameras[s.viewing_camera];
+      camera.dolly(double(direction)*z_diff);
+      //const double min_zoom = 0.01;
+      //const double max_zoom = 10.0;
+      //s.camera.zoom = min(max_zoom,max(min_zoom,s.camera.zoom));
+    }
+  }else
+  {
+  }
+}
+
+void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
+{
+  using namespace std;
+  using namespace Eigen;
+  using namespace igl;
+  bool tw_using = TwEventMouseButtonGLUT(glutButton,glutState,mouse_x,mouse_y);
+  switch(glutButton)
+  {
+    case GLUT_RIGHT_BUTTON:
+    case GLUT_LEFT_BUTTON:
+    {
+      switch(glutState)
+      {
+        case 1:
+          // up
+          glutSetCursor(GLUT_CURSOR_INHERIT);
+          is_rotating = false;
+          break;
+        case 0:
+          if(!tw_using)
+          {
+            push_undo();
+            glutSetCursor(GLUT_CURSOR_CYCLE);
+            // collect information for trackball
+            is_rotating = true;
+            down_camera = s.cameras[s.viewing_camera];
+            down_x = mouse_x;
+            down_y = mouse_y;
+          }
+        break;
+      }
+      break;
+      // Scroll down
+      case GLUT_WHEEL_DOWN:
+      {
+        mouse_wheel(0,-1,mouse_x,mouse_y);
+        break;
+      }
+      // Scroll up
+      case GLUT_WHEEL_UP:
+      {
+        mouse_wheel(0,1,mouse_x,mouse_y);
+        break;
+      }
+      // Scroll left
+      case GLUT_WHEEL_LEFT:
+      {
+        mouse_wheel(1,-1,mouse_x,mouse_y);
+        break;
+      }
+      // Scroll right
+      case GLUT_WHEEL_RIGHT:
+      {
+        mouse_wheel(1,1,mouse_x,mouse_y);
+        break;
+      }
+    }
+  }
+}
+
+void mouse_drag(int mouse_x, int mouse_y)
+{
+  using namespace igl;
+  using namespace std;
+  using namespace Eigen;
+  /*bool tw_using =*/ TwMouseMotion(mouse_x,mouse_y);
+
+  if(is_rotating)
+  {
+    glutSetCursor(GLUT_CURSOR_CYCLE);
+    auto & camera = s.cameras[s.viewing_camera];
+    switch(rotation_type)
+    {
+      case ROTATION_TYPE_IGL_TRACKBALL:
+      {
+        // Rotate according to trackball
+        igl::trackball<double>(
+          width,
+          height,
+          2.0,
+          down_camera.m_rotation.coeffs().data(),
+          down_x,
+          down_y,
+          mouse_x,
+          mouse_y,
+          camera.m_rotation.coeffs().data());
+          break;
+      }
+      case ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP:
+      {
+        Quaterniond down_q = down_camera.m_rotation;
+        Vector3d axis(0,1,0);
+        const double speed = 2.0;
+        Quaterniond q;
+        q = down_q * 
+          Quaterniond(
+            AngleAxisd(
+              M_PI*((double)(mouse_x-down_x))/(double)width*speed/2.0,
+              axis.normalized()));
+        q.normalize();
+        {
+          Vector3d axis(1,0,0);
+          const double speed = 2.0;
+          if(axis.norm() != 0)
+          {
+            q = 
+              Quaterniond(
+                AngleAxisd(
+                  M_PI*(mouse_y-down_y)/(double)width*speed/2.0,
+                  axis.normalized())) * q;
+            q.normalize();
+          }
+        }
+        camera.m_rotation = q;
+        break;
+      }
+      default:
+        break;
+    }
+    const bool orbit = true;
+    if(orbit)
+    {
+      // at should be fixed
+      // Undo rotation from translation part: translation along view (from
+      // `at`)
+      Vector3d t = down_camera.m_rotation * down_camera.m_translation;
+      // Rotate to match new rotation
+      camera.m_translation = camera.m_rotation * t;
+      //assert((down_camera.at() - camera.at()).squaredNorm() < DOUBLE_EPS);
+    }else
+    {
+      // eye should be fixed
+      // flip rotation?
+    }
+  }
+}
+
+void key(unsigned char key, int mouse_x, int mouse_y)
+{
+  using namespace std;
+  int mod = glutGetModifiers();
+  switch(key)
+  {
+    // ESC
+    case char(27):
+      rebar.save(REBAR_NAME);
+    // ^C
+    case char(3):
+      exit(0);
+    case 'z':
+    case 'Z':
+      if(mod & GLUT_ACTIVE_COMMAND)
+      {
+        if(mod & GLUT_ACTIVE_SHIFT)
+        {
+          redo();
+        }else
+        {
+          undo();
+        }
+        break;
+      }
+    default:
+      if(!TwEventKeyboardGLUT(key,mouse_x,mouse_y))
+      {
+        cout<<"Unknown key command: "<<key<<" "<<int(key)<<endl;
+      }
+  }
+}
+
+
+int main(int argc, char * argv[])
+{
+  using namespace std;
+  using namespace Eigen;
+  using namespace igl;
+
+  // print key commands
+  cout<<"[Command+Z]         Undo."<<endl;
+  cout<<"[Shift+Command+Z]   Redo."<<endl;
+  cout<<"[^C,ESC]            Exit."<<endl;
+
+  // Init glut
+  glutInit(&argc,argv);
+  if( !TwInit(TW_OPENGL, NULL) )
+  {
+    // A fatal error occured
+    fprintf(stderr, "AntTweakBar initialization failed: %s\n", TwGetLastError());
+    return 1;
+  }
+  // Create a tweak bar
+  rebar.TwNewBar("bar");
+  TwDefine("bar label='camera' size='200 550' text=light alpha='200' color='68 68 68'");
+  rebar.load(REBAR_NAME);
+  init_cameras();
+
+  // Init antweakbar
+  glutInitDisplayString( "rgba depth double samples>=8");
+  // Top right corner
+  glutInitWindowSize(glutGet(GLUT_SCREEN_WIDTH)/2.0,glutGet(GLUT_SCREEN_HEIGHT)/2.0);
+  glutInitWindowPosition(glutGet(GLUT_SCREEN_WIDTH)/2.0,-1);
+  glutCreateWindow("camera");
+  glutDisplayFunc(display);
+  glutReshapeFunc(reshape);
+  glutKeyboardFunc(key);
+  glutMouseFunc(mouse);
+  glutPassiveMotionFunc((GLUTmousemotionfun)TwEventMouseMotionGLUT);
+  glutMotionFunc(mouse_drag);
+
+  glutMainLoop();
+
+  return 0;
+}

+ 304 - 78
examples/shadow-mapping/example.cpp

@@ -56,16 +56,110 @@
 #include <stack>
 #include <iostream>
 
+
+
+// Initialize shadow textures. Should be called on reshape()
+//
+// Inputs:
+//   windowWidth  width of viewport
+//   windowHeight  width of viewport
+//   factor  up-/down-sampling factor {1}
+// Outputs:
+//   shadowMapTexture  texture id of shadow map
+//   fbo  buffer id of depth frame buffer
+//   cfbo  buffer id of color frame buffer
+bool initialize_shadows(
+  const double windowWidth,
+  const double windowHeight,
+  const double factor,
+  GLuint & shadowMapTexture,
+  GLuint & fbo,
+  GLuint & cfbo);
+// Implementation
+bool initialize_shadows(
+  const double windowWidth,
+  const double windowHeight,
+  const double factor,
+  GLuint & shadowMapTexture,
+  GLuint & fbo,
+  GLuint & cfbo)
+{
+  //Create the shadow map texture
+  glDeleteTextures(1,&shadowMapTexture);
+  glGenTextures(1, &shadowMapTexture);
+  glBindTexture(GL_TEXTURE_2D, shadowMapTexture);
+  glTexImage2D(
+    GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 
+    factor*windowWidth,
+    factor*windowHeight, 
+    0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+  glBindTexture(GL_TEXTURE_2D, 0);
+
+  // Frame buffer
+  glGenFramebuffersEXT(1, &fbo);
+  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
+  glFramebufferTexture2DEXT(
+    GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 
+    shadowMapTexture,0);
+  // Attach color render buffer
+  glGenRenderbuffersEXT(1,&cfbo);
+  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,cfbo);
+  glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, 
+    factor*windowWidth, factor*windowHeight);
+  //-------------------------
+  //Attach color buffer to FBO
+  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 
+    GL_RENDERBUFFER_EXT, cfbo);
+  //-------------------------
+  //Does the GPU support current FBO configuration?
+  GLenum status;
+  status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+  switch(status)
+  {
+    case GL_FRAMEBUFFER_COMPLETE_EXT:
+      break;
+    default:
+      assert(false);
+      return false;
+  }
+  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+  return true;
+}
+
+GLuint shadowMapTexture=0,fbo=0,cfbo=0;
+
+#define MAX_SPEED 0.01
 struct Mesh
 {
   Eigen::MatrixXd V,N;
   Eigen::MatrixXi F;
+  Eigen::Affine3d a,da;
+  Mesh():V(),N(),F(),a(Eigen::Affine3d::Identity()),da(Eigen::Affine3d::Identity())
+  { 
+    using namespace Eigen;
+    Quaterniond r(Eigen::Vector4d::Random());
+    Quaterniond i(1,0,0,0);
+    const double speed = 0.001;
+    Quaterniond q = Quaterniond((   speed)*r.coeffs() + (1.-speed)*i.coeffs()).normalized();
+    da.rotate(q);
+    da.translate(Eigen::Vector3d::Random().normalized()*MAX_SPEED);
+  }
 };
 std::vector<Mesh> meshes;
 
 struct State
 {
   igl::Camera camera;
+  State():
+    camera()
+  {
+    camera.pan[1] = 1;
+  }
 } s;
 
 // See README for descriptions
@@ -90,7 +184,8 @@ Eigen::Quaterniond animation_from_quat;
 Eigen::Quaterniond animation_to_quat;
 
 int width,height;
-Eigen::Vector4f light_pos(-0.1,-0.1,0.9,0);
+bool is_view_from_light = false;
+Eigen::Vector4f light_pos(9,9,1,1);
 
 #define REBAR_NAME "temp.rbr"
 igl::ReTwBar rebar;
@@ -105,39 +200,6 @@ void push_undo()
   redo_stack = std::stack<State>();
 }
 
-void TW_CALL set_rotation_type(const void * value, void * clientData)
-{
-  using namespace Eigen;
-  using namespace std;
-  using namespace igl;
-  const RotationType old_rotation_type = rotation_type;
-  rotation_type = *(const RotationType *)(value);
-  if(rotation_type == ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP && 
-    old_rotation_type != ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP)
-  {
-    push_undo();
-    copy(s.camera.rotation,s.camera.rotation+4,animation_from_quat.coeffs().data());
-    const Vector3d up = animation_from_quat.matrix() * Vector3d(0,1,0);
-    Vector3d proj_up(0,up(1),up(2));
-    if(proj_up.norm() == 0)
-    {
-      proj_up = Vector3d(0,1,0);
-    }
-    proj_up.normalize();
-    Quaterniond dq;
-    dq = Quaterniond::FromTwoVectors(up,proj_up);
-    animation_to_quat = dq * animation_from_quat;
-    // start animation
-    animation_start_time = get_seconds();
-    is_animating = true;
-  }
-}
-void TW_CALL get_rotation_type(void * value, void *clientData)
-{
-  RotationType * rt = (RotationType *)(value);
-  *rt = rotation_type;
-}
-
 void reshape(int width, int height)
 {
   ::width = width;
@@ -145,18 +207,26 @@ void reshape(int width, int height)
   glViewport(0,0,width,height);
   // Send the new window size to AntTweakBar
   TwWindowSize(width, height);
+  if(!initialize_shadows(width,height,1,shadowMapTexture,fbo,cfbo))
+  {
+    assert(false);
+    exit(-1);
+  }
 }
 
-void push_scene()
+void push_scene(
+  const int width,
+  const int height,
+  const double angle,
+  const double zNear = 1e-2,
+  const double zFar = 100,
+  const bool correct_perspective_scaling = true)
 {
   using namespace igl;
   using namespace std;
-  const double angle = s.camera.angle;
   glMatrixMode(GL_PROJECTION);
   glPushMatrix();
   glLoadIdentity();
-  double zNear = 1e-2;
-  double zFar = 100;
   double aspect = ((double)width)/((double)height);
   // Amount of scaling needed to "fix" perspective z-shift
   double z_fix = 1.0;
@@ -177,22 +247,53 @@ void push_scene()
     // Make sure aspect is sane
     aspect = aspect < 0.01 ? 0.01 : aspect;
     gluPerspective(angle,aspect,zNear,zFar);
-    z_fix = 2.*tan(angle/2./360.*2.*M_PI);
+    if(correct_perspective_scaling)
+    {
+      z_fix = 2.*tan(angle/2./360.*2.*M_PI);
+    }
   }
 
   glMatrixMode(GL_MODELVIEW);
   glPushMatrix();
   glLoadIdentity();
-  gluLookAt(0,0,camera_z,0,0,0,0,1,0);
+  glTranslatef(0,0,-camera_z);
   // Adjust scale to correct perspective
-  glScaled(z_fix,z_fix,z_fix);
+  if(correct_perspective_scaling)
+  {
+    glScaled(z_fix,z_fix,z_fix);
+  }
+}
+
+void push_lightview_camera(const Eigen::Vector4f & light_pos)
+{
+  using namespace igl;
+  glMatrixMode(GL_MODELVIEW);
+  glPushMatrix();
+  //glTranslatef(-light_pos(0),-light_pos(1),-light_pos(2));
+  gluLookAt(
+    light_pos(0), light_pos(1), light_pos(2),
+    0,0,0,
+    0,1,0);
+}
+
+void push_camera(const igl::Camera & camera)
+{
+  using namespace igl;
+  glMatrixMode(GL_MODELVIEW);
+  glPushMatrix();
   // scale, pan
-  glScaled( s.camera.zoom, s.camera.zoom, s.camera.zoom);
+  glScaled(camera.zoom, camera.zoom, camera.zoom);
   double mat[4*4];
-  quat_to_mat(s.camera.rotation,mat);
+  quat_to_mat(camera.rotation,mat);
   glMultMatrixd(mat);
 }
 
+void pop_camera()
+{
+  glMatrixMode(GL_MODELVIEW);
+  glPopMatrix();
+}
+
 void pop_scene()
 {
   glMatrixMode(GL_PROJECTION);
@@ -202,7 +303,7 @@ void pop_scene()
 }
 
 // Set up double-sided lights
-void lights()
+void lights(const Eigen::Vector4f & pos)
 {
   using namespace std;
   using namespace Eigen;
@@ -211,54 +312,61 @@ void lights()
   glEnable(GL_LIGHT0);
   float WHITE[4] = {1,1,1,1.};
   float BLACK[4] = {0.,0.,0.,1.};
-  Vector4f pos = light_pos;
   glLightfv(GL_LIGHT0,GL_AMBIENT,BLACK);
   glLightfv(GL_LIGHT0,GL_DIFFUSE,WHITE);
   glLightfv(GL_LIGHT0,GL_SPECULAR,BLACK);
   glLightfv(GL_LIGHT0,GL_POSITION,pos.data());
 }
 
-void display()
+void update_meshes()
 {
-  using namespace igl;
-  using namespace std;
   using namespace Eigen;
-  glClearColor(1,1,1,0);
-  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-  if(is_animating)
+  for(auto & mesh : meshes)
   {
-    double t = (get_seconds() - animation_start_time)/ANIMATION_DURATION;
-    if(t > 1)
+    //mesh.da.translate(Vector3d::Random()*0.001);
+    mesh.a = mesh.a * mesh.da;
+    Vector3d o = mesh.a.translation();
+    const Vector3d xo(5,5,5);
+    const Vector3d no(5,0,5);
+    for(int d = 0;d<3;d++)
     {
-      t = 1;
-      is_animating = false;
+      if(o(d) > xo(d))
+      {
+        o(d) = xo(d);
+        mesh.da.translation()(d) *= -1.;
+      }
+      if(o(d) < -no(d))
+      {
+        o(d) = -no(d);
+        mesh.da.translation()(d) *= -1.;
+      }
     }
-    Quaterniond q;
-    q.coeffs() = 
-      animation_to_quat.coeffs()*t + animation_from_quat.coeffs()*(1.-t);
-    q.normalize();
-    copy(q.coeffs().data(),q.coeffs().data()+4,s.camera.rotation);
+    mesh.a.translation() = o;
+    mesh.da.translation() = MAX_SPEED*mesh.da.translation().normalized();
   }
+}
 
-  glEnable(GL_DEPTH_TEST);
-  glEnable(GL_NORMALIZE);
-  lights();
-  push_scene();
+void draw_objects()
+{
+  using namespace igl;
+  using namespace std;
+  using namespace Eigen;
 
-  for(auto & mesh : meshes)
+  for(int m = 0;m<(int)meshes.size();m++)
   {
+    Mesh & mesh = meshes[m];
+    Vector4f color(0,0,0,1);
+    jet(1.f-(float)m/(float)meshes.size(),color.data());
     // Set material properties
     glDisable(GL_COLOR_MATERIAL);
-    glMaterialfv(GL_FRONT, GL_AMBIENT,  GOLD_AMBIENT);
-    glMaterialfv(GL_FRONT, GL_DIFFUSE,  GOLD_DIFFUSE  );
-    glMaterialfv(GL_FRONT, GL_SPECULAR, GOLD_SPECULAR);
-    glMaterialf (GL_FRONT, GL_SHININESS, 128);
-    glMaterialfv(GL_BACK, GL_AMBIENT,  SILVER_AMBIENT);
-    glMaterialfv(GL_BACK, GL_DIFFUSE,  FAST_GREEN_DIFFUSE  );
-    glMaterialfv(GL_BACK, GL_SPECULAR, SILVER_SPECULAR);
-    glMaterialf (GL_BACK, GL_SHININESS, 128);
+    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,  SILVER_AMBIENT);
+    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,  color.data());
+    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, SILVER_SPECULAR);
+    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 128);
+    glPushMatrix();
+    glMultMatrixd(mesh.a.matrix().data());
     draw_mesh(mesh.V,mesh.F,mesh.N);
+    glPopMatrix();
   }
   
   // Draw a nice floor
@@ -266,14 +374,93 @@ void display()
   {
     const float GREY[4] = {0.5,0.5,0.6,1.0};
     const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
-    draw_floor(GREY,DARK_GREY);
+    //draw_floor(GREY,DARK_GREY);
+    glTranslatef(0,0.3,0);
+    glScaled(10,0.1,10);
+    glDisable(GL_COLOR_MATERIAL);
+    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,  DARK_GREY);
+    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,  GREY);
+    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, SILVER_SPECULAR);
+    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 128);
+    glutSolidCube(1.0);
   }
   glPopMatrix();
 
+}
+
+void draw_scene()
+{
+  glEnable(GL_DEPTH_TEST);
+  glEnable(GL_NORMALIZE);
+  push_scene(width,height,s.camera.angle,1e-2,100,true);
+  if(is_view_from_light)
+  {
+    push_lightview_camera(light_pos);
+  }else
+  {
+    push_camera(s.camera);
+  }
+  lights(light_pos);
+  draw_objects();
+  glPushMatrix();
+    glTranslatef(light_pos(0),light_pos(1),light_pos(2));
+    glutWireSphere(1,20,20);
+  glPopMatrix();
+  pop_camera();
   pop_scene();
 
-  report_gl_error();
+  ////First pass - from light's point of view
+  //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
+  //glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, cfbo);
+  //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  //glMatrixMode(GL_PROJECTION);
+  //glLoadMatrixf(lightProjectionMatrix);
+  //glMatrixMode(GL_MODELVIEW);
+  //glLoadMatrixf(lightViewMatrix);
+  ////Use viewport the same size as the shadow map
+  //glViewport(0, 0, factor*windowWidth, factor*windowHeight);
+  ////Draw back faces into the shadow map
+  //glEnable(GL_CULL_FACE);
+  //glCullFace(GL_FRONT);
+  ////Disable color writes, and use flat shading for speed
+  //glShadeModel(GL_FLAT);
+  //glColorMask(0, 0, 0, 0);
+  ////Draw the scene
+  //draw_objects();
+  //////Read the depth buffer into the shadow map texture
+  ////glBindTexture(GL_TEXTURE_2D, shadowMapTexture);
+  ////glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, factor*windowWidth, factor*windowHeight);
+  //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+  //glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+}
+
+void display()
+{
+  using namespace igl;
+  using namespace std;
+  using namespace Eigen;
+  glClearColor(1,1,1,0);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  if(is_animating)
+  {
+    double t = (get_seconds() - animation_start_time)/ANIMATION_DURATION;
+    if(t > 1)
+    {
+      t = 1;
+      is_animating = false;
+    }
+    Quaterniond q;
+    q.coeffs() = 
+      animation_to_quat.coeffs()*t + animation_from_quat.coeffs()*(1.-t);
+    q.normalize();
+    copy(q.coeffs().data(),q.coeffs().data()+4,s.camera.rotation);
+  }
+  update_meshes();
 
+  draw_scene();
+
+  report_gl_error();
   TwDraw();
   glutSwapBuffers();
   glutPostRedisplay();
@@ -514,6 +701,38 @@ void key(unsigned char key, int mouse_x, int mouse_y)
       }
   }
 }
+void TW_CALL set_rotation_type(const void * value, void * clientData)
+{
+  using namespace Eigen;
+  using namespace std;
+  using namespace igl;
+  const RotationType old_rotation_type = rotation_type;
+  rotation_type = *(const RotationType *)(value);
+  if(rotation_type == ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP && 
+    old_rotation_type != ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP)
+  {
+    push_undo();
+    copy(s.camera.rotation,s.camera.rotation+4,animation_from_quat.coeffs().data());
+    const Vector3d up = animation_from_quat.matrix() * Vector3d(0,1,0);
+    Vector3d proj_up(0,up(1),up(2));
+    if(proj_up.norm() == 0)
+    {
+      proj_up = Vector3d(0,1,0);
+    }
+    proj_up.normalize();
+    Quaterniond dq;
+    dq = Quaterniond::FromTwoVectors(up,proj_up);
+    animation_to_quat = dq * animation_from_quat;
+    // start animation
+    animation_start_time = get_seconds();
+    is_animating = true;
+  }
+}
+void TW_CALL get_rotation_type(void * value, void *clientData)
+{
+  RotationType * rt = (RotationType *)(value);
+  *rt = rotation_type;
+}
 
 int main(int argc, char * argv[])
 {
@@ -523,14 +742,13 @@ int main(int argc, char * argv[])
   vector<string> filenames;
   switch(argc)
   {
-    case 2:
+    default:
       // Read and prepare meshes
       for(int a = 1;a<argc;a++)
       {
         filenames.push_back(argv[a]);
       }
       break;
-    default:
     case 1:
       cerr<<"Usage:"<<endl<<
         "    ./example input1.obj input2.obj input3.obj ..."<<endl;
@@ -551,6 +769,10 @@ int main(int argc, char * argv[])
   {
     meshes.push_back(Mesh());
     Mesh & mesh = meshes.back();
+    mesh.a.translate(Vector3d(0,1,0));
+    Vector3d offset = Vector3d::Random()*3;
+    offset(1) = 0;
+    mesh.a.translate(offset);
     // dirname, basename, extension and filename
     string d,b,ext,f;
     pathinfo(filename,d,b,ext,f);
@@ -602,10 +824,13 @@ int main(int argc, char * argv[])
   // Create a tweak bar
   rebar.TwNewBar("bar");
   TwDefine("bar label='Shadow Mapping' size='200 550' text=light alpha='200' color='68 68 68'");
+  rebar.TwAddVarRW("camera_zoom", TW_TYPE_DOUBLE,&s.camera.zoom,"");
   rebar.TwAddVarRW("camera_rotation", TW_TYPE_QUAT4D,s.camera.rotation,"");
   TwType RotationTypeTW = ReTwDefineEnumFromString("RotationType","igl_trackball,two_axis_fixed_up");
   rebar.TwAddVarCB( "rotation_type", RotationTypeTW,
     set_rotation_type,get_rotation_type,NULL,"keyIncr=] keyDecr=[");
+  rebar.TwAddVarRW( "is_view_from_light",TW_TYPE_BOOLCPP,&is_view_from_light,
+    "key=l");
   rebar.load(REBAR_NAME);
 
   animation_from_quat = Quaterniond(1,0,0,0);
@@ -624,6 +849,7 @@ int main(int argc, char * argv[])
   glutMouseFunc(mouse);
   glutMotionFunc(mouse_drag);
   glutPassiveMotionFunc((GLUTmousemotionfun)TwEventMouseMotionGLUT);
+
   glutMainLoop();
 
   return 0;

+ 2 - 2
include/igl/active_set.cpp

@@ -43,7 +43,7 @@ IGL_INLINE igl::SolverStatus igl::active_set(
   Eigen::PlainObjectBase<DerivedZ> & Z
   )
 {
-#define ACTIVE_SET_CPP_DEBUG
+//#define ACTIVE_SET_CPP_DEBUG
   using namespace igl;
   using namespace Eigen;
   using namespace std;
@@ -114,7 +114,7 @@ IGL_INLINE igl::SolverStatus igl::active_set(
   while(true)
   {
 #ifdef ACTIVE_SET_CPP_DEBUG
-    cout<<iter<<":"<<endl;
+    cout<<"Iteration: "<<iter<<":"<<endl;
     cout<<"  pre"<<endl;
 #endif
     // FIND BREACHES OF CONSTRAINTS

+ 1 - 0
include/igl/jet.cpp

@@ -101,4 +101,5 @@ void igl::jet(const T x, T & r, T & g, T & b)
 #ifndef IGL_NO_HEADER
 template void igl::jet<double>(double, double*);
 template void igl::jet<double>(double, double&, double&, double&);
+template void igl::jet<float>(float, float*);
 #endif