注意:我编辑了下面与我的真实问题相关的问题,而不是下面的文字,如果您可以跳过这个问题,但我会因历史原因将其留在此处。 < / p>
要查看我是否正确,C中的float
与弧度值相同吗?我的意思是,360º= 6.28318531弧度,我刚刚注意到我的OpenGL应用程序,完全旋转从0.0到6.28,这似乎正确加起来。我只是想确保我做对了。
我正在使用float
(我们称之为anglePitch
)从0.0到360.0(它更容易以度数读取并避免将int
投射到float
所有我在网上看到的所有代码都使用某种DEG2RAD()
宏,定义为DEG2RAD 3.141593f / 180
。最后它会是这样的:
anglePitch += direction * 1; // direction will be 1 or -1
refY = tan(anglePitch * DEG2RAD);
这确实是一个完整的旋转,但完全旋转将在anglePitch = 180
和anglePitch * DEG2RAD = 3.14
时完成,但完整旋转应为360 | 6.28。如果我将宏更改为以下任何一个:
#define DEG2RAD 3.141593f / 360
#define DEG2RAD 3.141593f / 2 / 180
按预期工作,anglePitch = 360
时会发生完整旋转。
我在这里缺少什么,我应该用什么来正确地将角度转换为弧度/浮点数?
重要编辑(真实问题):
我现在理解我在网上到处看到的关于DEG2RAD
的代码,我对数学太愚蠢了(是的,我知道,在使用这种东西时这很重要)。所以我要重新解释一下我的问题:
我现在已将此添加到我的代码中:
#define PI 3.141592654f
#define DEG2RAD(d) (d * PI / 180)
现在,当以floats
为单位处理音高/哈欠角时,为了避免一直投射,我只使用DEG2RAD
宏,度数值将正确转换为弧度。这些值将传递给sin / cos / tan函数,并返回正确的值以在GLUT相机中使用。
现在真正的问题,我以前真的很困惑,但无法更好地解释自己:
angleYaw += direction * ROTATE_SPEED;
refX = sin(DEG2RAD(angleYaw));
refZ = -cos(DEG2RAD(angleYaw));
当我按下向左/向右键时,将执行此代码,相机将相应地在Y轴上旋转。完整旋转从0º到360º。
anglePitch += direction * ROTATE_SPEED;
refY = tan(DEG2RAD(anglePitch));
这是类似的代码,当我按下向上/向下键并且相机将在X轴上旋转时将执行。但在这种情况下,完全旋转从0度到180度,这就是让我感到困惑的原因。我确定它与切线功能有关但我无法理解它。
有没有办法可以使用sin / cos(就像我在哈欠代码中那样)来实现相同的旋转?什么是正确的方法,我可以添加/修复的最简单的代码以及从0º到360º创建完整音高旋转的更有意义?
答案 0 :(得分:3)
'float'是一种类型,如int或double。弧度和度数是度量单位,两者都可以用您想要的任何精度表示。也就是说,没有理由你不能拥有22.5度,并将该值保存在浮点数中。
以弧度为单位的完整旋转为2 * pi,约为6.283,而以度为单位的完整旋转为360.您可以通过将起始单位的整圆除去,然后乘以所需单位的整圆来进行转换。
例如,要从90度到弧度,首先将度数除以。 90°360超过0.25(注意这个值是'革命')。现在将0.25乘以6.283,得到1.571弧度。跟进
你看到你的音高周期快两倍的原因正是因为你使用tan(音高)来计算Y分量。你应该拥有的是Y分量取决于sin(音高)。即,尝试更改
refY = tan(DEG2RAD(anglePitch));
到
refY = sin(DEG2RAD(anglePitch));
一个技术细节:进入外观矩阵的数字应该都在-1到+1的范围内,如果你要检查你要反馈的值,并在你的外面运行你的音高 - 45到+45度,你会看到问题; tan()以+/- 90度的速度运行到无穷远。
另外,请注意,从int到float 的转换值在度和弧度之间转换。 cast只是为您提供新存储类型中最接近的等效值。例如,如果你将整数22转换为浮点数,则得到22.0f,而如果你将33.3333f转换为int类型,那么当你处理角度时,你将留下33.你真的应该坚持使用浮点数,除非你受限于使用嵌入式处理器或其他东西。这对于弧度尤其重要,其中整数增量表示(约)57.3度的跳跃。
答案 1 :(得分:3)
360°= 2 * Pi,Pi = 3.141593 ......
弧度由沿半径为1的圆的角度弧长定义。圆的圆周为2 * r * Pi,因此单位圆上的一整圈的弧长为2 * Pi = 6.28 ...
以度为单位的角度测量源于这样的事实:通过对齐6个等边三角形,您可以跨越一整圈。所以我们有6个三角形,每个构成转弯的第6个,所以旧的巴比伦人将一个圆分成1 /(6 * 6)= 1/36的碎片,为了进一步细化,它被细分为10.这就是为什么我们以一个完整的圆圈结束了360°。不过,这个数字是任意选择的。
因此,如果有2 * Pi / 360°,这使得Pi / 180°= 3.141593 ... / 180°,这是从度到弧度的转换因子。倒数,180°/ Pi = 180 / 3.141593 ......
为什么在地球上旧的OpenGL函数glRotate和GLU的gluPerspective使用的度数而不是弧度我无法理解。从数学的角度来看,只有弧度才有意义。我认为欧拉方程最精彩地证明了这一点
e^(i*Pi) - 1 = 0
在一个单一的等式中,你拥有它,所有重要的数学数字。这与角度有什么关系?良好:
e^(i*alpha) = cos(alpha) + i * sin(alpha), alpha is in radians!
编辑,关于修改后的问题:
你的角度漂浮都很好。为什么你甚至认为degress是整数我无法理解。通常,您不必自己定义PI,它在math.h中预定义,通常称为M_PI,M_2PI和M_PI2,用于Pi,2 * Pi和Pi / 2。你也应该改变你的宏,它现在写的方式会产生奇怪的效果。
#define DEG2RAD(d) ( (d) * M_PI/180. )
GLUT根本没有相机。 GLUT是我推荐不使用的相当愚蠢的OpenGL框架。你可能会参考 gluLookAt 。
这些障碍让我们看看你在那里做什么。请记住,三角函数在单位圆上运算。让角度0指向右侧,角度逆时针增加。然后 sin(a)被定义为向右和 cos(a)的数量以及到达单位圆上角度a的点的向前量。这就是refX
和refZ
被分配给的目的。
refY
没有任何意义。 tan = sin / cos 因此当我们接近n * pi / 2(即90°)时,它会发散到+/-无穷大。至少它解释了你的pi / 180°循环范围,因为那是 tan 的时期。
我首先想到 tan 可能已被用来规范方向向量,但也没有意义。因素应为1./sqrt(sin²(Pitch)+ 1)
我仔细检查过:使用棕褐色做了正确的事情。
EDIT2:我看不出你的问题所在:俯仰角为-90°到+ 90°,这非常有意义。去做一个地球仪(地球仪):东西坐标(经度)从-180°到+ 180°,南北坐标(纬度)从-90°到+ 90°。想一想:任何更大的坐标范围都会产生歧义。
我给你的唯一好建议是:拿一些数学教科书,围绕球坐标弯曲你的想法!很抱歉告诉你。无论你做得多么好,你只需要了解精确的几何学。
您使用的是Yaw和Pitch。这些通常用于欧拉角。现在不幸的是,欧拉角最初引人注目,后来会引起严重的麻烦(比如万向节锁)。你根本不应该使用它们。如果你用一些铅笔/棍棒/任何东西来分解你想要的旋转来理解它们的力学,这也许是一个好主意。
顺便说一下:还有非整数度。只需跳到http://maps.google.com即可看到它们的效果(只需选择一个地方,然后让http://maps.google.com为您提供链接)。
答案 2 :(得分:1)
假设您的参考组件旨在用作您的观察矢量,我认为您需要的是
refY = sin(DEG2RAD(anglePitch));
XZfactor = cos(DEG2RAD(anglePitch));
refX = XZfactor*sin(DEG2RAD(angleYaw));
refZ = -XZfactor*cos(DEG2RAD(angleYaw));