2009-08-01 70 views
2

我一直在空间模拟一段时间了。 起初我使用我自己的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度工作向左,然后flighsim

旋转它“向上”。 它会滚动。

下面是一个图像,说明我的问题。

Image Link

我试了几个招数,试图解决这个,但不知何故,我觉得我失去了一些东西。 它不能帮助模拟器样式旋转的例子几乎不可能找到。

因此,我正在寻找示例,链接和旋转3d模型(如飞船,飞机)的理论。

我是否应该使用3个向量(左,上,前)作为方向,因为我还必须计算诸如推力器的加速度以及随着旋转(方向?)和模型透视点像火箭发动机这样的方向。

我不是很好的数学和努力可视化解决方案只给出头痛

+0

我终于破解了! 我使用描述模型方向的矩阵。 当我按下向上键时,一个函数调用创建一个旋转矩阵的函数,我旋转x所需的量,然后将其乘以模型方向矩阵。 – kvasan 2009-08-06 03:54:10

回答

2

你会想在这里使用什么是四元。它们消除了你正在经历的奇怪行为。将它们想象成具有类似功能的类固醇的矩阵。通过使用任何OpenGL功能,您可以更好地使用矩阵(在上面的代码中),使您可以在特定的旋转轴矢量上创建旋转矩阵,但是四元数会将您的旋转存储为未来的修改。例如,您从身份四元数开始,并将其旋转到特定的轴向量上。四元数然后被转换为你的对象的世界矩阵,但是你保持四元数存储在你的对象中。下次需要执行旋转时,只需进一步修改该四元数,而不必尝试跟踪X,Y和Z轴的旋转角度等。

我的经验是在directx中(对不起,没有OpenGL在这里体验),尽管当我试图旋转在他们遇到地板,墙壁和彼此时旋转的房间&旋转的沙滩球时,我曾遇到过您的问题。

谷歌有一堆的“OpenGL的四元”的选项,但是这一点,特别是,似乎是一个很好的来源:

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

我不知道我完全理解的情况,但它听起来像是你可能会描述gimbal lock。你可能想看看使用quaternions来代表你的旋转。

+0

我一直在尝试四元数,但再次尝试。 好吧,它似乎使旋转更正确,但是现在当我旋转它时,盒子会变得有点扭曲。 – kvasan 2009-08-02 19:46:52

4

获得这个权利当然是一个挑战。我认为你面临的问题是你正在使用相同的变换矩阵进行旋转,而不管'船'是如何定位的。但是你不想旋转你的飞船,当它面向前方时它将会转动,你想根据它现在面对的方式旋转。要做到这一点,你应该像转换你的船一样转换你的控制转矩阵。例如,假设我们有三个矩阵,每个矩阵代表我们想要做的转动。

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 

这样每次你想以某种方式旋转时,你只需调用其中一个函数。

1

四元数可能有帮助,但更简单的解决方案可能是观察旋转的严格顺序。这听起来像你围绕y旋转,然后围绕x旋转。您必须始终先旋转x,然后y,然后z。并不是说这个顺序有什么特别之处,只是如果你这样做的话,旋转往往会更接近你期望它们的工作方式。

编辑:为了澄清一点,你也不应该在游戏中横跨时间累积旋转。每个框架都应该以标识位置启动模型,然后将x,y和z旋转到该框架的新位置。

+0

damnit我只能为此投票 – 2009-08-10 21:03:43

1

一般的旋转很困难。物理学家倾向于使用一些所谓的Euler angles来描述它们。在这种方法中,一般的旋转通过固定连续的三个轴线所描述的三个角度来描述。但三轴不是原始框架的X轴,Y轴和Z轴。它们通常是原始帧的Z轴,Y轴和Z轴(是的,它实际上是完全一般的),或者是来自原始帧的两个轴,随后是中间帧中的轴。许多选择都是可用的,并确保您一直遵循相同的惯例可能是一件麻烦事。

2

您应该学习3D数学,以便您可以更深入地了解如何控制旋转。如果你不知道理论,甚至难以正确复制和粘贴。具体的文本,如3D数学入门(Amazon)和相关网站如http://gamemath.com将大大帮助您在您的项目(和所有未来的项目)。

我明白你现在可能不喜欢数学,但学习相关的算术将是你的问题的最佳解决方案。

+0

我已经有了3D数学入门书,并且在我开始时帮助了很多。 有时候我看了一下它,好像我需要再读一遍。 – kvasan 2009-08-02 19:36:00