对象选取示例的代码如程序清单8-11所示:
cpp
/******************************************* 对象选取示例 *************************************/
// 对象选取事件处理器
class PickHandler :public osgGA::GUIEventHandler
{
public:
PickHandler() :_mx(0.0f), _my(0.0f)
{
}
~PickHandler()
{
}
// 事件处理函数
bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
{
osg::ref_ptr<osgViewer::View> view = dynamic_cast<osgViewer::View*> (&aa);
if (!view)
{
return false;
}
switch (ea.getEventType())
{
// 鼠标按下
case(osgGA::GUIEventAdapter::PUSH) :
{
// 更新鼠标位置
_mx = ea.getX();
_my = ea.getY();
break;
}
case(osgGA::GUIEventAdapter::RELEASE) :
{
if (_mx == ea.getX() && _my == ea.getY())
{
// 执行对象选取
pick(view.get(), ea.getX(), ea.getY());
}
break;
}
default:
break;
}
return false;
}
// 对象选取事件处理器
void pick(osg::ref_ptr<osgViewer::View> view, float x, float y)
{
osg::ref_ptr<osg::Node> node = new osg::Node();
osg::ref_ptr<osg::Group> parent = new osg::Group();
// 创建一个线段交集检测函数
osgUtil::LineSegmentIntersector::Intersections intersections;
if (view->computeIntersections(x, y, intersections))
{
osgUtil::LineSegmentIntersector::Intersection intersection = *intersections.begin();
osg::NodePath &nodePath = intersection.nodePath;
// 得到选择的物体
node = (nodePath.size() >= 1) ? nodePath[nodePath.size() - 1] : 0;
parent = (nodePath.size() >= 2) ? dynamic_cast<osg::Group*>(nodePath[nodePath.size() - 2]) : 0;
}
// 用一种高亮显示来显示物体已经被选中
if (parent.get() && node.get())
{
osg::ref_ptr<osgFX::Scribe> parentAsScribe = dynamic_cast<osgFX::Scribe*>(parent.get());
if (!parentAsScribe)
{
// 如果对象选择列,高亮显示
osg::ref_ptr<osgFX::Scribe> scribe = new osgFX::Scribe();
scribe->addChild(node.get());
parent->replaceChild(node.get(), scribe.get());
}
else
{
// 乳沟没有选择到,则移除高亮显示的对象
osg::Node::ParentList parentList = parentAsScribe->getParents();
for (osg::Node::ParentList::iterator itr = parentList.begin(); itr != parentList.end(); ++itr)
{
(*itr)->replaceChild(parentAsScribe.get(), node.get());
}
}
}
}
public:
// 得到鼠标的位置
float _mx;
float _my;
};
/* 对象选取示例 */
void pickObject_8_11(const string &strDataFolder);
/* 对象选取示例 */
void pickObject_8_11(const string &strDataFolder)
{
// 创建Viewer对象,场景浏览器
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
viewer->addEventHandler(new PickHandler());
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->x = 40;
traits->y = 40;
traits->width = 600;
traits->height = 480;
traits->windowDecoration = true;
traits->doubleBuffer = true;
traits->sharedContext = 0;
osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setGraphicsContext(gc.get());
camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
camera->setDrawBuffer(buffer);
camera->setReadBuffer(buffer);
viewer->addSlave(camera.get());
// 创建场景租节点
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);
// 优化场景数据
osgUtil::Optimizer optimizer;
optimizer.optimize(root);
viewer->setSceneData(root);
viewer->realize();
viewer->run();
}
运行程序,截图如图8-24所示。
图8-24对象选取示例截图