九、OSG学习笔记-NodeVisitor节点遍历器
前一章节:
八、OSG学习笔记--CSDN博客https://blog.csdn.net/weixin_36323170/article/details/145600744?spm=1001.2014.3001.5501
一、
本章节代码:
OsgStudy/NodeVisitor · CuiQingCheng/OsgStudy - 码云 - 开源中国https://gitee.com/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();
}
代码运行结果如下图: