场景交互与场景漫游-对象选取(8-2)

对象选取示例的代码如程序清单8-11所示:

cpp 复制代码
/******************************************* 对象选取示例 *************************************/
// 对象选取事件处理器
class PickHandler :public osgGA::GUIEventHandler
{
public:
	PickHandler() :_mx(0.0f), _my(0.0f)
	{

	}
	~PickHandler()
	{

	}

	// 事件处理函数
	bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
	{
		osg::ref_ptr<osgViewer::View> view = dynamic_cast<osgViewer::View*> (&aa);
		if (!view)
		{
			return false;
		}

		switch (ea.getEventType())
		{
			// 鼠标按下
			case(osgGA::GUIEventAdapter::PUSH) :
			{
				// 更新鼠标位置
				_mx = ea.getX();
				_my = ea.getY();
				break;
			}
			case(osgGA::GUIEventAdapter::RELEASE) :
			{
				if (_mx == ea.getX() && _my == ea.getY())
				{
					// 执行对象选取
					pick(view.get(), ea.getX(), ea.getY());
				}
				break;
			}
			default:
				break;
		}

		return false;
	}

	// 对象选取事件处理器
	void pick(osg::ref_ptr<osgViewer::View> view, float x, float y)
	{
		osg::ref_ptr<osg::Node> node = new osg::Node();
		osg::ref_ptr<osg::Group> parent = new osg::Group();

		// 创建一个线段交集检测函数
		osgUtil::LineSegmentIntersector::Intersections intersections;
		if (view->computeIntersections(x, y, intersections))
		{
			osgUtil::LineSegmentIntersector::Intersection intersection = *intersections.begin();
			osg::NodePath &nodePath = intersection.nodePath;

			// 得到选择的物体
			node = (nodePath.size() >= 1) ? nodePath[nodePath.size() - 1] : 0;
			parent = (nodePath.size() >= 2) ? dynamic_cast<osg::Group*>(nodePath[nodePath.size() - 2]) : 0;
		}

		// 用一种高亮显示来显示物体已经被选中
		if (parent.get() && node.get())
		{
			osg::ref_ptr<osgFX::Scribe> parentAsScribe = dynamic_cast<osgFX::Scribe*>(parent.get());
			if (!parentAsScribe)
			{
				// 如果对象选择列,高亮显示
				osg::ref_ptr<osgFX::Scribe> scribe = new osgFX::Scribe();
				scribe->addChild(node.get());
				parent->replaceChild(node.get(), scribe.get());
			}
			else
			{
				// 乳沟没有选择到,则移除高亮显示的对象
				osg::Node::ParentList parentList = parentAsScribe->getParents();
				for (osg::Node::ParentList::iterator itr = parentList.begin(); itr != parentList.end(); ++itr)
				{
					(*itr)->replaceChild(parentAsScribe.get(), node.get());
				}
			}
		}
	}
public:
	// 得到鼠标的位置
	float _mx;
	float _my;
};

/* 对象选取示例 */
void pickObject_8_11(const string &strDataFolder);

/* 对象选取示例 */
void pickObject_8_11(const string &strDataFolder)
{
	// 创建Viewer对象,场景浏览器
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
	viewer->addEventHandler(new PickHandler());

	osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
	traits->x = 40;
	traits->y = 40;
	traits->width = 600;
	traits->height = 480;
	traits->windowDecoration = true;
	traits->doubleBuffer = true;
	traits->sharedContext = 0;

	osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());

	osg::ref_ptr<osg::Camera> camera = new osg::Camera;
	camera->setGraphicsContext(gc.get());
	camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
	GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
	camera->setDrawBuffer(buffer);
	camera->setReadBuffer(buffer);

	viewer->addSlave(camera.get());

	// 创建场景租节点
	osg::ref_ptr<osg::Group> root = new osg::Group();

	// 创建一个节点,读取牛的模型
	string strDataPath = strDataFolder + "cow.osg";
	osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(strDataPath);

	// 添加到场景
	root->addChild(node);

	// 优化场景数据
	osgUtil::Optimizer optimizer;
	optimizer.optimize(root);
	viewer->setSceneData(root);
	viewer->realize();
	viewer->run();
}

运行程序,截图如图8-24所示。

图8-24对象选取示例截图

相关推荐
大美B端工场-B端系统美颜师33 分钟前
多模态数据融合预警:从IoT传感器到卫星监测的可视化方案升级
物联网·交互·数据预警
小彭努力中2 小时前
141.在 Vue 3 中使用 OpenLayers Link 交互:把地图中心点 / 缩放级别 / 旋转角度实时写进 URL,并同步解析显示
前端·javascript·vue.js·交互
小小小小王王王2 小时前
求猪肉价格最大值
数据结构·c++·算法
岁忧2 小时前
(LeetCode 面试经典 150 题 ) 58. 最后一个单词的长度 (字符串)
java·c++·算法·leetcode·面试·go
梓贤Vigo3 小时前
【Axure高保真原型】动态打字输入效果
交互·产品经理·axure·原型
码农编程录3 小时前
【c/c++3】类和对象,vector容器,类继承和多态,systemd,std&boost
c++
??tobenewyorker5 小时前
力扣打卡第二十一天 中后遍历+中前遍历 构造二叉树
数据结构·c++·算法·leetcode
oioihoii6 小时前
C++11 forward_list 从基础到精通:原理、实践与性能优化
c++·性能优化·list
m0_687399846 小时前
写一个Ununtu C++ 程序,调用ffmpeg API, 来判断一个数字电影的视频文件mxf 是不是Jpeg2000?
开发语言·c++·ffmpeg
梓贤Vigo6 小时前
【Axure视频教程】大小图轮播
交互·产品经理·axure·原型·中继器