又复习了一下glTF模型,发现了一个很好的英文教程,讲解的非常详细。没有图形学知识背景的人也可以听懂。学习的时候,就顺便翻译成中文,来和大家分享 。当然,更推荐看英文教程。
Animations
如Simple animation所示, animation
可用于描述节点的translation
, rotation
或 scale
属性如何随时间变化。
下面是animation
的另一个例子。 这一次,动画包含两个通道。 一个通道用于动画的平移,另一个通道用于动画节点的旋转:
"animation0": {
"channels": [
{
"sampler": "translationSampler",
"target": {
"id": "node0",
"path": "translation"
}
},
{
"sampler": "rotationSampler",
"target": {
"id": "node0",
"path": "rotation"
}
}
],
"samplers": {
"translationSampler": {
"input": "timeAccessor",
"interpolation": "LINEAR",
"output": "translationAccessor"
},
"rotationSampler": {
"input": "timeAccessor",
"interpolation": "LINEAR",
"output": "rotationAccessor"
}
}
}
动画采样器
samplers
字典包含animation.sampler
对象,它定义了访问器提供的值如何在关键帧之间插值:
图 4a: 动画采样器
可以使用以下算法,计算当前动画时间的平移量:
- 将当前动画时间赋值给
currentTime
-
计算
timeAccessor
中的仅次于currentTime
的值和仅大于currentTime
的值:previousTime
=timeAccessor
中仅次于currentTime
的值nextTime
=timeAccessor
中仅大于currentTime
的值 -
从
translationAccessor
中获取相应元素previousTranslation
=translationAccessor
中对应previousTime
的元素nextTranslation
=translationAccessor
中对应nextTime
的元素 -
计算插值(0.0~1.0)。它描述了
previousTime
和nextTime
之间,当前时间点(currentTime
)的 相对 位置:interpolationValue = (currentTime - previousTime) / (nextTime - previousTime)
-
利用插值计算当前时间的平移量
currentTranslation = previousTranslation + interpolationValue * (nextTranslation - previousTranslation)
例子:
假设currentTime
是 1.2。timeAccessor
中仅次于它的值为 0.8,仅大于它的值为 1.6。所以
previousTime = 0.8
nextTime = 1.6
translationAccessor
中可以查到相应的值:
previousTranslation = (14.0, 3.0, -2.0)
nextTranslation = (18.0, 1.0, 1.0)
插值计算如下:
interpolationValue = (currentTime - previousTime) / (nextTime - previousTime)
= (1.2 - 0.8) / (1.6 - 0.8)
= 0.4 / 0.8
= 0.5
从插值可以计算出平移量:
currentTranslation = previousTranslation + interpolationValue * (nextTranslation - previousTranslation)`
= (14.0, 3.0, -2.0) + 0.5 * ( (18.0, 1.0, 1.0) - (14.0, 3.0, -2.0) )
= (14.0, 3.0, -2.0) + 0.5 * (4.0, -2.0, 3.0)
= (16.0, 2.0, -0.5)
因此当前时间是 1.2,节点的translation
为 (16.0, 2.0, -0.5)
动画通道
动画包含 animation.channel
对象数组。 通道在输入(即从采样器计算的值)和输出(即动画节点属性)之间建立连接。 因此,每个通道利用ID引用一个采样器,并且包含一个 animation.channel.target
对象。 target
利用ID引用了一个节点,并且包含一个 path
, path
定义了应该动画化的节点属性的路径。 来自采样器的值将写入此属性。
在上面的示例中,动画有两个通道,两者引用同一节点。第一通道的路径引用的是节点的translation
,第二通道的路径引用的是节点的rotation
。 因此,连接到节点的所有对象(网格)将被平移旋转:
图 4b: 动画通道
著作权声明
作者 陈兴旺,首次发布于 WunWun Blog,转载请保留以上链接