marching_cubes.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include "marching_cubes.h"
  2. #include <map>
  3. #include "MCTables.hh"
  4. class EdgeKey
  5. {
  6. public:
  7. EdgeKey(unsigned i0, unsigned i1) {
  8. if (i0 < i1) { i0_ = i0; i1_ = i1; }
  9. else { i0_ = i1; i1_ = i0; }
  10. }
  11. bool operator<(const EdgeKey& _rhs) const
  12. {
  13. if (i0_ != _rhs.i0_)
  14. return (i0_ < _rhs.i0_);
  15. else
  16. return (i1_ < _rhs.i1_);
  17. }
  18. private:
  19. unsigned i0_, i1_;
  20. };
  21. template <typename DerivedV, typename DerivedF>
  22. class MarchingCubes
  23. {
  24. typedef Eigen::PlainObjectBase<DerivedV> PointMatrixType;
  25. typedef Eigen::PlainObjectBase<DerivedF> FaceMatrixType;
  26. typedef std::map<EdgeKey, unsigned> MyMap;
  27. typedef typename MyMap::const_iterator MyMapIterator;
  28. public:
  29. MarchingCubes(const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &values,
  30. const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 3> &points,
  31. const unsigned x_res,
  32. const unsigned y_res,
  33. const unsigned z_res,
  34. PointMatrixType &vertices,
  35. FaceMatrixType &faces)
  36. {
  37. if(x_res <2 || y_res<2 ||z_res<2)
  38. return;
  39. faces.resize(10000,3);
  40. int num_faces = 0;
  41. vertices.resize(10000,3);
  42. int num_vertices = 0;
  43. unsigned n_cubes = (x_res-1) * (y_res-1) * (z_res-1);
  44. assert(points.rows() == x_res * y_res * z_res);
  45. unsigned int offsets_[8];
  46. offsets_[0] = 0;
  47. offsets_[1] = 1;
  48. offsets_[2] = 1 + x_res;
  49. offsets_[3] = x_res;
  50. offsets_[4] = x_res*y_res;
  51. offsets_[5] = 1 + x_res*y_res;
  52. offsets_[6] = 1 + x_res + x_res*y_res;
  53. offsets_[7] = x_res + x_res*y_res;
  54. for (unsigned cube_it =0 ; cube_it < n_cubes; ++cube_it)
  55. {
  56. unsigned corner[8];
  57. typename DerivedF::Scalar samples[12];
  58. unsigned char cubetype(0);
  59. unsigned int i;
  60. // get point indices of corner vertices
  61. for (i=0; i<8; ++i)
  62. {
  63. // get cube coordinates
  64. unsigned int _idx = cube_it;
  65. unsigned int X(x_res-1), Y(y_res-1);
  66. unsigned int x = _idx % X; _idx /= X;
  67. unsigned int y = _idx % Y; _idx /= Y;
  68. unsigned int z = _idx;
  69. // transform to point coordinates
  70. _idx = x + y*x_res + z*x_res*y_res;
  71. // add offset
  72. corner[i] = _idx + offsets_[i];
  73. }
  74. // determine cube type
  75. for (i=0; i<8; ++i)
  76. if (values[corner[i]] > 0.0)
  77. cubetype |= (1<<i);
  78. // trivial reject ?
  79. if (cubetype == 0 || cubetype == 255)
  80. continue;
  81. // compute samples on cube's edges
  82. if (edgeTable[cubetype]&1)
  83. samples[0] = add_vertex(values, points, corner[0], corner[1], vertices, num_vertices, edge2vertex);
  84. if (edgeTable[cubetype]&2)
  85. samples[1] = add_vertex(values, points, corner[1], corner[2], vertices, num_vertices, edge2vertex);
  86. if (edgeTable[cubetype]&4)
  87. samples[2] = add_vertex(values, points, corner[3], corner[2], vertices, num_vertices, edge2vertex);
  88. if (edgeTable[cubetype]&8)
  89. samples[3] = add_vertex(values, points, corner[0], corner[3], vertices, num_vertices, edge2vertex);
  90. if (edgeTable[cubetype]&16)
  91. samples[4] = add_vertex(values, points, corner[4], corner[5], vertices, num_vertices, edge2vertex);
  92. if (edgeTable[cubetype]&32)
  93. samples[5] = add_vertex(values, points, corner[5], corner[6], vertices, num_vertices, edge2vertex);
  94. if (edgeTable[cubetype]&64)
  95. samples[6] = add_vertex(values, points, corner[7], corner[6], vertices, num_vertices, edge2vertex);
  96. if (edgeTable[cubetype]&128)
  97. samples[7] = add_vertex(values, points, corner[4], corner[7], vertices, num_vertices, edge2vertex);
  98. if (edgeTable[cubetype]&256)
  99. samples[8] = add_vertex(values, points, corner[0], corner[4], vertices, num_vertices, edge2vertex);
  100. if (edgeTable[cubetype]&512)
  101. samples[9] = add_vertex(values, points, corner[1], corner[5], vertices, num_vertices, edge2vertex);
  102. if (edgeTable[cubetype]&1024)
  103. samples[10] = add_vertex(values, points, corner[2], corner[6], vertices, num_vertices, edge2vertex);
  104. if (edgeTable[cubetype]&2048)
  105. samples[11] = add_vertex(values, points, corner[3], corner[7], vertices, num_vertices, edge2vertex);
  106. // connect samples by triangles
  107. for (i=0; triTable[cubetype][0][i] != -1; i+=3 )
  108. {
  109. num_faces++;
  110. if (num_faces > faces.rows())
  111. faces.conservativeResize(faces.rows()+10000, Eigen::NoChange);
  112. faces.row(num_faces-1) <<
  113. samples[triTable[cubetype][0][i ]],
  114. samples[triTable[cubetype][0][i+1]],
  115. samples[triTable[cubetype][0][i+2]];
  116. }
  117. }
  118. vertices.conservativeResize(num_vertices, Eigen::NoChange);
  119. faces.conservativeResize(num_faces, Eigen::NoChange);
  120. };
  121. static typename DerivedF::Scalar add_vertex(const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &values,
  122. const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 3> &points,
  123. unsigned int i0,
  124. unsigned int i1,
  125. PointMatrixType &vertices,
  126. int &num_vertices,
  127. MyMap &edge2vertex)
  128. {
  129. // find vertex if it has been computed already
  130. MyMapIterator it = edge2vertex.find(EdgeKey(i0, i1));
  131. if (it != edge2vertex.end())
  132. return it->second;
  133. ;
  134. // generate new vertex
  135. const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> & p0 = points.row(i0);
  136. const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> & p1 = points.row(i1);
  137. typename DerivedV::Scalar s0 = fabs(values[i0]);
  138. typename DerivedV::Scalar s1 = fabs(values[i1]);
  139. typename DerivedV::Scalar t = s0 / (s0+s1);
  140. num_vertices++;
  141. if (num_vertices > vertices.rows())
  142. vertices.conservativeResize(vertices.rows()+10000, Eigen::NoChange);
  143. vertices.row(num_vertices-1) = (1.0f-t)*p0 + t*p1;
  144. edge2vertex[EdgeKey(i0, i1)] = num_vertices-1;
  145. return num_vertices-1;
  146. }
  147. ;
  148. // maps an edge to the sample vertex generated on it
  149. MyMap edge2vertex;
  150. };
  151. template <typename DerivedV, typename DerivedF>
  152. IGL_INLINE void igl::marching_cubes(const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &values,
  153. const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 3> &points,
  154. const unsigned x_res,
  155. const unsigned y_res,
  156. const unsigned z_res,
  157. Eigen::PlainObjectBase<DerivedV> &vertices,
  158. Eigen::PlainObjectBase<DerivedF> &faces)
  159. {
  160. MarchingCubes<DerivedV, DerivedF> mc(values,
  161. points,
  162. x_res,
  163. y_res,
  164. z_res,
  165. vertices,
  166. faces);
  167. }
  168. #ifndef IGL_HEADER_ONLY
  169. // Explicit template specialization
  170. template void igl::marching_cubes<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
  171. template void igl::marching_cubes<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
  172. template void igl::marching_cubes<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >&);
  173. template void igl::marching_cubes<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >&);
  174. # include "MCTables.cc"
  175. #endif