14

我正在尝试建立一个太阳系的比例模型。我想看看是否有人可以向我解释旋转速度是如何工作的。这是重要的部分:

objects[index].rotation.y += calculateRotationSpeed(value.radius,value.revolution) * delta;

转速与实际时间有何关系?因此,如果您的速度为 1,那是每毫秒 1 px 的移动吗?或者,如果您的速度为 0.1,那是不是每秒不到 1 个像素?

基本上,我正在尝试根据行星的半径和一天中的小时数来计算行星的正确旋转速度。因此,如果您在地球上,它将在 24 小时内完成 1 次旋转。这是我写的现在正在计算的函数:

/* In a day */
function calculateRotationSpeed(radius,hrs,delta) {
    var cir = findCircumference(radius);
    if(delta) {
        var d = delta;
    } else {
        var d = 1;
    }
    var ms = hrs2ms(hrs) * d;
    var pxPerMS = km2px(cir) / ms;
    return pxPerMS;
}

我试了一下,它似乎仍然移动得太快。我还需要类似的东西来计算轨道速度。

4

1 回答 1

70

旋转和单位

Three.JS 中的旋转以弧度为单位。对于那些完全不熟悉弧度的人(我的一篇旧论文的一小段摘录):

与数学常数Pi一样,弧度(大约 57.3 度)源自圆的半径(或直径)与其周长之间的关系。一个弧度是始终跨越一个圆的圆周上的弧角度,该圆的长度等于同一个圆的半径(对于任何圆都是如此,无论大小)。类似地,Pi 是周长与直径的比值,因此单位圆的周长正好是 Pi。弧度和度数实际上不是真正的单位,实际上角度通常是无量纲的(如百分比和分数,我们不使用实际单位来描述它们)。

但是,与度数不同的是,弧度不是任意定义的,因此在大多数情况下,它是更自然的选择;通常比在数学公式中使用度数更容易、更优雅、更清晰、更简洁。巴比伦人可能给了我们度数,将他们的圆分成 6 个相等的部分(使用等边三角形的角度)。考虑到它们的六十进制(以 60 为底)的数字系统,这 6 个部分中的每一个都可能进一步细分为 60 个相等的部分。这也将允许他们将这样的系统用于天文学,因为在他们的时间里,一年中的估计天数要准确得多,通常被认为是 360 天。

Three.JS 中的基本旋转

所以现在,知道您正在使用弧度,如果您在函数中使用以下第一个语句增加一次anim(回调到requestAnimFrame),您将mesh在 x 轴上的旋转增加一个弧度

mesh.rotation.x += 1;                      // Rotates   1 radian  per frame
mesh.rotation.x += Math.PI / 180;          // Rotates   1 degree  per frame
mesh.rotation.x += 45 * Math.PI / 180      // Rotates  45 degrees per frame

正如上面的最后两个语句所示,Math.PI / 180如果我们希望使用度数来代替,我们可以在赋值之前轻松地将度数转换为弧度。

考虑帧率

在您的情况下,您需要考虑每帧经过多少时间。这是你的delta。你必须这样想:我们以多少 FPS 运行?我们将声明一个全局clock变量,该变量将存储一个THREE.Clock对象,该对象具有我们所需信息的接口。我们需要一个我们将调用的全局变量clock(需要在其他函数中可访问,特别是anim):

在 内init,创建一个实例THREE.Clock;将其存储在外部声明的变量中init(范围更大):

clock = new THREE.Clock();

然后,在您的anim函数中,您将进行两次调用,以更新与以下相关的两个变量clock

  • time(自时钟实例化以来经过的总时间(以毫秒为单位))
  • delta(每帧之间的时间以毫秒为单位)在其他两个全局变量中:
时间 = 时钟.getElapsedTime();
 delta = clock.getDelta();

请注意,这delta意味着返回每帧之间的时间量;然而,当且clock.getDeltaanim/render

  1. 每个动画/渲染周期只有一次
  2. 每个动画周期都在同一个地方(开始或结束,据我所知,哪个不重要)

上述条件是THREE.Clock执行的结果。getDelta最初返回自时钟实例化以来的时间量,之后它返回的时间只是自上次调用以来的时间)。如果它以某种方式被错误地或不一致地调用,它将把事情搞砸。

以增量因子旋转

现在,如果您的场景没有让处理器或 GPU 陷入困境,Three.JS 及其包含的requestAnimationFrame shim将尝试(使用可用资源)以保持每秒 60 帧的平稳运行。这意味着理想情况下,我们将在每帧之间有大约1/60 = .016666几秒钟的时间,这是您delta可以从clock每帧中读取的值,并使用它通过乘以基于帧速率来标准化您的速度,如下所示。通过这种方式,您可以获得以秒为单位的值,而不管帧速率的微小变化,您可以每次相乘以获得以秒为单位的值。

因此,根据我们在您的anim函数开始时所拥有的内容,您可以像这样使用它:

mesh.rotation.x += delta * 1;                     // Rotates  1 radian  per second
mesh.rotation.x += delta * Math.PI / 180;         // Rotates  1 degree  per second
mesh.rotation.x += delta * 45 * Math.PI / 180;    // Rotates 45 degrees per second

转速和单位

因为我们对角度、弧度和度数的测量实际上并不是单位,所以当我们查看角速度的单位时,我们会发现它只会随时间起作用(而不是像您在代码)。

基于时间计算转速

至于您的具体情况,您不需要半径来计算转速(角速度),而是可以使用一天中的小时数(一整圈所需的时间,即2 * Math.PI 弧度在它的轴上旋转)。如果你有一个变量,revolutionTime那么你可以像这样计算它。

secondsInAnHour = 3600;
rotationalSpeed = (2 * Math.PI) / revolutionTime;

如果你假设地球24 hours = 24 * 60 * 60 = 86,400在一天之内(它没有)。然后我们会得到rotationalSpeed = 2 * PI / 86,400,或大致0.0000727 每秒的弧度。您应该能够找到可能比这更准确的教科书值(考虑到比我们的 24 小时平面数字更准确的测量值,即地球完成一圈所需的时间。

特别考虑你的情况

但是,我不会担心确保行星的所有角速度都完全正确。相反,一个更好的主意是计算出(行星的)每个角速度之间的比率并使用它。这将更好地工作有几个原因:您可能想要更快的旋转速度,这将允许您使用任何有效的旋转速度;重要的是,与任何模型一样(尤其是在涉及天文模型时),你要保持它的规模。

于 2012-07-06T15:04:07.043 回答