example.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. #include <igl/opengl/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/opengl2/draw_mesh.h>
  6. #include <igl/opengl2/draw_floor.h>
  7. #include <igl/quat_to_mat.h>
  8. #include <igl/opengl/report_gl_error.h>
  9. #include <igl/readOBJ.h>
  10. #include <igl/readDMAT.h>
  11. #include <igl/readOFF.h>
  12. #include <igl/readMESH.h>
  13. #include <igl/readWRL.h>
  14. #include <igl/trackball.h>
  15. #include <igl/list_to_matrix.h>
  16. #include <igl/polygon_mesh_to_triangle_mesh.h>
  17. #include <igl/material_colors.h>
  18. #include <igl/barycenter.h>
  19. #include <igl/matlab_format.h>
  20. #include <igl/anttweakbar/ReAntTweakBar.h>
  21. #include <igl/pathinfo.h>
  22. #include <igl/embree/EmbreeIntersector.h>
  23. #include <igl/embree/ambient_occlusion.h>
  24. #ifdef __APPLE__
  25. # include <GLUT/glut.h>
  26. #else
  27. # include <GL/glut.h>
  28. #endif
  29. #include <Eigen/Core>
  30. #include <vector>
  31. #include <iostream>
  32. #include <algorithm>
  33. // Width and height of window
  34. int width,height;
  35. // Rotation of scene
  36. float scene_rot[4] = {0,0,0,1};
  37. // information at mouse down
  38. float down_scene_rot[4] = {0,0,0,1};
  39. bool trackball_on = false;
  40. int down_mouse_x,down_mouse_y;
  41. // Position of light
  42. float light_pos[4] = {0.1,0.1,-0.9,0};
  43. // Vertex positions, normals, colors and centroid
  44. Eigen::MatrixXd V,N,C,mid;
  45. // Faces
  46. Eigen::MatrixXi F;
  47. // Bounding box diagonal length
  48. double bbd;
  49. igl::embree::EmbreeIntersector ei;
  50. // Running ambient occlusion
  51. Eigen::VectorXd S;
  52. int tot_num_samples = 0;
  53. #define REBAR_NAME "temp.rbr"
  54. igl::anttweakbar::ReTwBar rebar; // Pointer to the tweak bar
  55. bool lights_on = true;
  56. Eigen::Vector4f color(0.4,0.8,0.3,1.0);
  57. double ao_factor = 1.0;
  58. bool ao_normalize = false;
  59. bool ao_on = true;
  60. double light_intensity = 1.0;
  61. void reshape(int width,int height)
  62. {
  63. using namespace std;
  64. // Save width and height
  65. ::width = width;
  66. ::height = height;
  67. glMatrixMode(GL_PROJECTION);
  68. glLoadIdentity();
  69. glViewport(0,0,width,height);
  70. // Send the new window size to AntTweakBar
  71. TwWindowSize(width, height);
  72. }
  73. // Set up igl::opengl2::projection and model view of scene
  74. void push_scene()
  75. {
  76. using namespace igl;
  77. glMatrixMode(GL_PROJECTION);
  78. glLoadIdentity();
  79. gluPerspective(45,(double)width/(double)height,1e-2,100);
  80. glMatrixMode(GL_MODELVIEW);
  81. glLoadIdentity();
  82. gluLookAt(0,0,3,0,0,0,0,1,0);
  83. glPushMatrix();
  84. float mat[4*4];
  85. quat_to_mat(scene_rot,mat);
  86. glMultMatrixf(mat);
  87. }
  88. void pop_scene()
  89. {
  90. glPopMatrix();
  91. }
  92. // Scale and shift for object
  93. void push_object()
  94. {
  95. glPushMatrix();
  96. glScaled(2./bbd,2./bbd,2./bbd);
  97. glTranslated(-mid(0,0),-mid(0,1),-mid(0,2));
  98. }
  99. void pop_object()
  100. {
  101. glPopMatrix();
  102. }
  103. // Set up double-sided lights
  104. void lights()
  105. {
  106. using namespace std;
  107. glEnable(GL_LIGHTING);
  108. glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
  109. glEnable(GL_LIGHT0);
  110. glEnable(GL_LIGHT1);
  111. float amb[4];
  112. amb[0] = amb[1] = amb[2] = light_intensity;
  113. amb[3] = 1.0;
  114. float diff[4] = {0.0,0.0,0.0,0.0};
  115. diff[0] = diff[1] = diff[2] = (1.0 - light_intensity/0.4);;
  116. diff[3] = 1.0;
  117. float zeros[4] = {0.0,0.0,0.0,0.0};
  118. float pos[4];
  119. copy(light_pos,light_pos+4,pos);
  120. glLightfv(GL_LIGHT0,GL_AMBIENT,amb);
  121. glLightfv(GL_LIGHT0,GL_DIFFUSE,diff);
  122. glLightfv(GL_LIGHT0,GL_SPECULAR,zeros);
  123. glLightfv(GL_LIGHT0,GL_POSITION,pos);
  124. pos[0] *= -1;
  125. pos[1] *= -1;
  126. pos[2] *= -1;
  127. glLightfv(GL_LIGHT1,GL_AMBIENT,amb);
  128. glLightfv(GL_LIGHT1,GL_DIFFUSE,diff);
  129. glLightfv(GL_LIGHT1,GL_SPECULAR,zeros);
  130. glLightfv(GL_LIGHT1,GL_POSITION,pos);
  131. }
  132. const float back[4] = {30.0/255.0,30.0/255.0,50.0/255.0,0};
  133. void display()
  134. {
  135. using namespace Eigen;
  136. using namespace igl;
  137. using namespace std;
  138. if(!trackball_on && tot_num_samples < 10000)
  139. {
  140. if(S.size() == 0)
  141. {
  142. S.resize(V.rows());
  143. S.setZero();
  144. }
  145. VectorXd Si;
  146. const int num_samples = 20;
  147. igl::embree::ambient_occlusion(ei,V,N,num_samples,Si);
  148. S *= (double)tot_num_samples;
  149. S += Si*(double)num_samples;
  150. tot_num_samples += num_samples;
  151. S /= (double)tot_num_samples;
  152. }
  153. // Convert to 1-intensity
  154. C.conservativeResize(S.rows(),3);
  155. if(ao_on)
  156. {
  157. C<<S,S,S;
  158. C.array() = (1.0-ao_factor*C.array());
  159. }else
  160. {
  161. C.setConstant(1.0);
  162. }
  163. if(ao_normalize)
  164. {
  165. C.col(0) *= ((double)C.rows())/C.col(0).sum();
  166. C.col(1) *= ((double)C.rows())/C.col(1).sum();
  167. C.col(2) *= ((double)C.rows())/C.col(2).sum();
  168. }
  169. C.col(0) *= color(0);
  170. C.col(1) *= color(1);
  171. C.col(2) *= color(2);
  172. glClearColor(back[0],back[1],back[2],0);
  173. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  174. // All smooth points
  175. glEnable( GL_POINT_SMOOTH );
  176. glDisable(GL_LIGHTING);
  177. if(lights_on)
  178. {
  179. lights();
  180. }
  181. push_scene();
  182. glEnable(GL_DEPTH_TEST);
  183. glDepthFunc(GL_LEQUAL);
  184. glEnable(GL_NORMALIZE);
  185. glEnable(GL_COLOR_MATERIAL);
  186. glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
  187. push_object();
  188. // Draw the model
  189. // Set material properties
  190. glEnable(GL_COLOR_MATERIAL);
  191. igl::opengl2::draw_mesh(V,F,N,C);
  192. pop_object();
  193. // Draw a nice floor
  194. glPushMatrix();
  195. const double floor_offset =
  196. -2./bbd*(V.col(1).maxCoeff()-mid(1));
  197. glTranslated(0,floor_offset,0);
  198. const float GREY[4] = {0.5,0.5,0.6,1.0};
  199. const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
  200. igl::opengl2::draw_floor(GREY,DARK_GREY);
  201. glPopMatrix();
  202. pop_scene();
  203. igl::opengl::report_gl_error();
  204. TwDraw();
  205. glutSwapBuffers();
  206. glutPostRedisplay();
  207. }
  208. void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
  209. {
  210. using namespace std;
  211. using namespace Eigen;
  212. using namespace igl;
  213. bool tw_using = TwEventMouseButtonGLUT(glutButton,glutState,mouse_x,mouse_y);
  214. switch(glutState)
  215. {
  216. case 1:
  217. // up
  218. glutSetCursor(GLUT_CURSOR_LEFT_ARROW);
  219. trackball_on = false;
  220. break;
  221. case 0:
  222. // down
  223. if(!tw_using)
  224. {
  225. glutSetCursor(GLUT_CURSOR_CYCLE);
  226. // collect information for trackball
  227. trackball_on = true;
  228. copy(scene_rot,scene_rot+4,down_scene_rot);
  229. down_mouse_x = mouse_x;
  230. down_mouse_y = mouse_y;
  231. }
  232. break;
  233. }
  234. }
  235. void mouse_drag(int mouse_x, int mouse_y)
  236. {
  237. using namespace igl;
  238. if(trackball_on)
  239. {
  240. // Rotate according to trackball
  241. trackball<float>(
  242. width,
  243. height,
  244. 2,
  245. down_scene_rot,
  246. down_mouse_x,
  247. down_mouse_y,
  248. mouse_x,
  249. mouse_y,
  250. scene_rot);
  251. }else
  252. {
  253. TwEventMouseMotionGLUT(mouse_x, mouse_y);
  254. }
  255. }
  256. void key(unsigned char key, int mouse_x, int mouse_y)
  257. {
  258. using namespace std;
  259. switch(key)
  260. {
  261. // ESC
  262. case char(27):
  263. rebar.save(REBAR_NAME);
  264. // ^C
  265. case char(3):
  266. exit(0);
  267. default:
  268. if(!TwEventKeyboardGLUT(key,mouse_x,mouse_y))
  269. {
  270. cout<<"Unknown key command: "<<key<<" "<<int(key)<<endl;
  271. }
  272. }
  273. }
  274. int main(int argc, char * argv[])
  275. {
  276. using namespace Eigen;
  277. using namespace igl;
  278. using namespace std;
  279. // init mesh
  280. string filename = "../shared/beast.obj";
  281. if(argc < 2)
  282. {
  283. cerr<<"Usage:"<<endl<<" ./example input.obj"<<endl;
  284. cout<<endl<<"Opening default mesh..."<<endl;
  285. }else
  286. {
  287. // Read and prepare mesh
  288. filename = argv[1];
  289. }
  290. // dirname, basename, extension and filename
  291. string d,b,ext,f;
  292. pathinfo(filename,d,b,ext,f);
  293. // Convert extension to lower case
  294. transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
  295. vector<vector<double > > vV,vN,vTC;
  296. vector<vector<int > > vF,vFTC,vFN;
  297. if(ext == "obj")
  298. {
  299. // Convert extension to lower case
  300. if(!igl::readOBJ(filename,vV,vTC,vN,vF,vFTC,vFN))
  301. {
  302. return 1;
  303. }
  304. }else if(ext == "off")
  305. {
  306. // Convert extension to lower case
  307. if(!igl::readOFF(filename,vV,vF,vN))
  308. {
  309. return 1;
  310. }
  311. }else if(ext == "wrl")
  312. {
  313. // Convert extension to lower case
  314. if(!igl::readWRL(filename,vV,vF))
  315. {
  316. return 1;
  317. }
  318. //}else
  319. //{
  320. // // Convert extension to lower case
  321. // MatrixXi T;
  322. // if(!igl::readMESH(filename,V,T,F))
  323. // {
  324. // return 1;
  325. // }
  326. // //if(F.size() > T.size() || F.size() == 0)
  327. // {
  328. // boundary_facets(T,F);
  329. // }
  330. }
  331. if(vV.size() > 0)
  332. {
  333. if(!list_to_matrix(vV,V))
  334. {
  335. return 1;
  336. }
  337. polygon_mesh_to_triangle_mesh(vF,F);
  338. }
  339. // Compute normals, centroid, colors, bounding box diagonal
  340. per_vertex_normals(V,F,N);
  341. mid = 0.5*(V.colwise().maxCoeff() + V.colwise().minCoeff());
  342. bbd = (V.colwise().maxCoeff() - V.colwise().minCoeff()).maxCoeff();
  343. // Init embree
  344. ei.init(V.cast<float>(),F.cast<int>());
  345. // Init glut
  346. glutInit(&argc,argv);
  347. if( !TwInit(TW_OPENGL, NULL) )
  348. {
  349. // A fatal error occured
  350. fprintf(stderr, "AntTweakBar initialization failed: %s\n", TwGetLastError());
  351. return 1;
  352. }
  353. // Create a tweak bar
  354. rebar.TwNewBar("TweakBar");
  355. rebar.TwAddVarRW("scene_rot", TW_TYPE_QUAT4F, &scene_rot, "");
  356. rebar.TwAddVarRW("lights_on", TW_TYPE_BOOLCPP, &lights_on, "key=l");
  357. rebar.TwAddVarRW("color", TW_TYPE_COLOR4F, color.data(), "colormode=hls");
  358. rebar.TwAddVarRW("ao_factor", TW_TYPE_DOUBLE, &ao_factor, "min=0 max=1 step=0.2 keyIncr=] keyDecr=[ ");
  359. rebar.TwAddVarRW("ao_normalize", TW_TYPE_BOOLCPP, &ao_normalize, "key=n");
  360. rebar.TwAddVarRW("ao_on", TW_TYPE_BOOLCPP, &ao_on, "key=a");
  361. rebar.TwAddVarRW("light_intensity", TW_TYPE_DOUBLE, &light_intensity, "min=0 max=0.4 step=0.1 keyIncr=} keyDecr={ ");
  362. rebar.load(REBAR_NAME);
  363. glutInitDisplayString( "rgba depth double samples>=8 ");
  364. glutInitWindowSize(glutGet(GLUT_SCREEN_WIDTH)/2.0,glutGet(GLUT_SCREEN_HEIGHT));
  365. glutCreateWindow("ambient-occlusion");
  366. glutDisplayFunc(display);
  367. glutReshapeFunc(reshape);
  368. glutKeyboardFunc(key);
  369. glutMouseFunc(mouse);
  370. glutMotionFunc(mouse_drag);
  371. glutPassiveMotionFunc((GLUTmousemotionfun)TwEventMouseMotionGLUT);
  372. glutMainLoop();
  373. return 0;
  374. }