查看: 2540|回复: 14

求助请教世界坐标问题

[复制链接]

该用户从未签到

发表于 2012-6-9 20:50:42 | 显示全部楼层 |阅读模式
class getWorldCoordOfNodeVisitor : public osg::NodeVisitor
{
public:
        getWorldCoordOfNodeVisitor():
          osg::NodeVisitor(NodeVisitor::TRAVERSE_PARENTS), done(false)
          {
                  wcMatrix= new osg::Matrixd();
          }
          virtual void apply(osg::Node &node)
          {
                  if (!done)
                  {
                          if ( 0 == node.getNumParents() ) //到达根节点,此时节点路径也已记录完整
                          {
                                  wcMatrix->set( osg::computeLocalToWorld(this->getNodePath()) );
                                  done = true;
                          }
                          traverse(node);
                  }
          }
          osg::Matrixd* giveUpDaMat()
          {
                  return wcMatrix;
          }
private:
        bool done;
        osg::Matrix* wcMatrix;
};


osg::Matrixd* getWorldCoords( osg::Node* node)
{
        getWorldCoordOfNodeVisitor* ncv = new getWorldCoordOfNodeVisitor();
        if (node && ncv)
        {
                node->accept(*ncv);
                return ncv->giveUpDaMat();
        }
        else
        {
                return NULL;
        }
}

void main()
{
    osgViewer::Viewer viewer;
        osg::ref_ptr <osg::Group> root = new osg::Group() ;

        osg::ref_ptr<osg::Node> osgcool = osgDB::readNodeFile("cessna.osg") ;

        osg::ref_ptr<osg::MatrixTransform> trans = new osg::MatrixTransform ;
        trans ->setMatrix(osg::Matrix::translate(0, 0, 10)) ;
        trans ->addChild(osgcool.get()) ;
       
        osg::ref_ptr<osg::MatrixTransform> scale = new osg::MatrixTransform ;
        scale ->setMatrix(osg::Matrix::scale(0.5,0.5,0.5)*osg::Matrix::translate(0, 0, -50)) ;
        scale ->addChild(osgcool.get()) ;

        root ->addChild(osgcool.get()) ;
        root ->addChild(trans.get()) ;
        root ->addChild(scale.get()) ;
                //遍历世界坐标
        osg::Matrixd *pmatrix0 = getWorldCoords(osgcool);
        osg::Vec3 pVec0 = pmatrix0->getTrans();
       
        osg::Matrixd *pmatrix1 = getWorldCoords(trans);
        osg::Vec3 pVec1 = pmatrix1->getTrans();
       
        osg::Matrixd *pmatrix2 = getWorldCoords(scale);
        osg::Vec3 pVec2 = pmatrix2->getTrans();


        viewer.setSceneData(root.get());
    viewer.realize();
    viewer.run();
}

/*
程序当中       
osg::Matrixd *pmatrix0 = getWorldCoords(osgcool);
osg::Vec3 pVec0 = pmatrix->getTrans();

osg::Matrixd *pmatrix1 = getWorldCoords(trans);
osg::Vec3 pVec1 = pmatrix1->getTrans();

osg::Matrixd *pmatrix2 = getWorldCoords(scale);
osg::Vec3 pVec2 = pmatrix2->getTrans();

为什么pVec0和pVec1数值一样呢,即为什么pmatrix0和pmatrix1数值一样呢
我的理解应该是pmatrix0是单位矩阵,即pVec0是(0,0,0)
现在的结果是pVec0和pVec1都是(0,0,10),pVec2是(0,0,-50)。

*/

该用户从未签到

 楼主| 发表于 2012-6-10 09:35:50 | 显示全部楼层
自己顶一个,,,,,

该用户从未签到

发表于 2012-6-11 13:41:06 | 显示全部楼层
您得到的是从局部坐标系到世界坐标系的变换矩阵
从osgcool经由trans变换到世界,和直接从trans变换到世界,这结果是一样的

该用户从未签到

 楼主| 发表于 2012-6-11 23:23:01 | 显示全部楼层
array 发表于 2012-6-11 13:41
您得到的是从局部坐标系到世界坐标系的变换矩阵
从osgcool经由trans变换到世界,和直接从trans变换到世界, ...

但是 osgcool也经过矩阵scale变换,他为什么输出的不是scale的值呢

该用户从未签到

发表于 2012-6-12 10:29:17 | 显示全部楼层
您这里其实osgcool有两个父节点:trans,scale,而getWorldCoords()默认只是遍历第一个父节点的路径,也就是trans

该用户从未签到

 楼主| 发表于 2012-6-12 20:02:21 | 显示全部楼层
array 发表于 2012-6-12 10:29
您这里其实osgcool有两个父节点:trans,scale,而getWorldCoords()默认只是遍历第一个父节点的路径,也就是 ...

root ->addChild(osgcool.get()) ;
root ->addChild(trans.get()) ;
root ->addChild(scale.get()) ;
我程序中不是添加了三个节点么,并且osgcool是在场景中心,他的父节点应该只是root啊,(而其他两个节点的一级父节点才是trans和scale,再上一级父节点才是root)。。。对不对

该用户从未签到

 楼主| 发表于 2012-6-15 22:20:05 | 显示全部楼层
