通过相机旋转将点指向最近的相机位置

时间:2014-06-24 12:55:55

标签: three.js

我在Three.js(r67)中有一个由OrbitControls控制的相机的场景。

如果我现在在场景中选择一个任意点(Vector3),那么通过旋转相机将这个点(以编程方式)带到最近的相机位置的最佳方法是什么?


示例方案

在下图中,左侧是起点。相机围绕绿色球体旋转(如OrbitControls),其中相机的中心是球体的中心。我现在想要围绕球体自动旋转相机(进行最小量的移动),以便红色框最靠近相机(就像在右侧)。 enter image description here

3 个答案:

答案 0 :(得分:2)

与选择场景中的点的方法无关,可以通过旋转"带来相机来理解你的意思。

我想,你想要在途中旋转相机,使选定的点位于屏幕的中心。

这很简单:

camera.lookAt(your_point_in_scene);

你可以做得更复杂。首先,找到当前的指向矢量。默认情况下,相机会朝Vector(0,0,1)方向查看。当我们以与摄像机相同的旋转方式旋转它时,我们将有摄像机方向:

var vec = new THREE.Vector3(0,0,1);
vec.applyQuaternion(camera.rotation._quaternion);

现在我们必须确定角度来旋转我们的旋转相机和轴。 可以找到旋转轴作为摄像机方向和从摄像机到对象的矢量的交叉积。天使可以从点积中提取出来:

var object_dir = object_world_point.clone().sub(camera.position);
var axis = vec.clone().crossProduct(object_dir);
var angle = Math.acos( vec.clone().dot(object_dir) / vec.length() / object_dir.length());

有角度和轴,我们可以旋转相机:

camera.rotateOnAxis(axis, angle);

或者,如果你想让它顺利:

// before animation started
var total_rotation = 0, 
    rotateon,
    avel = 0.01; // 0.01 radian per second    


if(total_rotation < angle){
  rotateon = avel * time_delta;
  camera.rotateOnAxis(axis, angle);
  total_rotation += rotateon;
}

答案 1 :(得分:1)

嗯,这并不难 您有相机的中心/目标点。您计算从目标位置到点位置的差异,并将该矢量标准化为摄像机中心点距离的长度(即像pointdistance.multiplyScalar(cameradistance.length()/ pointdistance.length())。)。 p>

就是这样。如果我理解你的问题。您所做的就是将点的位置“延伸”到您的“相机移动圆顶”上,然后您就拥有了理想的新相机位置。由于您始终瞄准中心点,因此相机的旋转自动完成。

Aaand如果你想稍微平滑相机的移动,你只需插入角度(不是直接位置),例如指数函数,无论你喜欢什么。

答案 2 :(得分:1)

嗨亲爱的,请关注此事 与选择场景中的点的方法无关,通过旋转&#34;可以通过&#34;带来相机来理解你的意思。 我想,你想要在相机中旋转相机,使选定的点位于屏幕的中心。 这很简单:

camera.lookAt(your_point_in_scene);

你可以做得更复杂。首先,找到当前的指向矢量。默认情况下,相机在方向Vector(0,0,1)中查找。当我们以与摄像机相同的旋转方式旋转它时,我们将有摄像机方向:

var vec = new THREE.Vector3(0,0,1);
vec.applyQuaternion(camera.rotation._quaternion);

现在我们必须确定角度来旋转我们的旋转相机和轴。 可以找到旋转轴作为摄像机方向和从摄像机到对象的矢量的交叉积。 角度可以从点积中提取:

var object_dir = object_world_point.clone().sub(camera.position);
var axis = vec.clone().crossProduct(object_dir);
var angle = Math.acos( vec.clone().dot(object_dir) / vec.length() / object_dir.length());