旋转太空模拟器/游戏的宇宙飞船模型

发布于 2024-07-29 19:40:37 字数 722 浏览 6 评论 0原文

我从事太空模拟游戏已经有一段时间了。 起初,我使用自己的 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 度,然后“向上”旋转,则无法正常工作。 相反,它会滚动。

这是说明我的问题的图片。

但是

我尝试了几种技巧来尝试解决这个问题, 不知怎的,我觉得我错过了一些东西。 几乎不可能找到模拟器风格的旋转示例,这也无济于事。

所以我正在寻找旋转 3D 模型(如宇宙飞船、飞机)的示例、链接和理论。

我是否应该使用 3 个向量(左、上、前)来确定方向,因为我还必须计算诸如推进器的加速度之类的东西,以及随着旋转(方向?)而变化的东西,以及从模型角度点来看的东西像火箭发动机一样的方向。

我不太擅长数学,试图想象一个解决方案只是让我头疼

I been working on a space sim for sometime now.
At first I was using my own 3d engine with software rasterizer.

But I gave up when the time for implementing textures was due.
Now I started again after sometime and now I'm using Opengl (with SDL) instead to render the 3d models.

But now I hit another brick wall.

I can't figure out how to make proper rotations.
Being a space-simulator I want similar controls to a flighsim

using

glRotatef(angleX, 1.0f, 0.0f, 0.0f);
glRotatef(angleY, 0.0f, 1.0f, 0.0f);
glRotatef(angleZ, 0.0f, 0.0f, 1.0f);

or similar,
does not work properly if I rotate the model(spaceship) first 90 degrees to the left and then rotate it "up".
Instead it rolls.

Here's a image that illustrate my problem.

Image Link

I tried several tricks to try and counter this but somehow I feel I missing something.
It doesn't help either that simulator style rotation examples are almost impossible to find.

So I'm searching for examples, links and the theory of rotating a 3d model (like a spaceship, airplane).

Should I be using 3 vectors (left, up, forward) for orientation as I'm also going to have to calculate things like acceleration from thrusters and stuff that will change with the rotation (orientation?) and from the models perspective points in a direction like rocket-engines.

I'm not very good with math and trying to visualize a solution just give a headache

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

小ぇ时光︴ 2024-08-05 19:40:38

我不确定我完全理解这种情况,但听起来您可能正在描述 万向节锁< /a>. 您可能需要考虑使用 四元数 来表示您的旋转。

I'm not sure I entirely understand the situation, but it sounds like you might be describing gimbal lock. You might want to look at using quaternions to represent your rotations.

乖乖兔^ω^ 2024-08-05 19:40:38

正确地做到这一点当然具有挑战性。 我认为您面临的问题是,无论“船”已经如何定向,您都使用相同的变换矩阵进行旋转。 但是您不想根据船舶面向前方时的转向方式来旋转船舶,而是希望根据其现在的朝向来旋转船舶。 为此,您应该像改造船舶一样改造受控转弯矩阵。

例如,假设我们有三个矩阵,每个矩阵代表我们想要做的转弯类型。

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

每次您想要以一种或另一种方式旋转,您只需调用这些函数之一即可。

Getting this right certainly can be challenging. The problem I think you are facing is that you are using the same transformation matrices for rotations regardless of how the 'ship' is already oriented. But you don't want to rotate your ship based on how it would turn when it's facing forward, you want to rotate based on how it's facing now. To do that, you should transform your controlled turn matrices the same way you transform your ship.

For instance, say we've got three matrices, each representing the kinds of turns we want to do.

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]]

each which represent 10 degrees of rotation across each of the three flight attitude axes. Also we have a matrix for your ship's orientation, initially just strait forward. You will transform your ship's vertices by that orientation matrix to display it.

Then to get your orientation after a turn, you need to do just a bit of cleverness, first transform the attitude control matrices into the player's coordinates, and then apply that to the orientation to get a new orientation: something like

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

