3

I am quite sure that mOffsetMatrix transforms vertex from mesh space to bone space, which is confirmed by this one http://assimp.sourceforge.net/lib_html/structai_bone.html

But then I saw this, which says that it actually transforms vertices from bone space to mesh space. https://github.com/assimp/assimp/pull/1803

Now I am very confused. So what exactly does mOffsetMatrix do?

genpfault
  • 51,148
  • 11
  • 85
  • 139
Manh Nguyen
  • 373
  • 3
  • 12

3 Answers3

8

The offsetMatrix of a bone is the inverse of that bone's global transform at bind pose. In other words, if you traverse the bone/node hierarchy, applying the local transform (mTransformation in Assimp) of each bone/node hierarchically to its children, we get the global transform for each bone/node. The inverse of this matrix for a particular bone equals its offsetMatrix. As implied here, it can be computed manually - regardless, it is constant and should not be computed per frame.

The name "offsetMatrix", though somewhat confusing (something like inverseBind would be clearer), probably comes from its use. The transform we use for skinning is (B_keyframe * offsetMatrix), where B_keyframe is the global transformation of a bone at some target location, provided e.g. by an animation clip. This composite transformation is effectively an offset, from bind pose (where the mesh vertices are defined) to B_keyframe. When applied to vertices, (B_keyframe * offsetMatrix) will "move" vertices, from bind positions to whatever position B_keyframe transforms to.
Note that if B_keyframe is equal to the bind transform, e.g. computed from the skeleton's mTransformation:s as above, then (B_keyframe * offsetMatrix) is identity and vertices will not move from their original positions in bind pose.

I personally favour the "from mesh space to bone space" definition when it comes to offsetMatrix. Why? Because the inverse of offsetMatrix - the (global) bone transform (at bind pose) - is most intuitively understood as a transformation from bone to mesh/model space. Inverting back, offsetMatrix transforms from mesh/model space to bone space.
Compare with the View matrix in rendering: it is the inverse of the camera's world transform (T*R), and is generally understood to transform from world to view space.

CJG
  • 81
  • 1
  • 5
1

Here is the answer for your question ( coming from a solution from the bug ):

it depends how you think of the transform. If the matrix multiplications come after the point (i.e point * transform with point being a "row" vector) then it makes sense to say it converts from "mesh space to bone space", as it takes a point in mesh space and outputs a point in bone space. But when using matrix premultiplication as assimp does (tranform * point with point being a "column" vector) it makes more sense to think of it as transforming the space itself, from "bone space to mesh space", whereupon the point in mesh space can be used.

This is why the original poster is confused, because they are thinking about it backwards compared to how assimp treats point transformation. This is probably leading directly to their confusion with working out the transformation matrix of the bone and thinking this should be the same as mOffsetMatrix, when in fact it is the inverse.

This is all especially confusing as DirectX uses postmultiplication, and OpenGL uses premultiplication.

This all said, i hope that someone can update the documentation so that it makes it clear for everybody. It's very difficult to specify clearly without an "official" way of thinking about this sort of thing. I can't even find it documented anywhere how assimp treats transformation matrix multiplication... although the matrix notation used on the "Data Structures" page of the assimp docs implies premultiplication with column vectors.

Hope that this will help you.

KimKulling
  • 2,654
  • 1
  • 15
  • 26
0

The documentation is wrong. So I need to update our doc. See issue 1950

KimKulling
  • 2,654
  • 1
  • 15
  • 26
  • Thanks for your answer. I just want to clear something up. I try to calculate the inverse bind pose matrix by concatenating y concatenating all the mTransformation starting from scene->rootNode to each bone in question. The result I get is different from mOffsetMatrix, which from my understanding, shouldn't be. Is this expected? – Manh Nguyen May 08 '18 at 22:48
  • I would love to know the answer to that question. – livin_amuk Sep 15 '19 at 17:05