动画

glTF系列教程07

Posted by WunWun on July 22, 2017

又复习了一下glTF模型,发现了一个很好的英文教程,讲解的非常详细。没有图形学知识背景的人也可以听懂。学习的时候,就顺便翻译成中文,来和大家分享 。当然,更推荐看英文教程

Animations

Simple animation所示, animation可用于描述节点的translation, rotationscale属性如何随时间变化。

下面是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对象,它定义了访问器提供的值如何在关键帧之间插值:

java-javascript 图 4a: 动画采样器

可以使用以下算法,计算当前动画时间的平移量:

  • 将当前动画时间赋值给currentTime
  • 计算timeAccessor中的仅次于currentTime的值和仅大于currentTime的值:

    previousTime = timeAccessor中仅次于currentTime的值

    nextTime = timeAccessor中仅大于currentTime的值

  • translationAccessor中获取相应元素

    previousTranslation = translationAccessor中对应previousTime的元素

    nextTranslation = translationAccessor中对应nextTime的元素

  • 计算插值(0.0~1.0)。它描述了previousTimenextTime之间,当前时间点(currentTime)的 相对 位置:

    interpolationValue = (currentTime - previousTime) / (nextTime - previousTime)

  • 利用插值计算当前时间的平移量

    currentTranslation = previousTranslation + interpolationValue * (nextTranslation - previousTranslation)

例子:

假设currentTime1.2timeAccessor中仅次于它的值为 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引用了一个节点,并且包含一个 pathpath定义了应该动画化的节点属性的路径。 来自采样器的值将写入此属性。

在上面的示例中,动画有两个通道,两者引用同一节点。第一通道的路径引用的是节点的translation,第二通道的路径引用的是节点的rotation。 因此,连接到节点的所有对象(网格)将被平移旋转:

java-javascript 图 4b: 动画通道

著作权声明

作者 陈兴旺,首次发布于 WunWun Blog,转载请保留以上链接