// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2021 Alec Jacobson // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "marching_cubes.h" #include "march_cube.h" // Adapted from public domain code at // http://paulbourke.net/geometry/polygonise/marchingsource.cpp #include #include #include template IGL_INLINE void igl::marching_cubes( const Eigen::MatrixBase &S, const Eigen::MatrixBase &GV, const unsigned nx, const unsigned ny, const unsigned nz, const typename DerivedS::Scalar isovalue, Eigen::PlainObjectBase &V, Eigen::PlainObjectBase &F) { typedef typename DerivedS::Scalar Scalar; typedef unsigned Index; // use same order as a2fVertexOffset const unsigned ioffset[8] = {0,1,1+nx,nx,nx*ny,1+nx*ny,1+nx+nx*ny,nx+nx*ny}; std::unordered_map E2V; V.resize(std::pow(nx*ny*nz,2./3.),3); F.resize(std::pow(nx*ny*nz,2./3.),3); Index n = 0; Index m = 0; const auto xyz2i = [&nx,&ny] (const int & x, const int & y, const int & z)->unsigned { return x+nx*(y+ny*(z)); }; const auto cube = [ &GV,&S,&V,&n,&F,&m,&isovalue, &E2V,&xyz2i,&ioffset ] (const int x, const int y, const int z) { const unsigned i = xyz2i(x,y,z); //Make a local copy of the values at the cube's corners Eigen::Matrix cS; Eigen::Matrix cI; //Find which vertices are inside of the surface and which are outside for(int c = 0; c < 8; c++) { const unsigned ic = i + ioffset[c]; cI(c) = ic; cS(c) = S(ic); } march_cube(GV,cS,cI,isovalue,V,n,F,m,E2V); }; // march over all cubes (loop order chosen to match memory) // // Should be possible to parallelize safely if threads are "well separated". // Like red-black Gauss Seidel. Probably each thread need's their own E2V,V,F, // and then merge at the end. Annoying part are the edges lying on the // interface between chunks. for(int z=0;z IGL_INLINE void igl::marching_cubes( const Eigen::MatrixBase & S, const Eigen::MatrixBase & GV, const Eigen::MatrixBase & GI, const typename DerivedS::Scalar isovalue, Eigen::PlainObjectBase &V, Eigen::PlainObjectBase &F) { typedef Eigen::Index Index; typedef typename DerivedV::Scalar Scalar; std::unordered_map E2V; V.resize(4*GV.rows(),3); F.resize(4*GV.rows(),3); Index n = 0; Index m = 0; // march over cubes //Make a local copy of the values at the cube's corners Eigen::Matrix cS; Eigen::Matrix cI; for(Index c = 0;c, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, unsigned int, unsigned int, unsigned int, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::marching_cubes, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, unsigned int, unsigned int, unsigned int, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::marching_cubes, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, unsigned int, unsigned int, unsigned int, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::marching_cubes, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::marching_cubes, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif