查看: 1738|回复: 10

用NodeVisitor获取世界坐标的问题,

[复制链接]

该用户从未签到

发表于 2009-10-30 11:02:59 | 显示全部楼层 |阅读模式
本帖最后由 DancingGhost 于 2009-10-30 16:33 编辑

在场景中加入了一条连续的直线段,想获取最后一条直线段结束端点的世界坐标,却一直出现了问题,请大侠帮我分析分析可以么?源代码在下面

该用户从未签到

发表于 2009-10-30 11:18:09 | 显示全部楼层
请把您的代码缩短到大家可以一眼看清的地步,并且依然能够体现出问题,这样才有助于我们帮助您分析和判断。相信这个缩短代码的过程也会对您有所助益

该用户从未签到

 楼主| 发表于 2009-10-30 11:39:59 | 显示全部楼层
本帖最后由 DancingGhost 于 2009-10-30 16:21 编辑


  1. class WorldCoordOfNodeVisitor :public osg::NodeVisitor
  2. {
  3. public:
  4. WorldCoordOfNodeVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS),done(false)
  5. {
  6.   wMatrix = new osg::Matrix();
  7. }
  8. virtual void apply(osg::Node &node)
  9. {
  10.      if(!done)
  11.      {
  12.   if (node.getName()=="root"){//到达最上层的PositionAttitudeTransform节点
  13.    wMatrix->set(osg::computeLocalToWorld(this->getNodePath()));
  14.    done = true;
  15.    }
  16.   traverse(node);
  17.    }}
  18. osg::Matrix * getMatrix(){return wMatrix;}
  19. private:
  20. bool done;
  21. osg::Matrix *wMatrix;
  22. };
  23. int main()
  24. {
  25. osg::Group *group = new osg::Group();
  26. osg::PositionAttitudeTransform *last,*p= new osg::PositionAttitudeTransform();
  27. p->setName("root"); //设置最上层的PositionAttitudeTransform的Name为“root”,方便在NodeVisitor中使用
  28. group->addChild(p);
  29. for(int i=0;i<5;i++) {//创建一条连续的直线段
  30.   last= new osg::PositionAttitudeTransform();
  31.   last->addChild(createLine(osg::Vec3(0,0,0),osg::Vec3(0,4,4))); //加入直线节点
  32.   last->setPosition(osg::Vec3(0,4,4));
  33.   last->setAttitude(osg::Quat( osg::DegreesToRadians(i*10.0),osg::Vec3(0,1,0)));
  34.   p->addChild(last);
  35.   p = last;
  36. }
  37. osg::Node * line = last->getChild(0);
  38. if (line){ // 获取最末线段的结束端点的世界坐标,并在该坐标位置放置一个球,如果能成功获取到该点的坐标,那么最后球心也应该在此点
  39. WorldCoordOfNodeVisitor nodeVisitor;
  40. line->accept(nodeVisitor);
  41. osg::Vec3 pos = (*nodeVisitor.getMatrix())*osg::Vec3(0,4,4);
  42. p= new osg::PositionAttitudeTransform();
  43. p->addChild(createBall()); //创建一个球节点
  44. p->setPosition(pos); //将球节点移动到最末直线的结束点位置
  45. group->addChild(p);
  46. }
  47.   ...
  48. }
复制代码

谢谢array,
我想这个应该差不多了,没办法再缩了吧,期待回复。

该用户从未签到

发表于 2009-10-30 12:06:25 | 显示全部楼层
获取世界坐标的最快方法是,在遍历到指定节点时获取它的遍历路径NodeVisitor::getNodePath();然后执行osg::computeLocalToWorld()来获取坐标变换矩阵;将局部坐标系的坐标值左乘这个矩阵,结果就是世界坐标了

该用户从未签到

 楼主| 发表于 2009-10-30 14:56:43 | 显示全部楼层
我是这么做的呀,我上面的程序目的描述如下:先创建一条由5条线段组成的连续直线段,然后通过NodeVisitor获得该连续线段的结束点的位置,最后在该节点放置了一个球,但是显示出来的球心并不在该位置,显然是这样计算出来的位置有问题

该用户从未签到

发表于 2009-10-30 15:04:32 | 显示全部楼层
计算思路没有问题,至于您的程序,还是长得很……我只好等什么时候有足够的闲暇才看了

该用户从未签到

 楼主| 发表于 2009-10-30 15:15:21 | 显示全部楼层
谢谢了
长是长了点,但是很简单,不瞒您说,这还是参考了您博客上写的那篇教程。
我还想请教一下,当把NodeVisitor的访问模式设置为TRAVERSE_PARENTS时,在用Node.accept()调用时,会不会把该Node也加入到NodeVisitor的nodePath中呢?

该用户从未签到

 楼主| 发表于 2009-10-30 20:31:39 | 显示全部楼层
急啊,who can help me?

该用户从未签到

 楼主| 发表于 2009-11-2 10:37:31 | 显示全部楼层
各位高手,请帮帮小弟吧

该用户从未签到

发表于 2009-11-2 12:04:56 | 显示全部楼层
  1. osg::Vec3 pos = (*nodeVisitor.getMatrix())*osg::Vec3(0,4,4);
复制代码
别的我暂时没有细看,这一行很可能就有问题。OSG中,
v' = v * M是正确的顶点变换公式,因为v总是行向量;


v' = M * v
这个公式实际上有些迷惑人,它表示:行向量v 乘以 M的转置矩阵。它不是用在顶点变换中的。

至于TRAVERSE_PARENTS,它产生的路径中不会包含当前的节点。不过我不知道您为什么要用它。

该用户从未签到

 楼主| 发表于 2009-11-2 20:00:30 | 显示全部楼层
10# array
果然是牛人啊,非常感谢,谢谢
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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