OSG人机交互
来源:互联网 发布:东莞优化网站 编辑:程序博客网 时间:2024/06/06 00:04
OSG人机交互
标签(空格分隔): OSG 键盘 鼠标 事件
Windows与OSG事件传递流程
OSG在Windows平台上的消息传递仍然遵守Windows的规则,底层调用的也仍然是Windows的API。OSG中真正处理事件的函数是handelNativeWindowingEvent
,打开handelNativeWindowingEvent
的定义可以发现待处理事件都是压入事件序列osgGA::EventQueue
中。然后依次取出进行响应。
创建一个osg窗口
首先要解决的是如何使用OSG语句创建窗口以及在什么位置创建窗口。OSG定义了osg::GraphicsContext::Traits
类来决定窗口大小、高宽等参数。通过将该类的一个对象传入到Windows注册窗口的函数中,定义OSG窗口的特征。
代码
#include <osgViewer/api/Win32/graphicswindowwin32>
int main(){ osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer; osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; traits->x = 250; traits->y = 250; traits->width = 800; traits->height = 600; traits->windowDecoration = true; traits->doubleBuffer = true; traits->sharedContext = 0; //执行注册窗口的操作,内部调用了registerdWindowClasses osgViewer::GraphicsWindowWin32* gw = (osgViewer::GraphicsWindowWin32*) osg::GraphicsContext::createGraphicsContext(traits); gw->realizeImplementation(); int a; std::cin >> a; return 0;}
结果为一片白色的windows窗口
键盘和鼠标事件
事件被加入到osgGA::EventQueue
中后,最终由osgGA::GUIEventHandler
类处理,因此程序中我们只要继承osgGA::GUIEventHandler
类,重载handle
函数就可以实现对事件的处理。 osgGA::GUIEventHandler
实际是一个回调函数,在每一帧渲染当中,OSG会遍历所有的回调函数。 osgGA::GUIEventHandler
中的handle
函数为 bool handle(const GUIEventAdapter&,GUIActionAdapter&)
第一个参数为GUIEventAdapter
对象,它是一个事件适配器,里面定义了所有与事件相关的变量,包括键盘码,鼠标状态等。hangle
函数通过这个对象来判断当前要处理事件的类别并获得相关参数。
第二个参数GUIActionAdapter
为一个独立的类,里面包含asView
方法,且视口类View
是它的子类,因此可以在viewer当中进行事件处理。
总的来说就是通过继承osgGA::GUIEventHandler
类,在重载handle
函数的第一个回调参数中判断当前的待处理事件类别,在第二个回调参数中获得当前事件发生的视口,然后进行事件处理。
添加事件处理流程是这样的:从osgGA::GUIEventHandler
公有派生类A并实现handle
函数,然后使用viewer
类的addEventHandler
将其加入到事件处理序列中。
代码
实现的功能是按下键盘上左键时物体向左旋转,按下键盘上右键时物体向右旋转。
#include <osgViewer/viewer>#include <osgViewer/api/Win32/graphicswindowwin32>#include <osgViewer/viewerEventHandlers>#include <osgGA/StateSetManipulator>#include <osgGA/GUIEventHandler>#include <osgDB/readfile>#include <osg/matrixtransform>class RotateGlider : public osgGA::GUIEventHandler{public: bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { osgViewer::Viewer* vw = dynamic_cast<osgViewer::Viewer*>(&aa); if (vw) { osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(vw->getSceneData()); if (mt) { static float i = 0.1f; switch (ea.getEventType()) { case osgGA::GUIEventAdapter::KEYDOWN: { if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Left) { mt->setMatrix(osg::Matrix::rotate(i, osg::Vec3(0.f, 0.f, 1.f))); i += 0.0f; } else if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Right) { mt->setMatrix(osg::Matrix::rotate(i, osg::Vec3(0.f, 0.f, 1.f))); i -= 0.1f; } } break; default: break; } } } return false; }};int main(){ osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer; viewer->setUpViewOnSingleScreen(); osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform; osg::ref_ptr<osg::Node> glider = osgDB::readNodeFile("glider.osg"); mt->addChild(glider); viewer->setSceneData(mt); viewer->addEventHandler(new RotateGlider); return viewer->run();}
效果
鼠标Pick点选物体
在OSG中,Pick并不是OSG的库函数,需要自己实现。在pick的时候有2个重要参数,即单击时屏幕坐标xy,及这个点发出的垂直于屏幕的射线与场景中物体的交点。判断射线与viewer中物体相交是通过构造鼠标单击的法线并计算法线和场景中物体的交点,通过osgView::View::computeIntersections解决交点计算问题。下面看具体代码
#pragma comment(lib,"osgFXd.lib")#pragma comment(lib,"osgUtild.lib")#include <osgFX\scribe>#include <osgUtil\linesegmentintersector>class PickHandle : public osgGA::GUIEventHandler{public: PickHandle(osgViewer::Viewer* viewer) :mviewer(viewer) {} virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { switch (ea.getEventType()) { case(osgGA::GUIEventAdapter::PUSH): if (ea.getButton() == 1) { Pick(ea.getX(), ea.getY()); } return true; default: break; } return false; }protected: void Pick(float x, float y) { std::multiset< osgUtil::LineSegmentIntersector::Intersection> inters; if (mviewer->computeIntersections(x,y, inters)) { for (auto iter = inters.begin(); iter != inters.end(); ++iter) { if (!iter->nodePath.empty() && !iter->nodePath.back()->getName().empty()) { const osg::NodePath& np = iter->nodePath; for (int i = np.size()-1; i >0; --i) { osgFX::Scribe* sc = dynamic_cast<osgFX::Scribe*>(np[i]); if (sc != nullptr) { if (sc->getNodeMask() != 0) { sc->setNodeMask(0); } } } } } } }private: osgViewer::Viewer* mviewer;};int main(){osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer; viewer->setUpViewOnSingleScreen(); osg::ref_ptr<osg::Group> root = new osg::Group; osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("cow.osg"); osg::ref_ptr<osgFX::Scribe> sc = new osgFX::Scribe(); sc->addChild(cow); root->addChild(cow); root->addChild(osgDB::readNodeFile("cessna.osg")); root->addChild(sc); viewer->setSceneData(root); viewer->addEventHandler(new PickHandle(viewer)); return viewer->run();}
效果
- OSG人机交互
- 人机交互
- 人机交互
- 人机交互
- 人机交互
- OSG
- osg
- OSG
- osg-
- OSG
- osg
- OSG
- 五子棋人机交互
- 智能人机交互
- 人机交互复习
- 人机交互手势
- 人机交互界面设计
- 人机交互类型
- SylixOS 里NUC970平台上SPI总线驱动移植
- 126. Word Ladder II 、 127. Word Ladder(leetcode BFS+DFS)
- oracle:窗口函数
- MJExtension精髓都在这里了
- 【.Net Framework 体积大?】不安装.net framework 也能运行!?原理简介补充附带工具-2
- OSG人机交互
- C++随机数的生成
- eclipse中文件存储的编码格式设置与对编码解码的理解
- OSG环境搭建与编译
- SteamVR+HTCVive 交互事件
- 编译时间从33.8秒降到4.5秒我只多做了一件事
- 大数据学习笔记之三十 Spark介绍之一
- 前端工程师不得不知道的ES6新特性(二)
- mac下如何安装WebStorm 破解版