Charles Lohr
Charles Lohr

Reputation: 919

How do you invert euclidean (transform and rotation only) matrices in C?

How do you invert 4x3 matrices that are only translation and rotation, no scale? The sort of thing you would use to do an OpenGL Matrix inverse (just without scaling)?

Upvotes: 0

Views: 366

Answers (2)

Luis Colorado
Luis Colorado

Reputation: 12668

You can solve that for any 3 dimensional affine transformation whose 3x3 transformation matrix is invertible. This allows you to include scaling and non conformant applications. The only requirement is for the 3x3 matrix to be invertible.

Simply extend your 3x4 matrix to 4x4 by adding a row all zeros except the last element, and invert that matrix. For example, as shown below:

[[a  b   c   d]  [[x]    [[x']
 [e  f   g   h] * [y]  =  [y']
 [i  j   k   l]   [z]     [z']
 [0  0   0   1]]  [1]]    [1 ]]  (added row)

It's easy to see that this 4x4 matrix, applied to your vector produces exactly the same vector as before the extension.

If you get the inverse of that matrix, you'll have:

[[A  B   C   D]    [[x']    [[x]
 [E  F   G   H]  *  [y']  =  [y]
 [I  J   K   L]     [z']     [z]
 [0  0   0   1]]    [1 ]     [1]]

It's easy to see that it this works in one direction, it needs to be in the reverse direction, if A is the image of B, then B will be the inverse throug the inverse transformation, the only requisite is the matrix to be invertible.

More on... if you have a list of vectors you want to process, you can apply Gauss elimination method to an extended matrix of the form:

[[a  b   c   d     x0' x1' x2' ... xn']
 [e  f   g   h     y0' y1' y2' ... yn']
 [i  j   k   l     z0' z1' z2' ... zn']
 [0  0   0   1     1   1   1   ... 1  ]]

to obtain the inverses of all the vectors you do the Gauss elimination vector to get from above:

[[1  0   0   0     x0  x1  x2  ... xn ]
 [0  1   0   0     y0  y1  y2  ... yn ]
 [0  0   1   0     z0  z1  z2  ... zn ]
 [0  0   0   1     1   1   1   ... 1  ]]

and you will solve n problems in one shot, because the column vectors above will be the ones, that once transformed produce the former ones.

You can get a simple implementation I wrote to teach my son about linear algebra of Gauss/Jordan elimination method here. It's opensource (BSD license) and you can modify/adapt it to your needs. This method uses the last approach, and you can use it out of the box by trying the sist_lin program.

If you want the inverse transformation, put the following contents in the matrix, and apply Gauss elimination to:

a b c d 1 0 0 0
e f g h 0 1 0 0
i j k l 0 0 1 0
0 0 0 1 0 0 0 1

as input to sist_lin and you get:

1 0 0 0 A B C D   <-- these are the coefs of the
0 1 0 0 E F G H       inverse transformation
0 0 1 0 I J K L
0 0 0 1 0 0 0 1

you will have:

a * x + b * y + c * z + d = X
e * x + f * y + g * z + h = Y
i * x + j * y + k * z + l = Z
0 * x + 0 * y + 0 * z + 1 = 1

and

A * X + B * Y + C * Z + D = x
E * X + F * Y + G * Z + H = y
I * X + J * Y + K * Z + L = z
0 * X + 0 * Y + 0 * Z + 1 = 1

Upvotes: 0

Charles Lohr
Charles Lohr

Reputation: 919

Assuming your TypeMatrix3x4 is a [3][4] matrix, and you are only transforming a 1:1 scale, rotation and translation matrix, the following code seems to work -

This transposes the rotation matrix and applies the inverse of the translation.

TypeMatrix3x4 InvertHmdMatrix34( TypeMatrix3x4 mtoinv )
{
    int i, j;
    TypeMatrix3x4 out = { 0 };
    for( i = 0; i < 3; i++ )
        for( j = 0; j < 3; j++ )
            out.m[j][i] = mtoinv.m[i][j];

    for ( i = 0; i < 3; i++ )
    {
        out.m[i][3] = 0;
        for( j = 0; j < 3; j++ )
            out.m[i][3] += out.m[i][j] * -mtoinv.m[j][3];
    }
    return out;
}

Upvotes: 1

Related Questions