标签:
点选主要是重载osg的GUIEventHandler,
1 class CPickHandler : public osgGA::GUIEventHandler{ //自定义回调函数名:CPickHandler 2 osgViewer::Viewer * mViewer; //在这里定义要在重载函数里使用的变量 3 osg::Group * mGroup; 4 osg::Node * lastSelect; 5 osg::Node * replacedNode; 6 int replaceNum; 7 public: 8 CPickHandler(osgViewer::Viewer * viewer, osg::Group *group) :mViewer(viewer),mGroup(group),lastSelect(0),replacedNode(0){} //声明回调函数,括号中是回调函数需要传入的参数,冒号后的内容是给函数内自定义的变量初始化,前面是变量名,括 号内是初始化值。 9 virtual bool handle(const osgGA::GUIEventAdapter & ea, osgGA::GUIActionAdapter & aa){ 10 switch(ea.getEventType()){ 11 case(osgGA::GUIEventAdapter::PUSH):{ 12 if(lastSelect){ 13 lastSelect = 0; 14 } 15 Pick(ea.getX(),ea.getY()); //ea即鼠标点击的地方,ea.getX(),ea.getY(),是获得鼠标点击的屏幕坐标。 16 } 17 return true; 18 } 19 return false; 20 } 21 22 protected: 23 void Pick(float x, float y){}//在pick()函数里传入了鼠标点击的屏幕坐标,然后可以根据屏幕坐标写你想要点击完成的动作。 24 }
其中需要注意的是,OSG中有多个坐标系,我们通过鼠标点击获得的只是屏幕坐标,我们往往需要在场景中添加东西时,都需要得到某个点的世界坐标才能比较好操作:
但是在我们知道是哪个节点的情况下,我们可以根据:
geode->getBound().center() * osg::computeLocalToWorld(geode->getParentalNodePaths()[0])
来获得节点geode的世界坐标。
我的项目的3维模型是由Obj格式导出的ive和osg文件,原始的obj模型是用sketchup做的,在制作的时候把几个模型创建组的时候会给每个模型单独的命名,而在osg中可以通过->getName()获得这些名字,我可以通过用文本浏览器notePad++打开模型的obj文件来查看这些名字,这些名字的命名都是g mash开头的,为了方便,我把每个模型的各个部分的命名改成相同的,用python很好解决这个问题。
那么我的pick函数是这样的:
1 void Pick(float x, float y){ 2 osgUtil::LineSegmentIntersector::Intersections intersections; 3 4 if(mViewer->computeIntersections(x, y, intersections)){ 5 osgUtil::LineSegmentIntersector::Intersection intersection = *intersections.begin(); 6 for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin(); hitr!= intersections.end(); ++hitr){ 7 if(!hitr->nodePath.empty() && !(hitr->nodePath.back()->getName().empty())){ 8 const osg::NodePath& np = hitr->nodePath; 9 10 for(int i = np.size() - 1; i >= 0; --i){ //遍历选中的节点 11 osg::Node* nd = dynamic_cast<osg::Node *> (np[i]); 12 if(nd){ 13 if(nd->getName()=="pipelineTeam1"){ //根据模型的名字判断是否选中了某个模型 14 /* 15 在这儿写对该模型做的操作 16 */ 17 } 18 return; 19 } 20 } 21 } 22 } 23 }
但是,这只是写好了一个回调函数,最后需要在osg控制类(我的是OSG_MFC.cpp)中的void cOSG::InitCameraConfig(void){}函数中加上一句:
mViewer->addEventHandler(new CPickHandler(mViewer, mRoot)); //要把指针转为引用 ,因为mViewer定义的时候是 osgViewer::Viewer* mViewer;现在要使用&mViewer
那么在我们点击屏幕某点的时候,就会自动调用回调函数中的pick()函数,进行其中的操作。
我的项目在pick()回调中,做到了在选中节点的位置添加一个Geometry,在Geometry上显示文字消息,并给选中的模型加上选中效果,可以做成高亮显示和加上高亮的(自定义颜色)的边框,这些会在下一篇文章中介绍。
标签:
原文地址:http://www.cnblogs.com/xiaocainiao2hao/p/4541401.html