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\$
1
  • \$\begingroup\$ ...and the problem is? \$\endgroup\$ Commented Jun 25, 2013 at 23:58

3 Answers 3

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\$
3
  • \$\begingroup\$ Actually Row-Major and Column-Major matrices have the same layout in memory. \$\endgroup\$ Commented Jun 27, 2013 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
    Commented Jun 28, 2013 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\$ Commented Jun 28, 2013 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
  • 1
    \$\begingroup\$ I would now like the long answer please. \$\endgroup\$
    – CodeCamper
    Commented Jun 26, 2013 at 5:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .