matrices can be tricky!
One important thing to know about matrices is that their multiplication is not commutative, meaning if you have a Matrix A and a Matrix B the order of how you multiply these makes a difference.
Note that there are two ways to multiply, _pre-_multiplication (b*a) and _post-_multiplication (a*b)
with integers for example,
a*b == b*a
, so pre-and post-multiplication are essentially the same. That’s called “commutative”.
With matrices, however A*B != B*A, and you have to decide whether you want to pre- or _post-_multiply your matrices. Matrix multiplications are non-commutative. And the same holds true for multiplying a vector with a matrix.
Thing is, different frameworks and programming environments have different default multiplication methods for matrices, but they express this operation with the same mathematical symbol (*), which can lead to confusion.
In OpenGL Shader Language (=GLSL), for example, the symbol * is used to express post-multiplication, and so the multiplication order you used would be correct. You would apply your matrices from left to right, as in:
ProjectedVertex = ModelViewProjectionMatrix * v; // where v is a vec4 and ModelViewProjectionMatrix a mat4x4
or v = M * v;
In openFrameworks, however, the symbol * expresses pre-multiplication, and so the multiplication order is the opposite from what you’d expect. Which means, in openFrameworks, matrices mutliplied with the * operator are applied from right to left:
v = v * Matrix;
// or :
ProjectedVertex = v * ModelViewProjectionMatrix;
Here’s some more info on the gory maths of OpenGL matrices: <http://www.songho.ca/opengl/gl-matrix.html>
Also note that openFrameworks has two different ways of applying transformation operations(i.e: translate, rotate, scale) onto ofMatrix:
There is a difference between
The difference being, not hard to guess, the multiplication order of these matrix operations.
If you want to apply and combine your matrices like you did using the openGL matrix stack, I’d recommend using the ofMatrix.gl(*) - versions of the transform methods.
v = v * m;
will first rotate your point 90 degrees, then move it 20 units to the right (leading to: x=20, y=0), whereas
v = v * m;
will first translate your point 20 units to the right and then rotate the coordinate system 90 degrees, leading to x = 0, y= 20.
So, the short answer is:
- reverse your vector-matrix multiplication order
- use ofMatrix::glTranslate(), ofMatrix::glScale() etc instead of ofMatrix()::translate, ofMatrix()::scale of you want to combine transformations like you are used to from OpenGL