Three.js 3D桌宠实现
Three.js 3D 桌宠的 glTF 蒙皮动画原理与 TS 语义接口、依赖清单
摘要: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 语义接口如下。
三条核心交互的实现思路:动作混合由 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 抽象下各有实现,选型框架即可直接驱动代码骨架。