Three.js 3D桌宠实现
Three.js 3D 桌宠的 glTF 蒙皮动画原理与 TS 语义接口、依赖清单
Three.js 3D桌宠实现
摘要:3D 桌宠以网格蒙皮 + 骨骼动画为基底,提供四方案中最高的自由度——骨骼级控制、动作交叉混合、物理模拟与 360° 立体表现。本文说明 glTF/GLB 资产链与渲染管线,给出 TS 语义接口与依赖清单,覆盖载入、动作混合、分部位点击、视线跟随与销毁。
3D 方案把「结构」下沉到网格层级。美术在 Blender/Maya 中建模后绑定骨骼,以顶点权重(Skinning)把网格顶点关联到骨骼,再制作骨骼关键帧动画;导出为 glTF/GLB 标准格式后,网格、骨骼层级、动画轨道与材质全部内嵌于单文件。前端 GLTFLoader 解析后得到 scene、animations(每段动作一条 AnimationClip)与骨架,运行时由 AnimationMixer 逐帧推进骨骼姿态、GPU 完成蒙皮变形。与 Live2D 的参数插值相比,3D 的插值发生在骨骼空间,天然支持动作间交叉淡化(crossfade)与单骨骼独立控制。
渲染管线的关键点:AnimationMixer 管理多条动作轨道,clipAction 按权重混合,crossFadeTo 实现动作平滑过渡——这是 idle 与 walk 之间不跳变的基础;场景内宠物需要「鼠标穿透」体验时,容器设置 pointer-events: none,交互改用 Raycaster 手动做射线命中测试,命中结果落到具体网格即可识别「点了头还是手」;面向鼠标的头部转向通过 Quaternion 插值旋转头部骨骼节点实现,不必整模旋转。
Three.js 的 TS 语义接口如下。
// 依赖:three + @types/three(备选 babylonjs,接口等价)
interface GltfPet3D {
/** 载入 glTF/GLB,返回动画清单供 play 引用 */
load(url: string, opts?: { scale?: number; position?: [number, number, number] }): Promise<string[]>;
/** 播放动作,crossfade 秒内与当前动作交叉淡化 */
play(name: string, crossfade?: number): void;
/** 双动作按 t(0~1) 混合,用于过渡姿态 */
mix(a: string, b: string, t: number): void;
/** 头部朝向指定屏幕坐标(结合 Raycaster 换算世界方向) */
faceAt(screenX: number, screenY: number): void;
/** 点击回调:命中信息含被点部件名(网格名约定为部件契约) */
onTap(cb: (hit: { part: string; distance: number }) => void): void;
/** 启用/关闭物理模拟(需物理引擎,如 cannon-es) */
setPhysics(enabled: boolean): void;
/** 挂载到容器,内部创建 WebGL 渲染器并启动 rAF 循环 */
mount(container: HTMLElement): void;
update(dt: number): void;
destroy(): void;
}
三条核心交互的实现思路:动作混合由 mixer.clipAction(a).crossFadeTo(clipAction(b), t) 完成,权重由 clipAction.setEffectiveWeight 控制,配合 update(dt) 推进即可实现任何姿态插值;分部位点击用 Raycaster.setFromCamera 对全部网格做 intersectObjects,以命中对象名映射部件语义(因此网格命名是美术与代码的第二个契约,应在导出前规范化);视线跟随把指针坐标经 unproject 换算为射线,取与头部朝向平面的交点,再对头部骨骼 Quaternion.slerp 平滑旋转,限制俯仰角防止头部过度后仰。
注意点:模型体积与 GPU 开销是四方案之最,资产应经 gltf-transform 做 Draco/Meshopt 压缩并启用纹理降级(LOD),低端设备退回 SpriteAnimator 或 Live2DPet 实现;光照默认用 AmbientLight + DirectionalLight 双灯即可避免「廉价感」,忌无阴影或全高光;rAF 循环需在页面不可见时暂停(visibilitychange)以省电。展望:换装即运行时替换材质或网格;物理模拟可为头发、裙摆等附加软体约束;多角色同屏时按距离卸载动画轨道。至此四方案在统一 PetRenderer 抽象下各有实现,选型框架即可直接驱动代码骨架。