【问题标题】:Synchronize the animation timing with data (ThreeJS)将动画时间与数据同步(ThreeJS)
【发布时间】:2018-04-11 10:11:09
【问题描述】:

我有一个数据,以毫秒为单位的时间和当时对象的位置(x,y,z)。

msec    |poz_x  |poz_y  |poz_z
------------------------------
0       |318    |24     |3
25      |318    |24     |3
49      |318    |23     |3
70      |318    |22     |2
91      |318    |22     |2
113     |318    |21     |1
136     |318    |21     |1
e.t.c

问题在于实际数据和下一个数据之间的时间差不同(来自传感器)。 我正在寻找一种实时制作动画的方法。 如果在我的数据中我有 60 秒的信息,它需要在 60 秒内在浏览器中制作动画。 我读过requestAnimationFrame( animate ); 每秒会重复该功能 60 次,但如果我的场景很重,我想帧速率会下降。无论如何,这不能解决我的问题。

我正在寻找一种不依赖于浏览器当前帧速率的强大解决方案。 请帮忙。

【问题讨论】:

  • 我认为您的要求不清楚。
  • 请问您阅读后有什么问题,以便我更好地解释。当然,这也有助于其他人了解我的问题。这是我第一次尝试在这里提问,因为我没有看到其他解决方法。

标签: javascript html animation time three.js


【解决方案1】:

有几种方法可以解决这个问题,无论是否使用库。 你是对的,它并不像计算动画循环的滴答数那么简单,因为不能保证它每 1/60 秒发生一次。但是动画帧回调(下面代码中的loop)将获得一个时间戳作为第一个参数传递,该参数可用于计算动画进度。

所以,在 javascript 中,可能是这样的:

// these are your keyframes, in a format compatible with THREE.Vector3. 
// Please note that the time `t` is expected in milliseconds here.
// (must have properties named x, y and z - otherwise the copy below doesn't work)
const keyframes = [
  {t: 0, x: 318, y: 24, z: 3},
  {t: 25, x: 318, y: 24, z: 3},
  // ... and so on
];

// find a pair of keyframes [a, b] such that `a.t < t` and `b.t > t`. 
// In other words, find the previous and next keyframe given the 
// specific time `t`. If no previous or next keyframes is found, null 
// is returned instead.
function findNearestKeyframes(t) {
  let prevKeyframe = null;
  for (let i = 0; i < keyframes.length; i++) {
    if (keyframes[i].t > t) {
      return [prevKeyframe, keyframes[i]];
    }
    prevKeyframe = keyframes[i];
  }

  return [prevKeyframe, null];
}

const tmpV3 = new THREE.Vector3();

function loop(t) {
  const [prevKeyframe, nextKeyframe] = findNearestKeyframes(t);

  // (...not handling cases where there is no prev or next here)

  // compute the progress of time between the two keyframes 
  // (0 when t === prevKeyframe.t and 1 when t === nextKeyframe.t)
  let progress = (t - prevKeyframe.t) / (nextKeyframe.t - prevKeyframe.t);

  // copy position from previous keyframe, and interpolate towards the 
  // next keyframe linearly
  tmpV3.copy(nextKeyframe);
  someObject.position
    .copy(prevKeyframe)
    .lerp(tmpV3, progress);

  // (...render scene)

  requestAnimationFrame(loop);
}

// start the animation-loop
requestAnimationFrame(loop);

编辑:解决 cmets 关于优化 findNearestKeyframes-function 的一个问题:

一旦您获得了数千个关键帧,就可以稍微优化一下,是的。对于几百个这样的东西,不值得付出努力(我将其归类为过早的优化)。

为了优化,您可以创建一个索引表以跳过数组中不相关的部分。例如,您可以在每 10 秒或类似的开始时将索引存储在关键帧数组中,这样 - 当您在 t = 12.328s 附近搜索关键帧时,您可以从更高的索引开始预先计算的信息。您可能可以使用许多其他算法和结构来加速它。

【讨论】:

  • 如果不是在 findNearestKeyframes(t) 中执行前向循环,而是尝试从实际时间点在向上和向下方向进行某种类型的双循环,您认为它可以执行得更好吗?我是浏览器渲染的相对论新手,所以我不太熟悉它的性能。如果有时间我会尝试一些比较。
  • 顺便说一句。我认为你的代码中有一些奇怪的东西 getNearestKeyframes(t) findNearestKeyframes(t)
  • 谢谢,我更正了错误的函数名称,并在优化方面更新了答案
猜你喜欢
  • 1970-01-01
  • 2012-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-14
  • 2018-09-30
  • 1970-01-01
相关资源
最近更新 更多