2011-07-12 77 views
2

我已经实现了一个由OpenGL渲染的小场景图,所有对象都来自一个普通的Node类,在OpenGL帧渲染期间,我只是调用了根节点的visit方法,并且它遍历了图递归。开始遍历时,第一个矩阵是摄像机矩阵。3D场景图遍历问题

visit方法是这样的:

void Node::visit(const QMatrix4x4 &mv) { 
    QMatrix4x4 m = mv; 
    m.rotate(m_rot); 
    m.translate(m_pos); 
    m.scale(m_scale); 

    m_effectiveMV = m; 

    for (int i = 0; i < m_children.size(); i++) { 
     m_children[i]->visit(m_effectiveMV); 
    } 

    draw(); // draws if this node has anything to draw, 
      // otherwise just transformation. 
} 

的问题,我的经验是,当我一个子节点设置旋转,旋转恰好相对于父节点,而不是周围的节点本身。任何人都可以发现我在这里做错了吗?

+0

我认为这是这样的:一个男人拿着枪,枪围绕着男人转动,而不是在自己的起源“转向”。它是否正确? – ssell

+0

是的,就是这样。 – rgngl

回答

5

假设你的矩阵方法做正确的事,翻译应该是在列表中的第一个:

m.translate(m_pos); 
m.rotate(m_rot); 
m.scale(m_scale); 

这将第一缩放和旋转顶点,然后等翻译成家长制。

+0

这样做似乎可以修复旋转轴问题,但随后它完全混乱了我的相机位置。当我已经将相机放入(0,0,8)并且根节点处于相同位置时,它仍然看起来像物体在相机位置前8个单位。我正在检查QMatrix4x4源代码(http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/math3d/qmatrix4x4.cpp),看看它是否做了任何讨厌的事情,但我没有发现任何东西奇怪的。 – rgngl

+0

你能以某种方式发布你的空间层次吗?很难说出你的结局是怎么回事。 – kvark

+0

我原来是一个总noob,并意识到我构造默认构造函数中的默认旋转为QQuaternion(0,0,0,1),因为我没有完全知道四元数是如何工作的。在使用QQuaternion :: fromAxisAndAngle初始化四元数后,一切正常。并再次感谢有关转换顺序的建议。 – rgngl

3

矩阵运算是不可交换的,即矩阵乘法发生的顺序很重要。首先旋转某个东西,然后翻译它,不同于先旋转然后围绕原始中心旋转/旋转。

而不是通过连续应用各种转换创建转换,我建议直接构建它。左上角的3×3是旋转部分,可以直接从旋转矩阵中复制。缩放将x,y,z因子乘以矩阵的第1列,第2列和第3列。翻译是第四列。旋转或者存储为3×3矩阵或者四元数。不要使用欧拉角,它们在数值上不稳定。