marching_cubes.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2021 Alec Jacobson <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "marching_cubes.h"
  9. #include "march_cube.h"
  10. // Adapted from public domain code at
  11. // http://paulbourke.net/geometry/polygonise/marchingsource.cpp
  12. #include <unordered_map>
  13. #include <iostream>
  14. template <typename DerivedS, typename DerivedGV, typename DerivedV, typename DerivedF>
  15. IGL_INLINE void igl::marching_cubes(
  16. const Eigen::MatrixBase<DerivedS> &S,
  17. const Eigen::MatrixBase<DerivedGV> &GV,
  18. const unsigned nx,
  19. const unsigned ny,
  20. const unsigned nz,
  21. const typename DerivedS::Scalar isovalue,
  22. Eigen::PlainObjectBase<DerivedV> &V,
  23. Eigen::PlainObjectBase<DerivedF> &F)
  24. {
  25. typedef typename DerivedS::Scalar Scalar;
  26. typedef unsigned Index;
  27. // use same order as a2fVertexOffset
  28. const unsigned ioffset[8] = {0,1,1+nx,nx,nx*ny,1+nx*ny,1+nx+nx*ny,nx+nx*ny};
  29. std::unordered_map<int64_t,int> E2V;
  30. V.resize(std::pow(nx*ny*nz,2./3.),3);
  31. F.resize(std::pow(nx*ny*nz,2./3.),3);
  32. Index n = 0;
  33. Index m = 0;
  34. const auto xyz2i = [&nx,&ny]
  35. (const int & x, const int & y, const int & z)->unsigned
  36. {
  37. return x+nx*(y+ny*(z));
  38. };
  39. const auto cube =
  40. [
  41. &GV,&S,&V,&n,&F,&m,&isovalue,
  42. &E2V,&xyz2i,&ioffset
  43. ]
  44. (const int x, const int y, const int z)
  45. {
  46. const unsigned i = xyz2i(x,y,z);
  47. //Make a local copy of the values at the cube's corners
  48. Eigen::Matrix<Scalar,8,1> cS;
  49. Eigen::Matrix<Index,8,1> cI;
  50. //Find which vertices are inside of the surface and which are outside
  51. for(int c = 0; c < 8; c++)
  52. {
  53. const unsigned ic = i + ioffset[c];
  54. cI(c) = ic;
  55. cS(c) = S(ic);
  56. }
  57. march_cube(GV,cS,cI,isovalue,V,n,F,m,E2V);
  58. };
  59. // march over all cubes (loop order chosen to match memory)
  60. //
  61. // Should be possible to parallelize safely if threads are "well separated".
  62. // Like red-black Gauss Seidel. Probably each thread need's their own E2V,V,F,
  63. // and then merge at the end. Annoying part are the edges lying on the
  64. // interface between chunks.
  65. for(int z=0;z<nz-1;z++)
  66. {
  67. for(int y=0;y<ny-1;y++)
  68. {
  69. for(int x=0;x<nx-1;x++)
  70. {
  71. cube(x,y,z);
  72. }
  73. }
  74. }
  75. V.conservativeResize(n,3);
  76. F.conservativeResize(m,3);
  77. }
  78. template <
  79. typename DerivedS,
  80. typename DerivedGV,
  81. typename DerivedGI,
  82. typename DerivedV,
  83. typename DerivedF>
  84. IGL_INLINE void igl::marching_cubes(
  85. const Eigen::MatrixBase<DerivedS> & S,
  86. const Eigen::MatrixBase<DerivedGV> & GV,
  87. const Eigen::MatrixBase<DerivedGI> & GI,
  88. const typename DerivedS::Scalar isovalue,
  89. Eigen::PlainObjectBase<DerivedV> &V,
  90. Eigen::PlainObjectBase<DerivedF> &F)
  91. {
  92. typedef Eigen::Index Index;
  93. typedef typename DerivedV::Scalar Scalar;
  94. std::unordered_map<int64_t,int> E2V;
  95. V.resize(4*GV.rows(),3);
  96. F.resize(4*GV.rows(),3);
  97. Index n = 0;
  98. Index m = 0;
  99. // march over cubes
  100. //Make a local copy of the values at the cube's corners
  101. Eigen::Matrix<Scalar, 8, 1> cS;
  102. Eigen::Matrix<Index, 8, 1> cI;
  103. for(Index c = 0;c<GI.rows();c++)
  104. {
  105. for(int v = 0; v < 8; v++)
  106. {
  107. cI(v) = GI(c,v);
  108. cS(v) = S(GI(c,v));
  109. }
  110. march_cube(GV,cS,cI,isovalue,V,n,F,m,E2V);
  111. }
  112. V.conservativeResize(n,3);
  113. F.conservativeResize(m,3);
  114. }
  115. #ifdef IGL_STATIC_LIBRARY
  116. // Explicit template instantiation
  117. // generated by autoexplicit.sh
  118. template void igl::marching_cubes<Eigen::Matrix<float, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, unsigned int, unsigned int, unsigned int, Eigen::Matrix<float, -1, 1, 0, -1, 1>::Scalar, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
  119. // generated by autoexplicit.sh
  120. template void igl::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, unsigned int, unsigned int, unsigned int, Eigen::Matrix<double, -1, 1, 0, -1, 1>::Scalar, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
  121. // generated by autoexplicit.sh
  122. template void igl::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, unsigned int, unsigned int, unsigned int, Eigen::Matrix<double, -1, 1, 0, -1, 1>::Scalar, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  123. template void igl::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>::Scalar, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  124. template void igl::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 8, 0, -1, 8>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 8, 0, -1, 8> > const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>::Scalar, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  125. #endif