查看: 3037|回复: 8

求助:用Matrix变换移动后的模型,Dragger拖动时出问题了

[复制链接]

该用户从未签到

发表于 2013-8-16 10:10:37 | 显示全部楼层 |阅读模式
本帖最后由 vinsonxp 于 2013-8-19 10:07 编辑

我的场景由好几个模型文件构成,包括有机器人模型(flt文件)和几个加工工件(osg文件),出于场景布局,我先用osg::Matrix::translate对某些模型进行了移动,结果出现了拖动(dragger)的那个坐标标志出现问题了,它没有与模型在一起,而是在没有移动前的哪个地方,而没有移动过的其他模型的Dragger坐标标志正常。
下图红色的哪个模型是是移动过的,Dragger坐标标志不正常

draggererr.png

我是先用osg::ref_ptr<osg::Node>obj = osgDB::readNodeFile把模型从文件读入来,然后再把模型加到osg::ref_ptr<osg::MatrixTransform>,变换后:
        osg::Matrix newMatrix = osg::Matrix::translate(tonodeHeight);
        newMatrix.preMult(oldMatrix);
        mtPutnode->setMatrix(newMatrix);
再添加到根场景中的。拖动功能的代码如下:
  1. void PickDragHandler::pick(osgViewer::Viewer* viewer, const osgGA::GUIEventAdapter& ea, int interMode)
  2. {
  3.         osg::ref_ptr<osg::Node> node = new osg::Node();
  4.         osg::ref_ptr<osg::Group> parent = new osg::Group();

  5.         double x=ea.getX();
  6.         double y=ea.getY();
  7. /*方法1        */
  8.     //osgUtil::PolytopeIntersector* picker= new osgUtil::PolytopeIntersector(osgUtil::Intersector::WINDOW, x-0.5, y-0.5, x+0.5, y+0.5 );//多边形求交法
  9.         osgUtil::LineSegmentIntersector* picker= new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW,x,y);
  10.         osgUtil::IntersectionVisitor iv(picker);
  11.         viewer->getCamera()->accept(iv);

  12.         if(picker->containsIntersections())
  13.         {
  14.                 osg::NodePath& nodePath=picker->getFirstIntersection().nodePath;
  15.                 unsigned int idx=nodePath.size();
  16.                 while(idx--)
  17.                 {
  18.                         osg::MatrixTransform* mt=dynamic_cast<osg::MatrixTransform*>(nodePath[idx]);
  19.                         if(mt==NULL) continue;
  20.                         int cn = mt->getNumChildren();
  21.                         std::string str = mt->getName();
  22.                         if (str=="") continue;
  23.                         if (str=="Robot")
  24.                         {
  25.                                 AfxMessageBox(_T("机器人不允许移动"));
  26.                                 return;
  27.                         }
  28.                         switch(ea.getButton())
  29.                         {
  30.                         case osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON:
  31.                                 {
  32.                                         if(selectedObject.valid())
  33.                                         {
  34.                                                 unselectObj();
  35.                                         }
  36.                                         selectObj(mt);
  37.                                         break;
  38.                                 }
  39.                         case osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON:
  40.                                 if(selectedObject==NULL) return;
  41.                                 unselectObj();
  42.                                 break;
  43.                         }
  44.                         return;
  45.                 }
  46.         }
  47.         else if (selectedObject!=NULL)
  48.                 unselectObj();
