我目前正在查看一组球体,并分别按下按钮x,y或z时将它们围绕x,y,z旋转。旋转工程。但是,当我用i重置旋转时,我并不总是能得到完美的重置。
case 'x':
case 'X':
glMatrixMode(GL_MODELVIEW);
glutSetWindow(windowID[0]);
glRotatef(1, 1, 0, 0);
glutPostRedisplay();
xRotation++;
break;
case 'y':
case 'Y':
glMatrixMode(GL_MODELVIEW);
glutSetWindow(windowID[0]);
glRotatef(1, 0, 1, 0);
glutPostRedisplay();
yRotation++;
break;
case 'z':
case 'Z':
glMatrixMode(GL_MODELVIEW);
glutSetWindow(windowID[0]);
glRotatef(1, 0, 0, 1);
glutPostRedisplay();
zRotation++;
break;
case 'i':
case 'I':
glMatrixMode(GL_MODELVIEW);
glutSetWindow(windowID[0]);
glRotatef(-xRotation, 1, 0, 0);
glRotatef(-yRotation, 0, 1, 0);
glRotatef(-zRotation, 0, 0, 1);
glutPostRedisplay();
旋转完美。每次增量时,我都会将增量添加到各自的float(x \ y \ z)Rotation中,以存储围绕轴所做的增量,然后将其重置为原点。
我已经知道我的问题是当我沿2轴或更多轴旋转时。似乎我一次也只沿一个轴遇到此问题。
每个窗口都绘制有
void DrawWindowOne()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, 250, 250);
DrawAxis(1);
glMatrixMode(GL_MODELVIEW);
DrawSpheres();
glViewport(250, 0, 250, 250);
DrawAxis(1);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT1);
DrawSpheres();
glDisable(GL_LIGHT1);
glViewport(500, 0, 250, 250);
DrawAxis(1);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_LIGHT2);
DrawSpheres();
glDisable(GL_LIGHT2);
glDisable(GL_LIGHTING);
glutSwapBuffers();
}
最佳答案
samgak所说的回答您的问题的方法将起作用,但是当您的项目变得庞大而又复杂时,这是需要了解的并且很了解防止将来出现陷阱的知识。
当在3D空间中进行旋转并需要绕任何给定的轴[X,Y,Z]旋转时,在平移旋转矩阵中使用Euler角进行旋转会出现一个已知问题。这个问题称为万向节锁。以您的球体为例,您想要绕任何轴旋转的3D模型;在开始旋转之前,请想象一下,有一个比您的球体大且平行于每个轴的圆或圆环。我们可以说X轴环的手柄指向右或向东,Y轴环的手柄指向上或北,而Z轴环指向您。 。当您捕获手柄并开始移动手柄时,该环将沿该轴旋转对象。
想象一下您的球体是地球:
y轴的南北方向和地球将像地球日一样绕两极旋转。赤道不动。
这里有一个类比来证明这一点,例如通过环的运动来旋转3D模型:我将使用电单车,将轴的旋转考虑如下
注意:当您绕任何轴旋转对象时,环会移动,并且对象会显示旋转。
既然您已经了解了每次旋转发生的情况,那么我将与Euler Angels演示Gimbal Lock。我们将不理会Y轴,在这里使用X或Z轴都没有关系。我将使用Z轴,因为我们向下看它,当您旋转对象时,您可以看到它左右旋转。现在让我们在任一方向(CW,CCW)上旋转此对象90度或PI / 2,现在我们的Z轴环随该对象旋转,并且由于我们使用的是地球,因此我们仍然可以看到该对象前方的相同区域我们,但是赤道现在位于两极,而两极现在位于赤道。我们没有碰过另外两个轴,也没有旋转。但是,如果您注意到了,您将看到Z轴环现在与X轴对齐。现在,如果我们开始绕X轴旋转,那么Z轴将随之旋转。我们失去了旋转的自由。这就是术语“万向节锁定”。
如果重新设置所有内容,则这可能会在3轴之间以6种不同的组合发生。因此,无论您尝试哪种方式,仅使用3D数学或使用Euler角的3D旋转矩阵在所有3维中自由旋转;这是使用正弦和余弦函数来绕每个轴旋转的基本矩阵,因此,您总是会遇到万向节锁定的情况。
有一种避免这种情况的方法!使用四元数!对它们的数学理解起来有些棘手,因为它是一种4D vector 类型,并且确实涉及虚构平面和复数,但是对它们的编程非常容易,因为它们与 vector 和矩阵都非常相似。有了第四个组件,您就可以自由地绕(X,Y,Z)旋转,而不会出现此问题。云台锁定和四元数上有大量的资源可用于数学以及它们的编程,并且已经有许多不错的数学库已经为您定义了四元数,这只是阅读有关如何应用它们的文档的问题。在您的代码中。它们使生活变得更加轻松。
要注意的一件事是,在3D空间中旋转时不必总是使用四元数,它总是取决于需要。以下是一些一些示例,它们可以更好地使用四元数,并且可以使用欧拉角。
欧拉角:如果您知道您将只在一个轴上旋转。
四元数旋转:需要2个或更多轴的自由度时。
这是一个描述Gimbal Lock的视频的链接,该视频是非常精确而详细的 View ,可以在不到10分钟的时间内完全了解这种现象。 YouTube: Gimbal Lock
关于c++ - openGL旋转重置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30204714/