为太空模拟器/游戏旋转宇宙飞船模型
Posted
技术标签:
【中文标题】为太空模拟器/游戏旋转宇宙飞船模型【英文标题】:Rotating a spaceship model for a space simulator/game 【发布时间】:2009-08-01 23:33:03 【问题描述】:我从事太空模拟工作已有一段时间了。 起初我使用的是我自己的 3d 引擎和软件光栅化器。
但是当实现纹理的时间到期时,我放弃了。 现在我在一段时间后重新开始,现在我使用 Opengl(带有 SDL)来渲染 3d 模型。
但现在我又碰上了另一堵砖墙。
我不知道如何进行正确的旋转。 作为一个太空模拟器,我想要与飞行模拟类似的控制
使用
glRotatef(angleX, 1.0f, 0.0f, 0.0f);
glRotatef(angleY, 0.0f, 1.0f, 0.0f);
glRotatef(angleZ, 0.0f, 0.0f, 1.0f);
或类似的, 如果我先将模型(宇宙飞船)向左旋转 90 度然后将其“向上”旋转,则无法正常工作。 相反,它会滚动。
这是说明我的问题的图像。
Image Link
我尝试了几种技巧来尝试解决这个问题,但不知何故我觉得我错过了一些东西。 几乎找不到模拟器风格的旋转示例也无济于事。
所以我正在寻找示例、链接和旋转 3d 模型(如宇宙飞船、飞机)的理论。
我是否应该使用 3 个向量(左、上、前)作为方向,因为我还必须计算诸如推进器的加速度之类的东西,这些东西会随着旋转(方向?)和模型的角度而改变像火箭发动机一样指向一个方向。
我的数学不是很好,试图想象一个解决方案只是让人头疼
【问题讨论】:
我终于破解了!我使用描述模型方向的矩阵。当我按下向上键时,会调用一个函数来创建一个旋转矩阵,我围绕 x 旋转所需的量,然后将其乘以模型方向矩阵。 【参考方案1】:我不确定我是否完全理解这种情况,但听起来您可能在描述gimbal lock。您可能想看看使用quaternions 来表示您的旋转。
【讨论】:
我之前一直在尝试四元数,但又试了一次。好吧,它似乎使旋转更正确,但是现在当我旋转它时,盒子有点扭曲了。【参考方案2】:做到这一点当然具有挑战性。我认为您面临的问题是,无论“船”如何定向,您都在使用相同的转换矩阵进行旋转。但是你不想根据它面向前方时的转动方式来旋转你的船,你想根据它现在的面向方式来旋转。为此,您应该像变换飞船一样变换受控转向矩阵。
例如,假设我们有三个矩阵,每个矩阵代表我们想要做的转弯类型。
float theta = 10.0*(pi/180.0)
matrix<float> roll = [[ cos(theta), sin(theta), 0]
[ -sin(theta), cos(theta), 0]
[ 0, 0, 1]
matrix<float> pitch = [[ cos(theta), 0, sin(theta)]
[ 0, 1, 0]
[ -sin(theta), 0, cos(theta)]
matrix<float> yaw = [[1, 0, 0]
[0, cos(theta), sin(theta)]
[0, -sin(theta), cos(theta)]]
matrix<float> orientation = [[1, 0, 0]
[0, 1, 0]
[0, 0, 1]]
每个代表三个飞行姿态轴中的每一个旋转 10 度。此外,我们还有一个用于您的船方位的矩阵,最初只是海峡前进。您将通过该方向矩阵转换您的船的顶点以显示它。
然后要在转弯后获得你的方向,你需要做一些聪明的事情,首先将姿态控制矩阵转换为玩家的坐标,然后将其应用于方向以获得新的方向:类似于
function do_roll(float amount):
matrix<float> local_roll = amount * (roll * orientation)
orientation = orientation * local_roll
function do_pitch(float amount):
matrix<float> local_pitch = amount * (pitch * orientation)
orientation = orientation * pitch_roll
function do_yaw(float amount):
matrix<float> local_yaw = amount * (yaw * orientation)
orientation = orientation * local_yaw
这样每次您想以一种或另一种方式旋转时,您只需调用其中一个函数。
【讨论】:
【参考方案3】:您要在这里使用的是四元数。它们消除了您正在经历的奇怪行为。将它们视为具有类似功能的类固醇矩阵。您可以通过使用任何允许您在特定旋转轴矢量上创建旋转矩阵的 OpenGL 功能(在上面的代码中)更好地使用矩阵,但四元数将存储您的旋转以供将来修改.例如,您从一个恒等四元数开始并在特定的轴向量上旋转它。然后四元数被转换为您的对象的世界矩阵,但您将四元数存储在您的对象中。下次您需要执行旋转时,只需进一步修改该四元数,而不必尝试跟踪 X、Y 和 Z 轴旋转度数等。
我的经验是在 directx 中(抱歉,这里没有 OpenGL 经验),虽然我曾经遇到过你的问题,当时我试图旋转在房间里弹跳的沙滩球并在遇到地板、墙壁和彼此时旋转.
Google 有很多关于“OpenGL Quaternion”的选项,但是这似乎是一个很好的来源:
http://gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation
您现在可能已经猜到了,四元数非常适合在您的环境中处理相机。这是一个很棒的教程:
http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=Quaternion_Camera_Class
【讨论】:
【参考方案4】:您应该学习 3D 数学,以便更深入地了解如何控制旋转。如果您不了解理论,甚至很难正确复制和粘贴。具体而言,诸如 3D Math Primer(Amazon) 之类的文本以及诸如 http://gamemath.com 之类的相关网站将极大地帮助您(以及所有未来的项目)。 p>
我知道你现在可能不喜欢数学,但是学习相关的算术将是解决你问题的最佳方法。
【讨论】:
我已经有了 3D Math Primer,它在我开始的时候帮助很大。是不是有时我读过它,似乎我需要再读一遍。【参考方案5】:四元数可能会有所帮助,但更简单的解决方案可能是遵守严格的旋转顺序。听起来你在绕 y 旋转,然后绕 x 旋转。您必须始终先旋转 x,然后旋转 y,然后旋转 z。并不是说这个顺序有什么特别之处,只是如果你这样做,轮换往往会更接近你期望它们的工作方式。
编辑:澄清一点,你也不应该在游戏中随着时间累积轮换。每一帧你都应该在同一位置开始你的模型,然后旋转 x、y、z 到该帧的新位置。
【讨论】:
【参考方案6】:一般的旋转是困难的。物理学家倾向于使用一些所谓的Euler angles 来描述它们。在该方法中,一般旋转由围绕三个轴连续固定的三个角度来描述。但三轴并不是原车架的X、Y、Z轴。它们通常是原始框架的 Z、Y 和 Z 轴(是的,它确实是完全通用的),或者来自原始框架的两个轴,然后是中间框架中的一个轴。有很多选择,确保您始终遵循相同的约定可能会很麻烦。
【讨论】:
以上是关于为太空模拟器/游戏旋转宇宙飞船模型的主要内容,如果未能解决你的问题,请参考以下文章
玩·《Universe Sandbox》让你利用上帝视角创造宇宙!