Jump to content
  • Advertisement
jonwil

Matrix math help wanted

This topic is 366 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have the following fragments of code: (obviously there is more to the Matrix3 class, this is just the bits that are relavent)

class Matrix3
{
    float m[4][3];
    Matrix3 operator*(const Matrix3&) const;
};

Matrix3 Matrix3::operator*(const Matrix3 &m2) const
{
    Matrix3 ret;
    ret.m[0][0] = this->m[0][0] * m2.m[0][0] + this->m[0][1] * m2.m[1][0] + this->m[0][2] * m2.m[2][0];
    ret.m[1][0] = this->m[1][0] * m2.m[0][0] + this->m[1][1] * m2.m[1][0] + this->m[1][2] * m2.m[2][0];
    ret.m[2][0] = this->m[2][0] * m2.m[0][0] + this->m[2][1] * m2.m[1][0] + this->m[2][2] * m2.m[2][0];
    ret.m[3][0] = m2.m[0][0] * this->m[3][0] + m2.m[1][0] * this->m[3][1] + m2.m[2][0] * this->m[3][2] + m2.m[3][0];
    ret.m[0][1] = this->m[0][0] * m2.m[0][1] + this->m[0][1] * m2.m[1][1] + this->m[0][2] * m2.m[2][1];
    ret.m[1][1] = this->m[1][0] * m2.m[0][1] + this->m[1][1] * m2.m[1][1] + this->m[1][2] * m2.m[2][1];
    ret.m[2][1] = this->m[2][0] * m2.m[0][1] + this->m[2][1] * m2.m[1][1] + this->m[2][2] * m2.m[2][1];
    ret.m[3][1] = m2.m[0][1] * this->m[3][0] + m2.m[1][1] * this->m[3][1] + m2.m[2][1] * this->m[3][2] + m2.m[3][1];
    ret.m[0][2] = this->m[0][0] * m2.m[0][2] + this->m[0][1] * m2.m[1][2] + this->m[0][2] * m2.m[2][2];
    ret.m[1][2] = this->m[1][0] * m2.m[0][2] + this->m[1][1] * m2.m[1][2] + this->m[1][2] * m2.m[2][2];
    ret.m[2][2] = this->m[2][0] * m2.m[0][2] + this->m[2][1] * m2.m[1][2] + this->m[2][2] * m2.m[2][2];
    ret.m[3][2] = m2.m[2][2] * this->m[3][2] + m2.m[1][2] * this->m[3][1] + m2.m[0][2] * this->m[3][0] + m2.m[3][2];
    return ret;
}

 

Then I have code that does this as part of an exporter to a custom file format:

Matrix3 anim = //blah
Matrix3 inverse = //blah
Matrix3 m2 = anim * inverse;

Ignore the //blah bits, they are just giving both anim and inverse some values (how they do that doesn't matter).

 

I am writing an importer for this file format that does the opposite of the exporter and as part of that I am able to produce the "inverse" matrix and the "m2" matrix but not the "anim" matrix. Given the "inverse" and "m2" matrices and the above multiplication operator code, is it possible to write a function that can recover the "anim" matrix and what should that function look like?

And no there are no functions in the Matrix3 class that look to be useful for this.

 

Share this post


Link to post
Share on other sites
Advertisement

Mathematically it is

   m2 = a * i  <=>  m2 * i^-1 = a * i * i^-1  <=>  m2 * i^-1 = a  because  i * i^-1 == I (the identity matrix)  and  a * I == a

In other words, you need to compute the inverse of the matrix "inverse" (well, the name "inverse" for the one matrix is an unfortunate choose) and multiply it left and right of the equation sign AND on the same side of both terms.

