main.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. #undef IGL_STATIC_LIBRARY
  2. #include <igl/readOBJ.h>
  3. #include <igl/readDMAT.h>
  4. #include <igl/viewer/Viewer.h>
  5. #include <igl/barycenter.h>
  6. #include <igl/avg_edge_length.h>
  7. #include <vector>
  8. #include <igl/n_polyvector.h>
  9. #include <igl/conjugate_frame_fields.h>
  10. #include <stdlib.h>
  11. #include <igl/readOFF.h>
  12. #include <igl/jet.h>
  13. #include <igl/quad_planarity.h>
  14. #include <igl/planarize_quad_mesh.h>
  15. // Input mesh
  16. Eigen::MatrixXd V;
  17. Eigen::MatrixXi F;
  18. // Face barycenters
  19. Eigen::MatrixXd B;
  20. // Quad mesh generated from smooth field
  21. Eigen::MatrixXd VQS;
  22. Eigen::MatrixXi FQS;
  23. Eigen::MatrixXi FQStri;
  24. Eigen::MatrixXd PQS0, PQS1, PQS2, PQS3;
  25. // Quad mesh generated from conjugate field
  26. Eigen::MatrixXd VQC;
  27. Eigen::MatrixXi FQC;
  28. Eigen::MatrixXi FQCtri;
  29. Eigen::MatrixXd VQCplan;
  30. Eigen::MatrixXd PQC0, PQC1, PQC2, PQC3;
  31. Eigen::MatrixXd PQCp0, PQCp1, PQCp2, PQCp3;
  32. // Scale for visualizing the fields
  33. double global_scale;
  34. // Input constraints
  35. Eigen::VectorXi isConstrained;
  36. Eigen::MatrixXd constraints;
  37. Eigen::MatrixXd smooth_pvf;
  38. Eigen::MatrixXd conjugate_pvf;
  39. igl::ConjugateFFSolverData<Eigen::MatrixXd, Eigen::MatrixXi> *csdata;
  40. int conjIter = 2;
  41. int totalConjIter = 0;
  42. double lambdaOrtho = .1;
  43. double lambdaInit = 100;
  44. double lambdaMultFactor = 1.01;
  45. bool doHardConstraints = true;
  46. bool key_down(igl::Viewer& viewer, unsigned char key, int modifier)
  47. {
  48. using namespace std;
  49. using namespace Eigen;
  50. if (key <'1' || key >'6')
  51. return false;
  52. viewer.clear_mesh();
  53. viewer.options.show_lines = false;
  54. viewer.options.show_texture = false;
  55. if (key <= '3')
  56. {
  57. viewer.set_mesh(V, F);
  58. // Highlight in red the constrained faces
  59. MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
  60. for (unsigned i=0; i<F.rows();++i)
  61. if (isConstrained[i])
  62. C.row(i) << 1, 0, 0;
  63. viewer.set_colors(C);
  64. }
  65. if (key == '1')
  66. {
  67. // Frame field constraints
  68. MatrixXd F1_t = MatrixXd::Zero(F.rows(),3);
  69. MatrixXd F2_t = MatrixXd::Zero(F.rows(),3);
  70. for (unsigned i=0; i<F.rows();++i)
  71. if (isConstrained[i])
  72. {
  73. F1_t.row(i) = constraints.block(i,0,1,3);
  74. F2_t.row(i) = constraints.block(i,3,1,3);
  75. }
  76. viewer.add_edges (B - global_scale*F1_t, B + global_scale*F1_t , Eigen::RowVector3d(0,0,1));
  77. viewer.add_edges (B - global_scale*F2_t, B + global_scale*F2_t , Eigen::RowVector3d(0,0,1));
  78. }
  79. if (key == '2')
  80. {
  81. viewer.add_edges (B - global_scale*smooth_pvf.block(0,0,F.rows(),3),
  82. B + global_scale*smooth_pvf.block(0,0,F.rows(),3),
  83. Eigen::RowVector3d(0,1,0));
  84. viewer.add_edges (B - global_scale*smooth_pvf.block(0,3,F.rows(),3),
  85. B + global_scale*smooth_pvf.block(0,3,F.rows(),3),
  86. Eigen::RowVector3d(0,1,0));
  87. }
  88. if (key == '3')
  89. {
  90. if (totalConjIter <50)
  91. {
  92. double lambdaOut;
  93. igl::conjugate_frame_fields(*csdata, isConstrained, conjugate_pvf, conjugate_pvf, conjIter, lambdaOrtho, lambdaInit, lambdaMultFactor, doHardConstraints,
  94. &lambdaOut);
  95. totalConjIter += 2;
  96. lambdaInit = lambdaOut;
  97. }
  98. viewer.add_edges (B - global_scale*conjugate_pvf.block(0,0,F.rows(),3),
  99. B + global_scale*conjugate_pvf.block(0,0,F.rows(),3),
  100. Eigen::RowVector3d(0,1,0));
  101. viewer.add_edges (B - global_scale*conjugate_pvf.block(0,3,F.rows(),3),
  102. B + global_scale*conjugate_pvf.block(0,3,F.rows(),3),
  103. Eigen::RowVector3d(0,1,0));
  104. }
  105. if (key == '4')
  106. {
  107. viewer.set_mesh(VQS, FQStri);
  108. // show planarity
  109. VectorXd planarity;
  110. igl::quad_planarity( VQS, FQS, planarity);
  111. MatrixXd Ct;
  112. igl::jet(planarity, 0, 0.02, Ct);
  113. MatrixXd C(FQStri.rows(),3);
  114. C << Ct, Ct;
  115. viewer.set_colors(C);
  116. viewer.add_edges (PQS0, PQS1, Eigen::RowVector3d(0,0,0));
  117. viewer.add_edges (PQS1, PQS2, Eigen::RowVector3d(0,0,0));
  118. viewer.add_edges (PQS2, PQS3, Eigen::RowVector3d(0,0,0));
  119. viewer.add_edges (PQS3, PQS0, Eigen::RowVector3d(0,0,0));
  120. }
  121. if (key == '5')
  122. {
  123. viewer.set_mesh(VQC, FQCtri);
  124. // show planarity
  125. VectorXd planarity;
  126. igl::quad_planarity( VQC, FQC, planarity);
  127. MatrixXd Ct;
  128. igl::jet(planarity, 0, 0.02, Ct);
  129. MatrixXd C(FQCtri.rows(),3);
  130. C << Ct, Ct;
  131. viewer.set_colors(C);
  132. viewer.add_edges (PQC0, PQC1, Eigen::RowVector3d(0,0,0));
  133. viewer.add_edges (PQC1, PQC2, Eigen::RowVector3d(0,0,0));
  134. viewer.add_edges (PQC2, PQC3, Eigen::RowVector3d(0,0,0));
  135. viewer.add_edges (PQC3, PQC0, Eigen::RowVector3d(0,0,0));
  136. }
  137. if (key == '6')
  138. {
  139. igl ::planarize_quad_mesh(VQC, FQC, 50, 0.01, VQCplan);
  140. viewer.set_mesh(VQCplan, FQCtri);
  141. igl::slice( VQCplan, FQC.col(0), 1, PQCp0);
  142. igl::slice( VQCplan, FQC.col(1), 1, PQCp1);
  143. igl::slice( VQCplan, FQC.col(2), 1, PQCp2);
  144. igl::slice( VQCplan, FQC.col(3), 1, PQCp3);
  145. // show planarity
  146. VectorXd planarity;
  147. igl::quad_planarity( VQCplan, FQC, planarity);
  148. MatrixXd Ct;
  149. igl::jet(planarity, 0, 0.02, Ct);
  150. MatrixXd C(FQCtri.rows(),3);
  151. C << Ct, Ct;
  152. viewer.set_colors(C);
  153. viewer.add_edges (PQCp0, PQCp1, Eigen::RowVector3d(0,0,0));
  154. viewer.add_edges (PQCp1, PQCp2, Eigen::RowVector3d(0,0,0));
  155. viewer.add_edges (PQCp2, PQCp3, Eigen::RowVector3d(0,0,0));
  156. viewer.add_edges (PQCp3, PQCp0, Eigen::RowVector3d(0,0,0));
  157. }
  158. return false;
  159. }
  160. int main(int argc, char *argv[])
  161. {
  162. using namespace Eigen;
  163. using namespace std;
  164. // Load a mesh in OBJ format
  165. igl::readOBJ("../shared/inspired_mesh.obj", V, F);
  166. // Compute face barycenters
  167. igl::barycenter(V, F, B);
  168. // Compute scale for visualizing fields
  169. global_scale = .2*igl::avg_edge_length(V, F);
  170. // Load constraints
  171. MatrixXd temp;
  172. igl::readDMAT("../shared/inspired_mesh.dmat",temp);
  173. isConstrained = temp.block(0,0,temp.rows(),1).cast<int>();
  174. constraints = temp.block(0,1,temp.rows(),temp.cols()-1);
  175. // Interpolate to get a smooth field
  176. igl::n_polyvector(V, F, isConstrained, constraints, smooth_pvf);
  177. // Initialize conjugate field with smooth field
  178. csdata = new igl::ConjugateFFSolverData<Eigen::MatrixXd,Eigen::MatrixXi>(V,F);
  179. conjugate_pvf = smooth_pvf;
  180. // Load quad mesh generated by smooth field
  181. igl::readOFF("../shared/inspired_mesh_quads_Smooth.off", VQS, FQS);
  182. FQStri.resize(2*FQS.rows(), 3);
  183. FQStri << FQS.col(0),FQS.col(1),FQS.col(2),
  184. FQS.col(2),FQS.col(3),FQS.col(0);
  185. igl::slice( VQS, FQS.col(0), 1, PQS0);
  186. igl::slice( VQS, FQS.col(1), 1, PQS1);
  187. igl::slice( VQS, FQS.col(2), 1, PQS2);
  188. igl::slice( VQS, FQS.col(3), 1, PQS3);
  189. // Load quad mesh generated by conjugate field
  190. igl::readOFF("../shared/inspired_mesh_quads_Conjugate.off", VQC, FQC);
  191. FQCtri.resize(2*FQC.rows(), 3);
  192. FQCtri << FQC.col(0),FQC.col(1),FQC.col(2),
  193. FQC.col(2),FQC.col(3),FQC.col(0);
  194. igl::slice( VQC, FQC.col(0), 1, PQC0);
  195. igl::slice( VQC, FQC.col(1), 1, PQC1);
  196. igl::slice( VQC, FQC.col(2), 1, PQC2);
  197. igl::slice( VQC, FQC.col(3), 1, PQC3);
  198. igl::Viewer viewer;
  199. // Plot the original mesh with a texture parametrization
  200. key_down(viewer,'1',0);
  201. // Launch the viewer
  202. viewer.callback_key_down = &key_down;
  203. viewer.launch();
  204. }