5
\$\begingroup\$

I wrote a MatrixStack class in C# to use in a SceneGraph. So, to get the world matrix for an object I am suposed to use:

WorldMatrix = ParentWorld * LocalTransform

But, in fact, it only works as expected when I do the other way:

WorldMatrix = LocalTransform * ParentWorld

Mi code is:

public class MatrixStack
{
    Stack<Matrix> stack = new Stack<Matrix>();
    Matrix result = Matrix.Identity;

    public void PushMatrix(Matrix matrix)
    {
        stack.Push(matrix);
        result = matrix * result;
    }

    public Matrix PopMatrix()
    {
        result = Matrix.Invert(stack.Peek()) * result;
        return stack.Pop();
    }

    public Matrix Result
    {
        get { return result; }
    }

    public void Clear()
    {
        stack.Clear();
        result = Matrix.Identity;
    }
}

Why it works this way and not the other? Thanks!

\$\endgroup\$
  • \$\begingroup\$ ...and the problem is? \$\endgroup\$ – Maximus Minimus Jun 25 '13 at 23:58
2
\$\begingroup\$

As previously mentioned, matrix order matters with matrices, be sure to keep it consistent throughout your entire scene graph node update method.

I personally choose to use the order: M = T*R*S, to preserve non-uniform scaling and to preserve rotation in relation to translation.

model = worldTranslate * worldRotate * worldScale;

if(parentNode){
worldTranslate = parentNode->worldTranslate * translateMatrix;
/*
Other matrices here
*/

 } else {
worldTranslate = translateMatrix;
/*
Other matrices here
*/
}

if(!childNodes.empty()){
/*
Recursive update method
*/
}
\$\endgroup\$
2
\$\begingroup\$

The order in which the matrix is represented in memory affects the order of multiplication.

Row/Column-major order

column-major (P*V*M)

row-major (M*V*P)

\$\endgroup\$
  • \$\begingroup\$ Actually Row-Major and Column-Major matrices have the same layout in memory. \$\endgroup\$ – Maik Semder Jun 27 '13 at 10:52
  • \$\begingroup\$ @MaikSemder ok the layout in memory might be the same. What I mean is Pre-multiplication versus Post-multiplication. I had the exact same problem with my own matrix class. I had to swap the order of multiplication to get the desired result because my matrix is in row vector representation. So I needed to use Pre-multiplication. \$\endgroup\$ – redreggae Jun 28 '13 at 22:55
  • \$\begingroup\$ The rest of the answer is fine. Its just not due to a different memory layout, you were implying that in your answer. In memory they look exactly the same. Removing that part would improve your answer. \$\endgroup\$ – Maik Semder Jun 28 '13 at 23:17
2
\$\begingroup\$

Short answer - matrix multiplication is not commutative - A*B != B*A

Slightly longer answer - because matrix operations can be viewed as function compositions and function compositions aren't necessarily commutative - some matrix ops are commutative, say simple addition, but as soon as you add scaling or rotation..........

An even longer answer involves things like rings and I really try and stay away from number theory :-)

\$\endgroup\$
  • 1
    \$\begingroup\$ I would now like the long answer please. \$\endgroup\$ – CodeCamper Jun 26 '13 at 5:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.