-1

I'm reimplementing a closed source 3d library called noesis.

It exposes a python file with all of the basic classes.

All of the implementation details are actually hidden. The implementation is compiled so I can't preview it.

I want to implement one of the fuctions from that library called mat43Inverse.

I know normally it's not possible to inverse a 4x3 matrix, but this function exists.

Sample usage from a noesis plugin:

#4x3 matrix
class NoeMat43:

    # ...

    def inverse(self): #returns mat43
        return noesis.mat43Inverse(self)

source of exposed classes file: https://github.com/majimboo/mviewer/blob/master/noesis/plugins/python/inc_noesis.py#L478

noesis module is a compiled cpython module. (https://github.com/majimboo/mviewer/blob/master/noesis/plugins/NoesisPython.dll)

boneMtx = NoeMat43((
  NoeVec3((m01, m02, m03)),
  NoeVec3((m11, m12, m13)),
  NoeVec3((m21, m22, m23)),
  NoeVec3((m04, m14, m24))
)).inverse()

I prepared a set of correct results by calling the native function and printing the result.

input = NoeMat43((
    NoeVec3((2.5, 3.6, 4.7)),
    NoeVec3((2.9, 3.1, 4.3)),
    NoeVec3((6.5, 7.6, 8.7)),
    NoeVec3((1.1, 9.4, 3.2))
))

result = input.inverse()
expected = NoeMat43((
    NoeVec3((0.04392901062965393, 0.05095765367150307, 0.1142154261469841)),
    NoeVec3((0.044815145432949066, 0.038590818643569946, 0.09460975229740143)),
    NoeVec3((0.04042314738035202, 0.036982882767915726, 0.07482582330703735)),
    NoeVec3((-0.8928132057189941, -0.714801549911499, -0.6315471529960632))
))
noeassert('mat43Inverse', result, expected)

Correct results

1.

input: (
(1, 0, 0),
(0, 1, 0),
(0, 0, 1),
(0, 0, 0)
)

inverse result: (
(1.0, 0.0, 0.0),
(0.0, 1.0, 0.0),
(0.0, 0.0, 1.0),
(0.0, 0.0, 0.0)
)

2.

input: (
(2.5, 3.6, 4.7),
(2.9, 3.1, 4.3),
(6.5, 7.6, 8.7),
(1.1, 9.4, 3.2)
)

invserse result: (
(0.04392901062965393, 0.05095765367150307, 0.1142154261469841),
(0.044815145432949066, 0.038590818643569946, 0.09460975229740143),
(0.04042314738035202, 0.036982882767915726, 0.07482582330703735),
(-0.8928132057189941, -0.714801549911499, -0.6315471529960632)
)

3.

input: (
(0.0, 0.0, 1.0),
(0.0, 1.0, 0.0),
(-1.0, 0.0, 0.0),
(0.0, 32.29199981689453, -3.2665998935699463)
)

inverse result: (
(0.0, 0.0, -1.0),
(0.0, 1.0, 0.0),
(1.0, 0.0, 0.0),
(-3.2665998935699463, -32.29199981689453, 0.0)
)

4.

input: (
(0.0, 0.0, 2.0),
(0.0, 2.0, 0.0),
(-2.0, 0.0, 0.0),
(0.0, 32.29199981689453, -3.2665998935699463)
)

inverse result: (
(0.0, 0.0, -0.5),
(0.0, 0.5, 0.0),
(0.5, 0.0, 0.0),
(-1.6332999467849731, -16.145999908447266, 0.0)
)

5.

input: (
(2.0, 0.0, 2.0),
(0.0, 2.0, 0.0),
(-2.0, 0.0, 0.0),
(0.0, 32.29199981689453, -3.2665998935699463)
)

inverse result: (
(0.2499999850988388, 0.0, -0.2499999850988388),
(0.0, 0.5, 0.0),
(0.5, 0.0, 0.0),
(-0.8166499137878418, -16.145999908447266, 0.0)
)

Questions:

  • What is the formula behind mat43Inverse function?

1 Answers1

4

As Nico Schertler pointed out 4x3 matrix in 3D graphics is usually 4x4 uniform transform matrix where the last row or column (depends on the convention used) is omitted and represents (0,0,0,1) vector (no projection). This is done usually to preserve space.

I am too lazy to check your samples but if results does not match than you most likely got different convention on how the element/cells of the matrix are ordered. To check for correctness just multiply original and inverse matrix (both in full 4x4 representations) and the result should be unit matrix.

There are 3 approaches of how to compute inverse matrix in 3D graphics I know of:

  1. Horner scheme / GEM Gauss elimination method

    This is straightforward method usable on paper but in computer computation is this not very good choice as it need a bit sophistication for sorting the rows so the result is still leading to Inverse. That sometimes lead to trial and error which would mean possible performance problems latter on.

  2. Inverse from Determinant

    This is the best choice for unknown matrices as It need no sorting and is always computable if the matrix has an inverse. There are sometimes accuracy problems if numbers/vectors used have too big magnitudes. Here code in C++ for such (OpenGL convention):

    Look for matrix_inv function in the code.

  3. Pseudo inverse matrix

    In some cases you can avoid computing of inverse matrix by determinants or Horner scheme / Gauss elimination method because in some cases you can exploit the fact that Transpose of orthogonal rotational matrix is also its inverse. So the computations boils down to simple tranpose of 3x3 matrix (just swapping elements) and computing linear equation to match the inverse matrix origin. That is much much less computations hence better accuracy and speed. Here is how it is done (OpenGL convention):

    look for bullet #3 there.

Spektre
  • 49,595
  • 11
  • 110
  • 380