in src/PreprocessMesh.cpp [282:565]
int main(int argc, char** argv) {
std::string meshFileName;
bool vis = false;
std::string npyFileName;
std::string plyFileNameOut;
std::string spatial_samples_npz;
bool save_ply = true;
bool test_flag = false;
float variance = 0.005;
int num_sample = 500000;
float rejection_criteria_obs = 0.02f;
float rejection_criteria_tri = 0.03f;
float num_samp_near_surf_ratio = 47.0f / 50.0f;
CLI::App app{"PreprocessMesh"};
app.add_option("-m", meshFileName, "Mesh File Name for Reading")->required();
app.add_flag("-v", vis, "enable visualization");
app.add_option("-o", npyFileName, "Save npy pc to here")->required();
app.add_option("--ply", plyFileNameOut, "Save ply pc to here");
app.add_option("-s", num_sample, "Save ply pc to here");
app.add_option("--var", variance, "Set Variance");
app.add_flag("--sply", save_ply, "save ply point cloud for visualization");
app.add_flag("-t", test_flag, "test_flag");
app.add_option("-n", spatial_samples_npz, "spatial samples from file");
CLI11_PARSE(app, argc, argv);
if (test_flag)
variance = 0.05;
float second_variance = variance / 10;
std::cout << "variance: " << variance << " second: " << second_variance << std::endl;
if (test_flag) {
second_variance = variance / 100;
num_samp_near_surf_ratio = 45.0f / 50.0f;
num_sample = 250000;
}
std::cout << spatial_samples_npz << std::endl;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
pangolin::Geometry geom = pangolin::LoadGeometry(meshFileName);
std::cout << geom.objects.size() << " objects" << std::endl;
// linearize the object indices
{
int total_num_faces = 0;
for (const auto& object : geom.objects) {
auto it_vert_indices = object.second.attributes.find("vertex_indices");
if (it_vert_indices != object.second.attributes.end()) {
pangolin::Image<uint32_t> ibo =
pangolin::get<pangolin::Image<uint32_t>>(it_vert_indices->second);
total_num_faces += ibo.h;
}
}
// const int total_num_indices = total_num_faces * 3;
pangolin::ManagedImage<uint8_t> new_buffer(3 * sizeof(uint32_t), total_num_faces);
pangolin::Image<uint32_t> new_ibo =
new_buffer.UnsafeReinterpret<uint32_t>().SubImage(0, 0, 3, total_num_faces);
int index = 0;
for (const auto& object : geom.objects) {
auto it_vert_indices = object.second.attributes.find("vertex_indices");
if (it_vert_indices != object.second.attributes.end()) {
pangolin::Image<uint32_t> ibo =
pangolin::get<pangolin::Image<uint32_t>>(it_vert_indices->second);
for (int i = 0; i < ibo.h; ++i) {
new_ibo.Row(index).CopyFrom(ibo.Row(i));
++index;
}
}
}
geom.objects.clear();
auto faces = geom.objects.emplace(std::string("mesh"), pangolin::Geometry::Element());
faces->second.Reinitialise(3 * sizeof(uint32_t), total_num_faces);
faces->second.CopyFrom(new_buffer);
new_ibo = faces->second.UnsafeReinterpret<uint32_t>().SubImage(0, 0, 3, total_num_faces);
faces->second.attributes["vertex_indices"] = new_ibo;
}
// remove textures
geom.textures.clear();
pangolin::Image<uint32_t> modelFaces = pangolin::get<pangolin::Image<uint32_t>>(
geom.objects.begin()->second.attributes["vertex_indices"]);
float max_dist = BoundingCubeNormalization(geom, true);
if (vis)
pangolin::CreateWindowAndBind("Main", 640, 480);
else
pangolin::CreateWindowAndBind("Main", 1, 1);
glEnable(GL_DEPTH_TEST);
glDisable(GL_DITHER);
glDisable(GL_POINT_SMOOTH);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_POLYGON_SMOOTH);
glHint(GL_POINT_SMOOTH, GL_DONT_CARE);
glHint(GL_LINE_SMOOTH, GL_DONT_CARE);
glHint(GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE);
glDisable(GL_MULTISAMPLE_ARB);
glShadeModel(GL_FLAT);
// Define Projection and initial ModelView matrix
pangolin::OpenGlRenderState s_cam(
// pangolin::ProjectionMatrix(640,480,420,420,320,240,0.05,100),
pangolin::ProjectionMatrixOrthographic(-max_dist, max_dist, -max_dist, max_dist, 0, 2.5),
pangolin::ModelViewLookAt(0, 0, -1, 0, 0, 0, pangolin::AxisY));
pangolin::OpenGlRenderState s_cam2(
pangolin::ProjectionMatrixOrthographic(-max_dist, max_dist, max_dist, -max_dist, 0, 2.5),
pangolin::ModelViewLookAt(0, 0, -1, 0, 0, 0, pangolin::AxisY));
// Create Interactive View in window
pangolin::Handler3D handler(s_cam);
pangolin::GlGeometry gl_geom = pangolin::ToGlGeometry(geom);
pangolin::GlSlProgram prog = GetShaderProgram();
if (vis) {
pangolin::View& d_cam = pangolin::CreateDisplay()
.SetBounds(0.0, 1.0, 0.0, 1.0, -640.0f / 480.0f)
.SetHandler(&handler);
while (!pangolin::ShouldQuit()) {
// Clear screen and activate view to render into
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// glEnable(GL_CULL_FACE);
// glCullFace(GL_FRONT);
d_cam.Activate(s_cam);
prog.Bind();
prog.SetUniform("MVP", s_cam.GetProjectionModelViewMatrix());
prog.SetUniform("V", s_cam.GetModelViewMatrix());
pangolin::GlDraw(prog, gl_geom, nullptr);
prog.Unbind();
// Swap frames and Process Events
pangolin::FinishFrame();
}
}
// Create Framebuffer with attached textures
size_t w = 400;
size_t h = 400;
pangolin::GlRenderBuffer zbuffer(w, h, GL_DEPTH_COMPONENT32);
pangolin::GlTexture normals(w, h, GL_RGBA32F);
pangolin::GlTexture vertices(w, h, GL_RGBA32F);
pangolin::GlFramebuffer framebuffer(vertices, normals, zbuffer);
// View points around a sphere.
std::vector<Eigen::Vector3f> views = EquiDistPointsOnSphere(100, max_dist * 1.1);
std::vector<Eigen::Vector4f> point_normals;
std::vector<Eigen::Vector4f> point_verts;
size_t num_tri = modelFaces.h;
std::vector<Eigen::Vector4f> tri_id_normal_test(num_tri);
for (size_t j = 0; j < num_tri; j++)
tri_id_normal_test[j] = Eigen::Vector4f(0.0f, 0.0f, 0.0f, 0.0f);
int total_obs = 0;
int wrong_obs = 0;
for (unsigned int v = 0; v < views.size(); v++) {
// change camera location
s_cam2.SetModelViewMatrix(
pangolin::ModelViewLookAt(views[v][0], views[v][1], views[v][2], 0, 0, 0, pangolin::AxisY));
// Draw the scene to the framebuffer
framebuffer.Bind();
glViewport(0, 0, w, h);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
prog.Bind();
prog.SetUniform("MVP", s_cam2.GetProjectionModelViewMatrix());
prog.SetUniform("V", s_cam2.GetModelViewMatrix());
prog.SetUniform("ToWorld", s_cam2.GetModelViewMatrix().Inverse());
prog.SetUniform("slant_thr", -1.0f, 1.0f);
prog.SetUniform("ttt", 1.0, 0, 0, 1);
pangolin::GlDraw(prog, gl_geom, nullptr);
prog.Unbind();
framebuffer.Unbind();
pangolin::TypedImage img_normals;
normals.Download(img_normals);
std::vector<Eigen::Vector4f> im_norms = ValidPointsAndTrisFromIm(
img_normals.UnsafeReinterpret<Eigen::Vector4f>(), tri_id_normal_test, total_obs, wrong_obs);
point_normals.insert(point_normals.end(), im_norms.begin(), im_norms.end());
pangolin::TypedImage img_verts;
vertices.Download(img_verts);
std::vector<Eigen::Vector4f> im_verts =
ValidPointsFromIm(img_verts.UnsafeReinterpret<Eigen::Vector4f>());
point_verts.insert(point_verts.end(), im_verts.begin(), im_verts.end());
}
int bad_tri = 0;
for (unsigned int t = 0; t < tri_id_normal_test.size(); t++) {
if (tri_id_normal_test[t][3] < 0.0f)
bad_tri++;
}
std::cout << meshFileName << std::endl;
std::cout << (float)(wrong_obs) / float(total_obs) << std::endl;
std::cout << (float)(bad_tri) / float(num_tri) << std::endl;
float wrong_ratio = (float)(wrong_obs) / float(total_obs);
float bad_tri_ratio = (float)(bad_tri) / float(num_tri);
if (wrong_ratio > rejection_criteria_obs || bad_tri_ratio > rejection_criteria_tri) {
std::cout << "mesh rejected" << std::endl;
// return 0;
}
std::vector<Eigen::Vector3f> vertices2;
// std::vector<Eigen::Vector3f> vertices_all;
std::vector<Eigen::Vector3f> normals2;
for (unsigned int v = 0; v < point_verts.size(); v++) {
vertices2.push_back(point_verts[v].head<3>());
normals2.push_back(point_normals[v].head<3>());
}
KdVertexList kdVerts(vertices2);
KdVertexListTree kdTree_surf(3, kdVerts);
kdTree_surf.buildIndex();
std::vector<Eigen::Vector3f> xyz;
std::vector<Eigen::Vector3f> xyz_surf;
std::vector<float> sdf;
int num_samp_near_surf = (int)(47 * num_sample / 50);
std::cout << "num_samp_near_surf: " << num_samp_near_surf << std::endl;
SampleFromSurface(geom, xyz_surf, num_samp_near_surf / 2);
auto start = std::chrono::high_resolution_clock::now();
SampleSDFNearSurface(
kdTree_surf,
vertices2,
xyz_surf,
normals2,
xyz,
sdf,
num_sample - num_samp_near_surf,
variance,
second_variance,
2,
11);
auto finish = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(finish - start).count();
std::cout << elapsed << std::endl;
if (save_ply) {
writeSDFToPLY(xyz, sdf, plyFileNameOut, false, true);
}
std::cout << "num points sampled: " << xyz.size() << std::endl;
std::size_t save_npz = npyFileName.find("npz");
if (save_npz == std::string::npos)
writeSDFToNPY(xyz, sdf, npyFileName);
else {
writeSDFToNPZ(xyz, sdf, npyFileName, true);
}
return 0;
}