in src/SampleVisibleMeshSurface.cpp [59:142]
void SampleFromSurfaceInside(
pangolin::Geometry& geom,
std::vector<Eigen::Vector3f>& surfpts,
int num_sample,
KdVertexListTree& kdTree,
std::vector<Eigen::Vector3f>& surface_vertices,
std::vector<Eigen::Vector3f>& surface_normals,
float delta) {
float total_area = 0.0f;
std::vector<float> cdf_by_area;
std::vector<Eigen::Vector3i> linearized_faces;
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 (uint i = 0; i < ibo.h; ++i) {
linearized_faces.emplace_back(ibo(0, i), ibo(1, i), ibo(2, i));
}
}
}
pangolin::Image<float> vertices =
pangolin::get<pangolin::Image<float>>(geom.buffers["geometry"].attributes["vertex"]);
for (const Eigen::Vector3i& face : linearized_faces) {
float area = TriangleArea(
(Eigen::Vector3f)Eigen::Map<Eigen::Vector3f>(vertices.RowPtr(face(0))),
(Eigen::Vector3f)Eigen::Map<Eigen::Vector3f>(vertices.RowPtr(face(1))),
(Eigen::Vector3f)Eigen::Map<Eigen::Vector3f>(vertices.RowPtr(face(2))));
if (std::isnan(area)) {
area = 0.f;
}
total_area += area;
if (cdf_by_area.empty()) {
cdf_by_area.push_back(area);
} else {
cdf_by_area.push_back(cdf_by_area.back() + area);
}
}
std::random_device seeder;
std::mt19937 generator(seeder());
std::uniform_real_distribution<float> rand_dist(0.0, total_area);
while ((int)surfpts.size() < num_sample) {
float tri_sample = rand_dist(generator);
std::vector<float>::iterator tri_index_iter =
lower_bound(cdf_by_area.begin(), cdf_by_area.end(), tri_sample);
int tri_index = tri_index_iter - cdf_by_area.begin();
const Eigen::Vector3i& face = linearized_faces[tri_index];
Eigen::Vector3f point = SamplePointFromTriangle(
Eigen::Map<Eigen::Vector3f>(vertices.RowPtr(face(0))),
Eigen::Map<Eigen::Vector3f>(vertices.RowPtr(face(1))),
Eigen::Map<Eigen::Vector3f>(vertices.RowPtr(face(2))));
// Now test if this point is on the shell
int cl_index;
float cl_distance;
kdTree.knnSearch(point.data(), 1, &cl_index, &cl_distance);
Eigen::Vector3f cl_vert = surface_vertices[cl_index];
Eigen::Vector3f cl_normal = surface_normals[cl_index];
Eigen::Vector3f ray_vec = cl_vert - point;
float point_plane = fabs(cl_normal.dot(ray_vec));
if (point_plane > delta)
continue;
surfpts.push_back(point);
}
}