如何根据前向矢量计算俯仰和偏航值

问题描述 投票:0回答:2

我想根据相机实例化时获得的位置和目标点来计算相机的俯仰和偏航值。如果我将音高初始化为0,并将偏航角初始化为-90(如LearnOpenGL Camera Tutorial中所示),则在第一次旋转时,相机突然跳动;旋转后可以正常工作。因此,首先,从该教程中给出的方程式开始,我尝试从正向矢量获取俯仰和偏航值:

float pitch = glm::degrees(glm::asin(forward.y));
float yaw = glm::degreees(glm::acos((float)x/glm::cos(glm::asin(y))));

也是

float yaw = glm::degreees(glm::asin((float)z/glm::cos(glm::asin(y))));

并且cos(sin(y))不应为0,因此y不应为0或-1。我尝试实现这些功能,但是偏航的2个值不相同,偏航的第一个值似乎也是我想要的,但音高却不同。之后,我尝试了一种简单的方法,即知道间距是前向矢量与y轴之间的角度,而偏航是前向矢量与x轴之间的角度,因此我尝试(在纸上)计算以下内容:

const glm::vec3 yUnit(0, 1, 0);
const glm::vec3 xUnit(1, 0, 0);
float pitch = glm::degrees(glm::acos(glm::dot(forward, yUnit)));
float yaw = glm::degrees(glm::acos(glm::dot(forward, xUnit)));

[具有以下2个输入:位置=(0,0,0),目标=(0,1,2,5),正向=目标-位置=(0,1,2.5),归一化正向〜(0, 0.37,0.926),结果为俯仰〜68度,偏航= 90度。另外,我在应用程序内打印了俯仰和偏航值,并且期望值应该为pitch = -20和偏航= -90。

如果我错了,你能解释一下我的原因和原因吗?

opengl camera glm-math euler-angles
2个回答
0
投票

无法指向任何一行进行更改,但建议:

第一次旋转时,相机突然跳动

这表明某些东西尚未初始化为您认为的样子。在这种情况下,俯仰和偏航是可以从前向矢量计算得出的值,对吧?导出值后,永远不要直接初始化它们,因为有可能会弄错它。如果两个假定为“相同”的值不同,则会发生奇怪的事情。而是初始化前向矢量,并立即从中计算俯仰和偏航。

并且cos(sin(y))不应为0

我们都会不时犯此错误。但是在这种情况下,我认为这并不重要,稍后再说吧。

但是,您可能要测试正向向量为(0,0,0)时会发生什么。在图形编程中以某种方式获得全零向量是令人惊讶的普遍现象。

浮动偏航= glm :: deges(glm :: acos((float)x / glm :: cos(glm :: asin(y))))]]

您是否确定要使用哪种欧拉角表示形式?在简单的情况下,您不需要使用多个轴坐标值来计算角度,但是这里使用的是两个。

最简单的情况是偏航(航向),俯仰和横滚是独立的角度,因此,如果俯仰不变,则偏航不会改变,反之亦然。具有xUnit和yUnit向量的最后一个代码块似乎正在执行此操作。

然而,在飞行中,模拟器和航空航天计算的偏航-俯仰-侧倾有些复杂,因为它们不是独立的。偏航角可以在俯仰平面上测量,而不是绝对XZ。航空偏航通常是从“北” Z轴而不是X轴测量的。因此,您需要清楚要测量的偏航和俯仰角,并且始终保持一致。而且,您需要研究任何教科书示例或代码,以弄清它们如何使用音高-偏航-横滚,以及是否与您的相一致。

我建议暂时使用简单的单坐标测量。

浮动音调= glm :: degrees(glm :: acos(glm :: dot(forward,yUnit)));

再次,您确定前进是正常的吗?通常,将LookAt编码为比数学库更宽容的代码,这是一个容易犯的错误。

而且,您是否检查过-180至180度以外的机智值是什么数学库?还需要担心的一件事。

希望这会有所帮助。如果您发现欧拉角很烦人,那么您并不孤单!这就是为什么许多3D书籍和教程建议学习四元数的原因。


0
投票

根据您的期望值,您的音高似乎应该在-90到90度之间变化,因此您应该使用asin而不是acos进行音高。

计算偏航时,需要将前向矢量投影到xz平面上。您可以通过将y分量设置为零然后将其规格化来进行此操作。

偏航将需要在0到360度之间变化,但是acos仅返回0到180度之间。偏航在第一个180度是正确的,但是随着偏航从180增加到360,Acos将从180减小到零。当正向矢量和(0,0,1)之间的点积大于零时,偏航将大于180度,因此应通过从360减去它来调整acos值。

根据您的期望值,我对正确的偏航和俯仰值的猜测是

pitch = degrees(-asin(dot(forward, y_unit)))
forward.y = 0
forward = normalize(forward)
yaw = degrees(acos(dot(forward, x_unit)))
if(dot(forward, z_unit) > 0)
    yaw = 360 - yaw
© www.soinside.com 2019 - 2024. All rights reserved.