main.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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. bool key_down(igl::Viewer& viewer, unsigned char key, int modifier)
  41. {
  42. using namespace std;
  43. using namespace Eigen;
  44. if (key <'1' || key >'3')
  45. return false;
  46. viewer.data.lines.resize(0,9);
  47. // Highlight in red the constrained faces
  48. MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
  49. for (unsigned i=0; i<F.rows();++i)
  50. if (isConstrained[i])
  51. C.row(i) << 1, 0, 0;
  52. viewer.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<F.rows();++i)
  59. if (isConstrained[i])
  60. {
  61. F1_t.row(i) = constraints.block(i,0,1,3);
  62. F2_t.row(i) = constraints.block(i,3,1,3);
  63. }
  64. viewer.add_edges (B - global_scale*F1_t, B + global_scale*F1_t , Eigen::RowVector3d(0,0,1));
  65. viewer.add_edges (B - global_scale*F2_t, B + global_scale*F2_t , Eigen::RowVector3d(0,0,1));
  66. }
  67. if (key == '2')
  68. {
  69. // Interpolated result
  70. viewer.add_edges (B - global_scale*smooth_pvf.block(0,0,F.rows(),3),
  71. B + global_scale*smooth_pvf.block(0,0,F.rows(),3),
  72. Eigen::RowVector3d(0,0,1));
  73. viewer.add_edges (B - global_scale*smooth_pvf.block(0,3,F.rows(),3),
  74. B + global_scale*smooth_pvf.block(0,3,F.rows(),3),
  75. Eigen::RowVector3d(0,0,1));
  76. }
  77. if (key == '3')
  78. {
  79. // Conjugate field
  80. viewer.add_edges (B - global_scale*conjugate_pvf.block(0,0,F.rows(),3),
  81. B + global_scale*conjugate_pvf.block(0,0,F.rows(),3),
  82. Eigen::RowVector3d(0,0,1));
  83. viewer.add_edges (B - global_scale*conjugate_pvf.block(0,3,F.rows(),3),
  84. B + global_scale*conjugate_pvf.block(0,3,F.rows(),3),
  85. Eigen::RowVector3d(0,0,1));
  86. }
  87. return false;
  88. }
  89. int main(int argc, char *argv[])
  90. {
  91. using namespace Eigen;
  92. using namespace std;
  93. // Load a mesh in OBJ format
  94. igl::readOBJ("../shared/inspired_mesh.obj", V, F);
  95. // Compute face barycenters
  96. igl::barycenter(V, F, B);
  97. // Compute scale for visualizing fields
  98. global_scale = .4*igl::avg_edge_length(V, F);
  99. // Load constraints
  100. MatrixXd temp;
  101. igl::readDMAT("../shared/inspired_mesh.dmat",temp);
  102. isConstrained = temp.block(0,0,temp.rows(),1).cast<int>();
  103. constraints = temp.block(0,1,temp.rows(),temp.cols()-1);
  104. // Interpolate to get a smooth field
  105. igl::n_polyvector(V, F, isConstrained, constraints, smooth_pvf);
  106. // Initialize conjugate field with smooth field
  107. csdata = new igl::ConjugateFFSolverData<Eigen::MatrixXd,Eigen::MatrixXi>(V,F);
  108. conjugate_pvf = smooth_pvf;
  109. // Optimize the field
  110. int conjIter = 20;
  111. int totalConjIter = 0;
  112. double lambdaOrtho = .1;
  113. double lambdaInit = 100;
  114. double lambdaMultFactor = 1.01;
  115. bool doHardConstraints = true;
  116. double lambdaOut;
  117. igl::conjugate_frame_fields(*csdata, isConstrained, conjugate_pvf, conjugate_pvf, conjIter, lambdaOrtho, lambdaInit, lambdaMultFactor, doHardConstraints,
  118. &lambdaOut);
  119. // Launch the viewer
  120. igl::Viewer viewer;
  121. viewer.core.invert_normals = true;
  122. viewer.core.show_lines = false;
  123. viewer.core.show_texture = false;
  124. viewer.set_mesh(V, F);
  125. viewer.callback_key_down = &key_down;
  126. key_down(viewer,'3',0);
  127. viewer.launch();
  128. }