复制代码
  1. void PickDragHandler::selectObj(osg::ref_ptr<osg::MatrixTransform> obj)
  2. {
  3.         selection->addChild(obj.get());

  4.         osg::Node::ParentList parentList=obj->getParents();
  5.         for(osg::Node::ParentList::iterator itr=parentList.begin();
  6.                 itr!=parentList.end();
  7.                 itr++
  8.                 )
  9.         {
  10.                 if(*itr!=selection.get())
  11.                 {
  12.                         (*itr)->replaceChild(obj.get(), selection.get());
  13.                 }
  14.         }

  15.         sethighlight(obj);//设置高亮显示

  16.         float scale = obj->getBound().radius() * 1.6;
  17.         dragger->setMatrix(osg::Matrix::scale(scale, scale, scale) *
  18.                 osg::Matrix::translate(obj->getBound().center()));
  19.         selectedObject = obj;
  20.         sceneRoot->addChild(dragger.get());
  21.         cmdMgr->connect((*dragger.get()), (*selection.get()));
  22. }

  23. void PickDragHandler::unselectObj(bool flag)
  24. {
  25.         osg::Node::ParentList parentList=selection->getParents();

  26.         cleanhighlight(selectedObject->getChild(0));//取消高亮显示

  27.         /*变换选中模型的矩阵,实现移动*/
  28.         osg::Matrix mSelection=selection->getMatrix();
  29.         osg::Matrix mObject=selectedObject->getMatrix();
  30.         mObject.preMult(mSelection);
  31.         selectedObject->setMatrix(mObject);

  32.         //获取节点坐标
  33.         osg::Matrixd pos = selectedObject->getMatrix();
  34.         double x = pos.getTrans().x();
  35.         double y = pos.getTrans().y();
  36.         double z = pos.getTrans().z();

  37.         for(osg::Node::ParentList::iterator itr=parentList.begin();
  38.                 itr!=parentList.end();
  39.                 itr++
  40.                 )
  41.         {
  42.                 (*itr)->replaceChild(selection.get(), selectedObject.get());
  43.         }
  44.         osg::Matrix identity;
  45.         selection->setMatrix(identity);
  46.         selection->removeChildren(0, selection->getNumChildren());
  47.         selectedObject=NULL;
  48.         sceneRoot->removeChild(dragger.get());
  49. }
复制代码
拜托各位帮忙找找原因,先谢了!

该用户从未签到

 楼主| 发表于 2013-8-19 09:47:49 | 显示全部楼层
怎么没有人回应呢?

该用户从未签到

发表于 2013-8-19 12:06:04 | 显示全部楼层
看看是不是 获得的那个Node的 center是相对于它的父节点坐标系下的,而不是相对于世界坐标系的

该用户从未签到

 楼主| 发表于 2013-8-19 15:31:24 | 显示全部楼层
我把selectObj函数中的dragger->setMatrix(osg::Matrix::scale(scale, scale, scale) *
                osg::Matrix::translate(obj->getBound().center()));
修改成
        osg::Matrix mt = getWorldCoords(obj.get());

        float scale = obj->getBound().radius() * 1.6;
        dragger->setMatrix(osg::Matrix::scale(scale, scale, scale) *
                osg::Matrix::translate(osg::Vec3(mt.getTrans().x(),mt.getTrans().y(),mt.getTrans().z())) /*obj->getBound().center())*/);
其中:
osg::Matrixd getWorldCoords(osg::ref_ptr<osg::Node> node)
{
        osg::NodePath& nodepath = node->getParentalNodePaths()[0];
        osg::Matrixd mat = computeLocalToWorld(nodepath);
        return mat;
}
现象还是一样呀。不知道这样改,是不是相对于世界坐标系的中心。

该用户从未签到

 楼主| 发表于 2013-8-21 10:01:28 | 显示全部楼层
还没有解决!

该用户从未签到

 楼主| 发表于 2014-2-14 11:28:19 | 显示全部楼层
终于知道了,可以直接把Node转换成MatrixTransform然后再移动就没有问题了。
osg::ref_ptr<osg::Node>obj = osgDB::readNodeFile;
obj->asTransform()->asMatrixTransform()->setMatrix(osg::Matrix::translate(x,yz));

该用户从未签到

发表于 2015-5-17 20:07:57 | 显示全部楼层
时间跨度好长啊,关于拖拽部分的完整代码,能不能借鉴下

该用户从未签到

发表于 2015-5-29 15:03:10 | 显示全部楼层
明明就是对拖拽器理解不够深刻呀

该用户从未签到

发表于 2017-8-16 19:38:39 | 显示全部楼层
请问这个求得的x,y,z鼠标点击时的世界坐标吗还是什么坐标?
另外请教一下,boxdragger怎么获得外边的box大小?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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