【OSG学习笔记】Day 37: NodeVisitor(顶点访问器)

张开发
2026/6/7 17:01:10 15 分钟阅读
【OSG学习笔记】Day 37: NodeVisitor(顶点访问器)
NodeVisitor(顶点访问器)在 OSGOpenSceneGraph三维渲染引擎中顶点访问器Vertex Visitor是操作场景几何数据最核心、最常用的工具。它基于访问者设计模式实现完美实现了场景结构与操作逻辑的解耦让开发者无需修改引擎源码就能遍历、提取、修改场景中所有模型的顶点数据。本文将从设计思想、继承关系、核心API、实战代码、使用场景五个维度带你彻底掌握 OSG 顶点访问器。什么是顶点访问器顶点访问器是专门用于遍历、处理场景中几何顶点数据的访问器。OSG 场景是树形结构根节点 - 组节点(Group) - 几何节点(Geode) - 几何体(Geometry) - 顶点数组顶点数据存储在最底层的Geometry中顶点访问器的使命就是自动遍历整棵树找到所有顶点并对其操作。核心设计思想访问者模式将“遍历逻辑”与“业务逻辑”分离双重分发运行时动态匹配节点类型自动调用对应处理函数非侵入式不修改 Node、Geode、Geometry 源码自动递归无需手写递归遍历引擎自动完成全场景遍历类继承关系理解继承关系才能真正掌握访问器的运行机制。1. 顶层基类osg::NodeVisitor所有访问器的祖宗类提供遍历框架。osg::Referenced ↓ osg::NodeVisitor -- 所有访问器必须继承它2. 顶点访问器继承链你自定义的顶点访问器继承结构osg::NodeVisitor ↓ 你的顶点访问器VertexVisitor3. 被访问节点继承链顶点数据所在osg::Node ↓ osg::Geode -- 几何节点存放模型 ↓ osg::Geometry -- 真正存储顶点、法线、纹理坐标4. 顶点数据继承链osg::Array ↓ osg::Vec3Array -- 存储三维顶点坐标四大核心 API这是顶点访问器能工作的四大支柱1.accept()—— 入口函数节点提供位置osg::Node作用启动访问允许访问器进入节点代码node-accept(visitor);2.apply()—— 业务逻辑访问器重写位置osg::NodeVisitor作用处理具体节点顶点访问器必须重写apply(Geode)代码voidapply(osg::Geodegeode)override;3.traverse()—— 递归遍历作用继续遍历子节点必须调用否则遍历中断代码traverse(geode);4.validNodeMask()—— 节点过滤作用跳过不需要的节点提升性能完整实战代码这是工业级、可直接编译运行的顶点提取访问器逐行解析。完整代码#includeosgViewer/Viewer#includeosg/Node#includeosg/Geode#includeosg/Geometry#includeosgDB/readFile#includefstream#includeiostream// // 顶点访问器继承自 osg::NodeVisitor// classVertexExtractor:publicosg::NodeVisitor{public:// 存储提取的所有顶点osg::ref_ptrosg::Vec3Arrayvertices;// 构造设置遍历所有子节点VertexExtractor():osg::NodeVisitor(TRAVERSE_ALL_CHILDREN){verticesnewosg::Vec3Array;}// // 核心重写 apply只处理 Geode 模型节点// voidapply(osg::Geodegeode)override{// 遍历 Geode 下的所有几何体for(unsignedi0;igeode.getNumDrawables();i){// 转为 Geometry只有它有顶点osg::Geometry*geomdynamic_castosg::Geometry*(geode.getDrawable(i));if(!geom)continue;// 获取顶点数组osg::Vec3Array*vertsdynamic_castosg::Vec3Array*(geom-getVertexArray());if(!verts)continue;// 把顶点追加到结果中vertices-insert(vertices-end(),verts-begin(),verts-end());}// 必须遍历子节点traverse(geode);}};// // 主函数加载模型 使用访问器// intmain(){// 1. 加载模型osg::ref_ptrosg::NodemodelosgDB::readNodeFile(glider.osg);// 2. 创建顶点访问器VertexExtractor extractor;// 3. 启动访问核心acceptmodel-accept(extractor);// 4. 输出顶点数量std::cout提取顶点数extractor.vertices-size()std::endl;// 5. 保存到文件std::ofstreamout(vertices.txt);for(autov:*extractor.vertices)outv.x() v.y() v.z()\n;out.close();// 显示osgViewer::Viewer viewer;viewer.setSceneData(model);returnviewer.run();}代码执行流程model-accept(extractor) ↓ extractor.apply(geode) 处理模型 ↓ 提取 Geometry 顶点 ↓ traverse(geode) 继续遍历子节点 ↓ 遍历完成 → 得到所有顶点应用场景顶点访问器是 OSG 开发必备工具覆盖 90% 几何操作1. 数据导出与格式转换导出顶点、法线、UV 坐标转成 JSON/CSV/自定义格式模型轻量化、数据清洗2. 模型修改与实时形变水面波浪动画模型破碎、拉伸、扭曲顶点位移、缩放3. 碰撞检测与拾取鼠标点击获取顶点检测交点所在三角面物理仿真碰撞计算4. 网格优化与处理生成法线简化模型、减少三角面计算包围盒、中心点5. 分析与统计统计三角面数量检查模型错误计算模型体积、面积总结解耦场景结构 ↔ 操作逻辑自动遍历不用手写递归非侵入不修改引擎源码灵活扩展一个访问器实现一种功能工业必备仿真、车载、数字孪生必用

更多文章