main.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #undef IGL_STATIC_LIBRARY
  2. #include <igl/readOBJ.h>
  3. #include <igl/readDMAT.h>
  4. #include <igl/writeDMAT.h>
  5. #include <igl/viewer/Viewer.h>
  6. #include <igl/barycenter.h>
  7. #include <igl/avg_edge_length.h>
  8. #include <vector>
  9. #include <igl/n_polyvector.h>
  10. #include <igl/conjugate_frame_fields.h>
  11. #include <stdlib.h>
  12. #include <igl/readOFF.h>
  13. #include <igl/jet.h>
  14. #include <igl/quad_planarity.h>
  15. #include <igl/planarize_quad_mesh.h>
  16. // Input mesh
  17. Eigen::MatrixXd V;
  18. Eigen::MatrixXi F;
  19. // Face barycenters
  20. Eigen::MatrixXd B;
  21. // Quad mesh generated from smooth field
  22. Eigen::MatrixXd VQS;
  23. Eigen::MatrixXi FQS;
  24. Eigen::MatrixXi FQStri;
  25. Eigen::MatrixXd PQS0, PQS1, PQS2, PQS3;
  26. // Quad mesh generated from conjugate field
  27. Eigen::MatrixXd VQC;
  28. Eigen::MatrixXi FQC;
  29. Eigen::MatrixXi FQCtri;
  30. Eigen::MatrixXd VQCplan;
  31. Eigen::MatrixXd PQC0, PQC1, PQC2, PQC3;
  32. Eigen::MatrixXd PQCp0, PQCp1, PQCp2, PQCp3;
  33. // Scale for visualizing the fields
  34. double global_scale;
  35. // Input constraints
  36. Eigen::VectorXi b;
  37. Eigen::MatrixXd bc;
  38. Eigen::MatrixXd smooth_pvf;
  39. Eigen::MatrixXd conjugate_pvf;
  40. igl::ConjugateFFSolverData<Eigen::MatrixXd, Eigen::MatrixXi> *csdata;
  41. bool key_down(igl::Viewer& viewer, unsigned char key, int modifier)
  42. {
  43. using namespace std;
  44. using namespace Eigen;
  45. if (key <'1' || key >'3')
  46. return false;
  47. viewer.data.lines.resize(0,9);
  48. // Highlight in red the constrained faces
  49. MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
  50. for (unsigned i=0; i<b.size();++i)
  51. C.row(b(i)) << 1, 0, 0;
  52. viewer.data.set_colors(C);
  53. if (key == '1')
  54. {
  55. // Frame field constraints
  56. MatrixXd F1_t = MatrixXd::Zero(F.rows(),3);
  57. MatrixXd F2_t = MatrixXd::Zero(F.rows(),3);
  58. for (unsigned i=0; i<b.size();++i)
  59. {
  60. F1_t.row(b(i)) = bc.block(i,0,1,3);
  61. F2_t.row(b(i)) = bc.block(i,3,1,3);
  62. }
  63. viewer.data.add_edges(B - global_scale*F1_t, B + global_scale*F1_t , Eigen::RowVector3d(0,0,1));
  64. viewer.data.add_edges(B - global_scale*F2_t, B + global_scale*F2_t , Eigen::RowVector3d(0,0,1));
  65. }
  66. if (key == '2')
  67. {
  68. // Interpolated result
  69. viewer.data.add_edges(B - global_scale*smooth_pvf.block(0,0,F.rows(),3),
  70. B + global_scale*smooth_pvf.block(0,0,F.rows(),3),
  71. Eigen::RowVector3d(0,0,1));
  72. viewer.data.add_edges(B - global_scale*smooth_pvf.block(0,3,F.rows(),3),
  73. B + global_scale*smooth_pvf.block(0,3,F.rows(),3),
  74. Eigen::RowVector3d(0,0,1));
  75. }
  76. if (key == '3')
  77. {
  78. // Conjugate field
  79. viewer.data.add_edges(B - global_scale*conjugate_pvf.block(0,0,F.rows(),3),
  80. B + global_scale*conjugate_pvf.block(0,0,F.rows(),3),
  81. Eigen::RowVector3d(0,0,1));
  82. viewer.data.add_edges(B - global_scale*conjugate_pvf.block(0,3,F.rows(),3),
  83. B + global_scale*conjugate_pvf.block(0,3,F.rows(),3),
  84. Eigen::RowVector3d(0,0,1));
  85. }
  86. return false;
  87. }
  88. int main(int argc, char *argv[])
  89. {
  90. using namespace Eigen;
  91. using namespace std;
  92. // Load a mesh in OBJ format
  93. igl::readOBJ("../shared/inspired_mesh.obj", V, F);
  94. // Compute face barycenters
  95. igl::barycenter(V, F, B);
  96. // Compute scale for visualizing fields
  97. global_scale = .4*igl::avg_edge_length(V, F);
  98. // Load constraints
  99. igl::readDMAT("../shared/inspired_mesh_b.dmat",b);
  100. igl::readDMAT("../shared/inspired_mesh_bc.dmat",bc);
  101. // Interpolate to get a smooth field
  102. igl::n_polyvector(V, F, b, bc, smooth_pvf);
  103. // Initialize conjugate field with smooth field
  104. csdata = new igl::ConjugateFFSolverData<Eigen::MatrixXd,Eigen::MatrixXi>(V,F);
  105. conjugate_pvf = smooth_pvf;
  106. // Optimize the field
  107. int conjIter = 20;
  108. double lambdaOrtho = .1;
  109. double lambdaInit = 100;
  110. double lambdaMultFactor = 1.01;
  111. bool doHardConstraints = true;
  112. double lambdaOut;
  113. VectorXi isConstrained = VectorXi::Constant(F.rows(),0);
  114. for (unsigned i=0; i<b.size(); ++i)
  115. isConstrained(b(i)) = 1;
  116. igl::conjugate_frame_fields(*csdata, isConstrained, conjugate_pvf, conjugate_pvf, conjIter, lambdaOrtho, lambdaInit, lambdaMultFactor, doHardConstraints,
  117. &lambdaOut);
  118. // Launch the viewer
  119. igl::Viewer viewer;
  120. viewer.core.invert_normals = true;
  121. viewer.core.show_lines = false;
  122. viewer.core.show_texture = false;
  123. viewer.data.set_mesh(V, F);
  124. viewer.callback_key_down = &key_down;
  125. key_down(viewer,'3',0);
  126. viewer.launch();
  127. }