javascript Three.js 围绕物体旋转相机(可能会移动)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15030078/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Three.js Rotate camera around object (which may move)
提问by maaachine
I have a camera that moves in a few different ways in the scene. The camera should rotate around a target position. In my case, this is a point on a mesh that the user has targeted. Because the camera usually doesn't require moving relative to this point, I was not able to use the pivot idea here: https://github.com/mrdoob/three.js/issues/1830. My current solution uses the following code:
我有一个在场景中以几种不同方式移动的相机。相机应围绕目标位置旋转。就我而言,这是用户已定位的网格上的一个点。因为相机通常不需要相对于这一点移动,所以我无法在这里使用枢轴思想: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);
}
The issue is that we do not want to use lookAt, because of the reorientation. We want to be able to remove that line.
问题是我们不想使用lookAt,因为重新定向。我们希望能够删除该行。
If we use the code above without lookAt, we rotate around the point but we do not look at the point. My understanding is that my method should rotate the camera's view as much as the camera itself is rotate, but instead the camera is rotated only a small amount. Could anyone help me understand what's wrong?
如果我们在没有lookAt的情况下使用上面的代码,我们会围绕该点旋转但我们不会看该点。我的理解是我的方法应该像旋转相机本身一样旋转相机的视图,但是相机只旋转很小的量。谁能帮助我理解出了什么问题?
EDIT: Cleaned up the original post and code to hopefully clarify my question.
编辑:清理原始帖子和代码,希望能澄清我的问题。
My thinking is that I can translate to the origin (my target position), rotate my desired amount, and then translate back to the beginning position. Because of the rotation, I expect to be in a new position looking at the origin.
我的想法是我可以平移到原点(我的目标位置),旋转我想要的量,然后平移回起始位置。由于旋转,我希望在一个新的位置看原点。
In fact, I'm testing it now without the translation matrices being used, so the matrix multiplication line is:
事实上,我现在正在测试它而不使用转换矩阵,所以矩阵乘法线是:
matrix.multiply(rotationY).multiply(rotationX);
and it seems to be behaving the same. Thanks for all the help so far!
它似乎表现得一样。感谢到目前为止的所有帮助!
ONE MORE THING! A part of the problem is that when the camera behaves badly close to the north or south poles. I am looking for a 'free roaming' sort of feel.
还有一件事!问题的一部分是当相机在北极或南极附近表现不佳时。我正在寻找一种“自由漫游”的感觉。
回答by WestLangley
Put the following in your render loop:
将以下内容放入渲染循环中:
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 );
Alternatively, you can use THREE.OrbitControls
or THREE.TrackballControls
. See the three.js examples.
或者,您可以使用THREE.OrbitControls
或THREE.TrackballControls
。请参阅three.js 示例。
回答by gaitat
The Gimbal lock that you are referring to (reorientation) is because of the use of Euler angles in the default implementation of the camera lookat. If you set
您所指的万向节锁定(重新定向)是因为在相机观察的默认实现中使用了欧拉角。如果你设置
camera.useQuaternion = true;
before your call to lookat, then euler angles will not be used. Would this solve your problem ?
在您调用 lookat 之前,将不会使用欧拉角。这会解决您的问题吗?