Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: Matrix composition

  1. #1
    Junior Member Regular Contributor Lucretia's Avatar
    Join Date
    Mar 2000
    Location
    Leeds, West Yorkshire, England
    Posts
    117

    Matrix composition

    Hi,

    I've just started getting back into OpenGL and have started to write some matrix functions. I decided to separate out the 4x4 matrix into a 3x3 matrix for rotation and scale and use a 3 vector for the translation. Now, I worked out the proof that I needed to compose this into a 4x4 matrix.

    Given that a 4x4 matrix is composed thus:

    Code :
         |M|T|
    M1 = -----
         |0|1|
    Where M1 is a 3x3 matrix and T is a column vector representing the translation.

    This is the formula for multiplying 2 4x4 matrices:

    Code :
        |m0 m4 m8  m12|     |t0 t4 t8  t12|
    M = |m1 m5 m9  m13| T = |t1 t5 t9  t13|
        |m2 m6 m10 m14|     |t2 t6 t10 t14|
        |m3 m7 m11 m15|     |t3 t7 t11 t15|
     
         |(m0t0 + m4t1 + m8t2  + m12t3) (m0t4 + m4t5 + m8t6  + m12t7) (m0t8 + m4t9 + m8t10  + m12t11) (m0t12 + m4t13 + m8t14  + m12t15)|
    MT = |(m1t0 + m5t1 + m9t2  + m13t3) (m1t4 + m5t5 + m9t6  + m13t7) (m1t8 + m5t9 + m9t10  + m13t11) (m1t12 + m5t13 + m9t14  + m13t15)|
         |(m2t0 + m6t1 + m10t2 + m14t3) (m2t4 + m6t5 + m10t6 + m14t7) (m2t8 + m6t9 + m10t10 + m14t11) (m2t12 + m6t13 + m10t14 + m14t15)|
         |(m3t0 + m7t1 + m11t2 + m15t3) (m3t4 + m7t5 + m11t6 + m15t7) (m3t8 + m7t9 + m11t10 + m15t11) (m3t12 + m7t13 + m11t14 + m15t15)|
    So, substituting:

    Code :
    Proof 1:
     
    |m0 m4 m8  0|   |1 0 0 t0|
    |m1 m5 m9  0| * |0 1 0 t1| =
    |m2 m6 m10 0|   |0 0 1 t2|
    |0  0  0   1|   |0 0 0 1 |
     
    |(m0(1)  + m4(0)  + m8(0)  + (0)(0)) (m0(0)  + m4(1)  + m8(0)  + (0)(0)) (m0(0)  + m4(0)  + m8(1)  + (0)(0)) (m0t0  + m4t1  + m8t2  + (0)(0))|
    |(m1(1)  + m5(0)  + m9(0)  + (0)(0)) (m1(0)  + m5(1)  + m9(0)  + (0)(0)) (m1(0)  + m5(0)  + m9(1)  + (0)(0)) (m1t0  + m5t1  + m9t2  + (0)(0))| =
    |(m2(1)  + m6(0)  + m10(0) + (0)(0)) (m2(0)  + m6(1)  + m10(0) + (0)(0)) (m2(0)  + m6(0)  + m10(1) + (0)(0)) (m2t0  + m6t1  + m10t2 + (0)(0))|
    |((0)(1) + (0)(0) + (0)(0) + (1)(0)) ((0)(0) + (0)(1) + (0)(0) + (1)(0)) ((0)(0) + (0)(0) + (0)(1) + (1)(0)) ((0)t0 + (0)t1 + (0)t2 + (1)(1))|
     
    |(m0) (m4) (m8 ) (m0t0  + m4t1 + m8t2 )|
    |(m1) (m5) (m9 ) (m1t0  + m5t1 + m9t2 )|
    |(m2) (m6) (m10) (m2t0  + m6t1 + m10t2)|
    |(0 ) (0 ) (0  ) (1                   )|
    And, now if I multiply a 3x3 matrix with a 3 vector:

    Code :
    Proof 2:
     
    |m0 m4 m8 |   |t0|
    |m1 m5 m9 | * |t1| =
    |m2 m6 m10|   |t2|
     
    |m0t0 + m4t1 + m8t2 |
    |m1t0 + m5t1 + m9t2 |
    |m2t0 + m6t1 + m10t2|
    So, proof 2 is the same as the translation part of the matrix in proof 1, hence to compose a 4x4 matrix from a 3x3 and a vector, the final formula is:

    Code :
         |M|MT|
    M2 = ------
         |0|1 |
    Now, from my code, this doesn't quite work out. Yet, if I don't multiply the translation by the 3x3 matrix when I compose the 4x4, everything is fine, yet I don't quite understand why this works?

    I have seen a post on here that noted that M1 is equal to a rotation followed by a translation, and M2 is the opposite. But, surely if this were correct, M2 would work as expected, yet it doesn't; it's almost as though the triangle I'm rotating is being sheared.

    Can somebody shed some light on this problem?

    Thanks,
    Luke.
    Luke A. Guest

  2. #2
    Advanced Member Frequent Contributor plasmonster's Avatar
    Join Date
    Mar 2004
    Posts
    739

    Re: Matrix composition

    Be mindfull of the row, column order you're using. Remember, the reverse order law of transposition says that
    A^t B^t = (BA)^t, where ^t is transposition.
    My hunch is that you're ending up with the transpose, or reverse transpose, of what you want, hence the shearing.

  3. #3
    Junior Member Regular Contributor Lucretia's Avatar
    Join Date
    Mar 2000
    Location
    Leeds, West Yorkshire, England
    Posts
    117

    Re: Matrix composition

    Originally posted by RadicalHumility:
    Be mindfull of the row, column order you're using. Remember, the reverse order law of transposition says that
    A^t B^t = (BA)^t, where ^t is transposition.
    My hunch is that you're ending up with the transpose, or reverse transpose, of what you want, hence the shearing.
    Yes, but the numbering I've used in the examples, is the correct order for OpenGL, i.e. m0->m15 is an array like:

    Code :
    GLfloat mtx[16];
    Luke.
    Luke A. Guest

  4. #4
    Junior Member Regular Contributor Lucretia's Avatar
    Join Date
    Mar 2000
    Location
    Leeds, West Yorkshire, England
    Posts
    117

    Re: Matrix composition

    Here's the code (in Ada) that I'm using:

    Code :
      procedure Compose(Result : out Object; Left : in Vector3.Object; Right : in Matrix3x3.Object) is
     
        MT : Vector3.Object;
     
      begin
     
        Matrix3x3.Mul(MT, Right, Left);
     
        Result(0)  := Right(0);
        Result(1)  := Right(1);
        Result(2)  := Right(2);
        Result(3)  := 0.0;
        Result(4)  := Right(3);
        Result(5)  := Right(4);
        Result(6)  := Right(5);
        Result(7)  := 0.0;
        Result(8)  := Right(6);
        Result(9)  := Right(7);
        Result(10) := Right(8);
        Result(11) := 0.0;
        Result(12) := MT.X;
        Result(13) := MT.Y;
        Result(14) := MT.Z;
        Result(15) := 1.0;
     
      end Compose;
    Now, if I don't multiply the matrix and translation together and just pass T insteasd of MT into the translation column, it works fine.

    I just don't understand why the code I would've expected to work (going by the proofs), doesn't.

    Thanks,
    Luke.
    Luke A. Guest

  5. #5
    Advanced Member Frequent Contributor plasmonster's Avatar
    Join Date
    Mar 2004
    Posts
    739

    Re: Matrix composition

    Have you tried a reverse transpose? I'm not sure about your code, but I am sure that matrix multiplication with gl works correctly. There is a disturbing trend with some in the graphics community to bend the universe around the gl. Do your math the way its done in nearly every text, then do a transpose before you send it to gl. This might save you alot of headache.

  6. #6
    Senior Member OpenGL Pro
    Join Date
    May 2000
    Location
    Naarn, Austria
    Posts
    1,102

    Re: Matrix composition

    I don't think there is something wrong with your calculations. Your Proof 1 shows what happens if you call first glRotate and then glTranslate, meaning you first Translate and then Rotate. Remember if you want to transform objects you have to reverse the operations.

    Another way to look at it would be to transform not the objects but the local coordinate frame...

  7. #7
    Junior Member Regular Contributor Lucretia's Avatar
    Join Date
    Mar 2000
    Location
    Leeds, West Yorkshire, England
    Posts
    117

    Re: Matrix composition

    Originally posted by Overmind:
    I don't think there is something wrong with your calculations. Your Proof 1 shows what happens if you call first glRotate and then glTranslate, meaning you first Translate and then Rotate.
    Yes, but this isn't what is happening when I use that version of the Compose function. I would expect to see the object rotate around *me*, current'y I'm seeing nothing at all

    Luke.
    Luke A. Guest

  8. #8
    Advanced Member Frequent Contributor plasmonster's Avatar
    Join Date
    Mar 2004
    Posts
    739

    Re: Matrix composition

    Let's back up a tad and make sure we're on the same page. When you call MultMatrix(), you are concatenating a matrix with the current gl matrix:
    M = I,
    M = M * YourMatrix,
    M = M * YourMatrix2,
    ...
    Or, in general,
    M' = I * M1 * M2 * ... * Mn.
    When you transforma a point with this matrix, you have:
    P' = ( I * M1 * (M2 * ... * (Mn * P))).
    As you can see, the transformations will be applied in the reverse order. If you understand this, you should be good to go.

  9. #9
    Junior Member Regular Contributor Lucretia's Avatar
    Join Date
    Mar 2000
    Location
    Leeds, West Yorkshire, England
    Posts
    117

    Re: Matrix composition

    Originally posted by Portal:
    Let's back up a tad and make sure we're on the same page. When you call MultMatrix(), you are concatenating a matrix with the current gl matrix:
    M = I,
    M = M * YourMatrix,
    M = M * YourMatrix2,
    ...
    Or, in general,
    M' = I * M1 * M2 * ... * Mn.
    When you transforma a point with this matrix, you have:
    P' = ( I * M1 * (M2 * ... * (Mn * P))).
    As you can see, the transformations will be applied in the reverse order. If you understand this, you should be good to go.
    Yes, I understand all of this, but that isn't the problem.

    Here's my Draw function that is called on every frame:

    Code :
    procedure Draw is
     
      RX : Matrix3x3.Object;
      RY : Matrix3x3.Object;
     
    begin
     
      MeshData.TM.Translation := (Z => Zoom, others => 0.0);
     
      Matrix3x3.RotateX(RX, Maths.Degrees_To_Radians(XSpeed));
      Matrix3x3.RotateY(RY, Maths.Degrees_To_Radians(YSpeed));
     
      Matrix3x3.Mul(MeshData.TM.Matrix, RY, RX);
     
      Renderer.Clear;
     
      Renderer.SetMatrix(MeshData.TM.Matrix, MeshData.TM.Translation);
      Renderer.DrawMesh(MeshData);
     
     
      Renderer.SwapBuffers;
     
    end Draw;
    Now the SetMatrix call does the following:

    Code :
    procedure SetMatrix(Matrix : in Matrix3x3.Object; Translation : in Vector3.Object := (others => 0.0)) is
     
      TM : Matrix4x4.Object;
     
    begin
     
      Matrix4x4.Compose(TM, Translation, Matrix);
      GL.glLoadMatrixf(Float_To_GLfloat(TM(TM'First)'Unchecked_Access));
     
     
    end SetMatrix;
    Where that Compose function is the one I posted earlier.

    Something is going wrong when I use this Compose function. When I use the oher Compose function which doesn't multipy the matrix3x3 and the Vector3 I can see the object and rotate it in the manner I expect. I expect from what I've read about this Compose is that the operations should occur in the opposite order so I should have the object rotating about me, but that isn't happening. If I remove the translation completely, I can see the object but it is distorted.

    Luke.
    Luke A. Guest

  10. #10
    Advanced Member Frequent Contributor plasmonster's Avatar
    Join Date
    Mar 2004
    Posts
    739

    Re: Matrix composition

    Remember when you load the matrix to do a transpose, assuming your matrices are row major.
    glLoadMatrixf( MyRowMajorMatrix.transpose() ), or something to that effect.

    edit:
    By the way, the Compose() function looks a little odd, why is the "Left" matrix ignored in the result?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •