main.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #include <igl/readOBJ.h>
  2. #include <igl/readDMAT.h>
  3. #include <igl/opengl/glfw/Viewer.h>
  4. #include <igl/barycenter.h>
  5. #include <igl/avg_edge_length.h>
  6. #include <vector>
  7. #include <igl/n_polyvector_general.h>
  8. #include <igl/n_polyvector.h>
  9. #include <igl/local_basis.h>
  10. #include <igl/writeOFF.h>
  11. #include <stdlib.h>
  12. #include <igl/jet.h>
  13. #include <fstream>
  14. #include <iostream>
  15. // Input mesh
  16. Eigen::MatrixXd V;
  17. Eigen::MatrixXi F;
  18. // Per face bases
  19. Eigen::MatrixXd B1,B2,B3;
  20. // Face barycenters
  21. Eigen::MatrixXd B;
  22. // Scale for visualizing the fields
  23. double global_scale;
  24. // Random length factor
  25. double rand_factor = 5;
  26. Eigen::VectorXi samples;
  27. void readSamples(const std::string &fname, Eigen::VectorXi &samples)
  28. {
  29. int numSamples;
  30. FILE *fp = fopen(fname.c_str(),"r");
  31. if (fscanf(fp, "%d", &numSamples)!=1)
  32. {
  33. fclose(fp);
  34. return;
  35. }
  36. samples.resize(numSamples,1);
  37. int vali;
  38. for (int i =0; i<numSamples; ++i)
  39. {
  40. if (fscanf(fp, "%d", &vali)!=1 || vali<0)
  41. {
  42. fclose(fp);
  43. samples.resize(0,1);
  44. return;
  45. }
  46. samples[i]=vali;
  47. }
  48. fclose(fp);
  49. }
  50. // Create a random set of tangent vectors
  51. Eigen::VectorXd random_constraints(const
  52. Eigen::VectorXd& b1, const
  53. Eigen::VectorXd& b2, int n)
  54. {
  55. Eigen::VectorXd r(n*3);
  56. for (unsigned i=0; i<n;++i)
  57. {
  58. double a = (double(rand())/RAND_MAX)*2*M_PI;
  59. double s = 1 + ((double(rand())/RAND_MAX)) * rand_factor;
  60. Eigen::Vector3d t = s * (cos(a) * b1 + sin(a) * b2);
  61. r.block(i*3,0,3,1) = t;
  62. }
  63. return r;
  64. }
  65. bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
  66. {
  67. using namespace std;
  68. using namespace Eigen;
  69. if (key <'1' || key >'9')
  70. return false;
  71. viewer.data().lines.resize(0,9);
  72. int num = key - '0';
  73. // Interpolate
  74. std::cerr << "Interpolating " << num << "-PolyVector field" << std::endl;
  75. VectorXi b(3);
  76. b << 1511, 603, 506;
  77. int numConstraintsToGenerate;
  78. // if it's not a 2-PV or a 1-PV, include a line direction (2 opposite vectors)
  79. // in the field
  80. if (num>=5)
  81. numConstraintsToGenerate = num-2;
  82. else
  83. if (num>=3)
  84. numConstraintsToGenerate = num-1;
  85. else
  86. numConstraintsToGenerate = num;
  87. MatrixXd bc(b.size(),numConstraintsToGenerate*3);
  88. for (unsigned i=0; i<b.size(); ++i)
  89. {
  90. VectorXd t = random_constraints(B1.row(b(i)),B2.row(b(i)),numConstraintsToGenerate);
  91. bc.row(i) = t;
  92. }
  93. VectorXi rootsIndex(num);
  94. for (int i =0; i<numConstraintsToGenerate; ++i)
  95. rootsIndex[i] = i+1;
  96. if (num>=5)
  97. rootsIndex[num-2] = -2;
  98. if (num>=3)
  99. rootsIndex[num-1] = -1;
  100. // Interpolated PolyVector field
  101. Eigen::MatrixXd pvf;
  102. igl::n_polyvector_general(V, F, b, bc, rootsIndex, pvf);
  103. ofstream ofs;
  104. ofs.open("pvf.txt", ofstream::out);
  105. ofs<<pvf;
  106. ofs.close();
  107. igl::writeOFF("pvf.off",V,F);
  108. // Highlight in red the constrained faces
  109. MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
  110. for (unsigned i=0; i<b.size();++i)
  111. C.row(b(i)) << 1, 0, 0;
  112. viewer.data().set_colors(C);
  113. for (int n=0; n<num; ++n)
  114. {
  115. // const MatrixXd &VF = pvf.block(0,n*3,F.rows(),3);
  116. MatrixXd VF = MatrixXd::Zero(F.rows(),3);
  117. for (unsigned i=0; i<b.size(); ++i)
  118. VF.row(b[i]) = pvf.block(b[i],n*3,1,3);
  119. for (int i=0; i<samples.rows(); ++i)
  120. VF.row(samples[i]) = pvf.block(samples[i],n*3,1,3);
  121. VectorXd c = VF.rowwise().norm();
  122. MatrixXd C2;
  123. igl::jet(c,1,1+rand_factor,C2);
  124. // viewer.data().add_edges(B - global_scale*VF, B + global_scale*VF , C2);
  125. viewer.data().add_edges(B, B + global_scale*VF , C2);
  126. }
  127. return false;
  128. }
  129. int main(int argc, char *argv[])
  130. {
  131. using namespace Eigen;
  132. using namespace std;
  133. // Load a mesh in OBJ format
  134. igl::readOBJ(TUTORIAL_SHARED_PATH "/snail.obj", V, F);
  135. readSamples(TUTORIAL_SHARED_PATH "/snail.samples.0.2", samples);
  136. // Compute local basis for faces
  137. igl::local_basis(V,F,B1,B2,B3);
  138. // Compute face barycenters
  139. igl::barycenter(V, F, B);
  140. // Compute scale for visualizing fields
  141. global_scale = .1*igl::avg_edge_length(V, F);
  142. // Make the example deterministic
  143. srand(0);
  144. igl::opengl::glfw::Viewer viewer;
  145. viewer.data().set_mesh(V, F);
  146. viewer.callback_key_down = &key_down;
  147. viewer.data().show_lines = false;
  148. key_down(viewer,'3',0);
  149. std::cerr << " *** Press keys 1-9 to select number of vectors per point. ***" << std::endl;
  150. viewer.launch();
  151. }