[英]How to find vector for the quaternion from X Y Z rotations
我正在创建一个关于OpenGL的非常简单的项目,并且我坚持轮换。 我试图在所有3个轴上独立地旋转一个物体:X,Y和Z.由于围绕一个轴旋转后的“万向节锁定”问题,我已经度过了不眠之夜。 然后我才知道四元数会解决我的问题。 我已经研究了四元数并实现了它,但是我无法将我的旋转转换为四元数。 例如,如果我想绕Z轴旋转90度,我只需为我的四元数创建{0,0,1}向量,并使用此处的代码将其绕该轴旋转90度:
http://iphonedevelopment.blogspot.com/2009/06/opengl-es-from-ground-up-part-7_04.html (最复杂的底部矩阵)
这对于一个矢量是可以的,但是,比方说,我首先要围绕Z旋转90度,然后围绕X旋转90度(仅作为示例)。 我需要传递什么载体? 我该如何计算该向量。 我对矩阵和三角函数不太好(我知道基础和一般规则,但我不是一个高手)但我需要完成这个。 有很多关于四元数的教程,但我似乎没有理解(或者他们没有回答我的问题)。 我只需要学习构建围绕多个轴组合旋转的矢量。
更新 :我发现这个关于四元数的好页面并决定以这种方式实现它们: http : //www.cprogramming.com/tutorial/3d/quaternions.html
这是我的四元数乘法代码:
void cube::quatmul(float* q1, float* q2, float* resultRef){
float w = q1[0]*q2[0] - q1[1]*q2[1] - q1[2]*q2[2] - q1[3]*q2[3];
float x = q1[0]*q2[1] + q1[1]*q2[0] + q1[2]*q2[3] - q1[3]*q2[2];
float y = q1[0]*q2[2] - q1[1]*q2[3] + q1[2]*q2[0] + q1[3]*q2[1];
float z = q1[0]*q2[3] + q1[1]*q2[2] - q1[2]*q2[1] + q1[3]*q2[0];
resultRef[0] = w;
resultRef[1] = x;
resultRef[2] = y;
resultRef[3] = z;
}
这是我将四元数应用于我的模型视图矩阵的代码(我有一个tmodelview
变量,它是我的目标模型视图矩阵):
void cube::applyquat(){
float& x = quaternion[1];
float& y = quaternion[2];
float& z = quaternion[3];
float& w = quaternion[0];
float magnitude = sqrtf(w * w + x * x + y * y + z * z);
if(magnitude == 0){
x = 1;
w = y = z = 0;
}else
if(magnitude != 1){
x /= magnitude;
y /= magnitude;
z /= magnitude;
w /= magnitude;
}
tmodelview[0] = 1 - (2 * y * y) - (2 * z * z);
tmodelview[1] = 2 * x * y + 2 * w * z;
tmodelview[2] = 2 * x * z - 2 * w * y;
tmodelview[3] = 0;
tmodelview[4] = 2 * x * y - 2 * w * z;
tmodelview[5] = 1 - (2 * x * x) - (2 * z * z);
tmodelview[6] = 2 * y * z - 2 * w * x;
tmodelview[7] = 0;
tmodelview[8] = 2 * x * z + 2 * w * y;
tmodelview[9] = 2 * y * z + 2 * w * x;
tmodelview[10] = 1 - (2 * x * x) - (2 * y * y);
tmodelview[11] = 0;
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf(tmodelview);
glMultMatrixf(modelview);
glGetFloatv(GL_MODELVIEW_MATRIX, tmodelview);
glPopMatrix();
}
我的旋转代码(我称之为外部),其中quaternion
是多维数据集的类变量:
void cube::rotatex(int angle){
float quat[4];
float ang = angle * PI / 180.0;
quat[0] = cosf(ang / 2);
quat[1] = sinf(ang/2);
quat[2] = 0;
quat[3] = 0;
quatmul(quat, quaternion, quaternion);
applyquat();
}
void cube::rotatey(int angle){
float quat[4];
float ang = angle * PI / 180.0;
quat[0] = cosf(ang / 2);
quat[1] = 0;
quat[2] = sinf(ang/2);
quat[3] = 0;
quatmul(quat, quaternion, quaternion);
applyquat();
}
void cube::rotatez(int angle){
float quat[4];
float ang = angle * PI / 180.0;
quat[0] = cosf(ang / 2);
quat[1] = 0;
quat[2] = 0;
quat[3] = sinf(ang/2);
quatmul(quat, quaternion, quaternion);
applyquat();
}
我说,旋转,旋转rotatex
次只旋转1度,但我的立方体在10度1度后旋转了近90度,这没有意义。 此外,在调用不同轴的旋转函数后,My cube变得偏斜,得到2维,并且消失(模型视图矩阵中的列变为全零),这是不可逆转的,显然不应该正确实现四元数。
你接近这个错误的方式。 如果X轴,Y轴和Z轴有三个欧拉角旋转,将它们转换为四元数然后转换为矩阵将无法帮助您。 由于表示您想要的旋转,会产生万向节锁定。 如果您将所需的旋转存储为XYZ Euler角度,那么您将获得Gimbal锁定。
您需要将所需的方向存储为四元数以获得优势。 也就是说,可以将当前方向作为四元数,然后问一个问题“如何围绕Z轴旋转90度并将其作为我的新方向?”,但是问“我的当前”是没有用的方向由这些XYZ欧拉角定义,如何将其转换为四元数?“。
对四元数相关部分的完全处理将是相当漫长的。 值得注意的是,您链接的网站似乎真的在谈论轴角度旋转,而不是四元数。
编辑:你发布的代码是正确的,除了tmodelview[6]
和tmodelview[9]
的标志是错误的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.