Вращение модели космического корабля для космического симулятора / игры - PullRequest
2 голосов
/ 02 августа 2009

Я уже некоторое время работаю над космическим симом. Сначала я использовал свой собственный 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 вектора (влево, вверх, вперед) для ориентации, поскольку мне также придется рассчитывать такие вещи, как ускорение от движителей и тому подобное, которые будут меняться с вращением (ориентация?) И с точки зрения моделей указывает в направлении, похожем на ракетные двигатели.

Я не очень хорошо разбираюсь в математике, и пытаюсь визуализировать решение, просто болит голова

Ответы [ 6 ]

4 голосов
/ 02 августа 2009

Понимание этого, безусловно, может быть проблематичным. Я думаю, что проблема, с которой вы сталкиваетесь, заключается в том, что вы используете одни и те же матрицы преобразования для вращений независимо от того, как «корабль» уже ориентирован. Но вы не хотите вращать свой корабль в зависимости от того, как он будет поворачиваться, когда он направлен вперед, вы хотите вращаться в зависимости от того, как он смотрит сейчас. Чтобы сделать это, вы должны трансформировать свои матрицы контролируемого поворота так же, как вы трансформируете свой корабль.

Например, скажем, у нас есть три матрицы, каждая из которых представляет виды поворотов, которые мы хотим сделать.

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 градусов вращения по каждой из трех осей ориентации полета. Кроме того, у нас есть матрица для ориентации вашего корабля, первоначально просто сойти вперед. Вы преобразуете вершины своего корабля с помощью этой матрицы ориентации, чтобы отобразить ее.

Затем, чтобы получить свою ориентацию после хода, вам нужно немного поработать, сначала преобразовать матрицы управления ориентацией в координаты игрока, а затем применить это к ориентации, чтобы получить новую ориентацию: что-то вроде * 1008. *

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

так что каждый раз, когда вы хотите повернуть тем или иным способом, вы просто вызываете одну из этих функций.

4 голосов
/ 02 августа 2009

Я не уверен, что полностью понимаю ситуацию, но, похоже, вы описываете карданный замок . Возможно, вы захотите взглянуть на использование кватернионов для представления ваших вращений.

2 голосов
/ 02 августа 2009

Вы должны изучать трехмерную математику, чтобы глубже понять, как управлять вращением.Если вы не знаете теорию, это может быть трудно даже скопировать и вставить правильно.В частности, такие тексты, как 3D Math Primer ( Amazon ) и соответствующие сайты, такие как http://gamemath.com, окажут вам большую помощь в вашем проекте (и во всех будущих).

Я понимаю, что сейчас вам может не нравиться математика, но изучение соответствующей арифметики будет лучшим решением вашей проблемы.

2 голосов
/ 02 августа 2009

То, что вы собираетесь использовать здесь, это кватернионы. Они устраняют странное поведение, которое вы испытываете. Думая о них как о матрице на стероидах с похожей функциональностью. Вы МОЖЕТЕ использовать матрицы лучше, чем вы (в своем коде выше), используя любую функциональность OpenGL, которая позволяет вам создавать вращательную матрицу на конкретном векторе оси вращения, но кватернионы будут хранить ваших вращений для будущей модификации. Например, вы начинаете с единичного кватерниона и вращаете его по определенному вектору оси. Затем кватернион переводится в мировую матрицу для вашего объекта, но вы сохраняете кватернион в своем объекте. В следующий раз вам нужно выполнить вращение, а затем просто изменить этот кватернион вместо того, чтобы пытаться отслеживать градусы вращения по осям X, Y и Z и т. Д.

Мой опыт в Directx (извините, здесь нет опыта OpenGL), хотя я однажды столкнулся с вашей проблемой, когда пытался вращать пляжные мячи, которые подпрыгивали по комнате и вращались, когда сталкивались с полами, стенами и друг с другом. ,

У Google есть куча опций для "OpenGL Quaternion", но это, в частности, хороший источник:

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

Как вы уже догадались, Quaternions отлично подходят для работы с камерами в вашей среде. Вот отличный учебник:

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

1 голос
/ 02 августа 2009

Общие повороты сложны. Физики имеют тенденцию использовать некоторый набор так называемых углов Эйлера , чтобы описать их. В этом методе общее вращение описывается тремя углами, взятыми вокруг трех осей в фиксированной последовательности. Но эти три оси не являются осями X, Y и Z исходного кадра. Они часто являются осями Z, Y и Z исходного кадра (да, это действительно является полностью общим), или двумя осями от исходного кадра, за которыми следует ось в промежуточном кадре. Доступно много вариантов, и проверка того, что вы соблюдаете одно и то же соглашение, может стать настоящей проблемой.

1 голос
/ 02 августа 2009

Кватернионы могут помочь, но более простым решением может быть соблюдение строгого порядка вращений. Звучит так, будто вы вращаетесь вокруг y, а затем вращаетесь вокруг x. Вы всегда должны сначала вращать x, затем y, затем z. Не то чтобы в этом порядке было что-то особенное, просто если вы делаете это таким образом, ротация будет работать немного ближе к тому, что вы ожидаете от них.

Edit: чтобы прояснить немного, вы также не должны кумулятивно вращаться во времени в игре. В каждом кадре вы должны начать свою модель в позиции идентичности, а затем повернуть, x, y, затем z, в новое положение этого кадра.

...