creating models from files.

I thought like that too until I actually tried it:

ValueError: bpy_struct: item.attr= val: MeshColor.color1, sequence must have 3 i
tems total, not 4

Wants 3 values (RBG), doesnt allow 4 values (RGBA).

Also, how can I create bones from 4x4 transform matrices in Blender 2.6 API? The matrix attribute seems to be read-only now.

Also, can anyone explain the difference between Editbone and Bone? Bone has “matrix” attribute which is read-only, but the other allows you to set both 3x3 and 4x4 matrices.

Hi wynk,

Have a look at this documentation, hopefully this helps. http://www.blender.org/documentation/blender_python_api_2_61_release/info_gotcha.html#editbones-posebones-bone-bones

Cheers,
Truman

Hi. I think I realized that different types are accessible only in different modes.

OK.
I create bones like this:


for i in bone_names:
    bone = armature.edit_bones.new(i)

Then I want to add matrices to bones.
I go to object mode:

bpy.ops.object.mode_set(mode='OBJECT')

Then want to loop through “armature.bones”, but it is empty… what?


index = 0
for bone in armature.bones:
    bone.matrix_local = matrices[index]
    index += 1

the loop is never ran as “armature.bones” is empty.

Edit bones have a head and a tail. The default value for these is (0,0,0). Blender removes zero length bones after the edit mode toggle, hence the zero length of armature.bones.


import bpy
from mathutils import Vector

#create a new armature
Amt = bpy.data.armatures.new(name="newrig")
#create a new object using our armature
Obj = bpy.data.objects.new(name="NewRig",object_data=Amt)
#link it to the scene
bpy.context.scene.objects.link(Obj)

# give it the context
bpy.ops.object.select_name(name=Obj.name)
#put it in edit mode
bpy.ops.object.mode_set(mode="EDIT")

#add three bones
bonenames = ["Hip","Arm","Leg"]
for bonename in bonenames:
    bone = Amt.edit_bones.new(name=bonename)
    bone.tail = Vector([0,1,0])
#flip into object mode    
bpy.ops.object.mode_set(mode="OBJECT")    

for bone in Amt.bones:
    print(bone.name)

The edit bones define your “skeleton” or rest pose.

this works too


import bpy
names = ['head','spine']
obj = bpy.data.armatures[0]
print("=========obj=",obj)
for i,bone in enumerate(obj.bones[:]):
   bone.name = names[i]

If you go now to edit-mode the edit-bones are visible to the API and have (naturally?!) the same name as the bones itself.

And I would create bones for the active Armature !!! with
bpy.ops.armature.extrude_move(ARMATURE_OT_extrude={“forked”:False}, TRANSFORM_OT_translate={“value”:(0, 0, 0), “constraint_axis”:(False, False, False), “constraint_orientation”:‘GLOBAL’, “mirror”:False, “proportional”:‘DISABLED’, “proportional_edit_falloff”:‘SMOOTH’, “proportional_size”:1, “snap”:False, “snap_target”:‘CLOSEST’, “snap_point”:(0, 0, 0), “snap_align”:False, “snap_normal”:(0, 0, 0), “texture_space”:False, “release_confirm”:False})

defaults may be deleted …

For the example I added ONE bone like this before I used the script (above)

EDIT!!!
playing in the Python console get an edit-bone (armature in edit-mode)
then type e.g.
dir(eb0) #if you gave edit_bone[i] the name eb0 (i was 0 in my try))
help(eb0.transform) and you see what you can do with your editbone!
transform needs a matrix …!

Thanks, I though it makes a default 1 unit length bone.

Anyway, I have 4x4 absolute transform matrices in the file, so I thought I’d set them as matrix_local’s but I don’t see any changes, the bones are still at (0,0,0), same angle and same scale, though I get the right values when printing the matrix_local’s. Am I using the wrong attributes for assigning the matrices? Or do I need to update the bones somehow?

