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

【OSG学习笔记】Day 13: 事件处理——响应键盘与鼠标

在这里插入图片描述

OpenSceneGraph (OSG) 中,事件处理是实现用户交互功能的重要部分。

通过自定义按键事件(如 WASD 键控制模型移动),可以让用户与场景进行互动。

osgGA::GUIEventHandler

osgGA::GUIEventHandlerOpenSceneGraph (OSG) 中用于处理用户输入事件(如键盘、鼠标等)的一个基类。

通过继承 osgGA::GUIEventHandler 并重写其方法,可以实现自定义的事件处理逻辑,以便对用户的交互做出响应。

创建自定义事件处理器

OSG 提供了一个基类 osgGA::GUIEventHandler,可以用来自定义事件处理逻辑。

我们需要继承这个类,并重写其 handle() 方法。

#include <osgViewer/Viewer>
#include <osg/MatrixTransform>
#include <osgGA/GUIEventHandler>
#include <osg/PositionAttitudeTransform>// 自定义事件处理器
class CustomKeyboardHandler : public osgGA::GUIEventHandler {
public:CustomKeyboardHandler(osg::ref_ptr<osg::PositionAttitudeTransform> transform): _transform(transform), _moveSpeed(1.0f) {}// 重写 handle() 方法bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&) override {switch (ea.getEventType()) {case osgGA::GUIEventAdapter::KEYDOWN: {float delta = _moveSpeed; // 移动速度osg::Vec3d pos = _transform->getPosition(); // 获取当前模型位置switch (ea.getKey()) {case 'w': case 'W': // 向前移动pos.z() += delta;break;case 's': case 'S': // 向后移动pos.z() -= delta;break;case 'a': case 'A': // 向左移动pos.x() -= delta;break;case 'd': case 'D': // 向右移动pos.x() += delta;break;default:return false; // 未处理的按键}_transform->setPosition(pos); // 更新模型位置return true; // 表示事件已处理}default:return false; // 其他事件未处理}}private:osg::ref_ptr<osg::PositionAttitudeTransform> _transform; // 模型变换节点float _moveSpeed; // 移动速度
};

设置场景中的可移动模型

为了演示 WASD 控制,我们需要一个模型,并将其附加到 osg::PositionAttitudeTransform 节点上。

这个节点允许我们轻松地调整模型的位置和姿态。

osg::ref_ptr<osg::Node> createModel() {// 创建一个简单的几何体作为模型(例如立方体)osg::ref_ptr<osg::Geode> geode = new osg::Geode;geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0, 0, 0), 1.0f)));return geode.release();
}

整合事件处理器

将自定义事件处理器添加到 OSG 的视图器中,并运行程序。

int main() {// 创建视图器osgViewer::Viewer viewer;// 创建一个 PositionAttitudeTransform 节点用于控制模型位置osg::ref_ptr<osg::PositionAttitudeTransform> transform = new osg::PositionAttitudeTransform;transform->addChild(createModel()); // 将模型添加到变换节点// 将变换节点添加到场景根节点osg::ref_ptr<osg::Group> root = new osg::Group;root->addChild(transform);// 添加自定义事件处理器viewer.addEventHandler(new CustomKeyboardHandler(transform));// 设置场景数据viewer.setSceneData(root);// 运行视图器return viewer.run();
}

实战

我们来实现让我们的钢铁侠动起来的效果。

代码如下:

#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/MatrixTransform>
#include <osgViewer/Viewer>
#include <osgGA/GUIEventHandler>
#include <osgDB/ReadFile>
#include <iostream>
#include <cstdlib>// 自定义事件处理类
class KeyHandler : public osgGA::GUIEventHandler
{
public:KeyHandler(osg::MatrixTransform* transform) : _transform(transform) {}virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa){switch (ea.getEventType()){case osgGA::GUIEventAdapter::KEYDOWN:switch (ea.getKey()){case 'w':case 'W':// 向前移动translateNode(osg::Vec3(0.0f, 10.0f, 0.0f));return true;case 'a':case 'A':// 向左移动translateNode(osg::Vec3(-10.0f, 0.0f, 0.0f));return true;case 's':case 'S':// 向后移动translateNode(osg::Vec3(0.0f, -10.0f, 0.0f));return true;case 'd':case 'D':// 向右移动translateNode(osg::Vec3(10.0f, 0.0f, 0.0f));return true;default:break;}default:break;}return false;}private:void translateNode(const osg::Vec3& translation){// 获取当前矩阵osg::Matrix matrix = _transform->getMatrix();// 对矩阵进行平移操作matrix.preMultTranslate(translation);// 设置新的矩阵_transform->setMatrix(matrix);}osg::ref_ptr<osg::MatrixTransform> _transform;
};int main()
{// 创建Viewer对象osgViewer::Viewer viewer;// 创建一个MatrixTransform节点osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;// 加载模型(支持.osg/.obj格式)osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("../IronMan.osg");  // 替换为你的模型路径// 检查模型是否加载成功if (!model) {std::cerr << "模型加载失败!请检查路径和格式。" << std::endl;return 1;}// 将几何体添加到MatrixTransform节点transform->addChild(model);// 创建场景图的根节点osg::ref_ptr<osg::Group> root = new osg::Group;root->addChild(transform);// 设置场景数据viewer.setSceneData(root);// 创建自定义事件处理程序并添加到Viewerviewer.addEventHandler(new KeyHandler(transform));// 运行Viewerreturn viewer.run();
}

运行效果

在这里插入图片描述
距离做游戏又进了一步。_

在这里插入图片描述

http://www.xdnf.cn/news/2687.html

相关文章:

  • 12前端项目----添加购物车1.0
  • 计算机视觉——通过 OWL-ViT 实现开放词汇对象检测
  • Dockerfile 编写根据需求阶段而出现
  • Android wifi开发调试总结
  • 【ACL系列论文写作指北08-图表设计规范】-让数据与结构一目了然
  • STM32的SysTick
  • 9. 使用Gazebo和Rviz显示机器人(包括运动控制,雷达,摄像头仿真以及显示)
  • 【强化学习系列】贝尔曼最优方程
  • C语言-函数的嵌套调用,链式访问,函数的声明和函数的定义
  • Python数据结构与算法(5)——动态规划
  • CUDA 编程相关的开源库
  • 【深度学习】评估模型复杂度:GFLOPs与Params详解
  • 人脑、深思考大模型与其他大模型的区别科普
  • Kubernetes》》k8s》》Taint 污点、Toleration容忍度
  • 香橙派打包qt文件报错“xcb 插件无法加载”与“QObject::moveToThread”线程错误的解决方案
  • ElasticSearch深入解析(五):如何将一台电脑上的Elasticsearch服务迁移到另一台电脑上
  • 【Spark入门】Spark RDD基础:转换与动作操作深度解析
  • vr全景相机如何选择?
  • Android Studio学习记录1
  • Python(15)迭代器和生成器
  • IP SSL证书常见问题:快速实现HTTPS加密
  • 使用Docker安装Harbor
  • MCP 模型上下文协议配置MCP Server开发实践
  • android录音生成wav
  • Spring Boot定时任务
  • 深入浅出JavaScript常见设计模式:从原理到实战(2)
  • 一文读懂Tomcat应用之 CentOS安装部署Tomcat服务
  • rabbitmq-集群部署
  • 当所有人都用上先进ai,如何保持你的优势?
  • 用Postman验证IAM Token的实际操作