如何从CGAL::poisson_surface_reconstruction_delaunay提取输出适配OpenGL格式
CGAL Poisson重建结果转OpenGL顶点/索引格式
以下是补全后的完整函数实现,直接遍历CGAL的Surface_mesh并转换为OpenGL兼容的顶点数组和索引数组:
// 函数功能:将带法线的点云通过Poisson重建转为OpenGL可用的三角网格格式 void reconstructPointsToSurfaceInOpenGLFormat(const std::list<std::pair<Kernel::Point_3, Kernel::Vector_3>>& points, std::vector<glm::vec3>& vertices, std::vector<unsigned int>& indices) { CGAL::Surface_mesh<Kernel::Point_3> trimesh; double spacing = 10; // 执行Poisson表面重建 bool ok = CGAL::poisson_surface_reconstruction_delaunay( points.begin(), points.end(), CGAL::First_of_pair_property_map<std::pair<Kernel::Point_3, Kernel::Vector_3>>(), CGAL::Second_of_pair_property_map<std::pair<Kernel::Point_3, Kernel::Vector_3>>(), trimesh, spacing); // 清空输出容器,避免残留数据干扰 vertices.clear(); indices.clear(); // 重建失败直接返回空结果 if (!ok) { return; } // 建立CGAL顶点索引到OpenGL连续索引的映射 std::unordered_map<CGAL::Surface_mesh<Kernel::Point_3>::Vertex_index, unsigned int> vertex_to_gl_idx; // 注:如果编译器不支持对Vertex_index的哈希,可改用std::map,性能稍低但兼容性更好 // 遍历所有顶点,转换为glm::vec3格式存入vertices数组 for (const auto& v : trimesh.vertices()) { const auto& cgal_point = trimesh.point(v); vertices.emplace_back( static_cast<float>(CGAL::to_double(cgal_point.x())), static_cast<float>(CGAL::to_double(cgal_point.y())), static_cast<float>(CGAL::to_double(cgal_point.z())) ); vertex_to_gl_idx[v] = static_cast<unsigned int>(vertices.size() - 1); } // 遍历所有三角面,填充索引数组 for (const auto& f : trimesh.faces()) { // 获取当前面的所有顶点(Poisson重建输出为三角面,故每个面有3个顶点) std::vector<CGAL::Surface_mesh<Kernel::Point_3>::Vertex_index> face_verts; for (const auto& v : trimesh.vertices_around_face(trimesh.halfedge(f))) { face_verts.push_back(v); } // 校验并添加索引(确保是三角面,避免异常) if (face_verts.size() == 3) { indices.push_back(vertex_to_gl_idx[face_verts[0]]); indices.push_back(vertex_to_gl_idx[face_verts[1]]); indices.push_back(vertex_to_gl_idx[face_verts[2]]); } } }
关键细节说明
- 容器清空:每次重建前清空
vertices和indices,避免上一次调用的残留数据导致渲染错误 - 顶点映射:用哈希表(或有序映射)将CGAL的
Vertex_index(非连续)转换为OpenGL要求的连续无符号整数索引 - 坐标转换:使用
CGAL::to_double()将CGAL点的坐标转为标准浮点类型,再转成float适配glm::vec3 - 面遍历逻辑:通过
vertices_around_face遍历面的顶点,保持CGAL原生的逆时针顶点顺序,符合OpenGL默认的正面朝向规则 - 错误处理:检查Poisson重建的返回值
ok,失败时直接返回空结果
性能优化提示
- 若使用
std::unordered_map时出现编译错误(部分编译器不支持Vertex_index的哈希),可替换为std::map,兼容性更好但查询速度略慢 - 若确定Poisson重建100%输出三角面,可省略面顶点数量的校验步骤,提升遍历速度
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

