【问题标题】:Create smooth rotation in given time interval (+- x%)在给定的时间间隔内创建平滑旋转 (+- x%)
【发布时间】:2012-09-19 13:20:33
【问题描述】:

我的场景中有一个立方体,我想以特定的起始速度给定的时间间隔旋转它。
此外,立方体的结束角度应与开始角度相同。 因此,我想到了允许时间间隔± 5% 的偏差。

这是我目前的状态:http://jsfiddle.net/5NWab/1/
不要怀疑它目前工作。如果我更改时间间隔,就会出现问题,例如通过'3000':http://jsfiddle.net/5NWab/2/

我的立方体必不可少的move()方法:

Reel.prototype.move = function (delta) {
    if (this.velocity < 0 && this.mesh.rotation.x == 0) {
        return false;
    }

    // Create smooth end rotation
    if (this.velocity < 0 && this.mesh.rotation.x != 0) {
        this.mesh.rotation.x += Math.abs(delta * this.speedUp * 0.5 * this.timeSpan);
        if (Math.abs(this.mesh.rotation.x - 2 * Math.PI) < 0.1) {
            this.mesh.rotation.x = 0;
        }
    }

    else {
        this.mesh.rotation.x += delta * this.velocity;

        this.time -= delta;
        this.velocity = this.speedUp * this.time;
    }
}

问题是我想不出一个解决方案或方法来完成我的主题。 如果我的变量delta 保持不变,它就不会那么复杂了。
它应该 60fps = 1000/60,因为我使用的是requestAnimationFrame()

我还找到了this question,这可能有助于找到解决方案。

我认为代码应该是

  • 在到达实际终点之前减慢速度。
    如果最终角度略大于所需的(开始)角度,则应该是这种情况。

  • 还是应该在到达实际终点后加快转速。
    如果最终角度比所需(开始)角度小一点,情况应该如此。

但是当角度与所需角度相差一个半圆(即 180° 或 PI)时是什么情况?

为了澄清我的问题,以下是我的已知和未知数:

已知:

  • 起始速度
  • 时间间隔
  • 起始角度(通常为 0)

我希望立方体在旋转结束时具有相同的起始角度/位置。 因为 FPS 计数不是恒定的,我必须缩短或延长时间间隔才能让立方体进入所需位置。

【问题讨论】:

  • 这个问题读起来有点迟钝。你的已知和未知数是什么?
  • @IgnacioVazquez-Abrams 我在最后添加了一小段。现在清楚了吗?
  • 我不会将物理与渲染循环联系起来,只需为您的物理循环使用固定的时间步长。
  • @supernova 我希望立方体越来越慢,直到 0。所以你的意思是我应该在渲染之前预先计算插值角度?
  • @ComFreek:您需要保留最初的timeSpan,还是可以稍微关闭一下?

标签: javascript math animation 3d three.js


【解决方案1】:

这是一种可能的方法,虽然它没有我想要的那么好:http://jsfiddle.net/5NWab/8/

这个想法是逐渐降低速度,就像你做的那样,根据剩余的时间,直到你到达一个点,即立方体必须旋转到的距离达到它的起始旋转 (0) 变为大于或等于在给定当前速度和当前剩余时间的情况下可能进行的旋转量。之后,忽略剩余时间,按照剩余旋转量的比例减慢速度。

这对于某些timeSpans 来说效果很好,但对于其他人来说,结束减速动画需要一点时间。

【讨论】:

  • 我真的很喜欢这个解决方案。在我当前的应用程序中并不重要。但我仍然对只需要或多或少 5-10% 时间的解决方案感兴趣。
【解决方案2】:

如果您希望旋转在特定时间以特定角度结束,那么我建议您不要像当前代码 (2012-09-27) 那样不断减少旋转,而是设置目标时间和旋转您初始化动画并计算帧重新计算时的正确旋转。

所以,如果你正在做一个正弦形的速度曲线(缓进缓出,中间线性,很好的原生函数来计算它),那么(伪代码不使用你的变量):

//in init
var targetTime = now + animationTime;
// normalize the length of the sine curve
var timeFactor = pi/animationTime;
var startAngle = ...
var endAngle = ...
var angleChange = endAngle - startAngle;

// inside the animation, at some time t
var remainingT = targetTime - t;
if(remainingT <= 0) {
    var angle = endAngle;
} else {
    var angle = startAngle + cos(remainingT * timefactor) * angleChange;
}

[编辑添加 startAngle 到 andle 计算]

因为 cos 函数是奇数(即关于原点对称),当 t 接近 targetTime 时,剩余的 T 接近零,我们在曲线上从 pi 向后移动到 0。 sin 形状的曲线趋向于零(和 pi),因此它会在最后(并且在开始时)缓和。在 targetTime 处或之后有一个明确的角度归零,因此帧速率中的任何抖动都不会不要只是将它推入无限循环。

【讨论】:

  • 一个问题:我想让立方体在动画前后角度一致,所以angleChange = endAngle - startAngle = 0。但这会在 else 块中给我零。
  • @ComFreek:呸,忘了在角度计算中添加startAngle
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-06
  • 1970-01-01
  • 1970-01-01
  • 2018-07-27
  • 2019-08-01
  • 2019-09-17
  • 1970-01-01
相关资源
最近更新 更多