main.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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. #include <igl/dot_row.h>
  17. #include <igl/local_basis.h>
  18. // Input mesh
  19. Eigen::MatrixXd V;
  20. Eigen::MatrixXi F;
  21. // Face barycenters
  22. Eigen::MatrixXd B;
  23. // Scale for visualizing the fields
  24. double global_scale;
  25. // Input constraints
  26. Eigen::VectorXi b;
  27. Eigen::MatrixXd bc;
  28. Eigen::MatrixXd smooth_pvf;
  29. Eigen::MatrixXd conjugate_pvf;
  30. Eigen::VectorXd conjugacy_s;
  31. Eigen::VectorXd conjugacy_c;
  32. igl::ConjugateFFSolverData<Eigen::MatrixXd, Eigen::MatrixXi> *csdata;
  33. bool key_down(igl::Viewer& viewer, unsigned char key, int modifier)
  34. {
  35. using namespace std;
  36. using namespace Eigen;
  37. if (key <'1' || key >'5')
  38. return false;
  39. viewer.data.lines.resize(0,9);
  40. // Highlight in red the constrained faces
  41. MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
  42. for (unsigned i=0; i<b.size();++i)
  43. C.row(b(i)) << 1, 0, 0;
  44. double maxC = std::max(conjugacy_c.maxCoeff(), conjugacy_s.maxCoeff());
  45. double minC = std::min(conjugacy_c.minCoeff(), conjugacy_s.minCoeff());
  46. Eigen::VectorXd valS = conjugacy_s;
  47. // Eigen::VectorXd valS = (valS.array() - minC)/(maxC-minC);
  48. // valS = 1 - valS.array();
  49. Eigen::VectorXd valC = conjugacy_c;
  50. // Eigen::VectorXd valC = (valC.array() - minC)/(maxC-minC);
  51. // valC = 1 - valC.array();
  52. MatrixXd CS, CC;
  53. igl::jet(valS, 0, 0.004, CS);
  54. igl::jet(valC, 0, 0.004, CC);
  55. if (key == '1')
  56. {
  57. // Frame field constraints
  58. MatrixXd F1_t = MatrixXd::Zero(F.rows(),3);
  59. MatrixXd F2_t = MatrixXd::Zero(F.rows(),3);
  60. for (unsigned i=0; i<b.size();++i)
  61. {
  62. F1_t.row(b(i)) = bc.block(i,0,1,3);
  63. F2_t.row(b(i)) = bc.block(i,3,1,3);
  64. }
  65. viewer.data.add_edges(B - global_scale*F1_t, B + global_scale*F1_t , Eigen::RowVector3d(0,0,1));
  66. viewer.data.add_edges(B - global_scale*F2_t, B + global_scale*F2_t , Eigen::RowVector3d(0,0,1));
  67. viewer.data.set_colors(C);
  68. }
  69. if (key == '2')
  70. {
  71. // Interpolated result
  72. viewer.data.add_edges(B - global_scale*smooth_pvf.block(0,0,F.rows(),3),
  73. B + global_scale*smooth_pvf.block(0,0,F.rows(),3),
  74. Eigen::RowVector3d(0,0,1));
  75. viewer.data.add_edges(B - global_scale*smooth_pvf.block(0,3,F.rows(),3),
  76. B + global_scale*smooth_pvf.block(0,3,F.rows(),3),
  77. Eigen::RowVector3d(0,0,1));
  78. viewer.data.set_colors(C);
  79. }
  80. if (key == '3')
  81. {
  82. // Interpolated result
  83. viewer.data.set_colors(CS);
  84. }
  85. if (key == '4')
  86. {
  87. // Conjugate field
  88. viewer.data.add_edges(B - global_scale*conjugate_pvf.block(0,0,F.rows(),3),
  89. B + global_scale*conjugate_pvf.block(0,0,F.rows(),3),
  90. Eigen::RowVector3d(0,0,1));
  91. viewer.data.add_edges(B - global_scale*conjugate_pvf.block(0,3,F.rows(),3),
  92. B + global_scale*conjugate_pvf.block(0,3,F.rows(),3),
  93. Eigen::RowVector3d(0,0,1));
  94. viewer.data.set_colors(C);
  95. }
  96. if (key == '5')
  97. {
  98. // Conjugate field
  99. viewer.data.set_colors(CC);
  100. }
  101. return false;
  102. }
  103. int main(int argc, char *argv[])
  104. {
  105. using namespace Eigen;
  106. using namespace std;
  107. // Load a mesh in OBJ format
  108. igl::readOBJ("../shared/inspired_mesh.obj", V, F);
  109. // Compute face barycenters
  110. igl::barycenter(V, F, B);
  111. // Local bases (needed for conjugacy)
  112. Eigen::MatrixXd B1, B2, B3;
  113. igl::local_basis(V, F, B1, B2, B3);
  114. // Compute scale for visualizing fields
  115. global_scale = .4*igl::avg_edge_length(V, F);
  116. // Load constraints
  117. igl::readDMAT("../shared/inspired_mesh_b.dmat",b);
  118. igl::readDMAT("../shared/inspired_mesh_bc.dmat",bc);
  119. // Interpolate to get a smooth field
  120. igl::n_polyvector(V, F, b, bc, smooth_pvf);
  121. // Initialize conjugate field with smooth field
  122. csdata = new igl::ConjugateFFSolverData<Eigen::MatrixXd,Eigen::MatrixXi>(V,F);
  123. conjugate_pvf = smooth_pvf;
  124. // Optimize the field
  125. int conjIter = 20;
  126. double lambdaOrtho = .1;
  127. double lambdaInit = 100;
  128. double lambdaMultFactor = 1.01;
  129. bool doHardConstraints = true;
  130. double lambdaOut;
  131. VectorXi isConstrained = VectorXi::Constant(F.rows(),0);
  132. for (unsigned i=0; i<b.size(); ++i)
  133. isConstrained(b(i)) = 1;
  134. igl::conjugate_frame_fields(*csdata, isConstrained, conjugate_pvf, conjugate_pvf, conjIter, lambdaOrtho, lambdaInit, lambdaMultFactor, doHardConstraints, &lambdaOut);
  135. // local representations of field vectors
  136. Eigen::Matrix<double, Eigen::Dynamic, 2> pvU, pvV;
  137. pvU.resize(F.rows(),2); pvV.resize(F.rows(),2);
  138. //smooth
  139. const Eigen::MatrixXd &Us = smooth_pvf.leftCols(3);
  140. const Eigen::MatrixXd &Vs = smooth_pvf.rightCols(3);
  141. pvU << igl::dot_row(Us,B1), igl::dot_row(Us,B2);
  142. pvV << igl::dot_row(Vs,B1), igl::dot_row(Vs,B2);
  143. csdata->evaluateConjugacy(pvU, pvV, conjugacy_s);
  144. //conjugate
  145. const Eigen::MatrixXd &Uc = conjugate_pvf.leftCols(3);
  146. const Eigen::MatrixXd &Vc = conjugate_pvf.rightCols(3);
  147. pvU << igl::dot_row(Uc,B1), igl::dot_row(Uc,B2);
  148. pvV << igl::dot_row(Vc,B1), igl::dot_row(Vc,B2);
  149. csdata->evaluateConjugacy(pvU, pvV, conjugacy_c);
  150. // Launch the viewer
  151. igl::Viewer viewer;
  152. viewer.core.invert_normals = true;
  153. viewer.core.show_lines = false;
  154. viewer.core.show_texture = false;
  155. viewer.data.set_mesh(V, F);
  156. viewer.callback_key_down = &key_down;
  157. key_down(viewer,'1',0);
  158. viewer.launch();
  159. }