c++ - openGL旋转重置

标签 c++ opengl rotation

我目前正在查看一组球体,并分别按下按钮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轴环指向您。 。当您捕获手柄并开始移动手柄时,该环将沿该轴旋转对象。

想象一下您的球体是地球:

  • X轴:旋转3D模型时,它将绕x轴东西方向旋转,并且地球将随着南北极和赤道方向的变化而旋转。如果您向下看Z轴(LookAt),赤道将朝向或远离您倾斜或旋转
  • Y轴旋转3D模型时,这将使其绕
    y轴的南北方向和地球将像地球日一样绕两极旋转。赤道不动。
  • Z轴旋转3D模型时,这将使其绕z轴“LookAt”旋转(仍水平,但垂直于东西方),地球将绕LookAt轴旋转,而南北两极和赤道会改变方向。沿LookAt轴向下看,您会看到两极和赤道向东方和西方倾斜。

  • 这里有一个类比来证明这一点,例如通过环的运动来旋转3D模型:我将使用电单车,将轴的旋转考虑如下
  • X轴-自行车 throttle
  • Y轴-转动把手
  • Z轴-左右倾斜自行车

  • 注意:当您绕任何轴旋转对象时,环会移动,并且对象会显示旋转。

    既然您已经了解了每次旋转发生的情况,那么我将与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空间中旋转时不必总是使用四元数,它总是取决于需要。以下是一些一些示例,它们可以更好地使用四元数,并且可以使用欧拉角。

    欧拉角:如果您知道您将只在一个轴上旋转。
  • 在地面上滚动的桶
  • child 秋千
  • 跷跷板
  • 摇椅

  • 四元数旋转:需要2个或更多轴的自由度时。
  • 相机旋转
  • 在地面上滚动的球。
  • 飞机或喷气式飞机。
  • 在太空中移动的航天飞机或卫星。
  • 潜水艇
  • 角色AI-当高度是一个因素时的检测和跟踪算法!
  • 高度也是一个因素时的任何字符移动。鸟类飞行,鱼类游泳,角色动画-布娃娃物理。

  • 这是一个描述Gimbal Lock的视频的链接,该视频是非常精确而详细的 View ,可以在不到10分钟的时间内完全了解这种现象。 YouTube: Gimbal Lock

    关于c++ - openGL旋转重置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30204714/

    相关文章:

    C++ 链表 : "->" operator fails to change the internal values of node object

    CSS 同时旋转和替换图像

    c++ - Go 中的 OpenCV(或类似库)

    c++ - 具有单位 vector 约束的非线性优化

    c++ - 为什么使用 OpenGL 绘制黑色像素而不是透明像素来绘制 8 位纹理?

    c++ - 在每次移动过程中在 Opengl 中制作游戏时形成额外对象

    java - JOGL 和 Swing 的问题

    javascript - css,使用旋转和jquery到初始位置

    ios - 获取 UIView 的当前角度/旋转/弧度?

    c++ - 我可以在 C++ 中声明一个非成员函数 const 吗?