Rough Python Script To Position and Orient Bone

   3567   5   1
User Avatar
Member
355 posts
Joined: Nov. 2015
Offline
Hello, this is a rough python script to create, position and orient a bone in arbitrary space based on nulls. However, I've been careful to rotate the nulls so their axes match that of what I want for my bone axes. To the more advanced personnel, is this a good way to do this or can it be done better? If you have the time, check it out and let me know. Thanks.

import hou

# create nulls to position bone
root_null = hou.node('/obj').createNode('null', node_name = 'root_null')
root_null.setParms({'tx':0.3,'ty':0.5,'tz':0.1,'rx':66,'ry':80,'rz':-5,'geoscale':0.1})

child_null = hou.node('/obj').createNode('null', node_name = 'child_null')
child_null.setInput(0,root_null)
child_null.setParms({'tz':0.2,'geoscale':0.1})

# get null positions
root_null_t = root_null.worldTransform().extractTranslates()
child_null_t = child_null.worldTransform().extractTranslates()

# vector from root null to child null so we can rotate a vector representing our bone
# from its head to its tip, onto this vector
root_to_child_vec = child_null_t - root_null_t

# get distance of previously which will be used for the bone length
root_to_child_dist = root_null_t.distanceTo(child_null_t)

# this is the vector that represents our default bone from its head to its tip
# (which is in the negative Z by default)
orig_bone_vec = hou.Vector3(0,0,-root_to_child_dist)


# here we create a rotation matrix to rotate the vector which represents our initial bone onto
# the vector that represents root_null to child_null
root_bone_rot_mat = orig_bone_vec.matrixToRotateTo(root_to_child_vec)

# here we extarct only the rotates the that previously created matrix because we want to use it
# and the world translate values of root_null to build a new matrix that will position our bone
# correctly between root_null and child_null
root_bone_rot = root_bone_rot_mat.extractRotates()


bone_pos_and_rot_for_transf_matrix = {'translate':root_null_t,'rotate':root_bone_rot}

# build the bone transform matrix
root_bone_tansf_mat = hou.hmath.buildTransform(bone_pos_and_rot_for_transf_matrix)

# create bone
root_bone = hou.node('/obj/').createNode('bone', node_name = 'root_bone')

# set bone length
root_bone.setParms({'length':root_to_child_dist})

#transform bone with the matrix we created
root_bone.setWorldTransform(root_bone_tansf_mat)

### INITIAL BONE POS DONE. NEXT WE'LL PROPERLY ORIENT IT TO FIX X-AXIS ###





#### ALIGN BONE SO THAT THE 'X-AXIS' IS THE MAIN ROTATION AXIS. WE DO THIS USING DUMMY NULLS TO BUILD ####
#### VECTORS TO USE AS GUIDES TO ALIGN THE BONES X- AXIS WITH THE ROOT_NULL'S X-AXIS ####



#bone pre align, so that bones axes is exactly aligned with that of the root_null_t
# before we rotate the bone to fix our X axis
root_bone_pre_align_A = hou.node('/obj').createNode('null', node_name = 'root_bone_pre_align_A')

root_bone_pre_align_B = hou.node('/obj').createNode('null', node_name = 'root_bone_pre_align_B')

root_bone_pre_align_A.setInput(0,root_bone)

root_bone_pre_align_B.setInput(0,root_null)

root_bone_pre_align_A.setParms({'tx':0.1})

root_bone_pre_align_B.setParms({'ty':0.1})

root_bone_pre_align_A_t = root_bone_pre_align_A.worldTransform().extractTranslates()

root_bone_pre_align_B_t = root_bone_pre_align_B.worldTransform().extractTranslates()

root_bone_pre_align_vec_A = root_bone_pre_align_A_t - root_null_t

root_bone_pre_align_vec_B = root_bone_pre_align_B_t - root_null_t

root_bone_pre_z_rot = root_bone_pre_align_vec_A.normalized().angleTo(root_bone_pre_align_vec_B.normalized())

root_bone.setParms({'rz':root_bone_pre_z_rot})

hou.node('/obj/').deleteItems((root_bone_pre_align_A, root_bone_pre_align_B))


# bone final align
root_bone_x_align_A = hou.node('/obj').createNode('null', node_name = 'root_bone_x_align_A')

root_bone_x_align_B = hou.node('/obj').createNode('null', node_name = 'root_bone_x_align_B')

root_bone_x_align_A.setInput(0,root_null)

root_bone_x_align_B.setInput(0,root_null)

root_bone_x_align_A.setParms({'ty':0.1})

root_bone_x_align_B.setParms({'tx':0.1})

root_bone_x_align_A_t = root_bone_x_align_A.worldTransform().extractTranslates()

root_bone_x_align_B_t = root_bone_x_align_B.worldTransform().extractTranslates()

root_bone_align_x_vec_A = root_bone_x_align_A_t - root_null_t

root_bone_align_x_vec_B = root_bone_x_align_B_t - root_null_t

root_bone_z_rot = root_bone_align_x_vec_A.normalized().angleTo(root_bone_align_x_vec_B.normalized())

root_bone.setParms({'rz':root_bone_z_rot-root_bone.evalParm('rz')})

root_bone.moveParmTransformIntoPreTransform()

#hou.hscript("bonealigncapture -c *bone*")

hou.hscript('bonealigncapture -c {}'.format(root_bone.path()))

hou.node('/obj/').deleteItems((root_bone_x_align_A, root_bone_x_align_B))
hou.f*ckatdskmaya().forever()
User Avatar
Staff
3455 posts
Joined: July 2005
Offline
Have a look at the IK From Objects tool on the Rigging shelf which does something very similar.
it uses the python code forund in $HFS/houdini/python2.7libs/rigtoolutils
Michael Goldfarb | www.odforce.net
Training Lead
SideFX
www.sidefx.com
User Avatar
Member
355 posts
Joined: Nov. 2015
Offline
Yeh thanks, didn't remember about lookat constraint lol, just thinking I need to build some sort of aim constraint(maya lingo) and lookat is there looking at me like an idiot haha. By the way, if I set up a CHOP constraint network on an object, and want to keep the values created but delete the constraint network, is baking the constraints the only way to do it?
hou.f*ckatdskmaya().forever()
User Avatar
Staff
3455 posts
Joined: July 2005
Offline
miccetro
if I set up a CHOP constraint network on an object, and want to keep the values created but delete the constraint network, is baking the constraints the only way to do it?

yep.
Michael Goldfarb | www.odforce.net
Training Lead
SideFX
www.sidefx.com
User Avatar
Member
355 posts
Joined: Nov. 2015
Offline
Ok, thanks.
hou.f*ckatdskmaya().forever()
User Avatar
Member
41 posts
Joined: May 2021
Offline
Raising this one from the dead... Well I have a problem... how do you get world rotations from IK chain of bones or parent blend constrained chain of bones, yes I'm trying to create triple chain IKFK switch/match...
When I use worldTransform extractRotates I'm getting some crazy values... Also I cannot use hou.parm().eval() on these bones because returned value is zero
Edited by kriegmesser74 - May 23, 2021 12:17:28

Attachments:
Capture.JPG (294.6 KB)

  • Quick Links