| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- #include <igl/marching_cubes.h>
- #include <igl/signed_distance.h>
- #include <igl/read_triangle_mesh.h>
- #include <igl/voxel_grid.h>
- #include <igl/opengl/glfw/Viewer.h>
- #include <Eigen/Core>
- #include <iostream>
- int main(int argc, char * argv[])
- {
- using namespace Eigen;
- using namespace std;
- using namespace igl;
- MatrixXi F;
- MatrixXd V;
- // Read in inputs as double precision floating point meshes
- read_triangle_mesh(
- TUTORIAL_SHARED_PATH "/armadillo.obj",V,F);
- cout<<"Creating grid..."<<endl;
- // number of vertices on the largest side
- const int s = 100;
- // create grid
- MatrixXd GV;
- Eigen::RowVector3i res;
- igl::voxel_grid(V,0,s,1,GV,res);
-
- // compute values
- cout<<"Computing distances..."<<endl;
- // Batch based function for evaluating implicit
- const auto batch_implicit = [&V,&F](const MatrixXd & Q)->VectorXd
- {
- VectorXd S;
- {
- VectorXi I;
- MatrixXd C,N;
- signed_distance(Q,V,F,SIGNED_DISTANCE_TYPE_FAST_WINDING_NUMBER,S,I,C,N);
- // Extremely flatten out near zero
- S = S.array().sign() * S.array().abs().exp();
- }
- return S;
- };
- VectorXd S = batch_implicit(GV);
- cout<<"Marching cubes..."<<endl;
- MatrixXd SV;
- MatrixXi SF;
- igl::marching_cubes(S,GV,res(0),res(1),res(2),0,SV,SF);
- std::unordered_map<std::int64_t,int> E2V;
- igl::marching_cubes(S,GV,res(0),res(1),res(2),0,SV,SF,E2V);
- // Initialize min and max for root finding bisection
- assert(E2V.size() == SV.rows());
- Eigen::MatrixXd T(SV.rows(),2);
- Eigen::VectorXi I(SV.rows());
- // Precompute slices for end points
- Eigen::MatrixXd GVi(SV.rows(),3);
- Eigen::MatrixXd GVj(SV.rows(),3);
- // This is only used for the assertion below
- const auto ij2key = [](std::int32_t i,std::int32_t j)
- {
- if(i>j){ std::swap(i,j); }
- std::int64_t ret = 0;
- ret |= i;
- ret |= static_cast<std::int64_t>(j) << 32;
- return ret;
- };
- const auto key2ij = [](const std::int64_t & key, std::int32_t & i, std::int32_t & j)
- {
- i = key & 0xFFFFFFFF;
- j = key >> 32;
- };
- for (const auto& e2v: E2V)
- {
- const std::int64_t key = e2v.first;
- const std::int32_t v = e2v.second;
- std::int32_t i,j;
- key2ij(key,i,j);
- const std::int64_t key0 = ij2key(i,j);
- assert(key0 != key);
- T.row(v) << 0,1;
- // (i,j) is ordered so that i<j, but let's order so that S(i)<S(j)
- if(S(i)>S(j)) { std::swap(i,j); }
- GVi.row(v) = GV.row(i);
- GVj.row(v) = GV.row(j);
- }
- const auto root_find_iteration = [&SV,&I,&T,&GVi,&GVj,&batch_implicit]()
- {
- Eigen::VectorXd T_mid = (T.col(0)+T.col(1))/2;
- // Use this midpoint guess for the current visualization
- SV = GVi.array().colwise() * (1.0 - T_mid.array()) + GVj.array().colwise() * T_mid.array();
- // Compute values at midpoints
- VectorXd S_mid = batch_implicit(SV);
- // Update bounds
- T.col(1) = (S_mid.array() > 0).select(T_mid, T.col(1));
- T.col(0) = (S_mid.array() <= 0).select(T_mid, T.col(0));
- };
- cout<<R"(Usage:
- ' ' Conduct a bisection iteration
- )";
- igl::opengl::glfw::Viewer viewer;
- viewer.data().set_mesh(SV,SF);
- viewer.data().show_lines = false;
- viewer.callback_key_down =
- [&](igl::opengl::glfw::Viewer & viewer, unsigned char key, int mod)->bool
- {
- switch(key)
- {
- default:
- return false;
- case ' ':
- root_find_iteration();
- viewer.data().set_vertices(SV);
- viewer.data().compute_normals();
- break;
- }
- return true;
- };
- viewer.launch();
- }
|