Home > OS >  How to compute a 4x4 matrix bridge (i.e. A * C = B, find C)
How to compute a 4x4 matrix bridge (i.e. A * C = B, find C)

Time:01-07

I am trying to implement a C function that, given (4x4) Matrix A and Matrix B, can generate Matrix C such that A*C=B.

After some research, I produced this:

Matrix Matrix::GetBridge(Matrix* theOther)
{
    Matrix aIMat=GetInvert();
    if (!theOther) return Identity();

    Matrix aResult=*theOther;
    aResult*=aIMat;
    return aResult;
}

The result this produces is... kinda correct. It produces the correct numbers, but with different sign. Here is the output:

Matrix A: 1,0,0,0
          0,0.9063,0.4226,0
          0,-0.4226,0.9063,0
          0,0,0,1

Matrix B: 0,0,-1,0
          0,1,0,0
          1,0,0,0
          0,0,0,1

Matrix C: 0,-0.4226,-0.9063,0
          0,0.9063,-0.4226,0
          1,0,0,0
          0,0,0,1

Matrix B * C:  -1,-0,-0,0
               0,0.9063,-0.4226,0
               0,-0.4226,-0.9063,0
               0,0,0,1

So B*C = A for the numbers, but not the sign. I'm trying to use this to find what I need to multiply a certain matrix by in order to orient to another matrix (in 3D space).

How do I fix this function?

(Edit) Here's the code that produces the above results:

    Matrix aM1;aM1.RotateX(25);
    Matrix aM2;aM2.RotateY(90);
    Matrix aM3=aM1.GetBridge(&aM2);

    aM1.Debug("$Matrix A:");
    aM2.Debug("$Matrix B:");
    aM3.Debug("$Matrix C:");

    Matrix aM4=aM2;
    aM4*=aM3;
    aM4.Debug("!Matrix B * C:");

...and here are the contents of GetInvert, in case the error is there:

