example.cpp 10 KB

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