main.cpp.off 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #include <igl/read_triangle_mesh.h>
  2. #include <igl/box_simplices.h>
  3. #include <igl/eytzinger_aabb.h>
  4. #include <igl/lipschitz_octree.h>
  5. #include <igl/unique_sparse_voxel_corners.h>
  6. #include <igl/eytzinger_aabb_sdf.h>
  7. #include <igl/unique.h>
  8. #include <igl/readDMAT.h>
  9. #include <igl/grid.h>
  10. #include <igl/edges.h>
  11. #include <igl/marching_cubes.h>
  12. #include <igl/parallel_for.h>
  13. #include <igl/opengl/glfw/Viewer.h>
  14. #include <igl/matlab_format.h>
  15. #include <igl/variable_radius_offset.h>
  16. #include <igl/get_seconds.h>
  17. #include <igl/SphereMeshWedge.h>
  18. #include <limits>
  19. #include <Eigen/Geometry>
  20. #define sign(x) ((x>0) - (x<0))
  21. inline double dot2(const Eigen::RowVector3d & v)
  22. {
  23. return v.dot(v);
  24. }
  25. inline double clamp(const double & x, const double & a, const double & b)
  26. {
  27. return std::max(a, std::min(b, x));
  28. }
  29. // https://iquilezles.org/articles/triangledistance/
  30. template <typename T1, typename T2, typename T3, typename Tp>
  31. typename Tp::Scalar udTriangle(
  32. const T1 & v1, const T2 & v2, const T3 & v3, const Tp & p)
  33. {
  34. using vec3 = Eigen::Matrix<typename Tp::Scalar, 3, 1>;
  35. // prepare data
  36. vec3 v21 = v2 - v1; vec3 p1 = p - v1;
  37. vec3 v32 = v3 - v2; vec3 p2 = p - v2;
  38. vec3 v13 = v1 - v3; vec3 p3 = p - v3;
  39. vec3 nor = v21.cross( v13 );
  40. return sqrt( // inside/outside test
  41. (sign(v21.cross(nor).dot(p1)) +
  42. sign(v32.cross(nor).dot(p2)) +
  43. sign(v13.cross(nor).dot(p3))<2.0)
  44. ?
  45. // 3 edges
  46. std::min( std::min(
  47. dot2(v21*clamp(v21.dot(p1)/dot2(v21),0.0,1.0)-p1),
  48. dot2(v32*clamp(v32.dot(p2)/dot2(v32),0.0,1.0)-p2) ),
  49. dot2(v13*clamp(v13.dot(p3)/dot2(v13),0.0,1.0)-p3) )
  50. :
  51. // 1 face
  52. nor.dot(p1)*nor.dot(p1)/dot2(nor) );
  53. }
  54. template <typename Tp, typename Ta, typename Tb>
  55. typename Tp::Scalar udLineSegment(const Tp & p, const Ta & a, const Tb & b)
  56. {
  57. using vec3 = Eigen::Matrix<typename Tp::Scalar, 3, 1>;
  58. vec3 pa = p - a;
  59. vec3 ba = b - a;
  60. const auto h = clamp( pa.dot(ba)/ba.dot(ba), 0.0, 1.0 );
  61. return ( pa - ba*h ).norm();
  62. }
  63. int main(int argc, char * argv[])
  64. {
  65. const int ns = 256+1;
  66. Eigen::RowVector3i res(ns,ns,ns);
  67. IGL_TICTOC_LAMBDA;
  68. // Read mesh
  69. Eigen::Matrix<double,Eigen::Dynamic,3,Eigen::RowMajor> V;
  70. Eigen::Matrix<int,Eigen::Dynamic,3,Eigen::RowMajor> F;
  71. if(!igl::read_triangle_mesh
  72. (argc>1?argv[1]: TUTORIAL_SHARED_PATH "/decimated-knight.off",V,F)) {
  73. std::cout << "Failed to load mesh." << std::endl;
  74. }
  75. // Normalize
  76. V.rowwise() -= 0.5* (V.colwise().maxCoeff() + V.colwise().minCoeff());
  77. const double scale = 0.8/V.array().abs().maxCoeff();
  78. V *= scale;
  79. // if second arg exists read it to dmat
  80. Eigen::VectorXd R;
  81. if(argc>2)
  82. {
  83. igl::readDMAT( argv[2],R);
  84. R *= scale;
  85. }else
  86. {
  87. //Eigen::VectorXd R = (0.1+0.9*(0.5+(Eigen::VectorXd::Random(V.rows())*0.5).array()))*((2.0/(res(0)-1))*2);
  88. R = V.col(1);
  89. R.array() -= R.minCoeff();
  90. R /= R.maxCoeff();
  91. R.array() += 1.0;
  92. R = (R.array().pow(4)).eval();
  93. R *= 0.01;
  94. }
  95. tictoc();
  96. Eigen::Matrix<double,Eigen::Dynamic,3,Eigen::RowMajor> PB1,PB2;
  97. Eigen::Matrix<int,Eigen::Dynamic,2,Eigen::RowMajor> E;
  98. igl::edges(F,E);
  99. enum class OffsetType
  100. {
  101. EDGE_OFFSET = 0,
  102. TRIANGLE_OFFSET = 1,
  103. VARIABLE_RADIUS_OFFSET = 2
  104. } offset = OffsetType::VARIABLE_RADIUS_OFFSET;
  105. double isovalue = 0.16;(2.0/(res(0)-1))*2;
  106. std::function<double(const Eigen::RowVector3d &,const int i)> primitive;
  107. std::vector<igl::SphereMeshWedge<double>> data;
  108. switch(offset)
  109. {
  110. case OffsetType::EDGE_OFFSET:
  111. {
  112. igl::box_simplices(V,E,PB1,PB2);
  113. primitive = [&](const Eigen::RowVector3d & p, const int i)
  114. {
  115. return udLineSegment(p, V.row(E(i,0)), V.row(E(i,1)));
  116. };
  117. break;
  118. }
  119. case OffsetType::TRIANGLE_OFFSET:
  120. {
  121. igl::box_simplices(V,F,PB1,PB2);
  122. primitive = [&](const Eigen::RowVector3d & p, const int i)
  123. {
  124. return udTriangle( V.row(F(i,0)), V.row(F(i,1)), V.row(F(i,2)), p);
  125. };
  126. break;
  127. }
  128. case OffsetType::VARIABLE_RADIUS_OFFSET:
  129. {
  130. isovalue = 0;
  131. igl::variable_radius_offset(V,F,R,PB1,PB2,data,primitive);
  132. break;
  133. }
  134. }
  135. printf("%-20s: %g secs\n","PB",tictoc());
  136. tictoc();
  137. Eigen::Matrix<double,Eigen::Dynamic,3,Eigen::RowMajor> B1,B2;
  138. Eigen::VectorXi leaf;
  139. igl::eytzinger_aabb(PB1,PB2,B1,B2,leaf);
  140. printf("%-20s: %g secs\n","eytzinger_aabb",tictoc());
  141. //{
  142. // Eigen::VectorXi U;
  143. // igl::unique(leaf,U);
  144. // printf("%d → %d\n",PB1.rows(),U.size()-2);
  145. //}
  146. tictoc();
  147. Eigen::Matrix<double,Eigen::Dynamic,3> mV;
  148. Eigen::Matrix<int,Eigen::Dynamic,3> mF;
  149. if(ns <= 64+1)
  150. {
  151. Eigen::Matrix<double,Eigen::Dynamic,3,Eigen::RowMajor> GV;
  152. igl::grid(res,GV);
  153. GV *= 2;
  154. GV.array() -= 1;
  155. Eigen::VectorXd S;
  156. igl::eytzinger_aabb_sdf(GV,primitive,B1,B2,leaf,S);
  157. printf("%-20s: %g secs\n","eytzinger_aabb_sdf",tictoc());
  158. tictoc();
  159. igl::marching_cubes(S,GV,res(0),res(1),res(2),isovalue,mV,mF);
  160. printf("%-20s: %g secs\n","marching_cubes",tictoc());
  161. }
  162. tictoc();
  163. const std::function<double(const Eigen::RowVector3d &)>
  164. sdf = [&](const Eigen::RowVector3d & p) -> double
  165. {
  166. const std::function<double(const int)> primitive_p = [&](const int j)
  167. {
  168. return primitive(p,j);
  169. };
  170. double f;
  171. igl::eytzinger_aabb_sdf(p,primitive_p,B1,B2,leaf,f);
  172. return f;
  173. };
  174. const std::function<double(const Eigen::RowVector3d &)>
  175. udf = [&](const Eigen::RowVector3d & p) -> double
  176. {
  177. return std::abs(sdf(p));
  178. //// This made performance worse.
  179. //const std::function<double(const int)> primitive_p = [&](const int j)
  180. //{
  181. // const double d = udTriangle( V.row(F(j,0)), V.row(F(j,1)), V.row(F(j,2)), p);
  182. // const Eigen::RowVector3d r(R(F(j,0)),R(F(j,1)),R(F(j,2)));
  183. // const double min_r = r.minCoeff();
  184. // const double max_r = r.maxCoeff();
  185. // if(d > max_r)
  186. // {
  187. // return d - max_r;
  188. // }else if(d < min_r)
  189. // {
  190. // return d - min_r;
  191. // }
  192. // return 0.0;
  193. //};
  194. //double f;
  195. //igl::eytzinger_aabb_sdf(p,primitive_p,B1,B2,leaf,f);
  196. //return f;
  197. };
  198. Eigen::RowVector3d origin(-1,-1,-1);
  199. const double h0 = 2;
  200. const int max_depth = floor(log2(res(0)));
  201. Eigen::Matrix<int,Eigen::Dynamic,3,Eigen::RowMajor> ijk;
  202. igl::lipschitz_octree( origin,h0,max_depth,udf,ijk);
  203. printf("%-20s: %g secs\n","lipschitz_octree",tictoc());
  204. Eigen::Matrix<double,Eigen::Dynamic,3> oV;
  205. Eigen::Matrix<int,Eigen::Dynamic,3> oF;
  206. {
  207. tictoc();
  208. // Gather the corners of those leaf cells
  209. const double h = h0 / (1 << max_depth);
  210. Eigen::Matrix<int,Eigen::Dynamic,8,Eigen::RowMajor> J;
  211. Eigen::Matrix<int,Eigen::Dynamic,3,Eigen::RowMajor> unique_ijk;
  212. Eigen::Matrix<double,Eigen::Dynamic,3,Eigen::RowMajor> unique_corner_positions;
  213. igl::unique_sparse_voxel_corners(origin,h0,max_depth,ijk,unique_ijk,J,unique_corner_positions);
  214. //printf("unique_sparse_voxel_corners: %0.7f seconds\n",tictoc());
  215. printf("%-20s: %g secs\n","unique_sparse_vo...",tictoc());
  216. /// Evaluate the signed distance function at the corners
  217. Eigen::VectorXd S(unique_corner_positions.rows());
  218. //for(int u = 0;u<unique_corner_positions.rows();u++)
  219. igl::parallel_for(
  220. unique_corner_positions.rows(),
  221. [&](const int u)
  222. {
  223. // evaluate the function at the corner
  224. S(u) = sdf(unique_corner_positions.row(u));
  225. },1000);
  226. //printf(" sdf: %0.7f seconds\n",tictoc());
  227. printf("%-20s: %g secs\n","sdf",tictoc());
  228. // Run marching cubes on the sparse set of leaf cells
  229. igl::marching_cubes( S,unique_corner_positions,J, 0, oV,oF);
  230. //printf(" marching_cubes: %0.7f seconds\n",tictoc());
  231. printf("%-20s: %g secs\n","marching_cubes",tictoc());
  232. }
  233. //tictoc();
  234. //printf("------------------\n");
  235. //igl::variable_radius_offset(V,F,R,origin,h0,max_depth,oV,oF);
  236. //printf("%-20s: %g secs\n","variable_radius_offset",tictoc());
  237. igl::opengl::glfw::Viewer viewer;
  238. viewer.data().set_mesh(V,F);
  239. viewer.data().set_face_based(true);
  240. viewer.data().show_lines = false;
  241. viewer.append_mesh();
  242. viewer.data().set_mesh(mV,mF);
  243. viewer.data().set_face_based(true);
  244. viewer.data().show_lines = true;
  245. viewer.data().show_faces = true;
  246. viewer.data().set_colors(Eigen::RowVector3d(0.8,0.2,0.2));
  247. viewer.append_mesh();
  248. viewer.data().set_mesh(oV,oF);
  249. viewer.data().set_face_based(true);
  250. viewer.data().show_lines = true;
  251. viewer.data().show_faces = true;
  252. viewer.data().set_colors(Eigen::RowVector3d(0.2,0.8,0.2));
  253. viewer.launch();
  254. return 0;
  255. }