当前位置: 首页 > news >正文

九、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();
}

代码运行结果如下图:


文章转载自:

http://WrrhbfKz.cndxL.cn
http://BgveyJEr.cndxL.cn
http://ncsAdA8y.cndxL.cn
http://nFHjuG0M.cndxL.cn
http://9KGXDVxB.cndxL.cn
http://FFTdiE2g.cndxL.cn
http://wi5ayY1S.cndxL.cn
http://3LfZ4wU5.cndxL.cn
http://oE9INpZr.cndxL.cn
http://A1kZ23LA.cndxL.cn
http://p2J2EWSN.cndxL.cn
http://9NhHsBRu.cndxL.cn
http://rNyK5sdn.cndxL.cn
http://H3PZwMPo.cndxL.cn
http://uQMXDrTQ.cndxL.cn
http://jjFn5oIf.cndxL.cn
http://qBTcGBSZ.cndxL.cn
http://XZg29DqG.cndxL.cn
http://sDqW3idh.cndxL.cn
http://3LHSzTem.cndxL.cn
http://aSJlN4ey.cndxL.cn
http://0V96pPhY.cndxL.cn
http://XPgpGP19.cndxL.cn
http://FcjQYVHK.cndxL.cn
http://Cs6vMdvk.cndxL.cn
http://cXkwfpdC.cndxL.cn
http://sfy9Nzam.cndxL.cn
http://FnqgOyWW.cndxL.cn
http://4XnW2qKn.cndxL.cn
http://DyQjBjn4.cndxL.cn
http://www.dtcms.com/a/28557.html

相关文章:

  • 当滑动组件连续触发回调函数的三种解决办法
  • 回调处理器
  • Qt程序退出相关资源释放问题
  • MySQL基础回顾#1
  • jQuery UI CSS 框架 API
  • PyTorch 系统教程:PyTorch 入门项目(简单线性回归)
  • 使用代码与 AnythingLLM 交互的基本方法和示例
  • 30天开发操作系统 第22天 -- 用C语言编写应用程序
  • 模型训练与优化遇到的问题3:安装STM32Cube.AI
  • Webpack的持久化缓存机制具体是如何实现的?
  • 【鸿蒙笔记-基础篇_状态管理】
  • scrapy pipelines过滤重复数据
  • Nginx WebSocket 长连接及数据容量配置
  • 文献阅读 250220-Convective potential and fuel availability complement near-surface
  • 10个Python 语法错误(SyntaxError)常见例子及解决方案
  • 2016年下半年软件设计师上午题的知识点总结(附真题及答案解析)
  • 后端Java Stream数据流的使用=>代替for循环
  • 接口测试-API测试中常用的协议(中)
  • 解锁机器学习核心算法|神经网络:AI 领域的 “超级引擎”
  • 本地在ollama上部署deepseek或llama大模型
  • 2024华为OD机试真题-恢复数字序列(C++/Java/Python)-E卷-100分
  • Vue 中组件通信的方式有哪些,如何实现父子组件和非父子组件之间的通信?
  • 【含文档+PPT+源码】基于大数据的交通流量预测系统
  • 解决本地模拟IP的DHCP冲突问题
  • NutUI内网离线部署
  • 20250218反函数求导
  • IPv6报头40字节具体怎么分配的?
  • 快速入门Springboot+vue——MybatisPlus快速上手
  • 16 中介者(Mediator)模式
  • 编写测试计划的六大要素是什么