1

我正在开发一个在其视口交互中与 MotionBuilder 具有相似功能的应用程序。它有三个按钮: 按钮 1 根据 X/Y 鼠标拖动围绕 X 和 Y 旋转视口。按钮 2 根据 X/Y 鼠标拖动来平移 X 和 Y 周围的视口。按钮 3 通过沿 Z 轴平移“缩放”视口。

代码很简单:

glTranslatef(posX,posY,posZ);
glRotatef(rotX, 1, 0, 0);
glRotatef(rotY, 0, 1, 0);   

现在,问题是如果我先平移,平移将是正确的,但旋转会跟随世界轴。我也试过先旋转:

glRotatef(rotX, 1, 0, 0);
glRotatef(rotY, 0, 1, 0);
glTranslatef(posX,posY,posZ);

^ 旋转有效,但平移根据世界轴进行。

我的问题是,我怎样才能做到这两点才能实现代码片段 1 的翻译和代码片段 2 的旋转。

编辑我画了这个相当粗糙的图像来说明我所说的世界和局部旋转/翻译的意思。我需要相机围绕其局部轴旋转和平移。 http://i45.tinypic.com/2lnu3rs.jpg

4

3 回答 3

1

好的,图像使事情变得更加清晰。

如果您只是在谈论一个对象,那么您的第一个代码片段会很好,但对于相机来说就完全不同了。

由于在opengl中技术上没有对象作为“相机”,因此您在构建相机时所做的只是通过与您移动相机的方式相反的方式移动所有东西。即你没有在 Y 轴上将相机向上移动 +1,你只是在 y 轴上将世界移动 -1,这样就可以达到与拥有相机相同的视觉效果。

想象一下,您有一个位于 (Cx, Cy, Cz) 位置的相机,并且它具有 x/y 旋转角度 (CRx, CRy)。如果这只是一个普通对象,而不是相机,您可以通过以下方式对其进行转换:

glTranslate(Cx, Cy, Cz);
glRotate(CRx, 1, 0, 0);
glRotate(CRy, 0, 1, 0);

但是因为这是相机,所以我们需要做这个操作的逆操作(我们只想通过 (-Cx, -Cy, 和 -Cz) 移动世界来模拟“相机”的移动。反转矩阵,您只需要对每个单独的变换进行相反的操作,并以相反的顺序进行。

glRotate(-CRy, 0, 1, 0); 
glRotate(-CRx, 1, 0, 0);
glTranslate(-Cx, -Cy, -Cz);

我认为这将为您提供您在图像中提到的那种相机。

于 2012-04-29T01:29:33.577 回答
1

我建议你咬苹果,实现一个相机类来存储相机的当前状态(位置、视图方向、向上向量、右向量)并根据你的控制方案操纵该状态。然后您可以使用 gluLookAt() 设置投影矩阵。然后,操作的顺序变得不重要了。这是一个例子:

设 camPos 为相机的当前位置,camView 为它的视图方向,camUp 为上向量,camRight 为右向量。

要通过 moveDelta 平移相机,只需将 moveDelta 添加到 camPos。旋转有点困难,但如果你理解四元数,你就能很快理解它。

首先,您需要为两个旋转中的每一个创建一个四元数。我假设您的水平旋转始终围绕正 Z 轴(如果您愿意,它指向“天花板”)。令 hQuat 为代表水平旋转的四元数。我进一步假设您想要围绕其右轴旋转相机以进行垂直旋转(创建俯仰效果)。为此,您必须将水平旋转应用于相机的当前角度。结果是垂直旋转 hQuat 的旋转轴。总旋转四元数为 rQuat = hQuat * vQuat。然后将 rQuat 应用于相机的视图方向、向上和向右向量。

Quat hRot(rotX, 0, 0, 1);      // creates a quaternion that rotates by angle rotX about the positive Z axis
Vec3f vAxis = hRot * camRight; // applies hRot to the camera's right vector
Quat vRot(rotY, vAxis);        // creates a quaternion that rotates by angle rotY about the rotated camera's right vector
Quat rQuat = hRot * vRot;      // creates the total rotation
camUp = rQuat * camUp;
camRight = rQuat * camRight;
camView = rQuat * camView;

希望这可以帮助您解决问题。

于 2012-04-29T10:29:06.127 回答
0

glRotate 总是围绕原点工作。如果你这样做:

glPushMatrix();
glTranslated(x,y,z);
glRotated(theta,1,0,0);
glTranslated(-x,-y,-z);
drawObject();
glPopMatrix();

然后“对象”围绕 (x,y,z) 而不是原点旋转,因为您将 (x,y,z) 移动到原点,进行旋转,然后将 (x,y,z) 推回原点它开始了。

但是,我认为这不足以达到您所描述的效果。如果您总是希望针对当前参考框架进行转换,那么您需要自己跟踪转换矩阵。这就是人们使用基于四元数的相机的原因。

于 2012-04-29T02:11:52.970 回答