Matrix usage

Hi,

I’m confused with matrices, and I can’t figure how to use them.

Example:
I have a point (x=10, y=10).
I want to apply a translation to this point. I want it to move 10 to the right.
I tried:

  
ofMatrix4x4 m;  
m.translate(10, 0, 0);  
ofVec3f v(10, 10, 0);  
v = m * v;  
cout << "x = " << v.x << endl;  
cout << "y = " << v.y << endl;  

Output is:
x = 0.0990099
y = 0.0990099
I expected:
x = 20
y = 10

Does anybody know how to do please ?
Translations aren’t my unique goal of course, I want to apply a serie of transformations to this point, such as a translation followed by a rotation followed by a scaling.

Examples:

  
ofMatrix4x4 m;  
m.translate(10, 0, 0);  
m.scale(2, 1, 1);  
ofVec3f v(10, 10, 0);  
v = m * v;  
cout << "x = " << v.x << endl;  
cout << "y = " << v.y << endl;  
// expected:  
// x = 40 (  (10 + 10) * 2  )  
// x = 10  

  
ofMatrix4x4 m;  
m.translate(10, 0, 0);  
m.scale(2, 1, 1);  
m.rotate(90);  
ofVec3f v(10, 10, 0);  
v = m * v;  
cout << "x = " << v.x << endl;  
cout << "y = " << v.y << endl;  
// expected:  
// x = - 10  
// x = 40  

Thank you.

Hey lilive,

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

  
**ofMatrix.translate() **  

and

  
**ofMatrix.glTranslate()**  

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.

  
ofMatrix4x4 m;  
m.glTranslate(20,0,0);  
m.glRotate(90,0,0,1);  
ofVec3f v(0,0,0);  
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

  
ofMatrix4x4 m;  
m.translate(20,0,0);  
m.rotate(90,0,0,1);  
ofVec3f v(0,0,0);  
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:

  1. reverse your vector-matrix multiplication order
  2. 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

***

Good luck!

6 Likes

Thank you very much for this detailled explanation tgfrerer !
My problem is now solved.
I agree, OF Matrices are tricky if you use the classic math notation (the one I learned).

I use matrices in my current project, to compute texture coords.
I add it to this reply, if you want to see it. For the moment it’s just a little video mapping tool for the webcam. Drag the corners to stretch the video. Bonus: A wave distortion (hit the space key)
This project require:
ofxTweener
ofxXMLSettings
ofxUI
and the data folder content

Thank you again !

v-forum.zip

1 Like

Someone asked for the missing last example. I post it again.
v-forum.zip (32.3 KB)