However, the original matrix is usually only reconstructed approximately because of numerical imprecision introducing small differences during matrix inversion and multiplication. Of course, it works if and only if "inverse" is invertible at all (but the name indicates that, doesn't it?).

Edited by haegarr

Share this post


Link to post
Share on other sites

As it happens the code that sets "inverse" happens to be set by calling Inverse on another different matrix.

So we have 4 matrices: (a complete set of 4 matrices is given below as an example)

base

0.0, 0.0, 1.0
1.0, 0.0, 0.0
0.0, 1.0, 0.0
-0.29698506, 0.00000071708286, 0.86644721

inverse

1.0, 0.00000011920929, 0.00000023841858
-0.00000011920929, 1.0, 0.0
-0.00000023841858, 0.0, 1.0
-0.86644721, 0.29698506, 0.1759115

anim

0.00000011920929, 0.00000023841858, 1.0
1.0, 0.0, -0.00000011920929
0.0, 1.0, -0.00000023841858
-0.000000010647835, 0.17591222, -0.000000013998365

m2

1.0, 0.00000011920929, 0.00000023841858
-0.00000011920929, 1.0, 0.0
-0.00000023841858, 0.0, 1.0
-0.86644721, 0.29698506, 0.1759115

 

Given that I have base, inverse (which looks like its an inverse of "base" although I cant be sure that the function called "Inverse" (the source code of which I dont have access to) is actually doing what it says and m2, what exactly is the formula for getting anim? (or as close to it as the floating point precision limitations allow)

 

Share this post


Link to post
Share on other sites

The 4 matrices as given above cannot be the entire truth, because they are given as 3 columns by 4 rows matrices. First, a matrix need to be quadratic to be invertible (so here either 3 x 3 or 4 x 4). Second, a 3 x 4 matrix cannot be multiplied by a 3 x 4 matrix; in general a n x m matrix can be multiplied by a m x n matrix only.

Presumably the full base matrix looks like (a 4th column added)

0.0, 0.0, 1.0, 0.0
1.0, 0.0, 0.0, 0.0
0.0, 1.0, 0.0, 0.0
-0.29698506, 0.00000071708286, 0.86644721, 1.0

so that the upper left 3 x 3 matrix is a combined rotation and scale matrix, and the lower 3 x 1 matrix the position vector. Is that a correct assumption?

However, the "inverse" matrix seems me not to be the inverse of the "base" matrix, because the product of their upper left 3 x 3 matrices isn't the identity matrix. 

Share this post


Link to post
Share on other sites

Based on the "operatior*" code above it looks like its doing something other than a conventional matrix multiplication given that its definitely working with a pair of matricies both defined as float m[4][3];

I suspect the "inverse" code (which I dont have) is probably not doing a bog standard matrix inverse either. Might need to dig deeper into that one as well and see just what its really doing.

Then once I have that, maybe I can figure out some way to get the information I need given the inputs I have and the knowledge of the workings of both the operator* and Inverse functions.

Share this post


Link to post
Share on other sites

Ah, I forgot about the routine implementation as mentioned in the OP. Yes, that routine works as like the matrices would have a forth column of [ 0 0 0 1 ], so the assumption is correct. It just has left out the term where a multiplication with 0.0 would happen (because adding the resulting 0.0 would not change anything), and left out the multiplication with 1.0 (because that would not change anything of m[3][j]). So the routine actually implements a standard matrix product under the condition that the 4th vector is statically given as [ 0 0 0 1 ] and hence just not stored explicitly but known implicitly.

16 minutes ago, jonwil said:

I suspect the "inverse" code (which I dont have) is probably not doing a bog standard matrix inverse either. Might need to dig deeper into that one as well and see just what its really doing.

Feed well known matrices into it and look at the result. E.g. feeding the identity matrix must result in the identity matrix if inversion is implemented.

Share this post


Link to post
Share on other sites

After some further analysis I see that the actual result of calling this Inverse function on the "base" matrix is this

0.0, 1.0, 0.0
0.0, 0.0, 1.0
1.0, 0.0, 0.0
-0.86644721, 0.29698506, -0.00000071708286

which looks a lot more like the inverse of the base matrix given above

0.0, 0.0, 1.0
1.0, 0.0, 0.0
0.0, 1.0, 0.0
-0.29698506, 0.00000071708286, 0.86644721

So given the matrices "base", "inverse" and "m2" and the already mentioned calculations for how m2 is calculated from "inverse" and "anim", what math do I need to do to get "anim"? (or as close as possible allowing for FPU precision loss)

 

Share this post


Link to post
Share on other sites
19 minutes ago, jonwil said:

which looks a lot more like the inverse of the base matrix given above

Just checked the orientation/scale matrix, and yes - looks like the inverse.

20 minutes ago, jonwil said:

So given the matrices "base", "inverse" and "m2" and the already mentioned calculations for how m2 is calculated from "inverse" and "anim", what math do I need to do to get "anim"? (or as close as possible allowing for FPU precision loss)

As already written: With the definition

     m2 := anim * inv

the matrix "anim" is computed as

    anim = m2 * inv^-1

i.e. multiply "m2" with the inverse of "inverse" on the right.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!