marching_cubes.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. #include <cstdint>
  15. template <typename DerivedS, typename DerivedGV, typename DerivedV, typename DerivedF>
  16. IGL_INLINE void igl::marching_cubes(
  17. const Eigen::MatrixBase<DerivedS> &S,
  18. const Eigen::MatrixBase<DerivedGV> &GV,
  19. const unsigned nx,
  20. const unsigned ny,
  21. const unsigned nz,
  22. const typename DerivedS::Scalar isovalue,
  23. Eigen::PlainObjectBase<DerivedV> &V,
  24. Eigen::PlainObjectBase<DerivedF> &F)
  25. {
  26. std::unordered_map<std::int64_t,int> E2V;
  27. return marching_cubes(S,GV,nx,ny,nz,isovalue,V,F,E2V);
  28. }
  29. template <
  30. typename DerivedS,
  31. typename DerivedGV,
  32. typename DerivedV,
  33. typename DerivedF>
  34. IGL_INLINE void igl::marching_cubes(
  35. const Eigen::MatrixBase<DerivedS> & S,
  36. const Eigen::MatrixBase<DerivedGV> & GV,
  37. const unsigned nx,
  38. const unsigned ny,
  39. const unsigned nz,
  40. const typename DerivedS::Scalar isovalue,
  41. Eigen::PlainObjectBase<DerivedV> &V,
  42. Eigen::PlainObjectBase<DerivedF> &F,
  43. std::unordered_map<std::int64_t,int> &E2V)
  44. {
  45. typedef typename DerivedS::Scalar Scalar;
  46. typedef unsigned Index;
  47. // use same order as a2fVertexOffset
  48. const unsigned ioffset[8] = {0,1,1+nx,nx,nx*ny,1+nx*ny,1+nx+nx*ny,nx+nx*ny};
  49. V.resize(std::pow(nx*ny*nz,2./3.),3);
  50. F.resize(std::pow(nx*ny*nz,2./3.),3);
  51. Index n = 0;
  52. Index m = 0;
  53. const auto xyz2i = [&nx,&ny]
  54. (const int & x, const int & y, const int & z)->unsigned
  55. {
  56. return x+nx*(y+ny*(z));
  57. };
  58. const auto cube =
  59. [
  60. &GV,&S,&V,&n,&F,&m,&isovalue,
  61. &E2V,&xyz2i,&ioffset
  62. ]
  63. (const int x, const int y, const int z)
  64. {
  65. const unsigned i = xyz2i(x,y,z);
  66. //Make a local copy of the values at the cube's corners
  67. Eigen::Matrix<Scalar,8,1> cS;
  68. Eigen::Matrix<Index,8,1> cI;
  69. //Find which vertices are inside of the surface and which are outside
  70. for(int c = 0; c < 8; c++)
  71. {
  72. const unsigned ic = i + ioffset[c];
  73. cI(c) = ic;
  74. cS(c) = S(ic);
  75. }
  76. march_cube(GV,cS,cI,isovalue,V,n,F,m,E2V);
  77. };
  78. // march over all cubes (loop order chosen to match memory)
  79. //
  80. // Should be possible to parallelize safely if threads are "well separated".
  81. // Like red-black Gauss Seidel. Probably each thread need's their own E2V,V,F,
  82. // and then merge at the end. Annoying part are the edges lying on the
  83. // interface between chunks.
  84. for(int z=0;z<nz-1;z++)
  85. {
  86. for(int y=0;y<ny-1;y++)
  87. {
  88. for(int x=0;x<nx-1;x++)
  89. {
  90. cube(x,y,z);
  91. }
  92. }
  93. }
  94. V.conservativeResize(n,3);
  95. F.conservativeResize(m,3);
  96. }
  97. template <
  98. typename DerivedS,
  99. typename DerivedGV,
  100. typename DerivedGI,
  101. typename DerivedV,
  102. typename DerivedF>
  103. IGL_INLINE void igl::marching_cubes(
  104. const Eigen::MatrixBase<DerivedS> & S,
  105. const Eigen::MatrixBase<DerivedGV> & GV,
  106. const Eigen::MatrixBase<DerivedGI> & GI,
  107. const typename DerivedS::Scalar isovalue,
  108. Eigen::PlainObjectBase<DerivedV> &V,
  109. Eigen::PlainObjectBase<DerivedF> &F)
  110. {
  111. typedef Eigen::Index Index;
  112. typedef typename DerivedV::Scalar Scalar;
  113. std::unordered_map<std::int64_t,int> E2V;
  114. V.resize(4*GV.rows(),3);
  115. F.resize(4*GV.rows(),3);
  116. Index n = 0;
  117. Index m = 0;
  118. // march over cubes
  119. //Make a local copy of the values at the cube's corners
  120. Eigen::Matrix<Scalar, 8, 1> cS;
  121. Eigen::Matrix<Index, 8, 1> cI;
  122. for(Index c = 0;c<GI.rows();c++)
  123. {
  124. for(int v = 0; v < 8; v++)
  125. {
  126. cI(v) = GI(c,v);
  127. cS(v) = S(GI(c,v));
  128. }
  129. march_cube(GV,cS,cI,isovalue,V,n,F,m,E2V);
  130. }
  131. V.conservativeResize(n,3);
  132. F.conservativeResize(m,3);
  133. }
  134. #ifdef IGL_STATIC_LIBRARY
  135. // Explicit template instantiation
  136. template void igl::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 8, 1, -1, 8>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 8, 1, -1, 8>> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>::Scalar, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3>>&);
  137. // generated by autoexplicit.sh
  138. 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> >&);
  139. // generated by autoexplicit.sh
  140. 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> >&);
  141. // generated by autoexplicit.sh
  142. 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> >&);
  143. 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> >&);
  144. 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> >&);
  145. #endif