场景交互与场景漫游-osgGA库(5)

news2024/12/23 3:13:28

osgGA

        osgGA库是OSG的一个附加的工具库,它为用户提供各种事件处理及操作处理。通过osgGA库读者可以像控制Windows窗口一样来处理各种事件

        osgGA的事件处理器主要由两大部分组成,即事件适配器动作适配器。osgGA:GUIEventHandler类主要提供了窗口系统的GUI事件接口它使用osgGA::GUIEventAdapter 实例来接收更新,使用osgGA::GUIActionAdapter 实例向系统发出请求

        在osgGA::GUIEventHandler 中包含了一系列的枚举事件类型,如NONE、PUSH、RELEASE、DOUBLECLICK2、DRAG、MOVE、KEYDOWN 和KEYUP 等。但osgGA::GUIEventHandler 会根据不同的事件类型实现一些相关的操作,主要包括下面的类型:

NONE
PUSH//鼠标事件
RELEASE//松开
DOUBLECLICK//双击
DRAG//拖动
MOVE//移动
KEYDOWN//按键
KEYUP//松开
FRAME//每一帧
RESIZE//大小缩放
SCROLL//滚轮
PEN_PRESSURE/鼠标笔压力
PEN_ORIENTATION//鼠标笔的方位
PEN_PROXIMITY_ENTER //开始鼠标笔
PEN_PROXIMITY_LEAVE标笔离开
CLOSE_WINDOW//关闭窗口
QUIT_APPLICATIONG//退出程序
USER

        这些事件类型与Windows的窗口事件非常类似。但在使用这些事件类型时,需要注意,有些OSG并没有实现好,如鼠标滑轮的事件。如果读者有兴趣实现的话,可以向 OSG 官方提供读者的实现代码,读者的大名将会出现在贡献人之列。

        相对而言,osgGA::GUIActionAdapter 类就简单多了,它主要包含系统执行的动作,如重新绘制和光标重置之类的请求。

        osgGA库还包含很多操作器,主要包含一个基类osgGA::MatrixManipulator和它的一些派生类osgGA::MatrixManipulator类是一个基类,提供了各种接口,这也是漫游会用到的一个基类。它提供的接口包括矩阵变换和事件处理,编写自己的操作器需要通过继承osgGA::MatrixManipulator 来实现,需要重载里面的矩阵变换函数和时间处理函数。这里只是简单介绍,后面会有详细说明。

        从osgGA::MatrixManipulator 类派生的子类就是OSG中默认的操作器,主要包括

osgGA::AnimalionPathManipulator//动画路径操作器
osgGA::DriveManipulator//车行操作器
osgGA::FlightManipulator//飞行操作器
osgGA::KeySwitchMatrixManipulator//按键切换操作器
osgGA::NodeTrackerManipulator//节点跟踪操作器
osgGA::TerrainManipulator//地形操作器
osgGA::TrackballManipulator//跟踪球操作器
osgGA::UFOManipulator//UFO操作器

        在默认情况下,OSG通常使用的是osgGA::TrackballManipulator 操作器。在前面很多程序中,都是直接使用 viewer->run(),其实,使用的操作器就是该跟踪球操作器。当然,读者可以将其设置为其他的操作器来处理,例如:

viewer->setCameraManipulator(new osgGA::TerrainManipulator());

        OSG中预设了很多操作器,读者可以在适当的时候选择适当的操作器来完成相应的功能,这里不再赘述,因为不可能把所有操作器的源代码都拿来讲解,在实际应用中,更偏向于编写自己的操作器。

键盘事件消息处理

        在osgGA库中,存在一个事件处理器 osgGA::GUIEventHandler,可以提供窗口系统的GUI事件接口。在OSG中,默认有很多已经写好的事件处理器。在osgViewer 应用程序中添加了很多在OSG中预定义的事件处理器,实现的功能有显示帧率、操作器切换和帮助等,这些事件处理器主要包括

