Hi,
I’ve a Blender add-on, which supposed to get the armature. This works great, I got all bones with parents, positions and rotation quaternions. Here’s an output:
LowerBack True <Vector (0.0000, 0.7860, 0.0000)> <Quaternion (w=1.0000, x=0.0000, y=0.0000, z=0.0000)>
UpperBack False <Vector (0.0000, 1.1325, 0.0000)> <Quaternion (w=1.0000, x=0.0000, y=0.0000, z=0.0000)>
Neck False <Vector (0.0000, 1.4946, 0.0000)> <Quaternion (w=1.0000, x=0.0000, y=0.0000, z=0.0000)>
Head False <Vector (0.0000, 1.6517, 0.0000)> <Quaternion (w=1.0000, x=0.0000, y=0.0000, z=0.0000)>
This is (name of the bone), (is root bone), (position), (rotation) in each line. If I load this into my renderer, everything works fine.
But I need to represent the child bones relative to their parents, so I thought I should multiply their transformation matrix by the parent’s inverse transformation matrix, right? And this works most of the time, but not always. With one particular test model, I get these strange results.
Here’s the relevant code:
for i,ob_main in enumerate(objects):
if ob_main.type != "ARMATURE":
continue
for b in ob_main.data.bones:
# get the bone's transformation matrix. global_matrix turns it +Y up
m = global_matrix @ ob_main.matrix_world @ b.matrix_local
if b.parent:
# multiply by parent's inverse matrix
p = global_matrix @ ob_main.matrix_world @ b.parent.matrix_local
m = p.inverted() @ m
p = m.to_translation()
q = m.to_quaternion()
q.normalize()
print(b.name,b.parent is None,p,q)
If I multiply the bone’s matrix by the parent’s inverse, then I get this:
LowerBack True <Vector (0.0000, 0.7860, 0.0000)> <Quaternion (w=1.0000, x=0.0000, y=0.0000, z=0.0000)>
UpperBack False <Vector (0.0000, 1.0000, 0.0000)> <Quaternion (w=1.0000, x=0.0000, y=0.0000, z=0.0000)>
Neck False <Vector (0.0000, 1.0450, 0.0000)> <Quaternion (w=1.0000, x=0.0000, y=0.0000, z=0.0000)>
Head False <Vector (0.0000, 0.4533, 0.0000)> <Quaternion (w=1.0000, x=0.0000, y=0.0000, z=0.0000)>
As you see, “LowerBack” which has no parent is left intact, and is correct. However “UpperBack”, which supposed to have relative coordinates, has invalid values! Because (0.0000, 0.7860, 0.0000) + (0.0000, 1.0000, 0.0000) != (0.0000, 1.1325, 0.0000)
If I dump the matrices too, it becomes obvious that multiplying with the inverse returns an invalid, almost an identity matrix, but why?
bone: LowerBack
model-space matrix <Matrix 4x4 (0.3465, 0.0000, 0.0000, 0.0000)
(0.0000, 0.3465, 0.0000, 0.7860)
(0.0000, 0.0000, 0.3465, 0.0000)
(0.0000, 0.0000, 0.0000, 1.0000)>
bone relative matrix <Matrix 4x4 (0.3465, 0.0000, 0.0000, 0.0000)
(0.0000, 0.3465, 0.0000, 0.7860)
(0.0000, 0.0000, 0.3465, 0.0000)
(0.0000, 0.0000, 0.0000, 1.0000)>
LowerBack True <Vector (0.0000, 0.7860, 0.0000)> <Quaternion (w=1.0000, x=0.0000, y=0.0000, z=0.0000)>
bone: UpperBack
model-space matrix <Matrix 4x4 (0.3465, 0.0000, 0.0000, 0.0000)
(0.0000, 0.3465, 0.0000, 1.1325)
(0.0000, 0.0000, 0.3465, 0.0000)
(0.0000, 0.0000, 0.0000, 1.0000)>
parent matrix <Matrix 4x4 (0.3465, 0.0000, 0.0000, 0.0000)
(0.0000, 0.3465, 0.0000, 0.7860)
(0.0000, 0.0000, 0.3465, 0.0000)
(0.0000, 0.0000, 0.0000, 1.0000)>
parent inverse <Matrix 4x4 ( 2.8859, -0.0000, 0.0000, -0.0000)
(-0.0000, 2.8859, -0.0000, -2.2685)
( 0.0000, -0.0000, 2.8859, -0.0000)
(-0.0000, 0.0000, -0.0000, 1.0000)>
bone relative matrix <Matrix 4x4 (1.0000, 0.0000, 0.0000, 0.0000)
(0.0000, 1.0000, 0.0000, 1.0000)
(0.0000, 0.0000, 1.0000, 0.0000)
(0.0000, 0.0000, 0.0000, 1.0000)>
UpperBack False <Vector (0.0000, 1.0000, 0.0000)> <Quaternion (w=1.0000, x=0.0000, y=0.0000, z=0.0000)>
My question is, what am I doing wrong? How come that matrix multiplication works almost all of the time, but not with this particular model? Where should I look? What should I change?
Thanks,
bzt