main.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #include <igl/avg_edge_length.h>
  2. #include <igl/barycenter.h>
  3. #include <igl/frame_field_deformer.h>
  4. #include <igl/frame_to_cross_field.h>
  5. #include <igl/jet.h>
  6. #include <igl/local_basis.h>
  7. #include <igl/readDMAT.h>
  8. #include <igl/readOBJ.h>
  9. #include <igl/rotate_vectors.h>
  10. #include <igl/copyleft/comiso/nrosy.h>
  11. #include <igl/copyleft/comiso/miq.h>
  12. #include <igl/copyleft/comiso/frame_field.h>
  13. #include <igl/opengl/glfw/Viewer.h>
  14. #include <igl/PI.h>
  15. #include "tutorial_shared_path.h"
  16. // Input mesh
  17. Eigen::MatrixXd V;
  18. Eigen::MatrixXi F;
  19. // Face barycenters
  20. Eigen::MatrixXd B;
  21. // Scale for visualizing the fields
  22. double global_scale;
  23. // Input frame field constraints
  24. Eigen::VectorXi b;
  25. Eigen::MatrixXd bc1;
  26. Eigen::MatrixXd bc2;
  27. // Interpolated frame field
  28. Eigen::MatrixXd FF1, FF2;
  29. // Deformed mesh
  30. Eigen::MatrixXd V_deformed;
  31. Eigen::MatrixXd B_deformed;
  32. // Frame field on deformed
  33. Eigen::MatrixXd FF1_deformed;
  34. Eigen::MatrixXd FF2_deformed;
  35. // Cross field on deformed
  36. Eigen::MatrixXd X1_deformed;
  37. Eigen::MatrixXd X2_deformed;
  38. // Global parametrization
  39. Eigen::MatrixXd V_uv;
  40. Eigen::MatrixXi F_uv;
  41. // Create a texture that hides the integer translation in the parametrization
  42. void line_texture(Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> &texture_R,
  43. Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> &texture_G,
  44. Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> &texture_B)
  45. {
  46. unsigned size = 128;
  47. unsigned size2 = size/2;
  48. unsigned lineWidth = 3;
  49. texture_R.setConstant(size, size, 255);
  50. for (unsigned i=0; i<size; ++i)
  51. for (unsigned j=size2-lineWidth; j<=size2+lineWidth; ++j)
  52. texture_R(i,j) = 0;
  53. for (unsigned i=size2-lineWidth; i<=size2+lineWidth; ++i)
  54. for (unsigned j=0; j<size; ++j)
  55. texture_R(i,j) = 0;
  56. texture_G = texture_R;
  57. texture_B = texture_R;
  58. }
  59. bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
  60. {
  61. using namespace std;
  62. using namespace Eigen;
  63. if (key <'1' || key >'6')
  64. return false;
  65. viewer.data().clear();
  66. viewer.data().show_lines = false;
  67. viewer.data().show_texture = false;
  68. if (key == '1')
  69. {
  70. // Frame field constraints
  71. viewer.data().set_mesh(V, F);
  72. MatrixXd F1_t = MatrixXd::Zero(FF1.rows(),FF1.cols());
  73. MatrixXd F2_t = MatrixXd::Zero(FF2.rows(),FF2.cols());
  74. // Highlight in red the constrained faces
  75. MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
  76. for (unsigned i=0; i<b.size();++i)
  77. {
  78. C.row(b(i)) << 1, 0, 0;
  79. F1_t.row(b(i)) = bc1.row(i);
  80. F2_t.row(b(i)) = bc2.row(i);
  81. }
  82. viewer.data().set_colors(C);
  83. MatrixXd C1,C2;
  84. VectorXd K1 = F1_t.rowwise().norm();
  85. VectorXd K2 = F2_t.rowwise().norm();
  86. igl::jet(K1,true,C1);
  87. igl::jet(K2,true,C2);
  88. viewer.data().add_edges(B - global_scale*F1_t, B + global_scale*F1_t ,C1);
  89. viewer.data().add_edges(B - global_scale*F2_t, B + global_scale*F2_t ,C2);
  90. }
  91. if (key == '2')
  92. {
  93. // Frame field
  94. viewer.data().set_mesh(V, F);
  95. MatrixXd C1,C2;
  96. VectorXd K1 = FF1.rowwise().norm();
  97. VectorXd K2 = FF2.rowwise().norm();
  98. igl::jet(K1,true,C1);
  99. igl::jet(K2,true,C2);
  100. viewer.data().add_edges(B - global_scale*FF1, B + global_scale*FF1 ,C1);
  101. viewer.data().add_edges(B - global_scale*FF2, B + global_scale*FF2 ,C2);
  102. // Highlight in red the constrained faces
  103. MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
  104. for (unsigned i=0; i<b.size();++i)
  105. C.row(b(i)) << 1, 0, 0;
  106. viewer.data().set_colors(C);
  107. }
  108. if (key == '3')
  109. {
  110. // Deformed with frame field
  111. viewer.data().set_mesh(V_deformed, F);
  112. viewer.data().add_edges(B_deformed - global_scale*FF1_deformed, B_deformed + global_scale*FF1_deformed ,Eigen::RowVector3d(1,0,0));
  113. viewer.data().add_edges(B_deformed - global_scale*FF2_deformed, B_deformed + global_scale*FF2_deformed ,Eigen::RowVector3d(0,0,1));
  114. viewer.data().set_colors(RowVector3d(1,1,1));
  115. }
  116. if (key == '4')
  117. {
  118. // Deformed with cross field
  119. viewer.data().set_mesh(V_deformed, F);
  120. viewer.data().add_edges(B_deformed - global_scale*X1_deformed, B_deformed + global_scale*X1_deformed ,Eigen::RowVector3d(0,0,1));
  121. viewer.data().add_edges(B_deformed - global_scale*X2_deformed, B_deformed + global_scale*X2_deformed ,Eigen::RowVector3d(0,0,1));
  122. viewer.data().set_colors(RowVector3d(1,1,1));
  123. }
  124. if (key == '5')
  125. {
  126. // Deformed with quad texture
  127. viewer.data().set_mesh(V_deformed, F);
  128. viewer.data().set_uv(V_uv,F_uv);
  129. viewer.data().set_colors(RowVector3d(1,1,1));
  130. viewer.data().show_texture = true;
  131. }
  132. if (key == '6')
  133. {
  134. // Deformed with quad texture
  135. viewer.data().set_mesh(V, F);
  136. viewer.data().set_uv(V_uv,F_uv);
  137. viewer.data().set_colors(RowVector3d(1,1,1));
  138. viewer.data().show_texture = true;
  139. }
  140. // Replace the standard texture with an integer shift invariant texture
  141. Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> texture_R, texture_G, texture_B;
  142. line_texture(texture_R, texture_G, texture_B);
  143. viewer.data().set_texture(texture_R, texture_B, texture_G);
  144. viewer.core().align_camera_center(viewer.data().V,viewer.data().F);
  145. return false;
  146. }
  147. int main(int argc, char *argv[])
  148. {
  149. using namespace Eigen;
  150. // Load a mesh in OBJ format
  151. igl::readOBJ(TUTORIAL_SHARED_PATH "/bumpy-cube.obj", V, F);
  152. // Compute face barycenters
  153. igl::barycenter(V, F, B);
  154. // Compute scale for visualizing fields
  155. global_scale = .2*igl::avg_edge_length(V, F);
  156. // Load constraints
  157. MatrixXd temp;
  158. igl::readDMAT(TUTORIAL_SHARED_PATH "/bumpy-cube.dmat",temp);
  159. b = temp.block(0,0,temp.rows(),1).cast<int>();
  160. bc1 = temp.block(0,1,temp.rows(),3);
  161. bc2 = temp.block(0,4,temp.rows(),3);
  162. // Interpolate the frame field
  163. igl::copyleft::comiso::frame_field(V, F, b, bc1, bc2, FF1, FF2);
  164. // Deform the mesh to transform the frame field in a cross field
  165. igl::frame_field_deformer(
  166. V,F,FF1,FF2,V_deformed,FF1_deformed,FF2_deformed);
  167. // Compute face barycenters deformed mesh
  168. igl::barycenter(V_deformed, F, B_deformed);
  169. // Find the closest crossfield to the deformed frame field
  170. igl::frame_to_cross_field(V_deformed,F,FF1_deformed,FF2_deformed,X1_deformed);
  171. // Find a smooth crossfield that interpolates the deformed constraints
  172. MatrixXd bc_x(b.size(),3);
  173. for (unsigned i=0; i<b.size();++i)
  174. bc_x.row(i) = X1_deformed.row(b(i));
  175. VectorXd S;
  176. igl::copyleft::comiso::nrosy(
  177. V,
  178. F,
  179. b,
  180. bc_x,
  181. VectorXi(),
  182. VectorXd(),
  183. MatrixXd(),
  184. 4,
  185. 0.5,
  186. X1_deformed,
  187. S);
  188. // The other representative of the cross field is simply rotated by 90 degrees
  189. MatrixXd B1,B2,B3;
  190. igl::local_basis(V_deformed,F,B1,B2,B3);
  191. X2_deformed =
  192. igl::rotate_vectors(X1_deformed, VectorXd::Constant(1,igl::PI/2), B1, B2);
  193. // Global seamless parametrization
  194. igl::copyleft::comiso::miq(V_deformed,
  195. F,
  196. X1_deformed,
  197. X2_deformed,
  198. V_uv,
  199. F_uv,
  200. 60.0,
  201. 5.0,
  202. false,
  203. 2);
  204. igl::opengl::glfw::Viewer viewer;
  205. // Plot the original mesh with a texture parametrization
  206. key_down(viewer,'6',0);
  207. // Launch the viewer
  208. viewer.callback_key_down = &key_down;
  209. viewer.launch();
  210. }