class HelpHandler //帮助事件处理器
class StatsHandler //状态事件处理器
class WindowSizeHandler //窗口大小事件处理器
class ThreadingHandler //线程模型设置事件处理器
class RecordCameraPathHandler //动画记录事件处理器
class LODScaleHandler//LOD缩放事件处理器
class ScrccnCaptureHandler //截屏事件处理器

        这些事件处理器的源代码可以在osgViewer目录下找到,有兴趣的读者可以去研究一下,或者改写为自己的事件处理器。

        在实际过程中,编写自己的事件处理器是一件不可避免的事情,这也是交互的重要部分之一。如果一个平台没有交互,那就只是给客户放电影,就没有必要用到3D这样充满挑战的技术。

        编写一个自己的事件处理器是非常简单的,主要操作步骤如下:

        <1> 编写一个新类,继承自osgGA:GUIEventHandler类。

        <2> 重载成员函数handle(),在osgGA::GUIEventHandler中,该函数原型如下,是一个虚函数:

   

     virtual bool handle(const GUIEventAdapter &, GUIActionAdapter &)

        这一步是非常关键的,也是十分重要的。通过重载该函数,可以根据事件的类型执行自定义动作(可参看第8.2.3节的示例)。

        <3> 将事件处理器压入处理器列表。这一步是非常必要的,如果没有这一步,所写的事件处理器将不会执行,这相当于启动该事件处理器的作用,在使用时一定要注意。

        在编写自己的事件处理器时,在事件处理函数中,事件处理函数的返回值与事件处理器列表中的当前处理器的键盘和鼠标时间相关,并保持一一对应关系。如果返回值为true,则系统会认为该事件已经处理,就不再传递给下一个事件处理器。如果返回值是false,那么它会继续传递给下一个事件处理器,执行对应事件的动作。在用户的应用程序中,可以包含多个事件处理器,在编写时要注意事件不要重复,否则可能会造成有些事件没有响应,有些事件却重复响应。

        在第8.2.3节将演示一个抓图的示例。抓图本身比较简单,可以通过下面的代码实现:

// 读取像素信息抓图

image->readPixels(0, 0, width, height, GL_RGB,GL_UNSIGNED_BYTE);

        但在OSG2x系列以后,这样简单的执行会出现问题,读者会发现使用上面代码根本抓不到图片因为此时并没有得到当前的 RC 设备,这个问题曾经在邮件列表上也讨论过,最好的解决方案就是使用osg::Camera::DrawCallback,这样可以确保在当前RC设备下执行 readPixels(),从而可以保证抓取到图片。这时写一个简单的类,继承自 osg:Camera::DrawCallback类,在开始渲染前就执行绘制回调可以很容易抓到图片。

        抓图示例的代码如程序如下所示。

/******************************************* 键盘事件-抓图示例 *************************************/
osg::ref_ptr<osg::Image> image_c = new osg::Image();// 定义一个全局变量

// 得到抓图
struct CaptureDrawCallback :public osg::Camera::DrawCallback
{
	CaptureDrawCallback(osg::ref_ptr<osg::Image>image)
	{
		_image = image;
	}

	~CaptureDrawCallback(){}

	virtual void operator()(const osg::Camera &camera) const
	{
		// 得到窗口系统接口
		osg::ref_ptr<osg::GraphicsContext::WindowingSystemInterface> wsi = osg::GraphicsContext::getWindowingSystemInterface();

		unsigned int width, height;
		
		// 得到分辨率
		wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height);
		
		// 分配一个image
		_image->allocateImage(width, height, 1, GL_RGB, GL_UNSIGNED_BYTE);

		// 读取像素信息抓图
		_image->readPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE);
	}

	osg::ref_ptr<osg::Image> _image;
};

// 抓图时间处理器
class ImageHandle :public osgGA::GUIEventHandler
{
public:
	ImageHandle()
	{

	}
	~ImageHandle()
	{

	}
	
	// 重置handle()函数
	bool ImageHandle::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
	{
		osg::ref_ptr<osgViewer::Viewer> viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
		if (viewer == nullptr)
		{
			return false;
		}

		// 定义一个静态变量
		static int _screenCaptureSequence = 0;
		switch (ea.getEventType())
		{
			case osgGA::GUIEventAdapter::KEYDOWN:// 按键
			{
				int iValue = ea.getKey();
				if (ea.getKey() == 'c' || ea.getKey() == 'C')
				{
					char filename[128];
					
					// 确定一个合理的文件名,以保证能够连续抓图
					sprintf_s(filename, "D:\\ScreenShot%04d.bmp", _screenCaptureSequence);
					++_screenCaptureSequence;

					// 写入文件
					osgDB::writeImageFile(*(image_c.get()), filename);
				}
				break;
			}
			default:
			{
				return false;
			}
		}

		return true;
	}
};
// 键盘事件之抓图示例
void CaptureImage_8_7(const string &strDataFolder)
{
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
	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.get());

	// 优化场景数据
	osgUtil::Optimizer optimizer;
	optimizer.optimize(root.get());

	// 设置绘制回调
	viewer->getCamera()->setPostDrawCallback(new CaptureDrawCallback(image_c.get()));
	viewer->setSceneData(root.get());

	// 添加抓图时间
	viewer->addEventHandler(new ImageHandle());

	viewer->realize();
	viewer->run();
}