so that each time you want to rotate in one way or another, you just call one of those functions.

戏剧牡丹亭 2024-08-05 19:40:38

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

我的经验是在 directx 中(抱歉,这里没有 OpenGL 经验),尽管当我试图旋转在房间和房间周围弹跳的沙滩球时,我确实遇到过你的问题。 当它们遇到地板、墙壁和彼此时旋转。

Google 在“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

What you're going to want to use here is quaternions. They eliminate the strange behaviors you are experiencing. Thinking of them as a matrix on steroids with similar functionality. You CAN use matrices better than you are (in your code above) by using whatever OpenGL functionality that allows you to create a rotational matrix upon a particular rotational axis vector, but quaternions will store your rotations for future modification. For example, You start with an identity quaternion and rotate it upon a particular axis vector. The quaternion then gets translated into a world matrix for your object, but you keep the quaternion stored within your object. Next time you need to perform a rotation, then just further modify that quaternion instead of having to try and keep track of X, Y, and Z axis rotation degrees, etc.

My experience is within directx (sorry, no OpenGL experience here), though I did once run into your problem when I was attempting to rotate beachballs that were bouncing around a room & rotating as they encountered floors, walls, and each other.

Google has a bunch of options on "OpenGL Quaternion", but this, in particular, appears to be a good source:

http://gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation

As you may have guessed by now, Quaternions are great for handling cameras within your environment. Here's a great tutorial:

http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=Quaternion_Camera_Class

妄断弥空 2024-08-05 19:40:38

您应该学习 3D 数学,以便能够更深入地了解如何控制旋转。 如果您不了解理论,甚至很难正确复制和粘贴。 具体来说,例如 3D Math Primer(Amazon) 等文本,以及 < strong>http://gamemath.com 将极大地帮助您项目(以及所有未来的项目)。

我知道您现在可能不喜欢数学,但学习相关的算术将是解决您问题的最佳方法。

You should study 3D mathematics so that you can gain a deeper understanding of how to control rotations. If you don't know the theory it can be hard to even copy and paste correctly. Specifically texts such as 3D Math Primer(Amazon), and relevant sites like http://gamemath.com will greatly aid you in your project (and all future ones).

I understand you may not like math now, but learning the relevant arithmetic will be the best solution to your issue.

〆凄凉。 2024-08-05 19:40:38

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

编辑:为了澄清一点,你也不应该在游戏中累积轮换时间。 您应该在每一帧中以同一位置开始模型,然后依次旋转 x、y、z,到达该帧的新位置。

Quaternions may help, but a simpler solution may be to observe a strict order of rotations. It sounds like you're rotating around y, and then rotating around x. You must always rotate x first, then y, then z. Not that there's anything particularly special about that order, just that if you do it that way, rotations tend to work a little bit closer to how you expect them to work.

Edit: to clarify a little bit, you also shouldn't cumulatively rotate across time in the game. Each frame you should start your model out in identity position, and then rotate, x, y, then z, to that frame's new position.

泅渡 2024-08-05 19:40:38

一般轮换是困难的。 物理学家倾向于使用一些所谓的欧拉角来描述它们。 在此方法中,一般旋转由围绕三个轴以固定顺序获取的三个角度来描述。 但这三个轴并不是原始框架的X、Y、Z轴。 它们通常是原始帧的 Z、Y 和 Z 轴(是的,这确实是完全通用的),或者原始帧中的两个轴,后跟中间帧中的一个轴。 有很多选择,并且确保您始终遵循相同的约定可能是一个真正的麻烦。

General rotations are difficult. Physicist tend to use some set of so-called Euler angles to describe them. In this method a general rotation is described by three angles taken about three axis in fixed succession. But the three axis are not the X-, Y- and Z- axis of the original frame. They are often the Z-, Y- and Z- axis of the original frame (yes, it really is completely general), or two axis from the original frame followed by an axis in the intermediate frame. Many choices are available, and making sure that you are following the same convention all the way through can be a real hassle.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文