You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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]]);
        }
    }
}

关键细节说明

  1. 容器清空:每次重建前清空vertices和indices,避免上一次调用的残留数据导致渲染错误
  2. 顶点映射:用哈希表(或有序映射)将CGAL的Vertex_index(非连续)转换为OpenGL要求的连续无符号整数索引
  3. 坐标转换:使用CGAL::to_double()将CGAL点的坐标转为标准浮点类型,再转成float适配glm::vec3
  4. 面遍历逻辑:通过vertices_around_face遍历面的顶点,保持CGAL原生的逆时针顶点顺序,符合OpenGL默认的正面朝向规则
  5. 错误处理:检查Poisson重建的返回值ok,失败时直接返回空结果

性能优化提示

  • 若使用std::unordered_map时出现编译错误(部分编译器不支持Vertex_index的哈希),可替换为std::map,兼容性更好但查询速度略慢
  • 若确定Poisson重建100%输出三角面,可省略面顶点数量的校验步骤,提升遍历速度

内容的提问来源于stack exchange,提问作者Andy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 03:35:42