|
最近做了一个鼠标点击在球面点击位置添加模型的功能,现在要求实现拖拽功能。Pick到球面上的模型的时候模型高亮显示,然后可沿地表拖拽,释放的时候高亮消失,模型拖拽结束,步骤如下:
1、新建一个继承自osgGA::GUIEventHandler的类DragHandle,重载函数handle(),和增加成员函数Pick();
2、在函数handle()中将会判断3个事件,PUSH、DRAG、和RELEASE;
3、先写好Pick()函数的功能,Pick()函数的功能就是求交将所有跟鼠标当前点击点有交集的节点全部保存起来,然后可以遍历这个交集得到一个个的NodePath;然后继续遍历NodePath通过动态转换判断有没有我们要的存放模型的节点。
- void DragHandle::Pick( osgViewer::Viewer* view,float x,float y )
- {
- osgUtil::LineSegmentIntersector::Intersections intersections;
- if (view->computeIntersections(x,y,intersections))
- {
- for ( hitr= intersections.begin();hitr != intersections.end();++hitr)
- {
- if (!hitr->nodePath.empty()&&!(hitr->nodePath.back()->getName().empty()))
- {
- const osg::NodePath& np = hitr->nodePath;
- for (int i = np.size()-1;i>=0;--i)
- {
- node = dynamic_cast<osgEarth::Util::ObjectLocatorNode*>(np[i]);
- if (node)
- {
- if (!(node->getName().empty()))
- {
- std::string _name = node->getName();
- if (_name=="Locator_1")
- {
- _model = node;
- _flag = true;
- }
- }
- }
- }
- }
- }
- }
- }
复制代码
4、如果成功遍历到我们需要的节点以后赋值保存起来,并且赋值信号flag为true;
5、这时候可以再PUSH继续执行判断flag是否为true,是的话高亮显示这个模型;
- if (_flag)
- {
- osgFX::Scribe* sc = new osgFX::Scribe;
- sc->addChild(_model);
- sc->setNodeMask(1);
- manager->addChild(sc);
- }
复制代码
6、然后判断拖拽事件,在拖拽事件当中,实时获得鼠标的当前位置转换成经纬度,然后得到我们保存的存放模型的ObjectLocatorNode节点的定位器将每一帧鼠标的位置设置给定位器_model->getLocator()->setPosition(osg::Vec3d(lon,lat,hig));
7、判断RELEASE,如果鼠标释放,删除高亮显示的节点,将保存模型的指针置空,flag赋值为false;拖拽完毕
需要注意的一点是,在事件队列当中拖拽操作,会跟earth操作器的拖拽都执行,会出现你拖模型的时候地球也在跟着被拖动,这个只需要你将handle()中的返回值return true就行了,事件队列到这儿将不再传递。
新人拙作,不喜勿喷....
|
|