自定义事件处理器
- osgGA::GUIEventHandler 事件处理器/事件遍历器的回调
- 重载
- handle
-
参数osgGA::GUIEventAdapter
- getEventType

- getModKeyMask 返回MODKEY_CTRL/MODKEY_SHIFT/MODKEY_ALT
- 注意:相应set方法不适合在handle中出现,用于osg底层显示系统向事件队列添加事件
-
参数osgGA::GUIActionAdapter
- osgViewer::Viewer* viewer = dynamic_castosgViewer::Viewer*(&aa);
-
- handle
- 重载
- 事件处理管理
- addEventHandler
- removeEventHandler
- 步骤
- 自定义事件处理器
- viewer中加入自定义事件处理器
- 取消viewer主相机控制器
- viewer.getCamera()->setAllowEventFocus(false);
- 设置viewer的ViewMatrix
- viewer.getCamera()->setViewMatrixAsLookAt(osg::Vec3(0.0f,-100.0f,0.0f), osg::Vec3(), osg::Z_AXIS );
示例
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgGA/GUIEventHandler>
#include <osgViewer/Viewer>
class ModelController : public osgGA::GUIEventHandler
{
public:
ModelController(osg::MatrixTransform* node)
: _model(node)
{}
virtual bool handle(const osgGA::GUIEventAdapter& ea,
osgGA::GUIActionAdapter& aa);
protected:
osg::ref_ptr<osg::MatrixTransform> _model;
};
bool ModelController::handle(const osgGA::GUIEventAdapter& ea,
osgGA::GUIActionAdapter& aa)
{
if (!_model) return false;
osg::Matrix matrix = _model->getMatrix();
switch (ea.getEventType())
{
case osgGA::GUIEventAdapter::KEYDOWN:
switch (ea.getKey())
{
case 'a': case 'A':
matrix *= osg::Matrix::rotate(-0.1f, osg::Z_AXIS);
break;
case 'd': case 'D':
matrix *= osg::Matrix::rotate(0.1f, osg::Z_AXIS);
break;
case 'w': case 'W':
matrix *= osg::Matrix::rotate(-0.1f, osg::X_AXIS);
break;
case 's': case 'S':
matrix *= osg::Matrix::rotate(0.1f, osg::X_AXIS);
break;
default:break;
}
_model->setMatrix(matrix);
break;
default:
break;
}
return false;
}
int main(int argc, char** argv)
{
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("cessna.osg");
osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
mt->addChild(model.get());
osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild(mt.get());
osg::ref_ptr<ModelController> ctrler =
new ModelController(mt.get());
osgViewer::Viewer viewer;
viewer.addEventHandler(ctrler.get());
viewer.getCamera()->setAllowEventFocus(false);
viewer.getCamera()->setViewMatrixAsLookAt(
osg::Vec3(0.0f, -100.0f, 0.0f), osg::Vec3(), osg::Z_AXIS);
viewer.setSceneData(root.get());
return viewer.run();
}
自定义事件
- osgGA::EventQueue
- addEvent
- osgGA::GUIEventAdapter
- setEventType
- setButton
- osgGA::GUIEventAdapter
- userEvent
- 参数为osg::Referenced
- addEvent
- 说明:每一个事件都将遍历事件处理器
示例
#include <osg/Switch>
#include <osgDB/ReadFile>
#include <osgGA/GUIEventHandler>
#include <osgViewer/Viewer>
#include <iostream>
struct TimerInfo : public osg::Referenced
{
TimerInfo(unsigned int c) : _count(c) {}
unsigned int _count;
};
class TimerHandler : public osgGA::GUIEventHandler
{
public:
TimerHandler(osg::Switch* sw) : _switch(sw), _count(0) {}
virtual bool handle(const osgGA::GUIEventAdapter& ea,
osgGA::GUIActionAdapter& aa);
protected:
osg::ref_ptr<osg::Switch> _switch;
unsigned int _count;
};
bool TimerHandler::handle(const osgGA::GUIEventAdapter& ea,
osgGA::GUIActionAdapter& aa)
{
switch (ea.getEventType())
{
case osgGA::GUIEventAdapter::FRAME:
if (_count % 100 == 0)
{
osgViewer::Viewer* viewer =
dynamic_cast<osgViewer::Viewer*>(&aa);
if (viewer)
{
viewer->getEventQueue()->userEvent(
new TimerInfo(_count));
}
}
_count++;
break;
case osgGA::GUIEventAdapter::USER:
if (_switch.valid())
{
const TimerInfo* ti =
dynamic_cast<const TimerInfo*>(ea.getUserData()
);
std::cout << "Timer event at: " << ti->_count <<
std::endl;
_switch->setValue(0, !_switch->getValue(0));
_switch->setValue(1, !_switch->getValue(1));
}
break;
default:
break;
}
return false;
}
int main(int argc, char** argv)
{
osg::ref_ptr<osg::Node> model1 = osgDB::readNodeFile("cessna.osg");
osg::ref_ptr<osg::Node> model2 = osgDB::readNodeFile("cessnafire.osg");
osg::ref_ptr<osg::Switch> root = new osg::Switch;
root->addChild(model1.get(), false);
root->addChild(model2.get(), true);
osgViewer::Viewer viewer;
viewer.setSceneData(root.get());
viewer.addEventHandler(new TimerHandler(root.get()));
return viewer.run();
}
物体相交
- osgUtil::IntersectionVisitor
-
继承osg::NodeVisitor
-
参数为osgUtil::Intersector

