Вращение модели космического корабля для космического симулятора/игры

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

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


person kvasan    schedule 01.08.2009    source источник
comment
Я, наконец, взломать его! Я использую матрицу, которая описывает ориентацию моделей. Когда я нажимаю клавишу «вверх», вызывается функция, которая создает матрицу вращения, которую я поворачиваю вокруг x на желаемую величину, а затем умножаю ее на матрицу ориентации моделей.   -  person kvasan    schedule 06.08.2009


Ответы (6)


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

person Mike Daniels    schedule 01.08.2009
comment
Я экспериментировал с кватернионами раньше, но попробовал еще раз. Ну, кажется, это делает вращения более правильными, однако теперь коробка немного искажается, когда я ее поворачиваю. - person kvasan; 02.08.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 градусов вращения по каждой из трех осей положения в полете. Также у нас есть матрица для ориентации вашего корабля, изначально прямо прямо. Вы преобразуете вершины вашего корабля с помощью этой матрицы ориентации, чтобы отобразить ее.

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

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

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

person SingleNegationElimination    schedule 01.08.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

person Brian Webster    schedule 01.08.2009

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

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

person viperld002    schedule 02.08.2009
comment
У меня уже есть 3D Math Primer, и он мне очень помог, когда я начинал. Когда-то я читал ее, хотя, кажется, мне нужно прочитать ее снова. - person kvasan; 02.08.2009

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

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

person Breton    schedule 01.08.2009

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

person dmckee --- ex-moderator kitten    schedule 02.08.2009