Matrix multiplication is not commutative. What is the work around or solution?

后端 未结 3 1503
一个人的身影
一个人的身影 2021-01-29 09:52

I basically have this problem:

Generic Simple 3D Matrix Rotation Issue

and it is driving me mad. I have been on Google for hours but cannot find any posts about

相关标签:
3条回答
  • 2021-01-29 10:14

    Thanks for all your help. I have found the answer here:

    http://www.learnopengles.com/tag/rotation/

    The solution is: "One easy way to work around this problem is to keep a second matrix around that will store all of the accumulated rotations." :-)

    0 讨论(0)
  • 2021-01-29 10:17

    If I get it right you want to rotate direct object transform matrix around its own axises.

    • in that case it is really simple (but I also spend much time solving this years back)
    • M0 is original object matrix
    • R is transformation you want to apply (rotation)
    • M1 is the result new object matrix
    • M1 = Inverse(Inverse(M0)*R)

    That is all. you just have to add 4x4 inverse matrix routine to your code for example here is mine

    void  matrix_subdet    (double *c,double *a)
            {
            double   q[16];
            int     i,j;
            for (i=0;i<4;i++)
             for (j=0;j<4;j++)
              q[j+(i<<2)]=matrix_subdet(a,i,j);
            for (i=0;i<16;i++) c[i]=q[i];
            }
    double matrix_subdet    (         double *a,int r,int s)
            {
            double   c,q[9];
            int     i,j,k;
            k=0;                            // q = sub matrix
            for (j=0;j<4;j++)
             if (j!=s)
              for (i=0;i<4;i++)
               if (i!=r)
                    {
                    q[k]=a[i+(j<<2)];
                    k++;
                    }
            c=0;
            c+=q[0]*q[4]*q[8];
            c+=q[1]*q[5]*q[6];
            c+=q[2]*q[3]*q[7];
            c-=q[0]*q[5]*q[7];
            c-=q[1]*q[3]*q[8];
            c-=q[2]*q[4]*q[6];
            if (int((r+s)&1)) c=-c;       // add signum
            return c;
            }
    double matrix_det       (         double *a)
            {
            double c=0;
            c+=a[ 0]*matrix_subdet(a,0,0);
            c+=a[ 4]*matrix_subdet(a,0,1);
            c+=a[ 8]*matrix_subdet(a,0,2);
            c+=a[12]*matrix_subdet(a,0,3);
            return c;
            }
    double matrix_det       (         double *a,double *b)
            {
            double c=0;
            c+=a[ 0]*b[ 0];
            c+=a[ 4]*b[ 1];
            c+=a[ 8]*b[ 2];
            c+=a[12]*b[ 3];
            return c;
            }
    void  matrix_inv       (double *c,double *a)
            {
            double   d[16],D;
            matrix_subdet(d,a);
            D=matrix_det(a,d);
            if (D) D=1.0/D;
            for (int i=0;i<16;i++) c[i]=d[i]*D;
            }
    
    • hope I did not forget to copy something
    • usage is matrix_inv(dst,src)
    • returns inverse matrix of src to dst
    • both src and dst are double[16] linear arrays representing 4x4 transform matrix

    [Edit1] 3x3 matrix

    Mine matrix layout is this (OpenGL like):

    double M[16];
    a00 a04 a08 a12
    a01 a05 a09 a13
    a02 a06 a10 a14
    a03 a07 a11 a15
    
    • where a?? is ??-th value from M[]

    Now if you want to use 4x4 inverse of 3x3 matrix just do this

    double m[9];
    b00 b03 b06 0
    b01 b04 b07 0
    b02 b05 b08 0
    0   0   0   1
    
    • where b?? is ??-th value from your 3x3 m[]
    • so load 4x4 matrix this way
    • invert
    • and extract 3x3 matrix back
    • You can always rewrite mine 4x4 inverse to 3x3 (I am too lazy to do that)
    • but it will get very simplified because determinant and sub-determinants will get very simple

    just to be sure you get it right m[3*3] -> M[4*4] will be like this:

    M[ 0]=m[0];
    M[ 1]=m[1];
    M[ 2]=m[2];
    M[ 3]=0.0;
    M[ 4]=m[3];
    M[ 5]=m[4];
    M[ 6]=m[5];
    M[ 7]=0.0;
    M[ 8]=m[6];
    M[ 9]=m[7];
    M[10]=m[8];
    M[11]=0.0;
    M[12]=0.0;
    M[13]=0.0;
    M[14]=0.0;
    M[15]=1.0;
    

    And backwards m[3*3] <- M[4*4] will be like this:

    m[0]=M[ 0];
    m[1]=M[ 1];
    m[2]=M[ 2];
    m[3]=M[ 4];
    m[4]=M[ 5];
    m[5]=M[ 6];
    m[6]=M[ 8];
    m[7]=M[ 9];
    m[8]=M[10];
    
    0 讨论(0)
  • 2021-01-29 10:29

    The solution/workaraound is to apply the rotations in the correct order.

    If you have rotation matrices A, B and C and want to apply them to matrix M in order A, B, C then the solution is:

    First apply A:

    A * M
    

    Then B:

    B * A * M
    

    And finally C:

    C * B * A * M
    

    If you want to apply ABC frequently you can precalculate the combined rotation matrix R:

    R = C * B * A
    

    and then you can apply R to M:

    R * M
    
    0 讨论(0)
提交回复
热议问题