IC 8 Python API:Facial Animation
- Main article: iC8 Python API.
iClone 8 has redesigned the facial animation architecture to allow for different expression sets and customized expression morphs. Currently, three expression sets are supported: Traditional, CC4 Standard, and CC4 Extended. You can view their differences by operating the Face Key dialog window.
The name of the expression set can be obtained with the RIFaceComponent.GetExpressionSetUid() function.
1 face_component = avatar.GetFaceComponent()
2 print(face_component.GetExpressionSetUid())
3 # IC7 Standard, CC4 Standard, CC4 Extended
You can also use RIFaceComponent.GetExpressionGroups() to get the category names of expressions (e.g. "Brow", "Eye", "Nose"). To get all the expression names, use RIFaceComponent.GetExpressionNames(), or enter the group name to get all the expression names that belong to it. Afterward, the expression name can be used to set keys.
1 face_component = avatar.GetFaceComponent()
2 exp_groups = face_component.GetExpressionGroups()
3 print("expression groups="+str(exp_groups ))
4 # Brow, Eye, Nose…
5
6 # all expressions
7 exp_names = face_component.GetExpressionNames("")
8 print("expression names="str(exp_names))
9 # Brow_Raise_Inner_Left, Brow_Raise_Inner_Right, Brow_Raise_Outer_Left…
10
11 # expressions in Eye group
12 exp_names = face_component.GetExpressionNames("Eye")
13 print("Eye expression names="str(exp_names))
14 # Eyes_Blink, Eye_Blink_L, Eye_Blink_R…
When you are generating facial animation, use RIFaceComponent.AddClip() to add an expression clip at a specified time. Then use RIFaceComponent.AddExpressionKeys to enter the Key in the clip range. In order to improve the performance for setting keys, AddExpressionKeys needs to be wrapped between RIFaceComponent.BeginKeyEditing() and RIFaceComponent.EndKeyEditing(). The code is as follows:
1 face_component = avatar.GetFaceComponent()
2
3 # get Expression names
4 exp_names = face_component.GetExpressionNames("")
5 print ("expression names="+str(exp_names))
6
7 # create an expression clip
8 srt_time = RLPy.IndexedFrameTime(30, RLPy.RGlobal.GetFps())
9 clip_length = RLPy.IndexedFrameTime(100, RLPy.RGlobal.GetFps())
10 face_component.AddClip(srt_time, "ExpressionClip", clip_length)
11
12 # add Expression Key
13 exp_val = [1.0]*len(exp_names)
14 Inv_time = RLPy.IndexedFrameTime(0, RLPy.RGlobal.GetFps())
15 key_time = RLPy.IndexedFrameTime(40, RLPy.RGlobal.GetFps())
16 face_component.BeginKeyEditing()
17 face_component.AddExpressionKeys( key_time, exp_names, exp_val, Inv_time )
18 face_component.EndKeyEditing()
If you plan on setting keys at a fixed time interval, you can also specify Inv_time when RIFaceComponent.AddExpressionKeys is used to quicken the process.
1 face_component = avatar.GetFaceComponent()
2
3 # get Expression names
4 exp_names = face_component.GetExpressionNames("")
5 print ("expression names="+str(exp_names))
6
7 # create an expression clip
8 srt_time = RLPy.IndexedFrameTime(30, RLPy.RGlobal.GetFps())
9 clip_length = RLPy.IndexedFrameTime(100, RLPy.RGlobal.GetFps())
10 face_component.AddClip(srt_time, "ExpressionClip", clip_length)
11
12 # add Expression Keys repeatedly
13 exp_val = [0.0]*len(exp_names)
14 exp_val += [0.5]*len(exp_names)
15 exp_val += [1.0]*len(exp_names)
16 exp_val += [0.5]*len(exp_names)
17 exp_val += [0.0]*len(exp_names)
18
19 Inv_time = RLPy.IndexedFrameTime(10, RLPy.RGlobal.GetFps())
20 key_time = RLPy.IndexedFrameTime(30, RLPy.RGlobal.GetFps())
21 face_component.BeginKeyEditing()
22 face_component.AddExpressionKeys( key_time, exp_names, exp_val, Inv_time )
23 face_component.EndKeyEditing()
24 # add 0.0 at Frame 30
25 # add 0.5 at Frame 40
26 # add 1.0 at Frame 50
27 # add 0.5 at Frame 60
28 # add 0.0 at Frame 70
In addition, if you use mocap to generate facial animation, you'll need to make corresponding changes to call the API via RIFaceComponent.GetExpressionNames("", True). The second parameter must be set to "True" to get a list of expression names that are ordered according to the mocap. When calling RIFacialDevice.ProcessData(), the expression values in this order must be substituted. An example of this in practice is as follows:
1 face_component = mocap_avatar.GetFaceComponent()
2
3 exp_names = face_component.GetExpressionNames("", True)
4 print(str(exp_names))
5
6 # start mocap
7 mocap_manager.Start(RLPy.EMocapState_Preview)
8
9 # after receiving facial data from the device…
10 exp_list = [0.5]*len(exp_names)
11 facial_device.ProcessData(mocap_avatar, exp_list)
12
13 # end mocap
14 mocap_manager.Stop()