/** * ------------------------------------ * @author: Weipeng Kong * @date: 2021/11/17 * @email: yjxkwp@foxmail.com * @site: https://donot.fit * @description: * ------------------------------------ **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Octree/udf/UDFOctree.h" #include "Octree/OctreeBuilder.h" #include "Octree/OctreeTraverser.h" #include "Octree/udf/UDFTraversalSampler.h" #include "test-path.h" #include "search_assign.h" int main() { pMesh::io::fs_path data_base_path = TEST_DATA_BASE_PATH; BOOST_LOG_TRIVIAL(debug) << "base data path is " << boost::filesystem::absolute(data_base_path); bool use_udf = true; auto out_mc_path = data_base_path / (use_udf? "sphere-udf-mc.obj": "sphere-sdf-mc.obj"); Eigen::AlignedBox aabb(Eigen::Vector3d(0,0,0), Eigen::Vector3d(1, 1, 1)); int aabb_res_x = 400; int aabb_res_y = 400; int aabb_res_z = 400; int aabb_len = aabb_res_x * aabb_res_y * aabb_res_z; double x0 = 0; double y0 = 0; double z0 = 0; double R = 1.2; auto sphere_shape = [=](double x, double y, double z) { return sqrt(pow(x - x0, 2) + pow(y - y0, 2) + pow(z - z0, 2)) - R; }; Octree::UDFOctree octree(0, Octree::AABB(aabb.min(), aabb.max())); octree.get_root()->udf = std::make_shared(std::vector(aabb_len), aabb_res_x, aabb_res_y, aabb_res_z); auto &udf_data = *octree.get_root()->udf; BOOST_LOG_TRIVIAL(debug) << "Calculating UDF"; for (int x = 0; x < aabb_res_x; ++x) { double pos_x = ((aabb_res_x - x) * aabb.min().x() + x * aabb.max().x()) / (1.0 * aabb_res_x); for (int y = 0; y < aabb_res_y; ++y) { double pos_y = ((aabb_res_y - y) * aabb.min().y() + y * aabb.max().y()) / (1.0 * aabb_res_y); for (int z = 0; z < aabb_res_z; ++z) { double pos_z = ((aabb_res_z - z) * aabb.min().z() + z * aabb.max().z()) / (1.0 * aabb_res_z); int ind = udf_data.get_array_index(x, y, z); if(use_udf) udf_data.value[ind] = abs(sphere_shape(pos_x, pos_y, pos_z)); else udf_data.value[ind] = sphere_shape(pos_x, pos_y, pos_z); } } } BOOST_LOG_TRIVIAL(debug) << "End computing UDF"; if(use_udf) { int start[3] = {aabb_res_x/2, aabb_res_y/2, aabb_res_z/2}; double block_size[3] = { aabb.sizes().x() / (aabb_res_x - 1), aabb.sizes().y() / (aabb_res_y - 1), aabb.sizes().z() / (aabb_res_z - 1) }; // TODO: double threshold = std::max({block_size[0], block_size[1], block_size[2]}); boost::timer t; search_assign(udf_data, start, threshold); BOOST_LOG_TRIVIAL(debug) << "[search_assign]: " << t.elapsed(); } if (1) { Eigen::MatrixXd GV; Eigen::RowVector3i res; const int s = 10; igl::voxel_grid(aabb, s, 1, GV, res); // compute values std::cout << "Computing distances..." << std::endl; Eigen::VectorXd S = Eigen::VectorXd(GV.rows()), B; { for (int i = 0; i < GV.rows(); ++i) { auto node = octree.map_node(GV.row(i)); if (node == nullptr) { S[i] = 1000; } else { S[i] = node->get_udf(GV.row(i)); } } } std::cout << "Marching cubes..." << std::endl; Eigen::MatrixXd SV, BV; Eigen::MatrixXi SF, BF; igl::marching_cubes(S, GV, res(0), res(1), res(2), 0, SV, SF); igl::writeOBJ(out_mc_path.string(), SV, SF); } return 0; }