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

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.rhkb.cn/news/199119.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于单片机体温脉搏检测控制系统及源程序

一、系统方案 1、本设计采用51单片机作为主控器。 2、DS18B20传感器检测体温。 3、红外对接管采集心率值送到液晶1602显示。 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统初始化 /lcd1602初始化设置*/ void init_1602() { write_com(0x38); //显示…

二元分类模型评估方法

文章目录 前言一、混淆矩阵二、准确率三、精确率&召回率四、F1分数五、ROC 曲线六、AUC&#xff08;曲线下面积&#xff09;七、P-R曲线类别不平衡问题中如何选择PR与ROC 八、 Python 实现代码混淆矩阵、命中率、覆盖率、F1值ROC曲线、AUC面积 指标 公式 意义 真正例 (TP)被…

【项目设计】网络版五子棋游戏

文章目录 一、项目介绍1. 项目简介2. 开发环境3. 核心技术4. 开发阶段 二、环境搭建1. 安装 wget 工具2. 更换 yum 源3. 安装 lrzsz 传输工具4. 安装⾼版本 gcc/g 编译器5. 安装 gdb 调试器6. 安装分布式版本控制工具 git7. 安装 cmake8. 安装 boost 库9. 安装 Jsoncpp 库10. 安…

四旋翼无人机的飞行原理--【其利天下分享】

近年来&#xff0c;无人机在多领域的便捷应用促使其迅猛的发展&#xff0c;如近年来的多场战争&#xff0c;无人机的战场运用发挥得淋漓尽致。 下面我们针对生活中常见的四旋翼无人机的飞行原理做个基础的介绍&#xff0c;以飨各位对无人机有兴趣的朋友。 一&#xff1a;四旋翼…

春秋云境靶场CVE-2022-28512漏洞复现(sql手工注入)

文章目录 前言一、CVE-2022-28512靶场简述二、找注入点三、CVE-2022-28512漏洞复现1、判断注入点2、爆显位个数3、爆显位位置4 、爆数据库名5、爆数据库表名6、爆数据库列名7、爆数据库数据 总结 前言 此文章只用于学习和反思巩固sql注入知识&#xff0c;禁止用于做非法攻击。…

腐蚀监测常用技术及作用

上次我们介绍了设备状态监测中的红外热像技术>>热成像仪的工作原理及在工业设备状态监测中的应用&#xff0c;这次我们一起来探讨腐蚀监测技术方面的内容。 在工业领域中&#xff0c;腐蚀监测技术是腐蚀控制的重要部分和可靠而有效的手段。通过对设备的腐蚀情况进行监测和…

【JVM】Java虚拟机

本文主要介绍了JVM的内存区域划分,类加载机制以及垃圾回收机制. 其实JVM的初心,就是让java程序员不需要去了解JVM的细节,它把很多工作内部封装好了.但是学习JVM的内部原理有利于我们深入理解学习Java. 1.JVM的内存区域划分 JVM其实是一个java进程 ; 每个java进程,就是一个jvm…

Apache Airflow (九) :Airflow Operators及案例之BashOperator及调度Shell命令及脚本

&#x1f3e1; 个人主页&#xff1a;IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 &#x1f6a9; 私聊博主&#xff1a;加入大数据技术讨论群聊&#xff0c;获取更多大数据资料。 &#x1f514; 博主个人B栈地址&#xff1a;豹哥教你大数据的个人空间-豹…

科技创新 共铸典范 | 江西卫健办邓敏、飞图影像董事长洪诗诗一行到访拓世科技集团,提振公共卫生事业发展

2023年11月15日&#xff0c;拓世科技集团总部迎来了江西省卫健项目办项目负责人邓敏、江西飞图影像科技有限公司董事长洪诗诗一行的考察参观&#xff0c;集团董事长李火亮、集团高级副总裁方高强进行热情接待。此次多方交流&#xff0c;旨在共同探讨携手合作&#xff0c;激发科…

Django+Vue项目创建 跑通

参考链接&#xff1a; 【精选】DjangoVue项目构建_django vue-CSDN博客 一、背景 主要介绍如何使用后端Django 前端Vue 的技术栈快速地搭建起一套web项目的框架。 为什么使用Django和Vue? Django是Python体系下最成熟的web框架之一&#xff0c;由于Python语言的易用…

【机器学习Python实战】线性回归

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; &#x1f4a1;专栏&#xff1a;机器学习python实战 欢迎订阅&#xff01;后面的内容会越来越有意思~ ⭐内容说明&#xff1a;本专栏主要针对机器学习专栏的基础内容进行python的实现&#xff0c;部分…

Redux-状态管理组件

一、简介 react中的状态只属于某个组件。而Redux是一个全局管理js状态的架构&#xff0c;让组件通信更加容易。 之前是状态在所有组件间传递&#xff0c;而redux通过store来实现这个功能。 Redux特性&#xff1a; 1.Single source Of truth&#xff0c;通过store唯一维护状态…

网工内推 | 国企、港企网工,年底双薪,NA以上认证即可

01 中航期货有限公司 招聘岗位&#xff1a;信息技术部-网络工程师 职责描述&#xff1a; 1、负责总部、分支机构、外联单位网络的日常运维、故障和应急处置&#xff0c;特别是定期监测设备的运行状态&#xff0c;对存在隐患的地方及时发现改正&#xff0c;保持网络稳定通畅&am…

Java 12 及Tomcat 部署配置

使用的软件版本 1. Java12部署 和之前的Java版本不太一样&#xff0c;12版本不用配置JRE环境。 解压缩文件夹 root账户执行 tar -xzvf /home/software/jdk-12.0.2_linux-x64_bin.tar.gz创建java文件夹 root账户执行 cd /usr mkdir java移动Java文件到创建的文件夹下 root账…

多态语法详解

多态语法详解 一&#xff1a;概念1&#xff1a;多态实现条件 二:重写&#xff1a;三&#xff1a;向上转型和向下转型1:向上转型&#xff1a;1&#xff1a;直接赋值&#xff1a;2&#xff1a;方法传参3&#xff1a;返回值 2:向下转型 一&#xff1a;概念 1&#xff1a;同一个引…

LINMP搭建wordpress-数据库不分离

目录 一、nginx部署 1.安装nginx前的系统依赖环境检查 2.下载nginx源代码包 3.解压缩源码包 4.创建普通的nginx用户 5.开始编译安装nginx服务 6.创建一个软连接以供集中管理 7.配置nginx环境变量 二、mysql 1.创建普通mysql用户 2.下载mysql二进制代码包 3.创建mys…

力扣刷题-二叉树-完全二叉树的节点个数

222.完全二叉树的节点个数 给出一个完全二叉树&#xff0c;求出该树的节点个数。 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,4,5,6] 输出&#xff1a;6 示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;0 示例 3&#xff1a; 输入&#xff1a;root [1]…

鸿蒙4.0开发笔记之DevEco Studio之配置代码片段快速生成(三)

一、作用 配置代码片段可以让我们在Deveco Studio中进行开发时快速调取常用的代码块、字符串或者某段具有特殊含义的文字。其实现方式类似于调用定义好变量&#xff0c;然而这个变量是存在于Deveco Studio中的&#xff0c;并不会占用项目的资源。 二、配置代码段的方法 1、打…