【问题标题】:OpenGL Rotation - Local vs Global AxesOpenGL 旋转 - 局部与全局轴
【发布时间】:2012-03-30 23:10:30
【问题描述】:

所以我有一个对象,我正在尝试根据 Yaw、Pitch 和 Roll 方案旋转,相对于对象自己的局部轴而不是全局空间的轴。根据this,我需要按该顺序执行旋转。我将其解释为:

glRotatef(m_Rotation.y, 0.0, 1.0, 0.0);
glRotatef(m_Rotation.z, 0.0, 0.0, 1.0);
glRotatef(m_Rotation.x, 1.0, 0.0, 0.0);

但是,绕 Y 轴和 Z 轴的旋转不起作用。绕 Y 轴的旋转总是相对于全局空间,绕 Z 轴的旋转作用于绕 X 轴的旋转为 0,否则会乱码。

为了确定,我也尝试了相反的顺序,但这也不起作用。我想我也尝试了所有其他订单,所以问题一定是别的。可能吗?

这就是我获得旋转的方式:

    ///ROTATIONS
    sf::Vector3<float> Rotation;
    Rotation.x = 0;
    Rotation.y = 0;
    Rotation.z = 0;
    //ROLL
    if (m_pApp->GetInput().IsKeyDown(sf::Key::Up) == true)
    {
        Rotation.x -= TurnSpeed;
    }
    if (m_pApp->GetInput().IsKeyDown(sf::Key::Down) == true)
    {
        Rotation.x += TurnSpeed;
    }
    //YAW
    if (m_pApp->GetInput().IsKeyDown(sf::Key::Left) == true)
    {
        Rotation.y -= TurnSpeed;
    }
    if (m_pApp->GetInput().IsKeyDown(sf::Key::Right) == true)
    {
        Rotation.y += TurnSpeed;
    }
    //PITCH
    if (m_pApp->GetInput().IsKeyDown(sf::Key::Q) == true)
    {
        Rotation.z -= TurnSpeed;
    }
    if (m_pApp->GetInput().IsKeyDown(sf::Key::E) == true)
    {
        Rotation.z += TurnSpeed;
    }

然后将它们添加到 m_Rotation 中:

//Rotation
m_Rotation.x += Angle.x;
m_Rotation.y += Angle.y;
m_Rotation.z += Angle.z;

(它们被传递给正在移动的东西的内部函数,但没有对它们做任何其他事情)。

想法?还有什么我应该调用以确保所有旋转的轴都是局部轴吗?

【问题讨论】:

  • 无论如何使用旋转矩阵可能更好。
  • 你试过 P->R->Y 作为命令吗?您是否考虑到,一旦您旋转,应用新旋转所围绕的轴就是 轴,我的意思是原始轴旋转了某个角度?
  • 是的,我已经尝试过 P-R-Y,但这也无济于事 - Roll 粘在全局轴上。我没有使用转换矩阵的经验——他们会完全避免这个麻烦吗?难道我还需要三个 glRotatef() 调用并将它们按某种顺序排列吗?
  • 您的对象是在原点旋转之前吗..?如果不是,您必须将其转换为原点,然后旋转并转换回指定位置。否则它与您想要的旋转不同..

标签: c++ opengl 3d sfml


【解决方案1】:

加里克,

当您调用 glRotate(angle, x, y, z) 时,它会围绕您传递给 glRotate 的矢量旋转。向量从 (0,0,0) 到 (x,y,z)。

如果要围绕对象的局部轴旋转对象,则需要将对象 glTranslate 到原点,执行旋转,然后将其平移回原点。

这是一个例子:

//Assume your object has the following properties
sf::Vector3<float> m_rotation;
sf::Vector3<float> m_center;

//Here would be the rotate method
public void DrawRotated(sf::Vector<float> degrees) {
  //Store our current matrix 
  glPushMatrix();

  //Everything will happen in the reverse order...
  //Step 3: Translate back to where this object came from
  glTranslatef(m_center.x, m_center.y, m_center.z);

  //Step 2: Rotate this object about it's local axis
  glRotatef(degrees.y, 0, 1.0, 0);
  glRotatef(degrees.z, 0, 0, 1.0);
  glRotatef(degrees.x, 1.0, 0, 0);

  //Step 1: Translate this object to the origin
  glTranslatef(-1*m_center.x, -1*m_center.y, -1*m_center.z);

  //Render this object rotated by degrees
  Render();

  //Pop this matrix so that everything we render after this
  // is not also rotated
  glPopMatrix();
}

【讨论】:

    【解决方案2】:

    您的问题是您正在存储 x、y、z 旋转并累积添加它们。然后,当您渲染时,您正在对单位矩阵执行总累积旋转(您正在全局执行所有旋转)。从渲染循环中注释掉您的身份调用。并确保在初始化函数中设置身份。 那么

    rotate as normal
    m_Rotation.x = m_Rotation.y = m_Rotation.z = 0.0f; 
    //clear your rotations you don't want them to accumulate between frames
    glpush
    translate as normal
    (all other stuff)
    glpop
    //you should be back to just the rotations 
    //glclear and start next frame as usual
    

    我相信您在接受原始答案后会发现。旋转或平移的顺序不影响旋转发生在哪个轴上,而是影响执行旋转的点。例如,将行星旋转 15 度将使其在全局轴上旋转 15 度。将其从原点平移然后旋转将导致它在平移距离处绕原点运行(如果与旋转在同一轴上,则在 x 轴上平移然后在 y 轴上旋转不会产生任何混淆效果)。

    【讨论】:

      猜你喜欢
      • 2012-08-05
      • 2015-07-17
      • 2021-10-17
      • 1970-01-01
      • 2016-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多