OpenGL中的四元数旋转有什么问题?
在互联网上记笔记有助于正确构造四元数类。我的问题是将它们付诸实际使用,并在原始OpenGL中使用它们进行旋转 在我的输入事件中,我有以下内容:OpenGL中的四元数旋转有什么问题?,opengl,rotation,quaternions,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
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();
我感谢你的帮助
编辑:非常感谢@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;
四元数qPrev=qRot;
四元数轴;
轴从轴角度(-5./100,1,0,0.);
qRot=qPrev*轴;
现在我从旋转轴上创建了一个数学上正确的四元数。然后乘以
最后,我必须做的最后一件事是从我的四元数创建一个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;
}
void GetMatrix(_-Tp-matrix[16])
{
四元数temp(this->UnitQuaternion());
_Tp qw=温度w;
_Tp qx=温度x;
_Tp qy=温度y;
_Tp qz=温度z;
矩阵[0]=1.0f-2.0f*qy*qy-2.0f*qz*qz;
矩阵[1]=2.0f*qx*qy-2.0f*qz*qw;
矩阵[2]=2.0f*qx*qz+2.0f*qy*qw;
矩阵[3]=0;
矩阵[4]=2.0f*qx*qy+2.0f*qz*qw;
矩阵[5]=1.0f-2.0f*qx*qx-2.0f*qz*qz;
矩阵[6]=2.0f*qy*qz-2.0f*qx*qw;
矩阵[7]=0;
矩阵[8]=2.0f*qx*qz-2.0f*qy*qw;
矩阵[9]=2.0f*qy*qz+2.0f*qx*qw;
矩阵[10]=1.0f-2.0f*qx*qx-2.0f*qy*qy;
矩阵[11]=0;
矩阵[12]=0;
矩阵[13]=0;
矩阵[14]=0;
矩阵[15]=1;
}
使用glMultMatrix
立方体旋转
这不是将四元数旋转应用于GL状态的方式。必须按照公式将其转换为矩阵,然后调用glMultMatrix
或glMultTransposeMatrix
。在这一方法之后,3号将按预期工作
将任何非零四元数从锡库转换为矩阵的代码:
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)
);
}
模板
材料旋转(常量数量和x)
{
ts=2/norm2(x);//非单位四元数的廉价重正化
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;
回程垫(
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)
);
}
这不是将四元数旋转应用于GL状态的方式。必须按照公式将其转换为矩阵,然后调用glMultMatrix
或glMultTransposeMatrix
。在这一方法之后,3号将按预期工作
将任何非零四元数从锡库转换为矩阵的代码:
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)
);
}
模板
材料旋转(常量数量和x)
{
ts=2/norm2(x);//非单位四元数的廉价重正化
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;
回程垫(
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)
);
}
我见过像您所说的那样应用矩阵的代码,但我如何避免使用生成的矩阵而改用glRotatef?@Maverick:您无法避免矩阵,因为传统的OpenGL转换最终会使用矩阵堆栈。您可以通过normalize(x,y,z)
恢复旋转轴,通过2*atan2(长度(x,y,z),w)
恢复角度,然后调用glRotate
。但是下一件事是计算这个角度的正弦和余弦,然后计算出所说的矩阵。。。问题是你为什么不想用直接的方式来做呢?好吧。我对这段代码感到困惑:如果这旋转一个点并返回一个轴,为什么这不适用于glRotatef?@Maverick:你不需要它(除非你在顶点着色器中直接得到四元数进行变换——你不需要)。该代码将四元数应用于一个向量。相反,您需要的是通过矩阵乘法来表示转换。如果你做那q.QuatRotation(v)
的代数,你会发现它正好等于mat_rotation(q)*v
@Maverick:是的。这是正确的。换句话说:传统OpenGL的工作原理是通过M*v
将其内部GL\u MODELVIEW
矩阵M
应用到每个顶点v
。因为OpenGL不理解四元数,所以需要以矩阵向量乘法形式表示q.quartorrotation(v)
,而mat_rotation(q)*v
就是这样做的。你将M=mat_rotation(q)
存储在OpenGL的状态下,然后根据需要替换不同的顶点v
。我见过像你所说的那样应用矩阵的代码,但我如何避免使用结果矩阵而使用glRotatef呢?@Maverick:你无法避免矩阵,因为传统的OpenGL转换最终会使用矩阵堆栈。您可以通过normalize(x,y,z)
恢复旋转轴,通过2*atan2(长度(x,y,z),w)
恢复角度,然后调用glRotate
。但是下一件事是计算这个角度的正弦和余弦,然后计算出所说的矩阵。。。问题是为什么你不想用简单的方式来做呢?好吧。我对这段代码感到困惑:如果这旋转一个点并返回一个轴,为什么这对glRotatef不起作用?@Maverick:you
glRotatef(qRot.x, 1., 0, 0);
glRotatef(qRot.y, 0, 1., 0);
glRotatef(qRot.z, 0, 0, 1.);
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)
);
}