Maybe you should upload a *.blend and describe in a text of that blender file exactly what you want…
It is this way, at least not clear what you really want …
And die you try my suggestion? Using the console, help dir on bones of an armature? In object and edit mode?
And be aware if bones are connected.
Console output:
>>> b1e = arm.data.edit_bones[1] #in edit mode!
>>> b1 #is in my try the bone bone[1] in object mode
>>> b1e == b1
False

>>> b1e.trans #using Ctrl space!!!
form(
late(
>>> b1e.transform(

and use dir(b1) as well as dir(b1e) to see relevant info!
and if I give it a ‘changed’ matrix, editbone[1] moves to a different place (and rotation too)
by the way, in object mode the armature has changed its place and rot too

PKHG, I didn’t notice your post for some reason when I made mine.

I see you have a lot of knowledge on the API and are trying to help, I’m really grateful for that, really.

But can you cool down a bit? Almost in every of your posts lately you have to mention how completely amazed you are that someone can not understand everything in the API by just reading the doc strings and using dir() and help(). If everything was so simple nobody would need this forum subsection.

And if you don’t understand my problem, then I’m sorry, but I tried my best to explain, no blend will will help you, here is why:
All I asked was if matrix_local was the right attribute to use for creating bones because I see no changes with any value.
I also asked if it is possible to use RGBA colors for vertex colors, instead of just RGB, because right now Blender complaints I’m using 4 values instead of 3.
You do understand an example blend will not contain anything more than those functions?

And I will try the transform attribute, forgive me for not seeing it. I’m just confused that each bone mode seems to have it’s own way of setting matrices. Normal bones have matrix and matrix_local.

RGBA for verticex-colors is to my knowledge not available

Armatures and bones are created e.g.
bpy.ops.object.armature_add(view_align=False, enter_editmode=False, location=(-0.877631, -5.17806, -2.33516), rotation=(0, 0, 0), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False))
bpy.ops.object.editmode_toggle()
bpy.ops.armature.extrude_move(ARMATURE_OT_extrude={“forked”:False}, TRANSFORM_OT_translate={“value”:(0, 0, 0), “constraint_axis”:(False, False, False), “constraint_orientation”:‘GLOBAL’, “mirror”:False, “proportional”:‘DISABLED’, “proportional_edit_falloff”:‘SMOOTH’, “proportional_size”:1, “snap”:False, “snap_target”:‘CLOSEST’, “snap_point”:(0, 0, 0), “snap_align”:False, “snap_normal”:(0, 0, 0), “texture_space”:False, “release_confirm”:False})

by the way, to my knowledge, matrices are properties of objects but never used to generate objects.

Too bad you can’t set the Alpha of vertex color, but oh well.

I know how armatures are created.
Many formats only store transform matrices for bones. It’s enough to generate bones, they provide position, rotation and scale.

And the transform() method seems to do the trick.
I wonder how I can convert my bones from y-up space to z-up which Blender uses. I tried multiplying the matrix with a rotation matrix, but it changed the bone’s angle relative to itself.

The only other thing which I haven’t figured out is assigning vertices to bones and setting vertex weights. I know you can create vertex groups and set a weight for them, but in this format (and many others I believe) it’s a per-vertex value. And no idea how to assign the vertices to bones.

Have a look at the bvh import/export addon. There is an axis conversion method in blenderfolder\2.61\scripts\modules\bpy_extras\io_utils.py

I tried multiplying the matrix with a rotation matrix, but it changed the bone’s angle relative to itself.

Yep.

What about vertex weights, how do you set those?

Does this do the same (not that I haven’t tried, but I’m not too sure)?:


matrix = mathutils.Matrix(mydata).inverted() * mathutils.Matrix.Rotation(radians(90.0), 4, 'X')   

Also, what happens when your object has a transform matrix and you assign it an Armature? Should I convert the matrixes of the bones from one space to another if I have already done that for the object’s (Mesh’es) matrix?

Still no idea about weights.

You are asking questions which are not precise enough, at least for me.
See trying to understand what you ask:
>> c = C.active_object
>>> v = c.data.vert #ctrl space ==>
ex_colors
ices
>>> v = c.data.vertices[0]
>>> dir(v)
[‘doc’, ‘module’, ‘slots’, ‘bevel_weight’, ‘bl_rna’, ‘co’, ‘groups’, ‘hide’, ‘index’, ‘normal’, ‘rna_type’, ‘select’]

Meaning a vertex has no weight … and if you mean ‘bevel_weight’ you have to say that!

Not wanting to sound rude, but maybe it feels “imprecise” to you because you don’t know the subject? Vertex weight are values assigned to vertices to tell how much the vertex is influenced by a bone, I’m talking about OpenGL and DirectX apps. I don’t know how Blender stores it, that’s why I’m asking. Maybe it does it similar to vertex colors (access faces, then vertices of those faces, not directly vertices). That would make sense as a vertex can have multiple weights for each bone. No idea how its stored though.

You’ve probably used the Vertex paint tool, the vertex weight values there are represented as colors. I think red means 1.0 and blue means 0.0.
http://www.maxoncomputer.com/tutorials/Using_Vertex_Weights/images/Cap8_Vertex_Weight_Cylnd.gif

I’m basically asking how to set these values with Python, not the Weight paint window.

Oh ok…

Here is a code snippet that removes any vertex group not in the keep list (put “Group” in there for easy testing) and then removes all verts that have zero weight from those left. To add you would use add(…) rather than remove(…).

Wrote this a while back before i found bpy.ops.object.vertex_group_clean(limit=0.01, all_groups=False, keep_single=False), there are probably far nicer ways to code this with list comprehension, surely there are zillions of posts here for examples.


import bpy


TOL = 0.001

meshobj = bpy.context.active_object

# remove unwanted vertex-groups

keep = ["Group","jaw","upper_mouth","lower_mouth","eyelid.L","head"]

for vg in meshobj.vertex_groups:
    if vg.name not in keep:
        print(vg.name)
        meshobj.vertex_groups.remove(vg)
        
     
mesh = meshobj.data

mode = meshobj.mode

bpy.ops.object.mode_set(mode='OBJECT')
for vert in mesh.vertices :
    for vertgroup in vert.groups:
        verts_toremove = []
        if vertgroup.weight < TOL:
            verts_toremove.append(vert.index)
        if len(verts_toremove):
            meshobj.vertex_groups[vertgroup.group].remove(verts_toremove)  

bpy.ops.object.mode_set(mode=mode)      

The mystery for me is, do you already have the weights from your “my format” because if not I suggest using the automatic bone weight operator.

Sorry, but how does that help? I’m asking how to set the weight of an individual vertex.
And yes, “my format” has vertex weight values, most formats do.

wtf?

The code runs thru all vertices, each vertex group that the vert is assigned to, and what weight it has… surely that helps… then again maybe not.

Hmmm reading batFingers code, it seams that you have create for each vertex a vertexgroup, which can get a weight?!

I created a group in the Cube

>>> v0 = c.data.vertices[0]
>>> dir(v0)
[‘doc’, ‘module’, ‘slots’, ‘bevel_weight’, ‘bl_rna’, ‘co’, ‘groups’, ‘hide’, ‘index’, ‘normal’, ‘rna_type’, ‘select’]

>>> v0 = c.vertex_groups[0]
>>> dir(v0)
[‘doc’, ‘module’, ‘slots’, ‘add’, ‘bl_rna’, ‘index’, ‘lock_weight’, ‘name’, ‘remove’, ‘rna_type’, ‘weight’]

And the group has a ‘weight’ the vertex has not!

So not trying rude wynk, it seems that I am right! Hi hi! (Blender is different to other 3D-programs) .