Przeglądaj źródła

more intricate ambient occlusion demo

Former-commit-id: 75d3d5a1a62c1c953f12c40fac7c507571b4c284
Alec Jacobson (jalec 11 lat temu
rodzic
commit
93847a08e1
1 zmienionych plików z 109 dodań i 16 usunięć
  1. 109 16
      examples/ambient-occlusion/example.cpp

+ 109 - 16
examples/ambient-occlusion/example.cpp

@@ -13,6 +13,7 @@
 #include <igl/matlab_format.h>
 #include <igl/embree/EmbreeIntersector.h>
 #include <igl/embree/ambient_occlusion.h>
+#include <igl/ReAntTweakBar.h>
 
 #ifdef __APPLE__
 #  include <GLUT/glut.h>
@@ -45,6 +46,14 @@ igl::EmbreeIntersector<Eigen::MatrixXd,Eigen::MatrixXi,Eigen::Vector3d> ei;
 // Running ambient occlusion
 Eigen::VectorXd S;
 int tot_num_samples = 0;
+#define REBAR_NAME "temp.rbr"
+igl::ReTwBar rebar; // Pointer to the tweak bar
+bool lights_on = true;
+Eigen::Vector4f color(0.4,0.8,0.3,1.0);
+double ao_factor = 1.0;
+bool ao_normalize = false;
+bool ao_on = false;
+double light_intensity = 1.0;
 
 void reshape(int width,int height)
 {
@@ -55,6 +64,8 @@ void reshape(int width,int height)
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glViewport(0,0,width,height);
+  // Send the new window size to AntTweakBar
+  TwWindowSize(width, height);
 }
 
 // Set up projection and model view of scene
@@ -91,6 +102,36 @@ void pop_object()
   glPopMatrix();
 }
 
+// Set up double-sided lights
+void lights()
+{
+  using namespace std;
+  glEnable(GL_LIGHTING);
+  glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
+  glEnable(GL_LIGHT0);
+  glEnable(GL_LIGHT1);
+  float amb[4];
+  amb[0] = amb[1] = amb[2] = light_intensity;
+  amb[3] = 1.0;
+  float diff[4] = {0.0,0.0,0.0,0.0};
+  diff[0] = diff[1] = diff[2] = (1.0 - light_intensity/0.4);;
+  diff[3] = 1.0;
+  float zeros[4] = {0.0,0.0,0.0,0.0};
+  float pos[4];
+  copy(light_pos,light_pos+4,pos);
+  glLightfv(GL_LIGHT0,GL_AMBIENT,amb);
+  glLightfv(GL_LIGHT0,GL_DIFFUSE,diff);
+  glLightfv(GL_LIGHT0,GL_SPECULAR,zeros);
+  glLightfv(GL_LIGHT0,GL_POSITION,pos);
+  pos[0] *= -1;
+  pos[1] *= -1;
+  pos[2] *= -1;
+  glLightfv(GL_LIGHT1,GL_AMBIENT,amb);
+  glLightfv(GL_LIGHT1,GL_DIFFUSE,diff);
+  glLightfv(GL_LIGHT1,GL_SPECULAR,zeros);
+  glLightfv(GL_LIGHT1,GL_POSITION,pos);
+}
+
 const float back[4] = {30.0/255.0,30.0/255.0,50.0/255.0,0};
 void display()
 {
@@ -112,11 +153,27 @@ void display()
     S += Si*(double)num_samples;
     tot_num_samples += num_samples;
     S /= (double)tot_num_samples;
-    // Convert to 1-intensity
-    C.resize(S.rows(),3);
+  }
+
+  // Convert to 1-intensity
+  C.conservativeResize(S.rows(),3);
+  if(ao_on)
+  {
     C<<S,S,S;
-    C.array() = (1.0-C.array());
+    C.array() = (1.0-ao_factor*C.array());
+  }else
+  {
+    C.setConstant(1.0);
+  }
+  if(ao_normalize)
+  {
+    C.col(0) *= ((double)C.rows())/C.col(0).sum();
+    C.col(1) *= ((double)C.rows())/C.col(1).sum();
+    C.col(2) *= ((double)C.rows())/C.col(2).sum();
   }
+  C.col(0) *= color(0);
+  C.col(1) *= color(1);
+  C.col(2) *= color(2);
 
   glClearColor(back[0],back[1],back[2],0);
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -124,6 +181,10 @@ void display()
   glEnable( GL_POINT_SMOOTH );
 
   glDisable(GL_LIGHTING);
