Three.JS 的单位,计算旋转和轨道速度
Posted
技术标签:
【中文标题】Three.JS 的单位,计算旋转和轨道速度【英文标题】:Units of Three.JS, Calculating Rotation & Orbit Speeds 【发布时间】:2012-07-06 23:16:15 【问题描述】:我正在尝试建立一个按比例绘制的太阳系模型。我想看看是否有人可以向我解释旋转速度是如何工作的。这是重要的部分:
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;
我试了一下,它似乎仍然移动得太快。我还需要类似的东西来计算轨道速度。
【问题讨论】:
【参考方案1】:旋转和单位
Three.JS 中的旋转以 弧度 为单位。对于那些完全不熟悉弧度的人(我的一篇旧论文的一小段摘录):
与数学常数Pi 一样,radian(大约 57.3 度)源自圆的半径(或直径)与其周长之间的关系。一个弧度是 角,它总是跨越一个圆的圆周上的弧,该圆的长度等于同一个圆的半径(对于任何圆都是如此,无论大小如何)。类似地,Pi 是周长与直径的比值,因此单位圆的周长正好是 Pi。弧度和度数实际上不是真正的单位,实际上角度通常是无量纲的(如百分比和分数,我们不使用实际单位来描述它们)。
但是,与度数不同,弧度不是任意定义的,因此在大多数情况下它是更自然的选择;通常比在数学公式中使用度数更容易、更优雅、更清晰、更简洁。巴比伦人可能给了我们度数,将他们的圆分成 6 个相等的部分(使用等边三角形的角度)。考虑到它们的sexagesimal(以 60 为基数)数字系统,这 6 个部分中的每一个都可能进一步细分为 60 个相等的部分。这也将允许他们将这样的系统用于天文学,因为在他们的时间里,一年中估计的天数要低得多,通常被认为是 360 天。
Three.JS 中的基本旋转
所以现在,如果您在 anim
函数中使用以下语句中的 first once 递增(回调到 @987654327 @),您将在 x 轴上将 mesh
的旋转增加一个弧度
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.getDelta
在anim
/render
中始终被调用时,这将是正确的
-
仅每个动画/渲染周期一次
每个动画循环都在同一个地方(开始或结束,据我所知,哪个无关紧要)
上述条件是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 小时平面数字更准确的测量值,即地球完成一圈所需的时间。
特别考虑您的情况
但是,我不会担心确保行星的所有角速度都完全正确。相反,一个更好的主意是计算出(行星的)每个角速度之间的比率并使用它。这将更好地工作有几个原因:您可能想要更快的转速,这将允许您使用任何运行良好的转速;重要的是,与任何模型(尤其是在涉及天文模型时)一样,您要保持它的比例。
【讨论】:
太棒了,说得通。从来不擅长数学,所以我将如何根据半径和完成 1 圈所需的时间来计算每帧的速度或弧度? 查看我的编辑,我添加了很多东西。但就像我最后说的那样,我不会根据一天中的小时数来使用行星的实际速度。相反,将它们相互比较,并确保它们之间的比率保持不变。此外,我会先让所有东西都保持静止,然后在你尝试制作任何轨道之前,只处理它们各自的旋转。 完美!正是我需要的。非常感谢,如果您想尝试一下(请参阅 cmets),那就太棒了! link "请注意,delta 旨在返回每帧之间的时间量;但是,当且仅当在 anim/render 中始终调用 clock.getDelta 时,这才是正确的" 我想知道为什么getDelta()
在我的情况下返回垃圾......太糟糕了,我需要从 *** 学习一些应该在官方文档中作为粗体字体的东西。
这一定是我在 Stack Overflow 上见过的最好的答案之一以上是关于Three.JS 的单位,计算旋转和轨道速度的主要内容,如果未能解决你的问题,请参考以下文章
使用vue学习three.js之移动相机-使用轨道控件OrbitControls控制相机