我的Quaternion旋转在OpenGL中出了什么问题?

时间:2017-04-30 06:47:31

标签: opengl rotation quaternions

在互联网上关闭笔记有助于正确构建四元数类。我的问题是将它们用于实际使用并将它们用于原始OpenGL中的旋转。

在我的输入事件中,我有以下内容:

Quaternion<float> qPrev = qRot;
qRot = qRot.UnitQuaternion(); // #1.
Quaternion<float> axis(5., 0., 1., 0.);
qRot = qPrev*axis;
qRot *= qPrev.conjugate();
//#2. qRot = qRot.UnitQuaternion();

如果我使用#1制作旋转结果单元,它会旋转几秒钟,加速然后完全消失。

如果我使用#2作为单位结果,则框#34;摆动&#34;永远不会旋转

或者,我已经根据其他实现使用了这个:

Quaternion<float> qPrev = qRot;
Quaternion<float> axis(-5./100, 0., 1., 0.); // #3.
axis = axis.UnitQuaternion();
qRot = qPrev*axis;
// #4. qRot *= qPrev.conjugate();

#3。最有意义的是,取一个非单位四元组的单位,并将其最初乘以身份四元组;把所有东西都保持在单位季度。

#4。尝试根据我对方程旋转定义的理解来乘以共轭。

所有这些产生了一个小摆动,#1是我得​​到的最接近的;盒子旋转,然后迅速旋转,然后消失。

我的理解是我有一个可以旋转的轴I,其中w =多少(以弧度表示的角度)。我简单地乘以方向并将该结果乘以方向的负数;例如共轭。

渲染代码(这可能是罪魁祸首):

// Apply some transformations
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -100.f);
glRotatef(qRot.x, 1., 0, 0);
glRotatef(qRot.y, 0, 1., 0);
glRotatef(qRot.z, 0, 0, 1.);

// Draw the cube
glDrawArrays(GL_TRIANGLES, 0, 36);

// Draw some text on top of our OpenGL object
window.pushGLStates();

我很感激帮助

编辑:非常感谢@ybungalobill提供帮助

我想从四元数中得到的是四元数学方面的一个非常具体的应用。我想要一个旋转轴,而在我的例子中,我创建了一个带有直接值的四元数。这不是旋转矩阵的推导方式。我需要更多步骤:

void FromAxisAngle(_Tp theta, _Tp x, _Tp y, _Tp z)
{
    //Angle should be in radians
    this->w = cos(theta/2);

    //Axes
    this->x = x * sin(theta/2);
    this->y = y * sin(theta/2);
    this->z = z * sin(theta/2);
    //Normalize
    *this = this->UnitQuaternion();
}

同样,获取旋转矩阵是一个非常具体的应用程序,具有非常具体的步骤。四元数并不是开箱即用的。

旋转逻辑的一些小改动:

   Quaternion<float> qPrev = qRot;
   Quaternion<float> axis;
   axis.FromAxisAngle(-5./100, 1., 0., 0.);
   qRot = qPrev*axis;

所以现在我已经从旋转轴创建了数学上正确的四元数。然后相乘。

最后,我要做的最后一件事是从我的四元数中创建一个OpenGL可以使用的矩阵。所以我们有更多的数学要做,以便用旋转的东西来表达它:

void GetMatrix(_Tp matrix[16])
{
   Quaternion<_Tp> temp(this->UnitQuaternion());
  _Tp qw = temp.w;
  _Tp qx = temp.x;
  _Tp qy = temp.y;
  _Tp qz = temp.z;

  matrix[0] = 1.0f - 2.0f*qy*qy - 2.0f*qz*qz;
  matrix[1] = 2.0f*qx*qy - 2.0f*qz*qw;
  matrix[2] = 2.0f*qx*qz + 2.0f*qy*qw;
  matrix[3] = 0;

  matrix[4] = 2.0f*qx*qy + 2.0f*qz*qw;
  matrix[5] = 1.0f - 2.0f*qx*qx - 2.0f*qz*qz;
  matrix[6] = 2.0f*qy*qz - 2.0f*qx*qw;
  matrix[7] = 0;

  matrix[8] = 2.0f*qx*qz - 2.0f*qy*qw;
  matrix[9] = 2.0f*qy*qz + 2.0f*qx*qw;
  matrix[10] = 1.0f - 2.0f*qx*qx - 2.0f*qy*qy;
  matrix[11] = 0;

  matrix[12] = 0;
  matrix[13] = 0;
  matrix[14] = 0;
  matrix[15] = 1;
}

使用glMultMatrix立方体旋转。

1 个答案:

答案 0 :(得分:3)

glRotatef(qRot.x, 1., 0, 0);
glRotatef(qRot.y, 0, 1., 0);
glRotatef(qRot.z, 0, 0, 1.);

这不是如何将四元数旋转应用于GL状态。您必须按照here中的公式将其转换为矩阵,然后调用glMultMatrixglMultTransposeMatrix。在那之后,#3的方法将按预期工作。

将任何非零四元数转换为矩阵的代码,来自Stannum libs:

template<class T>
mat<T,3,3> mat_rotation(const quat<T> &x)
{
    T s = 2/norm2(x); // cheap renormalization even of non-unit quaternions
    T wx = x.w*x.x, wy = x.w*x.y, wz = x.w*x.z;
    T xx = x.x*x.x, xy = x.x*x.y, xz = x.x*x.z;
    T yy = x.y*x.y, yz = x.y*x.z;
    T zz = x.z*x.z;

    return mat<T,3,3>(
        1 - s*(yy+zz),  s*(xy-wz),  s*(xz+wy),
        s*(xy+wz),  1 - s*(xx+zz),  s*(yz-wx),
        s*(xz-wy),  s*(yz+wx),  1 - s*(xx+yy)
    );
}