2011-07-12 1 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); 

この意志第1のスケールと頂点を回転させ、その後、というように両親システムに翻訳。

+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番目の列に掛けます。翻訳は第4列です。回転は、3×3行列または四元数として格納されます。オイラー角を使用しないでください。数値的に不安定です。