0
$\begingroup$

I am working on a script that generates bones down an edge or face loop. I have figured out how to create a bone and move its head and tail into position at the top and bottom of a face, or onto a specific vertex. The problem now is how to roll the bone so that it is flat on the face normal (or if on an edge loop, so that it based on the vertex normals.)

Is there some existing way to do this, or any existing addons/scripts that handle this problem? Or do I have to somehow derive the bone’s angle?

$\endgroup$
2
$\begingroup$

Construct the bone matrix

enter image description here

TBH not quite sure what flat on the face normal is...

Here is a script that creates a bone at each edge such that the bones y axis is aligned vert 0 to vert 1 and the z axis to the "edge normal" ie the average of the two linked face normals.

Select mesh object in object mode, run script creates an armature with bone on each edge.

Edit re selected edges yada yada.

import bpy
import bmesh
from mathutils import Vector, Matrix
context = bpy.context
vl = context.view_layer
coll = context.collection
ob = context.object # the mesh
me = ob.data
bm = bmesh.new()
bm.from_mesh(me)
arm = bpy.data.armatures.new("Foo")
arm_obj = bpy.data.objects.new("Foo", arm)
coll.objects.link(arm_obj)
vl.objects.active = arm_obj
bpy.ops.object.mode_set(mode='EDIT')

for e in bm.edges:
    eb = arm.edit_bones.new(f"edge{e.index}")
    v = e.verts[1].co - e.verts[0].co

    y = v.normalized()
    z = sum((f.normal for f in e.link_faces), Vector()).normalized()
    x = y.cross(z)
    M = Matrix((x, y, z)).transposed().to_4x4()
    M.translation = e.verts[0].co
    eb.matrix = M
    eb.tail = e.verts[1].co

bpy.ops.object.mode_set()
| improve this answer | |
$\endgroup$
  • $\begingroup$ Yes, that looks like the right thing. By flat on the face normal, I meant that the bone has an axis perpendicular to the normal. I get the general idea of your script. Can you explain more how exactly it matches the roll to the normal? $\endgroup$ – Ascalon May 6 at 22:00
  • $\begingroup$ as explained here blender.stackexchange.com/a/176207/15543 make a 3x3 rotation matrix. Suppose I assume that edge vector and "edge normal" are perp. The face normals are normal to the two linked faces (assumed planes) that intersect at the edge.. If this is True then pretty much just making edit bone x y and z axis point where we want, which takes care of roll. $\endgroup$ – batFINGER May 6 at 22:17

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.