Matrix& Matrix::Invert()
{
    float aInv[16];

    aInv[0]=mData.mm[5]*mData.mm[10]*mData.mm[15]-mData.mm[5]*mData.mm[11]*mData.mm[14]-mData.mm[9]*mData.mm[6]*mData.mm[15] mData.mm[9]*mData.mm[7]*mData.mm[14] mData.mm[13]*mData.mm[6]*mData.mm[11]-mData.mm[13]*mData.mm[7]*mData.mm[10];
    aInv[4]=-mData.mm[4]*mData.mm[10]*mData.mm[15] mData.mm[4]*mData.mm[11]*mData.mm[14] mData.mm[8]*mData.mm[6]*mData.mm[15]-mData.mm[8]*mData.mm[7]*mData.mm[14]-mData.mm[12]*mData.mm[6]*mData.mm[11] mData.mm[12]*mData.mm[7]*mData.mm[10];
    aInv[8]=mData.mm[4]*mData.mm[9]*mData.mm[15]-mData.mm[4]*mData.mm[11]*mData.mm[13]-mData.mm[8]*mData.mm[5]*mData.mm[15] mData.mm[8]*mData.mm[7]*mData.mm[13] mData.mm[12]*mData.mm[5]*mData.mm[11]-mData.mm[12]*mData.mm[7]*mData.mm[9];
    aInv[12]=-mData.mm[4]*mData.mm[9]*mData.mm[14] mData.mm[4]*mData.mm[10]*mData.mm[13] mData.mm[8]*mData.mm[5]*mData.mm[14]-mData.mm[8]*mData.mm[6]*mData.mm[13]-mData.mm[12]*mData.mm[5]*mData.mm[10] mData.mm[12]*mData.mm[6]*mData.mm[9];
    aInv[1]=-mData.mm[1]*mData.mm[10]*mData.mm[15] mData.mm[1]*mData.mm[11]*mData.mm[14] mData.mm[9]*mData.mm[2]*mData.mm[15]-mData.mm[9]*mData.mm[3]*mData.mm[14]-mData.mm[13]*mData.mm[2]*mData.mm[11] mData.mm[13]*mData.mm[3]*mData.mm[10];
    aInv[5]=mData.mm[0]*mData.mm[10]*mData.mm[15]-mData.mm[0]*mData.mm[11]*mData.mm[14]-mData.mm[8]*mData.mm[2]*mData.mm[15] mData.mm[8]*mData.mm[3]*mData.mm[14] mData.mm[12]*mData.mm[2]*mData.mm[11]-mData.mm[12]*mData.mm[3]*mData.mm[10];
    aInv[9]=-mData.mm[0]*mData.mm[9]*mData.mm[15] mData.mm[0]*mData.mm[11]*mData.mm[13] mData.mm[8]*mData.mm[1]*mData.mm[15]-mData.mm[8]*mData.mm[3]*mData.mm[13]-mData.mm[12]*mData.mm[1]*mData.mm[11] mData.mm[12]*mData.mm[3]*mData.mm[9];
    aInv[13]=mData.mm[0]*mData.mm[9]*mData.mm[14]-mData.mm[0]*mData.mm[10]*mData.mm[13]-mData.mm[8]*mData.mm[1]*mData.mm[14] mData.mm[8]*mData.mm[2]*mData.mm[13] mData.mm[12]*mData.mm[1]*mData.mm[10]-mData.mm[12]*mData.mm[2]*mData.mm[9];
    aInv[2]=mData.mm[1]*mData.mm[6]*mData.mm[15]-mData.mm[1]*mData.mm[7]*mData.mm[14]-mData.mm[5]*mData.mm[2]*mData.mm[15] mData.mm[5]*mData.mm[3]*mData.mm[14] mData.mm[13]*mData.mm[2]*mData.mm[7]-mData.mm[13]*mData.mm[3]*mData.mm[6];
    aInv[6]=-mData.mm[0]*mData.mm[6]*mData.mm[15] mData.mm[0]*mData.mm[7]*mData.mm[14] mData.mm[4]*mData.mm[2]*mData.mm[15]-mData.mm[4]*mData.mm[3]*mData.mm[14]-mData.mm[12]*mData.mm[2]*mData.mm[7] mData.mm[12]*mData.mm[3]*mData.mm[6];
    aInv[10]=mData.mm[0]*mData.mm[5]*mData.mm[15]-mData.mm[0]*mData.mm[7]*mData.mm[13]-mData.mm[4]*mData.mm[1]*mData.mm[15] mData.mm[4]*mData.mm[3]*mData.mm[13] mData.mm[12]*mData.mm[1]*mData.mm[7]-mData.mm[12]*mData.mm[3]*mData.mm[5];
    aInv[14]=-mData.mm[0]*mData.mm[5]*mData.mm[14] mData.mm[0]*mData.mm[6]*mData.mm[13] mData.mm[4]*mData.mm[1]*mData.mm[14]-mData.mm[4]*mData.mm[2]*mData.mm[13]-mData.mm[12]*mData.mm[1]*mData.mm[6] mData.mm[12]*mData.mm[2]*mData.mm[5];
    aInv[3]=-mData.mm[1]*mData.mm[6]*mData.mm[11] mData.mm[1]*mData.mm[7]*mData.mm[10] mData.mm[5]*mData.mm[2]*mData.mm[11]-mData.mm[5]*mData.mm[3]*mData.mm[10]-mData.mm[9]*mData.mm[2]*mData.mm[7] mData.mm[9]*mData.mm[3]*mData.mm[6];
    aInv[7]=mData.mm[0]*mData.mm[6]*mData.mm[11]-mData.mm[0]*mData.mm[7]*mData.mm[10]-mData.mm[4]*mData.mm[2]*mData.mm[11] mData.mm[4]*mData.mm[3]*mData.mm[10] mData.mm[8]*mData.mm[2]*mData.mm[7]-mData.mm[8]*mData.mm[3]*mData.mm[6];
    aInv[11]=-mData.mm[0]*mData.mm[5]*mData.mm[11] mData.mm[0]*mData.mm[7]*mData.mm[9] mData.mm[4]*mData.mm[1]*mData.mm[11]-mData.mm[4]*mData.mm[3]*mData.mm[9]-mData.mm[8]*mData.mm[1]*mData.mm[7] mData.mm[8]*mData.mm[3]*mData.mm[5];
    aInv[15]=mData.mm[0]*mData.mm[5]*mData.mm[10]-mData.mm[0]*mData.mm[6]*mData.mm[9]-mData.mm[4]*mData.mm[1]*mData.mm[10] mData.mm[4]*mData.mm[2]*mData.mm[9] mData.mm[8]*mData.mm[1]*mData.mm[6]-mData.mm[8]*mData.mm[2]*mData.mm[5];
    float aDet=mData.mm[0]*aInv[0] mData.mm[1]*aInv[4] mData.mm[2]*aInv[8]  mData.mm[3]*aInv[12];
    if (aDet!=0) {aDet=1.0f/aDet;for (int aCount=0;aCount<16;aCount  ) mData.mm[aCount]=aInv[aCount]*aDet;}

    return *this;
}
inline Matrix   GetInvert() {Matrix aMat=*this;aMat.Invert();return aMat;}

(Note: This Invert function works for all other purposes I have put it to, i.e. to move coordinates into local space, so I don't expect the error to be there)

CodePudding user response:

The equation you need is:
A * (A-1 * B) = B
because
A * (A-1 * B) = (A * A-1) * B = I * B = B

So the "bridge matrix" is (A-1 * B). A-1 means the inverse of A.

However, it looks like your code is computing (B * A-1) which is not, generally, the same matrix. It should multiply in the opposite order.

  • Related