现在我一直在做一个太空模拟器。 起初我使用我自己的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度到左边,然后把它向上旋转,就不能正常工作。 相反,它滚动。
这是一个图像,说明我的问题。
图像链接
我尝试了几个技巧来试图解决这个问题,但不知何故,我觉得我错过了一些东西。 它不能帮助模拟器风格旋转的例子几乎不可能find。
所以我在寻找例子,链接和旋转3d模型的理论(比如飞船,飞机)。
我是否应该使用3个vector(左,上,前)来定向,因为我还必须计算诸如推力器的加速度以及随着旋转(方向?)和模型透视点像火箭发动机的方向。
我不是很擅长math,只是想象一个解决scheme,只是头痛
我不确定我完全理解这个情况,但是这听起来像是你可能会描述一下万向节锁 。 你可能想看看用四元数来表示你的旋转。
做对这当然是有挑战性的。 我认为你所面临的问题是,无论“船舶”是如何定位的,你都在使用相同的转换矩阵进行旋转。 但是你不想旋转你的飞船,因为它面向前方的时候将会转动,你想要根据它现在面对的方向旋转。 要做到这一点,你应该像转换你的船一样转换你的控制转矩矩阵。
例如,假设我们有三个矩阵,每个矩阵代表我们想要做的转弯。
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
所以每次你想以这样或那样的方式旋转时,你只需调用其中一个函数。
你要在这里使用的是四元数。 他们消除你正在经历的奇怪的行为。 把它们想象成类似功能类固醇的矩阵。 通过使用任何OpenGL功能,您可以更好地使用矩阵(在上面的代码中),使您可以在特定的旋转轴向量上创建旋转矩阵,但是四元数会存储您的旋转以供将来修改。 例如,您从身份四元数开始,并将其旋转到特定的轴矢量上。 四元数然后被翻译成你的对象的世界矩阵,但你保持四元数存储在你的对象。 下次需要执行旋转时,只需进一步修改四元数,而不必尝试跟踪X,Y和Z轴的旋转角度等。
我的经验是directx(对不起,这里没有OpenGL的经验),虽然我曾经碰到过你的问题,当我试图旋转的沙滩球,在房间和地面,墙壁和其他地方旋转的时候跳动。
Google在“OpenGL四元数”上有很多选项,但是这尤其是一个很好的来源:
http://gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation
正如您现在可能已经猜到的那样,Quaternion在您的环境中处理相机非常棒。 这是一个很好的教程:
http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=Quaternion_Camera_Class
你应该学习三维数学,以便你可以更深入地了解如何控制旋转。 如果你不知道理论,甚至很难正确复制和粘贴。 特别是像3D数学入门( Amazon )和像http://gamemath.com这样的相关站点的文本将会大大地帮助你在你的项目中(以及所有将来的项目)。
我明白你现在可能不喜欢数学,但是学习相关的算术将是解决你的问题的最好方法。
四元数可能会有帮助,但更简单的解决方案可能是遵循严格的旋转顺序。 这听起来像你正在旋转y,然后围绕x旋转。 您必须始终旋转x,然后y,然后z。 这并不是说这个顺序有什么特别的地方,只是如果你这样做的话,轮换往往会更接近你期望它们的工作方式。
编辑:澄清一点点,你也不应该累积在游戏中的时间跨越。 每个框架都应该以标识位置启动模型,然后将x,y和z旋转到该框架的新位置。
一般的轮换是困难的。 物理学家倾向于用一些所谓的欧拉角来描述它们。 在这种方法中,一般的旋转通过固定连续的三个轴所描述的三个角度来描述。 但三轴不是原始框架的X,Y和Z轴。 它们通常是原始帧的Z轴,Y轴和Z轴(是的,它实际上是完全一般的),或者是原始帧的两个轴,然后是中间帧的轴。 许多选择是可用的,并确保你一直遵循相同的惯例可能是一个真正的麻烦。