-
步骤
- 定义自定义事件处理器
- 定义intersector
- osg::ref_ptrosgUtil::LineSegmentIntersector intersector = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, ea.getX(), ea.getY());
- 遍历
- osgUtil::IntersectionVisitor iv( intersector.get() );
- camera->accept( iv );
- 检查相交
- containsIntersections
- 获取相交
- getIntersections 由近到远
- 获取相交点
- getLocalIntersectPoint
- getWorldIntersectPoint
- 获取相交几何体及父节点
- 获取相交三角组元索引
- …
- 定义intersector
示例
#include <osg/MatrixTransform>
#include <osg/ShapeDrawable>
#include <osg/PolygonMode>
#include <osgDB/ReadFile>
#include <osgUtil/LineSegmentIntersector>
#include <osgViewer/Viewer>
class PickHandler : public osgGA::GUIEventHandler
{
public:
osg::Node* getOrCreateSelectionBox();
virtual bool handle(const osgGA::GUIEventAdapter& ea,
osgGA::GUIActionAdapter& aa);
protected:
osg::ref_ptr<osg::MatrixTransform> _selectionBox;
};
osg::Node* PickHandler::getOrCreateSelectionBox()
{
if (!_selectionBox)
{
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(
new osg::ShapeDrawable(new osg::Box(osg::Vec3(),
1.0f)));
_selectionBox = new osg::MatrixTransform;
_selectionBox->setNodeMask(0x1);
_selectionBox->addChild(geode.get());
osg::StateSet* ss = _selectionBox->getOrCreateStateSet();
ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
ss->setAttributeAndModes(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE));
}
return _selectionBox.get();
}
bool PickHandler::handle(const osgGA::GUIEventAdapter& ea,
osgGA::GUIActionAdapter& aa)
{
if (ea.getEventType() != osgGA::GUIEventAdapter::RELEASE || ea.getButton() != osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON
||
!(ea.getModKeyMask()&osgGA::GUIEventAdapter::MODKEY_CTRL)
)
return false;
osgViewer::Viewer* viewer =
dynamic_cast<osgViewer::Viewer*>(&aa);
if (viewer)
{
osg::ref_ptr<osgUtil::LineSegmentIntersector>
intersector =
new osgUtil::LineSegmentIntersector(
osgUtil::Intersector::WINDOW, ea.getX(), ea.getY()
);
osgUtil::IntersectionVisitor iv(intersector.get());
iv.setTraversalMask(~0x1);
viewer->getCamera()->accept(iv);
if (intersector->containsIntersections())
{
osgUtil::LineSegmentIntersector::Intersection result = *(intersector->getIntersections().begin());
osg::BoundingBox bb = result.drawable->getBoundingBox();
osg::Vec3 worldCenter = bb.center() * osg::computeLocalToWorld(result.nodePath);
_selectionBox->setMatrix(
osg::Matrix::scale(bb.xMax() - bb.xMin(),
bb.yMax() - bb.yMin(),
bb.zMax() - bb.zMin()) *
osg::Matrix::translate(worldCenter));
}
}
return false;
}
int main(int argc, char** argv)
{
osg::ref_ptr<osg::Node> model1 = osgDB::readNodeFile("cessna.osg");
osg::ref_ptr<osg::Node> model2 = osgDB::readNodeFile("cow.osg");
osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild(model1.get());
root->addChild(model2.get());
osg::ref_ptr<PickHandler> picker = new PickHandler;
root->addChild(picker->getOrCreateSelectionBox());
osgViewer::Viewer viewer;
viewer.setSceneData(root.get());
viewer.addEventHandler(picker.get());
return viewer.run();
}
图形上下文
- 形式
- 相关的窗口API
- 缓冲,比如opengl的像素缓冲
- osg
- osg::GraphicsContext
-
createGraphicsContext()
- 参数为osg::GraphicsContext::Traits

-
- osgViewer::GraphicsWindow
- getEventQueue() 处理GUI事件
- osg::GraphicsContext
- 步骤
- 创建traits
- 创建graphics context
- 附加到相机
- 设置相机为主相机
示例
#include <osg/GraphicsContext>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
int main(int argc, char** argv)
{
osg::ref_ptr<osg::GraphicsContext::Traits> traits =
new osg::GraphicsContext::Traits;
traits->x = 50;
traits->y = 50;
traits->width = 800;
traits->height = 600;
traits->windowDecoration = true;
traits->doubleBuffer = true;
traits->samples = 4;
osg::ref_ptr<osg::GraphicsContext> gc =
osg::GraphicsContext::createGraphicsContext(traits.get());
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setGraphicsContext(gc);
camera->setViewport(
new osg::Viewport(0, 0, traits->width, traits->height));
camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
camera->setClearColor(osg::Vec4f(0.2f, 0.2f, 0.4f, 1.0f));
camera->setProjectionMatrixAsPerspective(
30.0f, (double)traits->width / (double)traits->height,
1.0, 1000.0);
osg::ref_ptr<osg::Node> root = osgDB::readNodeFile(
"cessna.osg");
osgViewer::Viewer viewer;
viewer.setCamera(camera.get());
viewer.setSceneData(root.get());
return viewer.run();
}
本文介绍了如何在osg中实现自定义事件处理器,包括处理不同类型的事件,以及如何在视图中添加和移除事件处理器。此外,还详细讲解了物体相交的步骤,包括使用IntersectionVisitor进行相交检查和获取相交信息。最后,探讨了图形上下文的创建和使用。
188

被折叠的 条评论
为什么被折叠?