array 发表于 2012-6-12 10:29
您这里其实osgcool有两个父节点:trans,scale,而getWorldCoords()默认只是遍历第一个父节点的路径,也就是 ...

root ->addChild(osgcool.get()) ;
root ->addChild(trans.get()) ;
root ->addChild(scale.get()) ;
我程序中不是添加了三个节点么,并且osgcool是在场景中心,他的父节点应该只是root啊,(而其他两个节点的一级父节点才是trans和scale,再上一级父节点才是root)。。。对不对

该用户从未签到

发表于 2012-6-20 12:56:52 | 显示全部楼层
我刚刚才发现原来您用的是自己的函数来获取过渡矩阵,而非我一直下意识认为的getWorldMatrices。我想您还是看一下osg自己的TransformVisitor是如何实现父节点path的收集的(事实上每次遍历都会对一个统一的_matrix进行累积)。我觉得您直接在最后获取nodePath的方法可能有些问题,打印一些调试信息吧,看看nodePath到底包含了什么

喔,一个重要的信息也许会对您有帮助:如果您是在viewer.setSceneData()之后执行这段程序的话,那么root节点的getNumParents()并不是0,至少是1(场景主相机)

该用户从未签到

 楼主| 发表于 2012-6-20 19:53:47 | 显示全部楼层
array 发表于 2012-6-20 12:56
我刚刚才发现原来您用的是自己的函数来获取过渡矩阵,而非我一直下意识认为的getWorldMatrices。我想您还是 ...

恩代码我会看的~
但是如果是对一个_matrix进行积累,那怎么node得打的只是 第一次父节点的转换矩阵
再者 这段代码 我是完全搬过来的书上的 海军那本书和肖鹏那本书上都有
我一点没改。。。

该用户从未签到

 楼主| 发表于 2012-6-20 19:57:48 | 显示全部楼层
array 发表于 2012-6-20 12:56
我刚刚才发现原来您用的是自己的函数来获取过渡矩阵,而非我一直下意识认为的getWorldMatrices。我想您还是 ...

恩代码我会看的~
但是如果是对一个_matrix进行积累,我理解的意思是只要对node进行操作过,就会在_matrix中进行积累,对不对
那怎么node得到的只是 第一次父节点的转换矩阵,而其他父节点对他根本没用,比方说本问题的 scale父节点 对node进行遍历时,scale好像不存在似的,但是你以前又说只是第一个父节点起作用,这是不是矛盾?
再者 这段代码 我是完全搬过来的书上的 海军那本书和肖鹏那本书上都有
我一点没改。。。
我先看代码还是

该用户从未签到

发表于 2012-6-21 09:21:25 | 显示全部楼层
maxix的积累没有问题,computeLocalToWorld也没有问题
您现在的问题是,nodePath是否得到了正确的结果,或者说是否得到了您想要的结果
调试是最快的确定问题的手段,看书没有意义

该用户从未签到

发表于 2012-6-21 11:21:47 | 显示全部楼层
本帖最后由 CWorld 于 2012-6-21 11:25 编辑

lz你好,正好这个问题我以前也有疑问,我帮你测试过了。好像是这样的,

对于场景树
      root

          tran   scale
         
osgcool

对于 osgcool ,如果输出打印,确实是只打印一条父节点的路径:及 root  --- >  tran --> osgcool

对于 tran 父节点路径为: root ---> tran
对于 scale 父节点路径为: root --->scale

那么对于 osg::computeLocalToWorld(this->getNodePath());

它里面计算的时候,仍然调用的是“ TransformVisitor” 节点访问器,TransformVisitor只重载了Transform节点的访问方式。

即  apply(osg::Transform * node)
  {
   }

对于osg的节点, MatrixTransform 节点继承自Transform节点。
  那么在计算 MatrixTransform节点时,
  调用MatrixTransform的computeLocalToWorld()方法,
  进行了matrix的累积连成,
{
  matrix.premult(_matrix);
};

这样考虑结果就是合理的,
对于osgcool节点,   只有tran参与实际的运算, 即matrixTranform,即变换结果是有 0,0,10;
对于tran节点, 仍然是只有 0  0  10
对于scale节点, 只有 0 0 -50

该用户从未签到

 楼主| 发表于 2012-6-21 22:20:19 | 显示全部楼层
CWorld 发表于 2012-6-21 11:21
lz你好,正好这个问题我以前也有疑问,我帮你测试过了。好像是这样的,

对于场景树

恩 我明白您的 意思了  
非常感谢
但是我怎么总是掉不过弯来:
我始终觉得 场景中的节点数应该是这样的:
osgcool在场景中的结构是:root-》osgcool

trans。。。。。。。。。:root->trans->osgcool
scale。。。。。。。。。:root->scale->osgcool
求解释

该用户从未签到

 楼主| 发表于 2012-6-21 22:51:15 | 显示全部楼层
buaahc 发表于 2012-6-21 22:20
恩 我明白您的 意思了  
非常感谢
但是我怎么总是掉不过弯来:

我的意思是场景中有三个osgcool 模型,所以肯定有三条路径啊。。。
我说的应该没错吧
但为什么打印会只是打印 trans那一条呢。。。

该用户从未签到

发表于 2012-6-25 10:27:37 | 显示全部楼层
因为默认只遍历第一条父节点路径
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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