我正在开发一个应用程序,它在视口交互中具有与MotionBuilder相似的功能。它有三个按钮:按钮1根据X/Y鼠标拖动围绕X和Y旋转视口。根据X/Y鼠标拖动,按钮2将围绕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
发布于 2012-04-29 09:29:34
好的,这张图片让事情变得更清晰了。
如果你只是在谈论一个对象,那么你的第一个代码片段就可以了,但是对于相机来说就完全不同了。
因为在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-29 18:29:06
我建议你咬住苹果,实现一个camera类来存储相机的当前状态(位置,视图方向,上方向向量,右向量),并根据您的控制方案操作该状态。然后,您可以使用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-29 10:11:53
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)推回它开始的位置。
然而,我认为这还不足以达到你所描述的效果。如果您总是希望相对于当前参考系完成转换,那么您需要自己跟踪转换矩阵。这就是为什么人们使用基于四元数的相机。
https://stackoverflow.com/questions/10368017
复制相似问题