2
$\begingroup$

I am editing the default OBJ exporter of Blender (io_scene_obj) to create my own version which supports bone weights, for skeletal animation.

I now know how to access the bone weights per vertex in the Object, however I need to correlate those Object vertices to the Mesh vertices.

I am able to fetch the "vertex index" of the vertex with this piece of code:

import bpy

arm = bpy.data.objects['Armature']
obj = bpy.data.objects['Cube']

obj_verts = obj.data.vertices
obj_group_names = [g.name for g in obj.vertex_groups]

for bone in arm.pose.bones:
    if bone.name not in obj_group_names:
        continue

    gidx = obj.vertex_groups[bone.name].index

    bone_verts = [v for v in obj_verts if gidx in [g.group for g in v.groups]]

    for v in bone_verts:
        for g in v.groups:
            if g.group == gidx: 
                w = g.weight
                print('Vertex',v.index,'has a weight of',w,'for bone',bone.name)

however I am not sure how to use this vertex index. is it a direct index into me.vertices? (I sure hope it is) Please note that I triangulate the mesh before I export it. I keep the vertex order though, so it should be the same.

Here's what I'm planning to do: My file format has a new kind of line:

vc f f f

and it modifies the f lines:

f position/uv/norm/skel position/uv/norm/skel position/uv/norm/skel

the vc lines were originally designed to hold color information like this

#Solid red
vc 1.0 0.0 0.0
#Solid green
vc 0.0 1.0 0.0

However I realized that this exact same system could contain skeletal animation information. Here are the steps:

1) Get the 3 most influential weights on a vertex

2) Make them add up to 1

3) Divide them by 2

4) Add the Bone ID to it

Here's an example:

#Bone 1 influences this vertex 100 percent, there are no others
vc 1.5 0.0 0.0
#50 percent influenced by bone 1, 25 percent by bone 2, and 25 percent by bone 3
vc 1.25 2.125 3.125

In order for this to work, I need to figure out how much each vertex (3D point, with X, Y, and Z) is weighted by each bone, pick the top 3 per vertex (and if there aren't 3, stick in a fake 0 bone with 0 weight for every missing spot) and write it to file in VC lines. If I do this for every 3d point, then I can simply use the same indices as the positions for the f lines.

f A/B/C/A

How could I achieve this?

I assume that there is only one armature in the scene called 'Armature' and that the only mesh currently being exported (But not necessarily the only one in the scene) is influenced by it.

I have access to the list of Objects to be exported, so I can access both the triangulated mesh from bpy.data.meshes[] and the object from bpy.data.objects[]

$\endgroup$
0
$\begingroup$

The objects data property contains the data used to define the objects appearance. For a mesh object that includes vertices, edges and polygons.

While vertex groups are stored within an objects properties, each groups vertex indices are direct indices into the objects data.vertices[] list. These are all kept in sync internally by blender so you don't have to be concerned, unless the mesh gets edited while you are accessing the data.

If you start with bpy.context.selected_objects you can export objects of type MESH. Then look at an objects modifiers list to find a modifier with a type of ARMATURE and get the object property from that to get the relevant armature.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.