图8-16 抓图示例截图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1222039.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

swin unetr的3D语义分割

基于monai库。其实我不是很喜欢这种&#xff0c;可扩展性太差了&#xff0c;除非说你想快速在自己的数据集上出结果。但是它的transform可以对3d医学图像增强操作&#xff0c;比torch的transform强一点&#xff0c;因为它的数据增强输入是&#xff08;x,y,z&#xff09;h,w,d格…

竞赛 题目:基于机器视觉opencv的手势检测 手势识别 算法 - 深度学习 卷积神经网络 opencv python

文章目录 1 简介2 传统机器视觉的手势检测2.1 轮廓检测法2.2 算法结果2.3 整体代码实现2.3.1 算法流程 3 深度学习方法做手势识别3.1 经典的卷积神经网络3.2 YOLO系列3.3 SSD3.4 实现步骤3.4.1 数据集3.4.2 图像预处理3.4.3 构建卷积神经网络结构3.4.4 实验训练过程及结果 3.5 …

FPGA基础以太网

以太网数据通信 物理层&#xff1a;网线网卡&#xff08;PHY芯片&#xff09; 数据链路层&#xff1a;Mac层(数据有效传输&#xff09; 如图所示&#xff1a;FPGA中的Mac层中的MII接口负责控制PHY芯片&#xff0c;PHY芯片通过网线与PC端进行以太网数据传输。 FPGA中&#xff…

linux高级篇基础理论四(rsync,inotify,squid,KVM虚拟机)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️不能因为人生的道路坎坷,就使自己的身躯变得弯曲;不能因为生活的历程漫长,就使求索的 脚步迟缓。 ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xff1a;云计算技…

利用NVIDIA DALI读取视频帧

1. NVIDIA DALI简介 NVIDIA DALI全称是NVIDIA Data Loading Library&#xff0c;是一个用GPU加速的数据加载和预处理库&#xff0c;可用于图像、视频和语音数据的加载和处理&#xff0c;从而为深度学习的训练和推理加速。 NVIDIA DALI库的出发点是&#xff0c;深度学习应用中…

springboot引入redisson分布式锁及原理

