example.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #include <igl/OpenGL_convenience.h>
  2. #include <igl/per_face_normals.h>
  3. #include <igl/per_vertex_normals.h>
  4. #include <igl/normalize_row_lengths.h>
  5. #include <igl/draw_mesh.h>
  6. #include <igl/draw_floor.h>
  7. #include <igl/quat_to_mat.h>
  8. #include <igl/report_gl_error.h>
  9. #include <igl/read.h>
  10. #include <igl/trackball.h>
  11. #include <igl/material_colors.h>
  12. #include <igl/barycenter.h>
  13. #include <igl/matlab_format.h>
  14. #include <igl/embree/EmbreeIntersector.h>
  15. #include <igl/embree/ambient_occlusion.h>
  16. #ifdef __APPLE__
  17. # include <GLUT/glut.h>
  18. #else
  19. # include <GL/glut.h>
  20. #endif
  21. #include <Eigen/Core>
  22. #include <vector>
  23. #include <iostream>
  24. // Width and height of window
  25. int width,height;
  26. // Rotation of scene
  27. float scene_rot[4] = {0,0,0,1};
  28. // information at mouse down
  29. float down_scene_rot[4] = {0,0,0,1};
  30. bool trackball_on = false;
  31. int down_mouse_x,down_mouse_y;
  32. // Position of light
  33. float light_pos[4] = {0.1,0.1,-0.9,0};
  34. // Vertex positions, normals, colors and centroid
  35. Eigen::MatrixXd V,N,C,mid;
  36. // Faces
  37. Eigen::MatrixXi F;
  38. // Bounding box diagonal length
  39. double bbd;
  40. igl::EmbreeIntersector<Eigen::MatrixXd,Eigen::MatrixXi,Eigen::Vector3d> ei;
  41. // Running ambient occlusion
  42. Eigen::VectorXd S;
  43. int tot_num_samples = 0;
  44. void reshape(int width,int height)
  45. {
  46. using namespace std;
  47. // Save width and height
  48. ::width = width;
  49. ::height = height;
  50. glMatrixMode(GL_PROJECTION);
  51. glLoadIdentity();
  52. glViewport(0,0,width,height);
  53. }
  54. // Set up projection and model view of scene
  55. void push_scene()
  56. {
  57. using namespace igl;
  58. glMatrixMode(GL_PROJECTION);
  59. glLoadIdentity();
  60. gluPerspective(45,(double)width/(double)height,1e-2,100);
  61. glMatrixMode(GL_MODELVIEW);
  62. glLoadIdentity();
  63. gluLookAt(0,0,3,0,0,0,0,1,0);
  64. glPushMatrix();
  65. float mat[4*4];
  66. quat_to_mat(scene_rot,mat);
  67. glMultMatrixf(mat);
  68. }
  69. void pop_scene()
  70. {
  71. glPopMatrix();
  72. }
  73. // Scale and shift for object
  74. void push_object()
  75. {
  76. glPushMatrix();
  77. glScaled(2./bbd,2./bbd,2./bbd);
  78. glTranslated(-mid(0,0),-mid(0,1),-mid(0,2));
  79. }
  80. void pop_object()
  81. {
  82. glPopMatrix();
  83. }
  84. const float back[4] = {30.0/255.0,30.0/255.0,50.0/255.0,0};
  85. void display()
  86. {
  87. using namespace Eigen;
  88. using namespace igl;
  89. using namespace std;
  90. if(!trackball_on && tot_num_samples < 10000)
  91. {
  92. if(S.size() == 0)
  93. {
  94. S.resize(V.rows());
  95. S.setZero();
  96. }
  97. VectorXd Si;
  98. const int num_samples = 20;
  99. ambient_occlusion(ei,V,N,num_samples,Si);
  100. S *= (double)tot_num_samples;
  101. S += Si*(double)num_samples;
  102. tot_num_samples += num_samples;
  103. S /= (double)tot_num_samples;
  104. // Convert to 1-intensity
  105. C.resize(S.rows(),3);
  106. C<<S,S,S;
  107. C.array() = (1.0-C.array());
  108. }
  109. glClearColor(back[0],back[1],back[2],0);
  110. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  111. // All smooth points
  112. glEnable( GL_POINT_SMOOTH );
  113. glDisable(GL_LIGHTING);
  114. push_scene();
  115. glEnable(GL_DEPTH_TEST);
  116. glDepthFunc(GL_LEQUAL);
  117. glEnable(GL_NORMALIZE);
  118. glEnable(GL_COLOR_MATERIAL);
  119. glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
  120. push_object();
  121. // Draw the model
  122. // Set material properties
  123. glEnable(GL_COLOR_MATERIAL);
  124. draw_mesh(V,F,N,C);
  125. pop_object();
  126. // Draw a nice floor
  127. glPushMatrix();
  128. const double floor_scale = 2./bbd;
  129. const double floor_offset =
  130. -2./bbd*(V.col(1).minCoeff()+mid(1));
  131. glTranslated(0,floor_offset,0);
  132. const float GREY[4] = {0.5,0.5,0.6,1.0};
  133. const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
  134. draw_floor(GREY,DARK_GREY);
  135. glPopMatrix();
  136. pop_scene();
  137. report_gl_error();
  138. glutSwapBuffers();
  139. glutPostRedisplay();
  140. }
  141. void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
  142. {
  143. using namespace std;
  144. using namespace Eigen;
  145. using namespace igl;
  146. switch(glutState)
  147. {
  148. case 1:
  149. // up
  150. glutSetCursor(GLUT_CURSOR_LEFT_ARROW);
  151. trackball_on = false;
  152. break;
  153. case 0:
  154. // down
  155. glutSetCursor(GLUT_CURSOR_CYCLE);
  156. // collect information for trackball
  157. trackball_on = true;
  158. copy(scene_rot,scene_rot+4,down_scene_rot);
  159. down_mouse_x = mouse_x;
  160. down_mouse_y = mouse_y;
  161. break;
  162. }
  163. }
  164. void mouse_drag(int mouse_x, int mouse_y)
  165. {
  166. using namespace igl;
  167. if(trackball_on)
  168. {
  169. // Rotate according to trackball
  170. trackball<float>(
  171. width,
  172. height,
  173. 2,
  174. down_scene_rot,
  175. down_mouse_x,
  176. down_mouse_y,
  177. mouse_x,
  178. mouse_y,
  179. scene_rot);
  180. }
  181. }
  182. void key(unsigned char key, int mouse_x, int mouse_y)
  183. {
  184. using namespace std;
  185. switch(key)
  186. {
  187. // Ctrl-c and esc exit
  188. case char(3):
  189. case char(27):
  190. exit(0);
  191. default:
  192. cout<<"Unknown key command: "<<key<<" "<<int(key)<<endl;
  193. }
  194. }
  195. int main(int argc, char * argv[])
  196. {
  197. using namespace Eigen;
  198. using namespace igl;
  199. using namespace std;
  200. // init mesh
  201. if(!read("../shared/beast.obj",V,F))
  202. {
  203. return 1;
  204. }
  205. // Compute normals, centroid, colors, bounding box diagonal
  206. per_vertex_normals(V,F,N);
  207. mid = 0.5*(V.colwise().maxCoeff() + V.colwise().minCoeff());
  208. bbd = (V.colwise().maxCoeff() - V.colwise().minCoeff()).maxCoeff();
  209. // Init embree
  210. ei = EmbreeIntersector<MatrixXd,MatrixXi,Vector3d>(V,F);
  211. // Init glut
  212. glutInit(&argc,argv);
  213. glutInitDisplayString( "rgba depth double samples>=8 ");
  214. glutInitWindowSize(glutGet(GLUT_SCREEN_WIDTH)/2.0,glutGet(GLUT_SCREEN_HEIGHT));
  215. glutCreateWindow("ambient-occlusion");
  216. glutDisplayFunc(display);
  217. glutReshapeFunc(reshape);
  218. glutKeyboardFunc(key);
  219. glutMouseFunc(mouse);
  220. glutMotionFunc(mouse_drag);
  221. glutMainLoop();
  222. return 0;
  223. }