I have implemented a small scene graph to be rendered by OpenGL, all the objects derive from a common Node
class and during OpenGL frame rendering I just call the visit
method of the root node and it traverses the graph recursively. The first matrix I pass when beginning traversal is the camera matrix.
The visit
method looks like this:
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++) {
开发者_Go百科 m_children[i]->visit(m_effectiveMV);
}
draw(); // draws if this node has anything to draw,
// otherwise just transformation.
}
The problem I experience is, when I set rotation for a child node, the rotation happens relative to the parent node, not around the node itself. Can anyone spot what I'm doing wrong here?
Assuming your matrix methods are doing the right thing, translation should be the first one in the list:
m.translate(m_pos);
m.rotate(m_rot);
m.scale(m_scale);
This will first scale and rotate the vertex, then translate it into the parents system and so on.
Matrix operations are not commutative, i.e. the order in which matrix multiplication happens does matter. Rotating something first, then translate it, is different to first translating and then rotate/orbit around the original center.
Instead of creating the transformation by successive application of various transformations I recommend building it directly. The upper left 3×3 is the rotation part, which you can copy directly from the rotation matrix. Scaling multiplies x,y,z factors to the 1st, 2nd and 3rd column of the matrix. Translation is the 4th column. The rotation is either stored as a 3×3 matrix or a quaternion. Don't use Euler angles, they are numerically instable.
精彩评论