ThreeJS Oribital相机短时旋转 [英] ThreeJS oribital camera short rotation

查看:215
本文介绍了ThreeJS Oribital相机短时旋转的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

使用TweenMax这样的动画-

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

这很好用,但是没有考虑到达那条路的最短路径.因此,它很可能经常绕地球转圈.

ThreeJS似乎在一个非常奇怪的单位系统中测量角度: 0、1.57(等于90度),3.14(等于180dg),然后在3.14之后跳到-3.14,-1.57(等于270dg),然后又回到0 ...

例如,假设摄影机处于2.6且需要移至-2.61,此刻摄影机将对CCW进行动画处理(2.6到-2.16),在视觉上需要对CW进行动画处理,而CW将从2.6至3.14,然后从-3.14降至-2.61.

在此方面的任何帮助将不胜感激.

我猜有两个问题,如何弄清楚该怎么走,但是如何从2.6-> 3.14进行动画处理,无缝跳转到-3.14-> -2.61

解决方案

因此,奇怪的单位系统"只是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;
  }
}

I have an orbital camera that orbits are a globe. There are several markers on the globe that the user can click on, and the camera will move to that point.

Using TweenMax for the animation like this -

 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);
     }
});

This works great, however is doesn't take into consideration the shortest route to get there. So it can quite often go 'round the back' of the globe.

ThreeJS seems to measure the angle in a really strange unit system: 0, 1.57 (equivalent to 90 degrees), 3.14 (eq 180dg), then after 3.14 is jumps to -3.14, -1.57 (eq to 270dg), then back to 0... So this blowing my mind on how to work it out.

For example, say the camera is at 2.6 and it needs to go over to -2.61, at the moment the camera will animate CCW (2.6 to -2.16), where as visual it needs to animate CW, which would move from 2.6 to 3.14, -3.14 then to -2.61.

Any help on this would be really appreciated.

I guess there are two problems, how to work out which way to go round, but then how to actually animate across from 2.6 -> 3.14, jump to -3.14 seamlessly -> -2.61

解决方案

So that "strange unit-system" is just radians and it's quite common to measure theta/phi values in a range from -180° to 180° and -90° to 90° (think latitude/longitude, same thing). The conversion is simple:

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

Now the tweening-library will just interpolate from one value to the other and doesn't know what these values represent. So it simply can't know how to handle the shortest path when it comes to rotations. However, you can do this before starting the tween.

Say we animate from 2.6 to -2.6 (or 149° to -149°).

var from = 2.6, to = -2.6;

The direction and angular distance for the animation can be calculated as

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

A negative value here means counterclockwise, and 5.2 (~298°) is the "distance" the camera will travel. Now keep in mind that any angle plus or minus 360° (2 * Math.PI) will essentially land you at the same position. So lets try:

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

So, if you rotate from your position at 2.6 to -2.6 + 2 * Math.PI (or, from 149° to -149° + 360° = 211°), you will get a clockwise animation with a shorter path.

To make sure that all values stay in their allowed range, we change the onUpdate-function a little bit to wrap around properly:

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

You will probably also want to update the currentPos value with the actual values before the animation starts and below computation happens.

What's left to do is solving this for the general case, so to find out when to do the clockwise and counterclockwise rotation. To see if the other way around would be shorter, we just need to see if the distance would be greater than 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;
  }
}

这篇关于ThreeJS Oribital相机短时旋转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