lishengzxc / bblog

My Blog
https://github.com/lishengzxc/bblog/issues
178 stars 8 forks source link

【翻译】Three.js — Animation system #40

Open lishengzxc opened 6 years ago

lishengzxc commented 6 years ago

原文:https://threejs.org/docs/index.html#manual/introduction/Animation-system

概述

在 three.js 的动画系统中,你可以为模型设置各种属性的动画,比如:蒙皮和绑定模型的骨骼顶点动画,不同的材质属性(颜色,不透明度,布尔值),可见性和形变。动画属性可以淡入、淡出、交叉渐变与变形。同一时间的不同动画对同一对象以及不同对象的权重和时间尺度可以独立修改,同一对象和不同对象上个各种动画可以同步变化。

为了实现同类系统中的所有动画功能,three.js 的动画系统已经在2015年完全改变,现在它具有类似于 Unity / Unreal Engine 4 的结构体系。本章将简要概述改动画系统的主要组件以及它们如何协同工作。

Animation Clips

如果你已经成功导入了一个动画 3D 对象(不用关心它是骨骼动画还是顶点动画或者它们都是)。举个例子,你在 Blender 中使用 Blender exporter 将模型导出,并使用 JSONLoader 将它加载到 three.js 的场景中,加载完成的几何体网格对象会有一个名为 "animations" 的数组,其中包含这个模型的 AnimationClips。

每个 AnimationClip 通常保存该对象的特定动画的数据。例如,如果网格是角色,则可能有一个用于步行循环的 AnimationClip,第二个用于跳转,第三个用于跳转等。

Keyframe Tracks

在 AnimationClip 中,每个动画属性的数据都存储在一个单独的 KeyframeTracks 对象中。假定一个角色模型具有骨架,一个 KeyframeTracks 可以存储随着时间推移下的骨骼位置变化的数据,另外一个用于存储骨骼的旋转变化,第三个用于旋转护着缩放另外一块骨骼。我们应该想象,AnimationClip 可以由多个这样的轨道组成。

再假设模型具有顶点动画(比如一个动画显示友好的脸部表情,另外一个动画显示愤怒的脸部表情),每个 KeyframeTracks 就保存如何影响动画片段在执行过程中的某个顶点动画。

Animation Mixer

那些被存储的数据仅仅是动画的基础,实际上动画的播放是用 AnimationMixer 来控制。你可以想象并认为它不仅是一个动画播放器,而是像一个真正的硬件混音器那般,可以用时控制几个动画并混合它们。

Animation Actions

AnimationMixer 本身只有很少的(普通)属性与方法,因为它可以通过控制 AnimationActions。通过配置一个 AnimationAction,你可以指定它何时应该在其中一个 AnimationMixer 中播放,暂停或者停止,是否需要重复,如何重复,以及是否使用渐变还是调整动画的播放时间,还有些其他额外的东西,如交叉淡入淡出或是同步。

Animation Object Groups

如果你希望一组对象接受并共享动画的状态,可以使用AnimationObjectGroup

已经支持的格式解析与加载器

请注意,并非所有模型的格式都包含动画(.obj 显然不包含动画),只有以下 three.js 的加载器支持 AnimationClip

注意,3ds max 和 Maya 目前无法将多个动画(即不在同一时间轴上的动画)直接导出到单个文件。

Example

var mesh;

// Create an AnimationMixer, and get the list of AnimationClip instances
var mixer = new THREE.AnimationMixer( mesh );
var clips = mesh.animations;

// Update the mixer on each frame
function update () {
    mixer.update( deltaSeconds );
}

// Play a specific animation
var clip = THREE.AnimationClip.findByName( clips, 'dance' );
var action = mixer.clipAction( clip );
action.play();

// Play all animations
clips.forEach( function ( clip ) {
    mixer.clipAction( clip ).play();
} );