gpt4 book ai didi

c++ - OpenGL + SDL绕局部轴旋转

转载 作者:行者123 更新时间:2023-11-30 02:07:15 34 4
gpt4 key购买 nike

我一直在研究半飞行模拟器。我想做的是使用俯仰滚转和偏航旋转对象。我已经在网上看了很多东西,尽管他们解释了问题所在,但我不知道如何实现该解决方案。例如,我这样做:

glRotatef(yaw,0,1,0);
glRotatef(pitch,1,0,0);

偏航不正常,俯仰会很好。从我一直在阅读的内容来看,似乎对象的局部轴已更改,因此我需要找到对象的新局部轴并围绕该轴旋转。所以我尝试了类似的东西:
newpitch=pitch/57.29
VectorA(0,cos(newpitch)-sin(newpitch),sin(newpitch)+cos(newpitch));
glRotatef(yaw,vec.getXAxis(),vec.getYAxis(),vec.getZAxis());
glRotatef(pitch,1,0,0);

这似乎也不起作用。

我还尝试过制作一个通用的旋转矩阵,并同时给出俯仰角和偏航角,并且仍然存在相同的问题。而且我尝试使用四元数,并且仍然存在相同的问题!

这是我的四元数代码:
void Quat::eulerToQuat(float roll,float pitch,float yaw){
float radiansY = yaw/57.2;
float radiansZ = roll/57.2;
float radiansX = pitch/57.2;

float sY = sinf(radiansY * 0.5);
float cY = cosf(radiansY * 0.5);
float sZ = sinf(radiansZ * 0.5);
float cZ = cosf(radiansZ * 0.5);
float sX = sinf(radiansX * 0.5);
float cX = cosf(radiansX * 0.5);

w = cY * cZ * cX - sY * sZ * sX;
x = sY * sZ * cX + cY * cZ * sX;
y = sY * cZ * cX + cY * sZ * sX;
z = cY * sZ * cX - sY * cZ * sX;
}

然后,我将其转换为矩阵,并将 glMultMatrix(matrix)与modelview矩阵一起使用,这存在相同的问题。因此,我相信它不会是gimble lock =)。

所以在我的代码中,我这样做:
float matrix[4][4];
Quat this;
this.eularToQuat(roll,pitch,yaw);
this.toMatrix(matrix);
glMultMatrix(matrix);

最佳答案

我认为您指的是万向节锁?没错,每次旋转都会修改将围绕其进行后续局部旋转的轴。在您的情况下,这会影响偏航,因为OpenGL矩阵堆栈可以工作,因此您添加到其中的每件事在概念上都在堆栈中已有的东西之前发生(即,以矩阵形式进行后乘)。

但是,即使正确实现,您的解决方案也无法解决问题。您想要做的是在局部坐标空间中获得全局y轴,以便即使绕全局z旋转也可以绕全局y旋转,从而移动局部轴。但这只会给您带来许多相同的问题,就像您始终卡在全局轴上并以其他顺序应用旋转一样。现在,第二个旋转将干扰第一个旋转,而不是相反。

使自己确信自己在做的事情是错误的另一种方法是查看您拥有多少信息。您试图用两个数字描述对象的方向。两个数字不足以描述任何旋转,因此显然存在一些其他规则将两个数字转换为一个完整的方向。无论您做什么修改该规则,都将最终限制您可以达到的方向。但是对于飞机,您真的希望能够达到任何方向,所以这是一个基本矛盾。

产生困惑的原因是,如果您有合适的方向存储方式,那么说“如果我通过将局部y旋转5左右,然后围绕z旋转10个来修改方向,那将是完全正确的做法”。等等。问题是尝试将所有这些转换汇总为一对旋转。这是不可能的。

如果您已经开始使用OpenGL,最简单的解决方案是将方向存储为完整的矩阵。通过将俯仰和偏航旋转应用于矩阵,可以累积它们。您可以通过glMultMatrix将该矩阵传递给OpenGL以执行绘图。

这不是最佳解决方案,但快速解决方案测试解决方案是使用glLoadMatrixglGet通过将矩阵加载到OpenGL矩阵堆栈中(然后从图形中检索出来)来应用转换,以进行转换。堆栈并不是真正的用途,因此您可能会遇到一些性能问题,随着时间的推移,舍入错误将导致异常行为,但是一旦您相信该方法,就可以修复这些错误。 OpenGL手册页提供了所有转换矩阵的公式,您应该查询矩阵归一化(无论您是否意识到,都可能使用正交矩阵,这将对Google有所帮助)来处理累积舍入。

编辑:关于您在我闲逛时发布的代码,四元数是表示方向的另一种有效方式,并且您可以安全地应用增量更新。它们也很紧凑,很容易防止舍入错误。但是,我认为您的问题可能是您没有将四元数用作定向存储,而只是将其用作中间容器。因此,将它们添加到链中并不能解决您的任何问题。

EDIT2:进一步的挥手解释,以推导直接存储俯仰和偏航还不够好的想法:想象一下,从飞行员的 Angular 来看,您应用90度偏航,然后施加30度,然后是-90度的偏航。然后,最终效果就好象应用了30度滚动。但是,如果您仅存储俯仰和偏航,则无法存储滚动。此外,如果仅将总偏航角和总俯仰角相加,则最终会以为您应用了30度而不是横滚角。因此,无论按什么顺序应用俯仰和偏航,或者使用全局轴还是局部轴,都不会得到错误的结果。

关于c++ - OpenGL + SDL绕局部轴旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8063293/

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