5
$\begingroup$

I'm making a script to import custom objects, it is still at early stage but so far vertices, faces and uv are created correctly. I want to do weight painting through Blender's Python API but I don't know how to do it properly.

Below an extract of the code that create the objects, how I could add vertex group and relative weights? I know how to extract vertex indices and weights from the input model but don't know how to use them,

(Blender version is 2.72)

    for i in range(0,self. subsetCount):
        subset = self.subset[i]
        coords = subset.getV3(0)
        faces = subset.getIndices()
        me = bpy.data.meshes.new(subset.name+"_Mesh")

        ob = bpy.data.objects.new(str(i).zfill(2)+'_'+subset.name, me)
        ob.location = (0, 0, 0)
        bpy.context.scene.objects.link(ob)

        me.from_pydata(coords, [], faces)
        me.update(calc_edges=True)

        mat = bpy.data.materials.new(subset.name)
        mat.diffuse_color = (random.uniform(0.0, 1.0), \
                             random.uniform(0.0, 1.0), \
                             random.uniform(0.0, 1.0))
        me.materials.append(mat)

        for f in me.polygons:
            f.material_index = 0
            f.use_smooth = 1

        # vert_uvs = subset.getV2(0x28)
        # if len(vert_uvs) > 0:
        #     me.uv_textures.new("UV0")
        #     uvlist = [uv for pair in [vert_uvs[l.vertex_index] for l in me.loops] for uv in pair]
        #     me.uv_layers[-1].data.foreach_set("uv", uvlist)

edit

found this to add the group:

        vxgroup = ob.vertex_groups.new("group")

still don't know how to set weights for vertices (best would be at once)

edit

I was hoping to use something like a foreach_set but can't figure out how to use it, instead solved this way:

        for grp in ob.vertex_groups:
            grp.add(range(0,len(me.vertices)), 1.0, 'REPLACE')

is just an example and set all vertices weight in all groups of the object ob (if you try it in console select another mesh then back to see the weights applied).

$\endgroup$
  • $\begingroup$ You can read vertex weights like ob.data.vertices[#].groups[#].weight, but the problem is that there is no way to add groups to .groups on the object level. Thus, VertexGroup.add() is the only way. You should post your 2nd edit as answer! Also, try ob.data.update(), it might help to make the applied weights visible immediately. $\endgroup$ – CoDEmanX Feb 4 '15 at 15:13
  • $\begingroup$ @CoDEmanX thank you for the clarification and the tip about update, I will (post as answer) $\endgroup$ – Alex Feb 4 '15 at 15:29
5
$\begingroup$

vertex_groups method .add() first argument is a list of vertices index, I group my input to reduce the calls to add to the minimum necessary.

Note: my input weights are stored in unsigned bytes (0-255).

First with a dict {grpID: ...} then another dict as value for weights {grpId: {weight: ...}}, finally the list of vertices id {grpId: {weight: [vxId, ...]}}, at this point the code is quite simple:

        weights = myGetWeights()
        for grpId, wv in weights.items():
            grpName = "Bone_"+str(grpId).zfill(3)
            ob.vertex_groups.new(grpName)
            for weight, vxIdList  in wv.items():
                ob.vertex_groups[grpName].add(vxIdList, 1.0 / 255 * weight, 'REPLACE')
$\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.