我正在绘制一个场景,其中摄影机可以在宇宙中自由移动。相机类跟踪视图(或注视)点,相机的位置以及向上矢量。然后将这些向量/点传递到gluLookAt。
平移和缩放几乎不容易实现。然而,我发现围绕转动一下点要多得多的问题。我想编写一个函数Camera.rotate,它具有2个角度,一个可以向上/向下旋转,另一个可以沿以视点为中心的假想球向左/向右旋转。
是否有捷径可寻?
我已经(简要地)阅读了有关四元数的信息,但是我想看看鉴于场景的构造相对简单,是否有更简单的解决方案。
我正在绘制一个场景,其中摄影机可以在宇宙中自由移动。相机类跟踪视图(或注视)点,相机的位置以及向上矢量。然后将这些向量/点传递到gluLookAt。
平移和缩放几乎不容易实现。然而,我发现围绕转动一下点要多得多的问题。我想编写一个函数Camera.rotate,它具有2个角度,一个可以向上/向下旋转,另一个可以沿以视点为中心的假想球向左/向右旋转。
是否有捷径可寻?
我已经(简要地)阅读了有关四元数的信息,但是我想看看鉴于场景的构造相对简单,是否有更简单的解决方案。
Answers:
您要的是称为Arcball旋转。只有了解四元数的工作原理,四元数才是简单的解决方案。但是,无需四元数就可以实现相同的目的。
先决条件
您知道一般如何旋转对象吗?假设您在原点有一个对象。您知道如何旋转吗(提示:乘以某个旋转矩阵)?如果是,那么我假设您知道如果先平移对象然后旋转它会发生什么?
您必须知道如何从角度轴计算旋转矩阵(像馅饼一样容易,在线查看无数个方程式,其中许多方程式也为您提供了代码)
解
注意事项
您必须注意相机会停止工作的某些情况或奇异之处。例如,向下看/向上看。我会让你弄清楚如何处理这些问题。
EDIT1:如何重新计算相机的正交向量
您已经知道了相机的方向((cameraPos-focusPoint).normalize())。现在,假设您的相机的上轴为+ Y(或者您的世界当前的上轴为...取决于您)。现在,只需穿过方向与向上,以获得正确的。做完了吗 不!您的向上向量不再与其他两个正交。要解决此问题,请与方向保持正确的对接,然后开始进行安装。
请注意,实际上应使用Gram-Schmidt对向量进行正态化。
再次注意一下警告,因为在某些情况下这将无法正常工作(例如,方向与向上平行)。
normalize(up ^ camFocusVector)
(如果是左撇子,则可以使用右向量)。
您需要的是典型的ArcBall摄像机,该摄像机基本上是保留目标位置并允许您以“球形”方式围绕目标移动摄像机的摄像机。
它在XNA中,但是IIRC我以前使用过此实现,并且效果很好:
http://roy-t.nl/index.php/2010/02/21/xna-simple-arcballcamera/
这是我旋转某个点的代码,发现自己经常重复使用它。
float distance; // Straight line distance between the camera and look at point
// Calculate the camera position using the distance and angles
float camX = distance * -sinf(camAngleX*(M_PI/180)) * cosf((camAngleY)*(M_PI/180));
float camY = distance * -sinf((camAngleY)*(M_PI/180));
float camZ = -distance * cosf((camAngleX)*(M_PI/180)) * cosf((camAngleY)*(M_PI/180));
// Set the camera position and lookat point
gluLookAt(camX,camY,camZ, // Camera position
0.0, 0.0, 0.0, // Look at point
0.0, 1.0, 0.0); // Up vector
实现这一非常简单的算法非常棒:
以P为您要旋转的中心点(“观察”或“目标”点):
translate(-P)
rotate horizontal
rotate vertical
translate(P)
我用它,它很好。
在姐妹站点stackoverflow上找到的来源:https : //stackoverflow.com/questions/287655/opengl-rotating-a-camera-around-a-point