6 · 角色与面部
身体
makeCharacter(spec) 定义在 recipe/engine/character.mjs 中,用于构建一个骨骼:头部半径 0.42,身体 0.8 高,腿部 0.52,手臂 0.30 + 0.28。这些比例构成了风格:一个大球头,一个分为上下两色的豆形身体,无烟煤色的细棒状四肢,肤色连指手套手,圆润的科涅克色鞋子。
const host = makeCharacter({
name: 'host', skin: SKIN.tan,
top: BRAND.blueCoral, bottom: BRAND.anthracite, split: 0.32, width: 1.0,
hair: 'curly', hairColor: '#2a1d18',
hat: null, glasses: true, beard: false,
face: { browColor: BRAND.anthracite, browThick: 3.4, mustache: null },
extras: torso => { /* 添加领结、纽扣、徽章、工具腰带…… */ },
});
host.root.position.set(x, 0, z); place.scene.add(host.root);
| 选项 | 取值 |
|---|---|
skin | SKIN.light / fair / medium / tan / brown / deep,或任意十六进制色。在整个演员阵容中混合使用。 |
top, bottom, split, width | 豆形身体的两种颜色、它们的分界位置(0–1 高度比),以及宽度因子(1.06 表示更魁梧的体型) |
hair | short(或 cap)、bob、bun、ponytail、curly、spiky、bald,以及两种时代假发:newton(长卷发)和 einstein(自发光效果的狂野白发) |
hat / hatColor | cap、tophat(含 hatBand)、helmet(圆壳)、hardhat、beret、crown |
glasses | true 或一个镜框颜色:覆盖在绘制眼睛上的圆形镜框 |
beard | true(使用发色)或一个颜色 |
face | { browColor, browThick, mustache }:眉毛颜色和粗细,可选绘制的胡子颜色 |
extras(torso) | 使用 part(geometry, color) 添加服装部件:领结、衣领、纽扣、徽章、工具 |
为新的主题设计角色: 先确定剪影(在手机尺寸下,头发或帽子的形状是最强烈的识别特征),然后选择一种品牌色作为上衣颜色,再选择肤色。历史人物将绘制成我们自己的卡通风格:时代发型和服装就足够了(牛顿的卷曲假发和红褐色外套;爱因斯坦的狂野白发、胡子和蓝色珊瑚毛衣)。切勿复制受版权保护的角色。
带有面部的物体(苹果、行星、分子、机器): 使用 faces.mjs 中的 faceDecal(radius, { skin: <物体颜色> }) 为它们赋予面部,将眼睑颜色设置为物体颜色,并将该物体的组添加到场景的 faceCamera 列表中,使其始终面向摄像机。
面部
头部正面的扁平绘制贴花(faceDecal):眉毛、带瞳孔和高光的眼睛、嘴巴,没有鼻子,全部来自同一组形状。没有口型同步;面部负责表演。
表情(faces.mjs 中的 EXPRESSIONS):neutral, content, sleepy, surprised, shocked, curious, thinking, eureka, delighted, smug, knowing, confused, worried(带一滴汗珠)、proud(脸红)、no, wheee, dizzy(螺旋眼)、lookDown。要添加一个表情,复制一个条目并修改眉毛 [内侧, 外侧](角度)、lid(0 睁开 … 1 闭合)、look(瞳孔偏移)、eye 和 pupil 缩放、以及 mouth(flat, smile, smirk, side, wavy, o, grin, shout)。
面部切换(参考规则,精确计时)
- 仅通过眨眼切换:一帧半闭,一帧全闭,然后出现新表情。
- 新表情出现在重音词前 2 帧(
W(i) - FACE)。 - 禁止在表情之间渐变。
- 主角大约每 1.2 秒更换一次表情;物体在它们的故事节拍处切换(苹果在“错误”时刻从
smug变为shocked)。 - 长时间保持表情时的自然眨眼:传入一个
blinks时间列表。
rig.faceAt(t, [[0, 'curious'], [W(17) - FACE, 'smug']], [0.75, 6.2]); // 切换表情,然后自然眨眼
objectFace.set('shocked'); // 对象的即时设置
手和手持道具
rig.handPos('L' | 'R' | 'both') 返回当前姿势下手部的世界位置;每一帧将手持道具放置在该位置(牛顿手中的书,爱因斯坦扔球前的保龄球)。rig.headPos() 返回头部中心位置,用于取景。
检查清单
- 在手机尺寸下,是否能仅凭剪影区分每个角色?
- 眼睑颜色是否与肤色或身体颜色匹配(眨眼时不透光)?
- 在角色表演的每个镜头中,面部是否始终面向摄像机?