九、OSG学习笔记-NodeVisitor节点遍历器
- 人工智能
- 2025-08-24 11:42:01

前一章节:
八、OSG学习笔记--CSDN博客 blog.csdn.net/weixin_36323170/article/details/145600744?spm=1001.2014.3001.5501
一、
本章节代码:
OsgStudy/NodeVisitor · CuiQingCheng/OsgStudy - 码云 - 开源中国 gitee /cuiqingcheng/osg-study/tree/master/OsgStudy/NodeVisitor
实现原理图:
实现一个简单的demo,代码如下:
#include<windows.h> #include<osg/Node> #include<osgViewer/Viewer> #include<osgViewer/ViewerEventHandlers> #include <osg/Group> #include<osgDB/ReadFile> #include<osg/MatrixTransform> #include <osg/NodeVisitor> class VisitorNodePath :public osg::NodeVisitor { public: // TRAVERSE_ALL_CHILDREN: 可以向下遍历所有的子节点 VisitorNodePath() :osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) {} void apply(osg::Node& node) { std::cout << "Apply node: " << node.getName() << std::endl; traverse(node);// 遍历该节点下的所有子节点 } }; int main() { osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer; // 获取WindowingSystemInterface实例 osg::ref_ptr<osg::GraphicsContext::WindowingSystemInterface> wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (!wsi) { std::cerr << "无法获取窗口系统接口。" << std::endl; return 1; } // 获取主显示器的屏幕设置 unsigned int screenNum = 0; // 主显示器的屏幕编号通常为0 osg::GraphicsContext::ScreenSettings settings; wsi->getScreenSettings(screenNum, settings); // 获取屏幕的宽度和高度 unsigned int width = settings.width; unsigned int height = settings.height; viewer->setUpViewInWindow(0, 0, width, height); viewer->addEventHandler(new osgViewer::WindowSizeHandler); osg::ref_ptr<osg::Group> rootGroup = new osg::Group; osg::ref_ptr<osg::Node> glider = osgDB::readNodeFile("glider.osg"); rootGroup->setName("root"); glider->setName("glider"); rootGroup->addChild(glider); viewer->setSceneData(rootGroup.get()); VisitorNodePath nv; rootGroup->accept(nv); return viewer->run(); }执行结果如下图:
二、针对复杂场景
场景模拟,在一个复杂的节点下进行模拟:
场景代码如下:
#include<windows.h> #include<osg/Node> #include<osgViewer/Viewer> #include<osgViewer/ViewerEventHandlers> #include <osg/Group> #include <osg/Geometry> #include<osg/Geode> #include<osgDB/ReadFile> #include<osg/MatrixTransform> #include <osg/NodeVisitor> #include <osg/Array> #include <osg/ShapeDrawable> #include <osg/Shape> class VisitorNodePath :public osg::NodeVisitor { public: // TRAVERSE_ALL_CHILDREN: 可以向下遍历所有的子节点 // TRAVERSE_PARENTS: 从叶节点往上遍历 VisitorNodePath() :osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) {} void apply(osg::Node& node) override { std::cout << "Apply node: " << node.getName() << std::endl; if (node.getName().empty()) { std::cout << "node className: " << node.className() << std::endl; } traverse(node);// 遍历该节点下的所有子节点 } void apply(osg::Group& group) override { std::cout << "Apply group: " << group.getName() << std::endl; if (group.getName().empty()) { std::cout << "group className: " << group.className() << std::endl; } traverse(group);// 遍历该节点下的所有子节点 } void apply(osg::MatrixTransform& mt) override { std::cout << "Apply MatrixTransform: " << mt.getName() << std::endl; if (mt.getName().empty()) { std::cout << "MatrixTransform className: " << mt.className() << std::endl; } traverse(mt);// 遍历该节点下的所有子节点 } void apply(osg::Geometry& gm) override { std::cout << "Apply Geometry: " << gm.getName() << std::endl; if (gm.getName().empty()) { std::cout << "Geometry className: " << gm.className() << std::endl; } traverse(gm);// 遍历该节点下的所有子节点 } void apply(osg::Geode& gd) override { std::cout << "Apply Geode: " << gd.getName() << std::endl; if (gd.getName().empty()) { std::cout << "Geode className: " << gd.className() << std::endl; } traverse(gd);// 遍历该节点下的所有子节点 } }; int main() { osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer; // 获取WindowingSystemInterface实例 osg::ref_ptr<osg::GraphicsContext::WindowingSystemInterface> wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (!wsi) { std::cerr << "无法获取窗口系统接口。" << std::endl; return 1; } // 获取主显示器的屏幕设置 unsigned int screenNum = 0; // 主显示器的屏幕编号通常为0 osg::GraphicsContext::ScreenSettings settings; wsi->getScreenSettings(screenNum, settings); // 获取屏幕的宽度和高度 unsigned int width = settings.width; unsigned int height = settings.height; viewer->setUpViewInWindow(0, 0, width, height); viewer->addEventHandler(new osgViewer::WindowSizeHandler); osg::ref_ptr<osg::Node> glider = osgDB::readNodeFile("glider.osg"); osg::ref_ptr<osg::Group> rootGroup = new osg::Group; rootGroup->setName("root"); osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("cow.osg"); osg::ref_ptr<osg::MatrixTransform> child1 = new osg::MatrixTransform; osg::ref_ptr<osg::MatrixTransform> child2 = new osg::MatrixTransform; osg::ref_ptr<osg::MatrixTransform> child3 = new osg::MatrixTransform; osg::ref_ptr<osg::MatrixTransform> child4 = new osg::MatrixTransform; osg::ref_ptr<osg::MatrixTransform> child5 = new osg::MatrixTransform; glider->setName("glider"); cow->setName("cow"); rootGroup->addChild(glider); rootGroup->addChild(child1); rootGroup->addChild(child2); child1->setName("child1"); child1->setMatrix(osg::Matrix::translate(-5,-5, 0)); child1->addChild(glider); child1->addChild(child3); child1->addChild(child4); child2->setName("child2"); child2->setMatrix(osg::Matrix::translate(5, -5, 0)); child2->addChild(glider); child2->addChild(child5); child3->setName("child3"); child3->setMatrix(osg::Matrix::translate(-5, -5, 0)); child3->addChild(cow); child4->setName("child4"); child4->setMatrix(osg::Matrix::translate(5, -5, 0)); child4->addChild(cow); child5->setName("child5"); child5->setMatrix(osg::Matrix::translate(5, -5, 0)); child5->addChild(cow); viewer->setSceneData(rootGroup.get()); VisitorNodePath nv; std::cout << "root node num: " <<rootGroup->getNumChildren() << std::endl; rootGroup->accept(nv); return viewer->run(); }运行如下图:
绘制顶点代码如下:
#include<windows.h> #include<osg/Node> #include<osgViewer/Viewer> #include<osgViewer/ViewerEventHandlers> #include <osg/Group> #include <osg/Geometry> #include<osg/Geode> #include<osgDB/ReadFile> #include<osg/MatrixTransform> #include <osg/NodeVisitor> #include <osg/Array> #include <osg/ShapeDrawable> #include <osg/Shape> // 创建小球 osg::ref_ptr<osg::Geode> CreateBox(osg::Vec3Array* va) { osg::ref_ptr<osg::Geode> gNode = new osg::Geode; for (size_t j = 0; j < va->size(); ++j) { osg::Vec3 vertex = (*va)[j]; gNode->addDrawable(new osg::ShapeDrawable(new osg::Box(vertex, 0.005, 0.005, 0.005))); } return gNode; } class BoundVisitor : public osg::NodeVisitor { public: void apply(osg::Geode& gd) override { int dlNum = gd.getNumDrawables(); for (int i = 0; i < dlNum; i++) { // 得到绘制单元 osg::Drawable* dr = gd.getDrawable(i); osg::ref_ptr<osg::Geometry> gm = dynamic_cast<osg::Geometry*>(dr); if (gm) { osg::Array* ar = gm->getVertexArray(); // 获取顶点数组 if (ar) { // 尝试将 osg::Array 转换为 osg::Vec3Array osg::ref_ptr<osg::Vec3Array> vertices = dynamic_cast<osg::Vec3Array*>(ar); if (vertices) { if (m_group.valid()) { if ("root" == m_group->getName()) { m_group->addChild(CreateBox(vertices)); } } // 遍历顶点数组并处理每个顶点 for (size_t j = 0; j < vertices->size(); ++j) { const osg::Vec3& vertex = (*vertices)[j]; // 这里可以对顶点进行各种处理,例如打印顶点坐标 //std::cout << "Vertex " << j << ": (" << vertex.x() << ", " << vertex.y() << ", " << vertex.z() << ")" << std::endl; } } else { std::cout << "Vertex array is not of type osg::Vec3Array." << std::endl; } } else { std::cout << "No vertex array found in the geometry." << std::endl; } } } } void setGroup(osg::Group* gp) { m_group = gp; } private: osg::ref_ptr<osg::Group> m_group; }; int main() { osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer; // 获取WindowingSystemInterface实例 osg::ref_ptr<osg::GraphicsContext::WindowingSystemInterface> wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (!wsi) { std::cerr << "无法获取窗口系统接口。" << std::endl; return 1; } // 获取主显示器的屏幕设置 unsigned int screenNum = 0; // 主显示器的屏幕编号通常为0 osg::GraphicsContext::ScreenSettings settings; wsi->getScreenSettings(screenNum, settings); // 获取屏幕的宽度和高度 unsigned int width = settings.width; unsigned int height = settings.height; viewer->setUpViewInWindow(0, 0, width, height); viewer->addEventHandler(new osgViewer::WindowSizeHandler); osg::ref_ptr<osg::Node> glider = osgDB::readNodeFile("glider.osg"); osg::ref_ptr<osg::Group> rootGroup = new osg::Group; rootGroup->setName("root"); rootGroup->addChild(glider); viewer->setSceneData(rootGroup.get()); BoundVisitor nv; nv.setGroup(rootGroup); glider->accept(nv); return viewer->run(); }代码运行结果如下图:
九、OSG学习笔记-NodeVisitor节点遍历器由讯客互联人工智能栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“九、OSG学习笔记-NodeVisitor节点遍历器”