OpenGL矩阵旋转四元数

7

我正在尝试对一个立方体进行简单的绕x轴和y轴旋转:

我想始终将立方体绕x轴旋转x角度,并将立方体绕y轴旋转y角度,独立于x轴旋转。

首先我天真地做了以下操作:

glRotatef(x,1,0,0);
glRotatef(y,0,1,0);

然后

但是首先要绕x轴旋转,然后再绕y轴旋转,我想独立地绕y轴旋转。

我开始研究四元数,所以我尝试了:

Quaternion Rotation1;
Rotation1.createFromAxisAngle(0,1, 0, globalRotateY);
Rotation1.normalize();

Quaternion Rotation2;
Rotation2.createFromAxisAngle(1,0, 0, globalRotateX);
Rotation2.normalize();

GLfloat Matrix[16];

Quaternion q=Rotation2 * Rotation1;

q.createMatrix(Matrix);
glMultMatrixf(Matrix);

这个代码几乎实现了通过连续的glRotates所实现的效果...所以我认为我可能缺少一两个步骤。

四元数是正确的选择吗?还是应该使用其他方法?如果四元数是正确的选择,那么我可以添加哪些步骤来使立方体独立于每个轴旋转。 我认为有人遇到了相同的问题: 在两个轴上旋转OpenGL场景


好的,让我这样说...我想做的是使用鼠标旋转一个立方体。我希望左右控制屏幕的y轴旋转,上下控制屏幕的x轴旋转。我希望它们独立于其他轴旋转,但只在屏幕的全局轴上旋转。如果我进行两个glRotations,我无法得到这种行为,因为一个轴旋转会影响另一个轴。 - yeahdixon
例如旋转一个立方体:没有旋转操作只会显示一个面然后我执行 glRotatef(90,1,0,0); glRotatef(45,0,1,0); ⁃ 给我一个倾斜的立方体(菱形),但我想要的是一个将其角落对着相机的立方体,这实际上是交换操作的结果: glRotatef(45,0,1,0); glRotatef(90,1,0,0);我只需交换旋转命令,但当角度值翻转时会遇到相同的问题。 - yeahdixon
4个回答

3
我使用四元数成功地实现了这个功能:虽然有其他方法,但经过一些研究,这对我来说完美地工作了。我在另一个论坛上发布了一个类似的版本。http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=280859&#Post280859 首先创建改变 x/y 的角度的四元数表示,然后每帧将变化的角度四元数乘以累加四元数,最后将该四元数转换为矩阵形式以乘以当前矩阵。以下是循环的主要代码:
Quaternion3D Rotation1=Quaternion3DMakeWithAxisAndAngle(Vector3DMake(-1.0f,0,0), DEGREES_TO_RADIANS(globalRotateX));
Quaternion3DNormalize(&Rotation1);

Quaternion3D Rotation2=Quaternion3DMakeWithAxisAndAngle(Vector3DMake(0.0f,-1.0f,0), DEGREES_TO_RADIANS(globalRotateY));
Quaternion3DNormalize(&Rotation2);


Matrix3D Mat;
Matrix3DSetIdentity(Mat);
Quaternion3DMultiply(&QAccum, &Rotation1);

Quaternion3DMultiply(&QAccum, &Rotation2);

Matrix3DSetUsingQuaternion3D(Mat, QAccum);
globalRotateX=0;
globalRotateY=0;

glMultMatrixf(Mat);

然后画立方体。

这个网站真的很有帮助:http://www.gamedev.net/reference/articles/article1095.asp 但一开始并不太容易理解,直到我进一步研究和尝试了一些东西。 - yeahdixon

0
如果您能更详细地解释您想要做什么以及您得到的结果与您想要的结果有何不同,那将会非常有帮助。但是通常使用欧拉角进行旋转存在一些问题,因为组合旋转可能会导致不直观的行为(在最坏的情况下失去一个自由度)。
如果您可以找到代表所需旋转的单个轴和单个角度,则四元数球面线性插值可能是您的选择。但是,使用四元数沿X和Y轴进行连续旋转并不能帮助您避免组合欧拉旋转固有的问题。
您链接的帖子似乎涉及另一个问题。发帖人似乎在平移对象然后进行旋转,而应该先旋转再平移。

我在上面更详细地描述了这个问题,但我认为官方术语是万向节锁定。 - yeahdixon

0

不清楚你想要实现什么。也许你应该考虑一些点,以及你希望它们旋转到哪里——例如,顶点(1,1,1)应该映射到(0,1,0)。然后,根据这些信息,你可以计算所需的旋转。

四元数通常用于在两个旋转“位置”之间进行插值。因此,第一步是确定你的起始和结束“位置”,而你目前还没有。一旦你有了这个,就可以使用四元数进行插值。这里似乎没有任何时间变化方面的问题。


我在上面更详细地描述了这个问题,但我认为官方术语是万向节锁定。 - yeahdixon

0

你的问题不是万向节锁定。实际上,你使用的四元数版本与矩阵(glRotate)版本在数学上是相同的,因此没有理由认为四元数版本会比矩阵版本更好。

如果你想要鼠标控制,可能需要查看arcballs


谢谢,是的,我完全同意,四元数和旋转矩阵可以互换,因此可以在没有四元数的情况下完成。这个问题的答案更多地在于矩阵的前乘,使用增量旋转。 - yeahdixon

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