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.