4
$\begingroup$

I've been using an old script for a long time to import a custom format which contains a 4x4 matrix for the bone transform (inverted) and 4x3 for the bone animation (3x3 rotation matrix + 1 location vector).

In the recent versions of blender, "bone.matrix" was read_only. So I decided to stick with my v2.49 script for the mean time. But, I recently noticed an update with the blender API that the "bone.matrix" is no longer read only. So, I decided to rewrite my old script to the latest API (not really rewrite as I script it from scratch, just used the old script as reference).

Now, with my new script completed, 2 problem arises.

  • Bone's aren't set right.
  • Animation is messed-up.

As for the first problem, I find it really odd. Let me show you the related codes:

In the old script, setting the "bone.matrix" was done, simply, like this:

bone.matrix=Matrix4x4(g.f(16)).invert()                
bvec = bone.tail- bone.head
bvec.normalize()
bone.tail = bone.head + 0.01 * bvec

And that worked well. As for the new script, I did it in a very identical way (I think)

bone_matrix = struct.unpack("<ffffffffffffffff", fObj.read(64))                                        
bone_imatrix = mathutils.Matrix((bone_matrix[0:4],\
                                 bone_matrix[4:8],\
                                 bone_matrix[8:12],\
                                 bone_matrix[12:16])).inverted()     

bone.matrix = bone_imatrix[0:16]
bone.tail = bone.head + 0.01 * bone.vector  

But here is where things gets weird... To my knowledge the 2 codes above are completely identical but the resulting data is quite different.

How different? When I try to check some values via the console, I get this:

# OLD SCRIPT
>>> bpy.data.objects["armature"].data.edit_bones["0"].matrix
Matrix(((-4.371138828673793e-08, 0.0, 1.0, 0.0),
    (0.0, 0.9999999403953552, 0.0, 1.9815000295639038),
    (-1.0, 0.0, -4.371138828673793e-08, -0.54830002784729),
    (0.0, 0.0, 0.0, 1.0)))
>>> bpy.data.objects["armature"].data.edit_bones["0"].head
Vector((0.0, 1.9815000295639038, -0.54830002784729))
>>> bpy.data.objects["armature"].data.edit_bones["0"].tail
Vector((0.0, 2.0815000534057617, -0.54830002784729))
>>> bpy.data.objects["armature"].data.edit_bones["0"].matrix.decompose()
(Vector((0.0, 1.9815000295639038, -0.54830002784729)), Quaternion((0.7071068286895752, 0.0, 0.7071068286895752, 0.0)), Vector((1.0, 0.9999999403953552, 1.0)))

# NEW SCRIPT
>>> bpy.data.objects["rig_0"].data.edit_bones["bone_0"].matrix
Matrix(((-4.371138828673793e-08, 0.0, 1.0, -0.0),
    (-1.0, 0.0, -4.371138828673793e-08, 1.9815000295639038),
    (0.0, -0.9999999403953552, 0.0, -0.54830002784729),
    (0.0, 0.0, 0.0, 1.0)))
>>> bpy.data.objects["rig_0"].data.edit_bones["bone_0"].head
Vector((-0.0, 1.9815000295639038, -0.54830002784729))
>>> bpy.data.objects["rig_0"].data.edit_bones["bone_0"].head
Vector((-0.0, 1.9815000295639038, -0.54830002784729))
>>> bpy.data.objects["rig_0"].data.edit_bones["bone_0"].matrix.decompose()
(Vector((-0.0, 1.9815000295639038, -0.54830002784729)), Quaternion((0.5, -0.5, 0.5000000596046448, -0.5000000596046448)), Vector((1.0, 0.9999999403953552, 1.0)))

Noticed that the quaternions from the decompose are different? That is my first question, why did this happen? What did I do wrong?

Moving on to my second problem, the messed-up animation. I believe this problem is a side-effect of the 1st problem. But I'm not entirely sure. So, I'll just share some info about it. (just in case the first problem doesn't have anything to do with the second problem)

On my old script, I did the animation like this:

matrix=Matrix3x3(g.f(9)).resize4x4()
pos=g.f(3)
matrix=matrix*VectorMatrix(pos)
boneMatrix=Blender.Object.Get('armature').getData().bones[str(k)].matrix['ARMATURESPACE']
# ...some other part
pbone=pose.bones[name]
pbone.poseMatrix=boneMatrix*matrix
pbone.insertKey(skeleton, 1+frame,\
    [Blender.Object.Pose.ROT,Blender.Object.Pose.LOC],True)
pose.update()

I think my code is quite similar but I'm no expert. Here is my new script:

name = "bone_%d" % bi
bone = rig.data.bones[name]
pbone = rig.pose.bones[name]

rot_matrix = struct.unpack("<fffffffff", fAni.read(36))
rot_matrix = mathutils.Matrix((rot_matrix[0:3],\
                            rot_matrix[3:6],\
                            rot_matrix[6:9]))
rot_matrix.resize_4x4()

loc_vector = struct.unpack("<fff", fAni.read(12))
loc_vector = mathutils.Vector( loc_vector[0:3] )
loc_matrix = mathutils.Matrix.Translation(loc_vector)

matrix = rot_matrix * loc_matrix
pbone.matrix = bone.matrix_local * matrix

pbone.keyframe_insert(
    data_path = "rotation_quaternion", 
    frame     = 1 + f,
    group     = name)                        
pbone.keyframe_insert(
    data_path = "location", 
    frame     = 1 + f,
    group     = name)

I have been trying to make this work for a week and I'm already going in circles, I just can't figure it out. Hopefully someone here can enlighten me.

Cheers!

$\endgroup$
3
  • $\begingroup$ perhaps worth reading through a list of changes, matrix multiplication is mentioned: wiki.blender.org/index.php/Dev:Py/Scripts/Guidelines/… $\endgroup$
    – zeffii
    Commented Sep 16, 2016 at 7:34
  • $\begingroup$ @zeffii I now think the problem isn't really the matrix itself but the matrix property, the docs says it doesn't support bone length. What could that mean? $\endgroup$
    – majidarif
    Commented Sep 16, 2016 at 17:17
  • $\begingroup$ it does appear that your matrices are both identical (inverted too), the document does suggest that internally the order in which matrices are multiplied did change to be more conventional. ..hate to see you being caught out by this, but I don't know anything about armature. Have you tried generating a test rig (simplest you can think of) and see if you get OK results from scratch/neutral start point? $\endgroup$
    – zeffii
    Commented Sep 16, 2016 at 18:06

0

You must log in to answer this question.

Browse other questions tagged .