OpenSceneGraph 事件响应处理与碰撞

事件响应(事件适配器)

OSG中通过osgGA::GUIEventAdapter类来响应所有交互事件,获得并记录相应数据。

其类方法如下:
image.png
image.png
image.png
image.png
image.png
image.png

OSG人机交互事件类型:
image.png

OSG键盘按键标识:
image.png
image.png
image.png

OSG鼠标按键标识:
image.png

image.png
image.png

动作适配器

用户向系统传递请求(窗口刷新,鼠标位置的设置等),通过GUIActionAdapter类来实现。
通常将其强制转换成Viewer类来使用。

其类方法如下:
image.png

处理交互事件

OSG中通过osgGA::GUIEventHander类来响应所有交互事件。

其类方法如下:
image.png

键盘控制例程:

image.png
image.png
image.png

image.png
image.png

交运算

交运算用于判断指定的几何体与场景图形有没有相交,获得其交集

鼠标点击事件的交运算

osgUtil::LineSegmentIntersector继承自osgUtil::Intersector类,用于检测指定线段和场景图形之间的相交情况,并向程序提供查询相交测试结果的函数。

osgUtil::PolytopeIntersectorosgUtil::LineSegmentIntersector类似,不过,该类用于检测由一系列平面构成的多面体的相交运算。当鼠标单击场景图形中某一区域,希望拾取到鼠标位置附近的一个封闭多面体区域时,osgUtil::PolytopeIntersector类最实用。

osgUtil::PlaneIntersector,与osgUtil::LineSegmentIntersector类似,用于检测出一系列平面构成的平面的相交运算。

// 创建一个线段交集检测对象
osgUtil::LineSegmentIntersector::Intersections intersections:
viewer->computelntersections(x,y,intersections)

// x,y 为鼠标点击的位置,判断鼠标所在坐标是否在一条线上,
//将该线上所有点的坐标存入intersections中。


// 得到相交交集的交点,并依次打印
 
for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = 
intersections.begin();hitr!=intersections.end();++hitr)
{
    // 输入流
    cout<<”Mouse in world X:”<<hitr->getWorldIntersectPoint().x()
    <<” Y:”<<hitr->getWorldIntersectPoint().y()<<” Z:”
    <<hitr->getWorldIntersectPoint().z()<<endl;
}

访问器创建和触发机制与osg::NodeVisitor实例大致相似,需要维护一个进行交集测试的线段列表,而对于其中的每一条线段,访问器都会创建一个交点列表(osgUtil::IntersectVisitor::HitList 实例),它主要用于搜索场景图形中与指定几何体相交的节点。而最后相交测试的工作将在osgUtil::Intersector 的继承类中完成,即通过osgUtil::Intersector 的继承类管理访问与场景图相交线段对应的节点所有线段对应的交点集都存在osgUtil::IntersectVisitor::HitList对象中。 每一条线段都有一个独立的交点列表。

在这里插入图片描述

// 创建一个交集访问器
osgUtil::IntersectVisitor ivXY;
// 根据新的位置得到两条线段检测(自定义线段),参数为线段起始点和终止点的坐标位置
osg::ref_ptr<LineSegment> lineXY = new osg::LineSegment(newPos, m_vPosition);

osg::ref_ptr<osg::LineSegment> lineZ = new osg::LineSegment(
newPos1 + osg::Vec3(0.0,0.0,10.0), newPos1 - osg::Vec3(0.0,0.0,-10.0));

// 添加两条线段
ivXY.addLineSegment(lineZ.get());
ivXY.addLineSegment(lineXY.get());
 
// 开启交集检测
m_pHowViewer->getSceneData()->accept(ivXY);

//m_pHowViewer为Viewer类
//检测该节点是否碰撞到 ivXY中的线段