【问题标题】:ThreeJS oribital camera short rotation三台JS轨道相机短转
【发布时间】:2017-02-08 17:37:10
【问题描述】:

我有一个轨道相机,它的轨道是一个地球仪。地球上有几个标记可供用户单击,相机将移动到该点。

使用 TweenMax 制作这样的动画 -

 TweenMax.to(currentPos, 3, {
     theta:targetPos.theta, 
     phi:targetPos.phi, 
     radius:targetPos.radius, 
     ease:Circ.easeIn, 
     onComplete:btnZoomComplete,
     onUpdateParams:["{self}"], 
     onComplete:SataliteTweenComplete, 
     onUpdate: function(tween) {
       controls.setThetaPhi(tween.target.theta, tween.target.phi, tween.target.radius);
     }
});

这很好用,但是没有考虑到那里的最短路线。所以它经常可以“绕地球一圈”。

ThreeJS 似乎在一个非常奇怪的单位系统中测量角度: 0、1.57(相当于 90 度)、3.14(eq 180dg),然后在 3.14 之后跳到 -3.14、-1.57(eq 到 270dg),然后回到 0... 所以这让我对如何工作感到震惊出去。

例如,假设相机在 2.6 并且它需要转到 -2.61,此时相机将为 CCW 设置动画(2.6 到 -2.16),而视觉上它需要为 CW 设置动画,这将从2.6 到 3.14,-3.14 然后到 -2.61。

对此的任何帮助将不胜感激。

我想有两个问题,如何计算出循环的方式,然后如何实际动画从 2.6 -> 3.14,无缝跳转到 -3.14 -> -2.61

【问题讨论】:

    标签: javascript math three.js trigonometry


    【解决方案1】:

    所以“奇怪的单位系统”只是radians,并且在 -180° 到 180° 和 -90° 到 90° 的范围内测量 theta/phi 值是很常见的(想想纬度/经度,相同事物)。转换很简单:

    angleDegrees = radians / Math.PI * 180;
    radians = angleDegrees / 180 * Math.PI;
    

    现在补间库只会从一个值插入到另一个值,并且不知道这些值代表什么。所以它根本不知道如何处理旋转时的最短路径。但是,您可以在开始补间之前执行此操作。

    假设我们的动画从 2.6-2.6(或 149° 到 -149°)。

    var from = 2.6, to = -2.6;
    

    动画的方向和角距离可以计算为

    var distance = to - from; 
    // === -5.2
    

    这里的负值表示逆时针方向,5.2 (~298°) 是相机行进的“距离”。现在请记住,任何正负 360° (2 * Math.PI) 的角度基本上都会使您处于相同的位置。那么让我们试试吧:

    var distance = (to + 2 * Math.PI) - from; 
    // === 1.083185307179586 (~62°)
    

    因此,如果您从 2.6 的位置旋转到 -2.6 + 2 * Math.PI(或者,从 149° 到 -149° + 360° = 211°),您将获得路径更短的顺时针动画。

    为了确保所有值都保持在允许的范围内,我们稍微更改了 onUpdate 函数以正确环绕:

    controls.setThetaPhi(
        tween.target.theta % Math.PI, 
        tween.target.phi % Math.PI, 
        tween.target.radius);
    

    您可能还想在动画开始之前和下面的计算发生之前用实际值更新currentPos 值。

    剩下要做的是解决一般情况下的问题,因此要找出何时进行顺时针和逆时针旋转。反之是否会更短,我们只需要看看距离是否大于 180°:

    if (Math.abs(to - from) > Math.PI) {
      if (to > 0) { // if to is positive we remove a full-circle, add it otherwise
        to = to - 2 * Math.PI;
      } else {
        to = to + 2 * Math.PI;
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-02-20
      • 2013-01-22
      • 1970-01-01
      • 1970-01-01
      • 2015-01-30
      • 2013-09-10
      • 1970-01-01
      • 2022-01-08
      • 2021-02-20
      相关资源
      最近更新 更多