Three.js围绕物体旋转相机(物体可能会移动)

13

我有一个在场景中以几种不同方式移动的相机。相机应该围绕目标位置旋转。在我的情况下,这是用户已经定位的网格上的点。因为相机通常不需要相对于此点移动,所以我无法在这里使用枢轴点的概念:https://github.com/mrdoob/three.js/issues/1830。我的当前解决方案使用以下代码:

var rotationY = new THREE.Matrix4();
var rotationX = new THREE.Matrix4();
var translation = new THREE.Matrix4();
var translationInverse = new THREE.Matrix4();
var matrix = new THREE.Matrix4();
function rotateCameraAroundObject(dx, dy, target) {  
    // collect up and right vectors from camera perspective
    camComponents.up = rotateVectorForObject(new THREE.Vector3(0,1,0), camera.matrixWorld);
    camComponents.right = rotateVectorForObject(new THREE.Vector3(1,0,0), camera.matrixWorld);

    matrix.identity();

    rotationX.makeRotationAxis(camComponents.right, -dx);
    rotationY.makeRotationAxis(camComponents.up, -dy);
    translation.makeTranslation(
        target.position.x - camera.position.x,
        target.position.y - camera.position.y,
        target.position.z - camera.position.z);
    translationInverse.getInverse(translation);

    matrix.multiply(translation).multiply(rotationY).multiply(rotationX).multiply(translationInverse);
    camera.applyMatrix(matrix);
    camera.lookAt(target.position); 
}

问题是我们不想使用lookAt,因为这会重新定位。我们希望能够去掉那一行。

如果我们在没有lookAt的情况下使用上面的代码,我们围绕某个点旋转,但却不朝向这个点。我理解的是,我的方法应该使相机的视角旋转与相机本身旋转的程度相同,但实际上相机只旋转了很小的角度。有谁能帮助我理解出了什么问题吗?

编辑:整理了原始帖子和代码,希望能更清楚地阐明我的问题。

我的想法是:我可以将位置平移到原点(即目标位置),按照所需旋转的角度进行旋转,然后再平移回起始位置。由于旋转的缘故,我期望自己会处于一个新的位置并朝向原点。

实际上,我现在正在测试时没有使用平移矩阵,所以矩阵乘法那一行变成了:

matrix.multiply(rotationY).multiply(rotationX);

看起来它的行为方式是一样的。到目前为止,感谢所有的帮助!

还有一件事!问题的一部分是当相机在靠近北极或南极时表现不佳。我正在寻找一种“自由漫游”的感觉。


(1) camera.lookAt( vector ) 不接受矩阵作为参数。 (2) 你到底想做什么? - WestLangley
我在试图清理我的代码时搞砸了,很抱歉!我已经编辑了帖子以反映正确的信息。 - maaachine
我正在寻找完全相同的东西...在2017年。我可能错过了什么,但我真的希望不必拿出我的计算器教科书并重新学习向量和三角函数。我只是想能够在物体周围“自由”旋转而已。这确实有点棘手。 - dylnmc
2个回答

12
将以下内容放入你的渲染循环中:
camera.position.x = target.position.x + radius * Math.cos( constant * elapsedTime );         
camera.position.z = target.position.z + radius * Math.sin( constant * elapsedTime );
camera.lookAt( target.position );

renderer.render( scene, camera );

或者,您可以使用THREE.OrbitControlsTHREE.TrackballControls。请参阅three.js示例。


嗯,这样做或许可以。不过我需要它能够自由地在三个方向上移动。其中一个关键问题是如何处理靠近极点的旋转。我已经更新了原帖以澄清这一点!(希望如此) - maaachine

0
您所指的万向节锁(重新定位)是由于默认实现相机lookat中使用了欧拉角。如果您设置
camera.useQuaternion = true;

如果在调用lookat之前设置欧拉角,那么欧拉角将不会被使用。这样能解决你的问题吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接