1.引入依赖 <dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.13.6</version> </dependency>2.配置类创建bean /*** author qujingye* Classname RedissonConfig* Description TOD…

相关系数和协方差的关系与区别

相关系数和协方差都是用来衡量两个变量之间关系的统计量&#xff0c;它们在描述变量之间的线性关系上提供了一些信息。下面是它们的关系与区别&#xff1a; 关系&#xff1a; 相关系数的计算涉及到协方差。相关系数等于协方差除以两个变量的标准差的乘积。具体而言&#xff0c…

深度优化数据库性能:Linux 内核参数调整解析

点击上方蓝字关注我 数据库服务器性能的优化是每个IT团队关注的焦点之一。除了数据库引擎的优化之外&#xff0c;合理调整操作系统的内核参数也是提高数据库性能的关键。本文将解析一些常见的 Linux 内核参数&#xff0c;以及它们在数据库服务器优化中的作用和建议的值。 1. 参…

Django学习日志07

多表查询&#xff08;跨表查询&#xff09; 子查询&#xff1a;分步查询 链表查询&#xff1a;把多个有关系的表拼接成一个大表(虚拟表) inner join left join 展示左表所有数据数据&#xff0c;右表展示符合查询条件的数据&#xff0c;查询不到的用null填充 …

工程建设智慧施工云平台源码 智慧工地平台源码

智慧工地平台源码 工程建设智慧施工云平台源码 技术框架&#xff1a;微服务架构JavaSpring Cloud UniApp MySql 智慧工地平台是一种智慧型、系统性的工地信息化解决方案&#xff0c;它把现代信息技术融入到建设工程管理中&#xff0c;协调各方资源&#xff0c;优化施工过程&…

LeetCode题 338比特位计数,20有效的括号,415字符串相加

目录 338比特位计数 题目要求&#xff1a; 解题思路&#xff1a; 1、暴力穷举 代码&#xff1a; 2、N&&#xff08;N - 1&#xff09;公式求解 代码&#xff1a; 3、奇偶数性质解法&#xff1a; 代码&#xff1a; 20有效的括号 题目要求&#xff1a; 解题思路 …

react-router-dom 版本6.18.0中NavLink的api和属性介绍

React Router 是一个基于 React 的路由库&#xff0c;它可以帮助我们在 React 应用中实现页面的切换和路由的管理。而 NavLink 则是 React Router 中的一个组件&#xff0c;它可以帮助我们实现导航栏的样式设置和路由跳转。 在 React Router 版本6.18.0 中&#xff0c;NavLink…

python时间变化与字符串替换技术及读JSON文件等实践笔记

1. 需求描述 根据预测出结果发出指令的秒级时间&#xff0c;使用时间戳&#xff0c;也就是设定时间&#xff08;字符串&#xff09;转为数字时间戳。时间计算转换过程中&#xff0c;出现单个整数&#xff08;例如8点&#xff09;&#xff0c;按字符串格式补齐两位“08”。字符…

多媒体ffmpeg学习教程

多媒体ffmpeg 目前比较流行的音视频文件为:MP4 flv m3u8 ffmpeg ffmpeg ffplay ffprobe ffserverffmpeg -i INPUT -vf "split [main][tmp]; [tmp] cropiw:ih/2:0:0, vflip [flip];[main][flip] overlay0:H/2" OUTPUTffmpeg -i 2022.mp4 -vcodec mpeg4 -b:…

酷柚易汛ERP - 通用设置操作指南

1、系统设置 对系统进行初步设置&#xff0c;如系统LOGO、站点名称、备案号、版权信息、尾部信息及系统相关的一些基础设置 2、应用/小程序配置 对系统移动端进行相关配置 3、短信配置 对系统短信进行配置&#xff0c;此配置用于移动端一些通知类信息发送【目前仅支持阿里云…

PostgreSQL按月计算每天值的累加

要按月计算每天值的累加&#xff0c;您可以使用PostgreSQL中的日期函数和窗口函数。下面是一个示例查询&#xff0c;假设您有一个名为"table_name"的表&#xff0c;其中包含一个日期列"date_column"和一个数值列"value_column"&#xff1a; SELE…

【Android】带下划线的TextView

序言 我们有时候需要一个类似这样的显示&#xff0c;上面是文字&#xff0c;下面是一条线 这样的显示效果是TextView实现不了的&#xff0c;需要我们自己进行修改一下。 实现 创建一个UnderlineTextView&#xff0c;继承系统的TextView class UnderlineTextView(mContext…

spider 网页爬虫中的 AWS 实例数据获取问题及解决方案

前言 AAWS实例数据对于自动化任务、监控、日志记录和资源管理非常重要。开发人员和运维人员可以通过AWS提供的API和控制台访问和管理这些数据&#xff0c;以便更好地管理和维护他们在AWS云上运行的实例。然而&#xff0c;在使用 spider 框架进行网页爬取时&#xff0c;我们常常…

【Kingbase FlySync】界面化管控平台:2.配置数据库同步之KES>KES

【Kingbase FlySync】界面化管控平台:3.配置数据库同步之KES->KES 部署KES数据库到KES数据库同步服务1.登录KFS管理平台2.开始配置数据节点信息(1)配置node1数据节点(2)配置node2数据节点 3.KFS拓扑图配置4.开始部署5.启动同步程序并查验是否运行正常 测试同步1.从node1数据…

nginx学习(2)

Nginx 反向代理案例2 1. 实现效果 实现效果&#xff1a;使用 nginx 反向代理&#xff0c;根据访问的路径跳转到不同端口的服务中 nginx 监听端口为 8001&#xff0c; 访问 http://127.0.0.1:8001/edu/ 直接跳转到 127.0.0.1:8081 访问 http://127.0.0.1:8001/vod/ 直接跳转到 …