Facial Rig GUI for Visemes

MakeHuman python API, python plugins, etc

Moderator: joepal

Facial Rig GUI for Visemes

Postby brkurt » Sat Jun 04, 2016 3:03 am

Hello everyone...

After about two days, I was able to find the python code to create the first step of a facial rig GUI that works directly with the bones, rather than through drivers. I need this because my model has to pass through Collada unscathed (so it can go to and from Blender and Marvelous Designer). :o

The interesting part is that I found the right code snippet to control FK bone rotation, but I can't find a snippet to control transform location that is as easy to understand. :)

Try this model yourself, to see how easy the script is:

http://www.geekopolis.ca/blender/visemes/euler_rotation2_264a.blend

To make things even weirder, I've got Thomas' old 2.4 lipsync script working just fine for FK bone transforms (it doesn't need the pydriver script for this).

Image

Unfortunately that code is so old, I can't make sense of how to move it to at least 2.64a. :?

Does anyone know how to move a bone's location in python for at least 2.64a? That's all I need to finish the first GUI.
The code will be clunky, but it will work.
brkurt
 
Posts: 1100
Joined: Sun Feb 17, 2008 8:49 pm

Re: Facial Rig GUI for Visemes

Postby brkurt » Sat Jun 04, 2016 8:09 pm

As usual, I had to figure this out myself, but here it is folks, the way to create a viseme GUI that will work everytime, in Blender 2.6x and up.
I've uploaded the changes to the same model as above.

Here is the 'AH' or 'Mouth Open' viseme, a dropped-down jaw and rotated to a wide open mouth.

Before the Python script:

Image

and after the Python script:

Image

And here is the code, clunky right now, but it will work.

import bpy
import math

ob = bpy.data.objects['aestheticaRig']
bpy.context.scene.objects.active = ob
bpy.ops.object.mode_set(mode='POSE')


# Create the 'AH' viseme

# drop Jaw slightly
# location[0] = X axis
# rotate Jaw 15 degrees on X axis

pbone = ob.pose.bones['Jaw']

# Z axis
pbone.location[2] = .1

# Y axis
pbone.location[1] = .1

pbone = ob.pose.bones['Jaw']
# Set rotation mode to Euler XYZ, easier to understand
# than default quaternions
pbone.rotation_mode = 'XYZ'
# select Z axis in ['X','Y','Z'] <--bone local
axis = 'Z'
angle = 0
pbone.rotation_euler.rotate_axis(axis, math.radians(angle))
# select Y axis
axis = 'Y'
angle = 0
pbone.rotation_euler.rotate_axis(axis, math.radians(angle))
# select X axis
axis = 'X'
angle = 15
pbone.rotation_euler.rotate_axis(axis, math.radians(angle))
# go to Object mode
bpy.ops.object.mode_set(mode='OBJECT')
#insert a keyframe
pbone.keyframe_insert(data_path="rotation_euler" ,frame=1)
brkurt
 
Posts: 1100
Joined: Sun Feb 17, 2008 8:49 pm

Re: Facial Rig GUI for Visemes

Postby brkurt » Fri Jun 10, 2016 5:24 pm

Okay, just about done.

Here is the same model, with a modified "hello.py" script that does what I needed. If you left-click on the 'AH' button, the sayAH() function runs like it is supposed to. Some fine-tuning and it is done.

Try it yourself: http://www.geekopolis.ca/blender/visemes/sayAH2_264a.blend

And here is the python script:

#----------------------------------------------------------
# File hello.py
#----------------------------------------------------------
import bpy
from sayAH import sayAH

#
# Menu in toolprops region
#
class ToolPropsPanel(bpy.types.Panel):
bl_label = "AH Viseme"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOL_PROPS"

def draw(self, context):
self.layout.operator("hello.hello", text='AH').viseme = "AH"

#
# The Hello button prints a message in the console
#

class OBJECT_OT_HelloButton(bpy.types.Operator):
bl_idname = "hello.hello"
bl_label = "Say Hello"
viseme = bpy.props.StringProperty()

def execute(self, context):
if self.viseme == 'AH':
print("Hello world!")
sayAH()
else:
print("Hello world from %s!" % self.viseme)
return{'FINISHED'}

#
# Registration
# All panels and operators must be registered with Blender; otherwise
# they do not show up. The simplest way to register everything in the
# file is with a call to bpy.utils.register_module(__name__).
#

bpy.utils.register_module(__name__)
brkurt
 
Posts: 1100
Joined: Sun Feb 17, 2008 8:49 pm

Re: Facial Rig GUI for Visemes

Postby brkurt » Thu Jun 16, 2016 2:27 am

Well, I shouldn't have, but I did. :D Since my teaching contracts are all signed, I've decided to teach myself Python.
I've seen really a lot of requests on Blender forums asking for an understanding of how to use quaternions, which supposedly are the way to go for multiple rotated axes (which is what my custom rig needs).

Now, I apologize for using late Cretaceous software, but that's what runs best on my rack servers, and Blender 2.49b really gets along well with Yafaray. There, apology finished.

Now, for those nasty quaternions. You can get all kinds of technical (very!) explanations off the net, so I won't go into that here.
What I will show you is how to control them.

The easist way is to go to: http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/

install Java for your browser (if it isn't already installed) and do the calculations there.

Image

Many thanks for Thomas for his lipsync script. :)

Here is some ancient Python, but I bet this won't be too hard to update:

=============BEGIN ANCIENT PYTHON=========================


def setBoneRotation(Jaw):
amtOb = Object.Get('humanRig')
amtOb.sel = True
pose = amtOb.getPose()
pbones = pose.bones
pbones['Jaw'].quat[:] = 1.0,0.25,0.00,0.00
pose.update()
Window.PoseMode(0)
Window.PoseMode(1)

meshOb = Object.Get('humanMesh')
meshOb.sel = True
Window.EditMode(1)
Window.EditMode(0)
amtOb.sel = True
Draw.Redraw(-1)
return


===============END ANCIENT PYTHON==========================

And this is what it looks like in action:

Image

And, finally this is what complete control looks like. I always add an 'innerJaw' to situate the lower dentures properly.
The design principle is: "one function for each viseme".

"""
'AH' : [('Jaw', (0,.1,0)), ('tongueBase', (0,0,0)), ('tongueTip', (0,0,0)), ('innerJaw', (0,-.1,0)), ('lipRing', (0,0,0)),('upperLip_R',(0,0,0)),('upperLipMiddle',(0,0,0)),('upperLip_L',(0,0,0)),('lowerLip_R',(0,0,0)),('lowerLipMiddle',(0,0,0)),('lowerLip_L',(0,0,0)),('mouthCorner_R',(0,0,0)),('mouthCorner_L',(0,0,0))], \

"""

===============BEGIN ANCIENT PYTHON==========================

# one function for each viseme

def setBoneRotation(Jaw):
amtOb = Object.Get('humanRig')
amtOb.sel = True
pose = amtOb.getPose()
pbones = pose.bones
pbones['Jaw'].quat[:] = 1.0,0.15,0.00,0.00
pbones['innerJaw'].quat[:] = 1.0,-0.15,0.00,0.00
for (b, (x,y,z)) in Visemes['AH']:
loc = Vector(float(x),(float(y)),float(z))
pbones[b].loc = loc
pose.update()
Window.PoseMode(0)
Window.PoseMode(1)

meshOb = Object.Get('humanMesh')
meshOb.sel = True
Window.EditMode(1)
Window.EditMode(0)
amtOb.sel = True
Draw.Redraw(-1)
return

===============END ANCIENT PYTHON==========================

Also: Remember to Delete All Actions in your Action Editor before running this script (or a variation of it); otherwise, the 'Rest' position will be determined by the action at that frame.
brkurt
 
Posts: 1100
Joined: Sun Feb 17, 2008 8:49 pm


Return to Python scripts

Who is online

Users browsing this forum: No registered users and 1 guest