+  if(lights_on)
+  {
+    lights();
+  }
   push_scene();
   glEnable(GL_DEPTH_TEST);
   glDepthFunc(GL_LEQUAL);
@@ -137,23 +198,23 @@ void display()
   glEnable(GL_COLOR_MATERIAL);
   draw_mesh(V,F,N,C);
 
-  pop_object();
 
   // Draw a nice floor
   glPushMatrix();
-  const double floor_scale = 2./bbd;
-  const double floor_offset =
-    -2./bbd*(V.col(1).minCoeff()+mid(1));
+  const double floor_offset = -V.col(1).minCoeff();
   glTranslated(0,floor_offset,0);
+  glScaled(bbd/2.0,bbd/2.0,bbd/2.0);
   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);
   glPopMatrix();
+  pop_object();
 
   pop_scene();
 
   report_gl_error();
 
+  TwDraw();
   glutSwapBuffers();
   glutPostRedisplay();
 }
@@ -163,6 +224,7 @@ 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(glutState)
   {
     case 1:
@@ -172,12 +234,15 @@ void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
       break;
     case 0:
       // down
-      glutSetCursor(GLUT_CURSOR_CYCLE);
-      // collect information for trackball
-      trackball_on = true;
-      copy(scene_rot,scene_rot+4,down_scene_rot);
-      down_mouse_x = mouse_x;
-      down_mouse_y = mouse_y;
+      if(!tw_using)
+      {
+        glutSetCursor(GLUT_CURSOR_CYCLE);
+        // collect information for trackball
+        trackball_on = true;
+        copy(scene_rot,scene_rot+4,down_scene_rot);
+        down_mouse_x = mouse_x;
+        down_mouse_y = mouse_y;
+      }
     break;
   }
 }
@@ -186,6 +251,7 @@ void mouse_drag(int mouse_x, int mouse_y)
 {
   using namespace igl;
 
+
   if(trackball_on)
   {
     // Rotate according to trackball
@@ -199,6 +265,9 @@ void mouse_drag(int mouse_x, int mouse_y)
       mouse_x,
       mouse_y,
       scene_rot);
+  }else
+  {
+    TwEventMouseMotionGLUT(mouse_x, mouse_y);
   }
 }
 
@@ -208,12 +277,17 @@ void key(unsigned char key, int mouse_x, int mouse_y)
   using namespace std;
   switch(key)
   {
-    // Ctrl-c and esc exit
-    case char(3):
+    // ESC
     case char(27):
+      rebar.save(REBAR_NAME);
+    // ^C
+    case char(3):
       exit(0);
     default:
-      cout<<"Unknown key command: "<<key<<" "<<int(key)<<endl;
+      if(!TwEventKeyboardGLUT(key,mouse_x,mouse_y))
+      {
+        cout<<"Unknown key command: "<<key<<" "<<int(key)<<endl;
+      }
   }
   
 }
@@ -240,6 +314,24 @@ int main(int argc, char * argv[])
 
   // 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("TweakBar");
+  rebar.TwAddVarRW("scene_rot", TW_TYPE_QUAT4F, &scene_rot, "");
+  rebar.TwAddVarRW("lights_on", TW_TYPE_BOOLCPP, &lights_on, "key=l");
+  rebar.TwAddVarRW("color", TW_TYPE_COLOR4F, color.data(), "colormode=hls");
+  rebar.TwAddVarRW("ao_factor", TW_TYPE_DOUBLE, &ao_factor, "min=0 max=1 step=0.2 keyIncr=] keyDecr=[ ");
+  rebar.TwAddVarRW("ao_normalize", TW_TYPE_BOOLCPP, &ao_normalize, "key=n");
+  rebar.TwAddVarRW("ao_on", TW_TYPE_BOOLCPP, &ao_on, "key=a");
+  rebar.TwAddVarRW("light_intensity", TW_TYPE_DOUBLE, &light_intensity, "min=0 max=0.4 step=0.1 keyIncr=} keyDecr={ ");
+  rebar.load(REBAR_NAME);
+
   glutInitDisplayString( "rgba depth double samples>=8 ");
   glutInitWindowSize(glutGet(GLUT_SCREEN_WIDTH)/2.0,glutGet(GLUT_SCREEN_HEIGHT));
   glutCreateWindow("ambient-occlusion");
@@ -248,6 +340,7 @@ int main(int argc, char * argv[])
   glutKeyboardFunc(key);
   glutMouseFunc(mouse);
   glutMotionFunc(mouse_drag);
+  glutPassiveMotionFunc((GLUTmousemotionfun)TwEventMouseMotionGLUT);
   glutMainLoop();
   return 0;
 }