[SOLVED] About armature python scripting

Hi,

I’m working on a Blender add-on, and so far I could do everything and I’ve found answer to all my questions in the docs. Thank you all for this wonderful software and awesome documentation! But now it seems I’m unable to figure out on my own how to access armature data properly.

What I would need is, a list of bones, position+rotation quaternion pairs, in Cartesian coordinate system (right handed, +Y up, +X right, +Z front), where the root bone is in model space, but sub bones are relative to their parents. Can someone help me how to achieve this?

The python script that I have so far is here:
https://gitlab.com/bztsrc/model3d/-/tree/master/blender

And the code in question can be found here (works, kind of, it gets the armature but with incorrect coordinates). Any idea what am I doing wrong?

Thank you,
bzt

I’ve commented out all axis or other transformations (no more global_matrix and parent inverse matrix_local multiplications) and saved the data as they appear in blender’s bpy.

This is what I got (using KhronosGroup’s CesiumMan model): https://user-images.githubusercontent.com/12779069/187603746-1c1ca254-ef01-415b-90be-1a7a828db4c1.gif

As you can see, some bones are correct, while others not. This is very confusing. Do I have to do some kind of “to model space” transformation on the bpy data manually in python? I assumed they are all in the same space (whatever that space is, model or world), isn’t that so? Can anyone please explain it to me, what’s going on, how could bone’s alignments differ?

Please advice, I really could use some help with this.
bzt

Okay, how to get data Z up as shown on the UI from bpy? It returns neither the mesh nor the bones as Z up, and that’s the reason why axis_conversion(from_forward='-Y', from_up='Z',to_forward='Z', to_up='Y') doesn’t work for me.

Using mesh.transform(global_matrix @ object.matrix_world) fixes it for the mesh, but then obviously the mesh and the armature isn’t aligned any more.

Here’s a demonstration:

What should I do so that both the armature and mesh would return Z up coordinates from bpy, just as seen on the UI? (And then I could use axis_conversion consistently on both.)

The model I imported in blender is this: glTF-Sample-Models/2.0/CesiumMan/glTF-Binary at master · KhronosGroup/glTF-Sample-Models · GitHub

Thanks,
bzt

Figured it out. Yes, blender suxx big time, just as I’ve suspected you must do a “to model space” conversion manually to actually get what you see on the UI… Otherwise the queried armature and mesh won’t align with each other.

For the bones:

for i,ob_main in enumerate(objects):
    if ob_main.type != "ARMATURE":
        continue
    for b in ob_main.data.bones:
        # this is armature's matrix_world
        m = ob_main.matrix_world @ b.matrix_local
        # now m is the translation matrix of the bone in model-space

And for the mesh:

for i, ob_main in enumerate(objects):
    if ob_main.type != "MESH":
        continue
    # you must apply modifiers manually too, and use the object's matrix_world
    o = ob_main.evaluated_get(depsgraph)
    mesh = o.to_mesh()
    mesh.transform(ob_main.matrix_world)
    # now mesh.vertices[x].co contains model-space coordinates

Cheers,
bzt