原文链接
在 blender 中使用 python 生成角色动画(一)| 包包凯
正文
初衷
在一些具体使用场景上,我们希望能够 根据不同的语音,自动生成对应的卡通角色动画,以节省大量的 3D 动画师的工作,故通过脚本生成动画是必要的技术。
为什么选用 Blender
轻巧、免费、够用,另外 Python 平时也用的多。
整体流程
整体流程如下:
本文对应 输入部分 不做过多描述,仅对 动画生成 和 渲染部分 进行说明。即假设目前已经有包含输入信息,包括:
- 语音:一般为 TTS 生成的语音
- 断句时间点:即语音中每一句话的起始时间点
- 语句情绪:即语音中每句话对应的情绪
- 嘴型:即和时间线对齐的嘴型参数,用于指导嘴型动画
动画生成
使用的模型
使用的模型如下,其中眼睛和嘴部包含了 BlendShape ,眼睛可以上下左右移动,嘴巴可以上下张合和左右扩展。
由于卡通角色比较简单,所以骨骼也做了大幅简化。
- 演示模型
该模型 保存了动作在动作库(Blender3.0 的新功能),如下所示包含了两个动作:stand
和 happy
,后面会使用。
- Blender 动作库
Python 控制
以下说明没有按照以上流程图的步骤来进行,而是按照类别的不同进行说明,具体每个步骤如何生成在此不进行赘述。
动画生成包含以下部分:
- BPY 控制的内容
1. BPY 控制形态键
# shape_keys -> key_blocks
shapekey = bpy.data.shape_keys.get("Key_eye") # 找到对应的形态键组
key_block = shapekey.key_blocks.get("eye_look_right") # 一个组中可能有多个 key
key_block.value = x # 对形态键赋值
key_block.keyframe_insert(data_path="value", frame=frame_id) # 插入关键帧
形态键组 可以在大纲视图中查到:
- 形态键组
对应的 形态键 为(建模时做的):
- 形态键
如本项目中,对于眼睛,随机插入关键帧使其有随机的小幅度移动;对于嘴,则根据口型来控制其张合和扩展。生成的动画摄影表如下:
- 形态键的动画摄影表
2. BPY 控制骨骼移动旋转
# pose -> bones -> rotation_euler
ob = bpy.data.objects['armature']
head=ob.pose.bones['head']
head.rotation_mode = 'XYZ' # 旋转有不同的模式,这里采用的是 XYZ 的模式
head.rotation_euler.rotate_axis("X", x)
head.rotation_euler.rotate_axis("Y", y)
head.rotation_euler.rotate_axis("Z", z)
head.keyframe_insert(data_path="rotation_euler" ,frame=frame_id) # 将旋转角度信息插入关键帧
和控制 形态键 类似,只是操作对象和参数不同,这里对头部和身体做随机的转动,生成的 动画摄影表 如下:
- 单个骨骼的动画摄影表
3. BPY 使用姿态库资源
由于有很多复杂的 动作,不可能都在代码里面控制一根根骨骼来实现,故在 Blender 中可以先制作 一批固定的动作,然后直接将其 应用到姿态后,再(针对 位置 和 旋转)插入关键帧 即可。
ob = bpy.data.objects['armature']
# 将 happy 姿态插入第 1 帧
act = bpy.data.actions.get("happy")
ob.pose.apply_pose_from_action(act)
for bone in ob.pose.bones:
bone.keyframe_insert(data_path="rotation_euler", frame=1)
bone.keyframe_insert(data_path="location", frame=1)
# 将 stand 姿态插入第 10 帧
act = bpy.data.actions.get("stand")
ob.pose.apply_pose_from_action(act)
for bone in ob.pose.bones:
bone.keyframe_insert(data_path="rotation_euler", frame=10)
bone.keyframe_insert(data_path="location", frame=10)
PS: 这里有一点需要 注意 的是,旋转有 四元数 形式或者 XYZ 形式,这个是不互通的,即
- 如果姿态库的姿态是在 四元数 形式做的话,设置的变量就是
data_path = "rotation_quaternion"
- 如果是 XYZ 形式的话就是
data_path = "rotation_euler"
更加灵活的动作控制可以参考 【转载】在 Blender 中使用 Python 生成角色动画(二)- NLA 非线性动画 ,即它可以单独控制某个动作在时间线的位置,也就是说可以将动作保存(动作编辑器),继而加入到对应实体的对应 动画轨道 上(NLA)
后台渲染
1. 在 Blender 中预设渲染属性
实际上渲染属性,如帧率、分辨率等都 可以使用 Python 脚本来控制,不过这里就直接在 Blender 里面设置了。
2. 后台渲染
由于后续需要支持自动化生成,故 命令行的方式 进行后台渲染是必要的。Blender 可以很方便的支持后台渲染:
CHCP 65001
blender -b xxx.blend -P xxx.py -a
在输出目录可以看到结果。
最终效果
以下效果仅验证 BPY 控制,未针对断句等进行处理。
后续工作
后面还会研究如何通过脚本生成动画