查看: 1380|回复: 1

添加到球面上的模型实现沿地形拖拽功能

[复制链接]

该用户从未签到

发表于 2014-5-9 10:38:45 | 显示全部楼层 |阅读模式
最近做了一个鼠标点击在球面点击位置添加模型的功能,现在要求实现拖拽功能。Pick到球面上的模型的时候模型高亮显示,然后可沿地表拖拽,释放的时候高亮消失,模型拖拽结束,步骤如下:
1、新建一个继承自osgGA::GUIEventHandler的类DragHandle,重载函数handle(),和增加成员函数Pick();
2、在函数handle()中将会判断3个事件,PUSH、DRAG、和RELEASE;
3、先写好Pick()函数的功能,Pick()函数的功能就是求交将所有跟鼠标当前点击点有交集的节点全部保存起来,然后可以遍历这个交集得到一个个的NodePath;然后继续遍历NodePath通过动态转换判断有没有我们要的存放模型的节点。
  1. void DragHandle::Pick( osgViewer::Viewer* view,float x,float y )
  2. {
  3.         osgUtil::LineSegmentIntersector::Intersections intersections;
  4.         if (view->computeIntersections(x,y,intersections))
  5.         {
  6.                 for ( hitr= intersections.begin();hitr != intersections.end();++hitr)
  7.                 {
  8.                         if (!hitr->nodePath.empty()&&!(hitr->nodePath.back()->getName().empty()))
  9.                         {
  10.                                 const osg::NodePath& np = hitr->nodePath;
  11.                                 for (int i = np.size()-1;i>=0;--i)
  12.                                 {
  13.                                         node = dynamic_cast<osgEarth::Util::ObjectLocatorNode*>(np[i]);
  14.                                         if (node)
  15.                                         {
  16.                                                 if (!(node->getName().empty()))
  17.                                                 {
  18.                                                         std::string _name = node->getName();
  19.                                                         if (_name=="Locator_1")
  20.                                                         {
  21.                                                                 _model = node;
  22.                                                                 _flag = true;
  23.                                                         }
  24.                                                 }
  25.                                         }
  26.                                 }
  27.                         }
  28.                 }
  29.         }
  30. }
复制代码

4、如果成功遍历到我们需要的节点以后赋值保存起来,并且赋值信号flag为true;
5、这时候可以再PUSH继续执行判断flag是否为true,是的话高亮显示这个模型;
  1. if (_flag)
  2.                                {
  3.                                         osgFX::Scribe* sc = new osgFX::Scribe;
  4.                                         sc->addChild(_model);
  5.                                         sc->setNodeMask(1);
  6.                                         manager->addChild(sc);
  7.                                 }
复制代码

6、然后判断拖拽事件,在拖拽事件当中,实时获得鼠标的当前位置转换成经纬度,然后得到我们保存的存放模型的ObjectLocatorNode节点的定位器将每一帧鼠标的位置设置给定位器_model->getLocator()->setPosition(osg::Vec3d(lon,lat,hig));

7、判断RELEASE,如果鼠标释放,删除高亮显示的节点,将保存模型的指针置空,flag赋值为false;拖拽完毕

需要注意的一点是,在事件队列当中拖拽操作,会跟earth操作器的拖拽都执行,会出现你拖模型的时候地球也在跟着被拖动,这个只需要你将handle()中的返回值return true就行了,事件队列到这儿将不再传递。


新人拙作,不喜勿喷....

该用户从未签到

发表于 2014-5-12 16:26:20 | 显示全部楼层
看看drager
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表