gpt4 book ai didi

c++ - 如何从 X Y Z 旋转中找到四元数的 vector

转载 作者:可可西里 更新时间:2023-11-01 17:46:54 26 4
gpt4 key购买 nike

我正在 OpenGL 上创建一个非常简单的项目,但我遇到了旋转问题。我试图在所有 3 个轴上独立地旋转一个对象:X、Y 和 Z。由于围绕一个轴旋转后的“万向节锁定”问题,我睡不着觉。然后我了解到四元数可以解决我的问题。我已经研究了四元数并实现了它,但我无法将我的旋转转换为四元数。例如,如果我想绕 Z 轴旋转 90 度,我只需为我的四元数创建 {0,0,1} vector 并使用此处的代码将它绕该轴旋转 90 度:

http://iphonedevelopment.blogspot.com/2009/06/opengl-es-from-ground-up-part-7_04.html (最复杂的矩阵往下)

这对于一个 vector 来说没问题,但是,比如说,我首先想围绕 Z 旋转 90 度,然后围绕 X 旋转 90 度(仅作为示例)。我需要传入什么 vector ?我如何计算该 vector 。我不擅长矩阵和三角学(我知道基础知识和一般规则,但我不是高手)但我需要完成这项工作。有很多关于四元数的教程,但我似乎一个都不明白(或者他们没有回答我的问题)。我只需要学习构造围绕多个轴组合旋转的 vector 。

更新:我找到了这个关于四元数的好页面并决定以这种方式实现它们: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;
}

这是我将四元数应用于我的模型 View 矩阵的代码(我有一个 tmodelview 变量,它是我的目标模型 View 矩阵):

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 10-11 次只旋转 1 度,但我的立方体在 1 度旋转 10-11 次后几乎旋转了 90 度,这没有意义.此外,在不同轴上调用旋转函数后,我的立方体变得倾斜,变成二维,并不可逆转地消失(模型 View 矩阵中的一列变为全零),这显然不应该在正确实现四元数的情况下发生。

最佳答案

您的处理方式有误。如果 X、Y 和 Z 轴有三个欧拉角旋转,将它们转换为四元数然后转换为矩阵将无济于事。万向节锁的出现是因为表示您想要的旋转。如果您将所需的旋转存储为 X-Y-Z 欧拉角,那么您将获得万向节锁定。

您需要将您的所需方向存储为四元数以获得优势。也就是说,可以将当前方向作为四元数,然后问“我如何将它绕 Z 轴旋转 90 度并将其用作我的新方向?”这个问题,但是问“我当前的方向”是没有用的方向是由这些 X-Y-Z 欧拉角定义的,我如何将其转换为四元数?”。

完整处理四元数的相关部分会相当冗长。值得注意的是,您链接到的网站似乎真的在谈论轴角旋转,而不是四元数。

编辑:您发布的代码是正确的,除了 tmodelview[6]tmodelview[9] 的符号是错误的。

关于c++ - 如何从 X Y Z 旋转中找到四元数的 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9863877/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com