OpenGL + SDL вращение вокруг локальной оси - PullRequest
1 голос
/ 09 ноября 2011

Я работал над симулятором полёта. То, что я пытаюсь сделать, это использовать бросок и рыскание, чтобы вращать объект. Я уже много смотрел в Интернете, и хотя они объясняют, в чем проблема, я понятия не имею, как реализовать решение. Так, например, я делаю:

glRotatef(yaw,0,1,0);
glRotatef(pitch,1,0,0);

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

newpitch=pitch/57.29
VectorA(0,cos(newpitch)-sin(newpitch),sin(newpitch)+cos(newpitch));
glRotatef(yaw,vec.getXAxis(),vec.getYAxis(),vec.getZAxis());
glRotatef(pitch,1,0,0);

Кажется, это тоже не работает.

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

Вот мой код кватернионов:

void Quat::eulerToQuat(float roll,float pitch,float yaw){
    float radiansY = yaw/57.2;
    float radiansZ = roll/57.2;
    float radiansX = pitch/57.2;

    float sY = sinf(radiansY * 0.5);
    float cY = cosf(radiansY * 0.5);
    float sZ = sinf(radiansZ * 0.5);
    float cZ = cosf(radiansZ * 0.5);
    float sX = sinf(radiansX * 0.5);
    float cX = cosf(radiansX * 0.5);

    w = cY * cZ * cX - sY * sZ * sX;
    x = sY * sZ * cX + cY * cZ * sX;
    y = sY * cZ * cX + cY * sZ * sX;
    z = cY * sZ * cX - sY * cZ * sX;
}

Затем я преобразовал это в матрицу и использую glMultMatrix(matrix) с матрицей вида модели, и это имеет ту же проблему. Так что я уверен, что это не будет блокируемая шумиха =).

Итак, в моем коде я делаю:

float matrix[4][4];
Quat this;
this.eularToQuat(roll,pitch,yaw);
this.toMatrix(matrix);
glMultMatrix(matrix);

Ответы [ 2 ]

3 голосов
/ 09 ноября 2011

Я думаю, ты имеешь в виду блокировку карданного подвеса? Вы правы, что каждое вращение изменяет оси, вокруг которых будут происходить последующие локальные вращения. В вашем случае это влияет на рыскание, потому что стек матрицы OpenGL работает так, что каждая вещь, которую вы добавляете к нему, происходит концептуально перед тем, что уже находится в стеке (т. Е. После умножения в матричных терминах).

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

Еще один способ убедить себя в том, что вы делаете неправильно, - посмотреть, сколько информации у вас есть. Вы пытаетесь описать ориентацию объекта двумя числами. Двух чисел недостаточно для описания какого-либо поворота, поэтому, очевидно, существует другое правило для преобразования двух чисел в полную ориентацию. Что бы вы ни делали, чтобы изменить это правило, вы в конечном итоге ограничите ориентацию, которую можете достичь. Но с самолетом вы действительно хотите достичь любой ориентации, так что это фундаментальное противоречие.

Путаница возникает из-за того, что, если у вас есть подходящий способ сохранения ориентации, то совершенно справедливо продолжить работу, сказав: «Какова ориентация, если я изменю ее, вращая вокруг локального y на 5, а затем вокруг локального z на 10? 'И т. Д. Проблема состоит в том, чтобы объединить все эти преобразования в одну пару вращений. Это невозможно.

Самым простым решением, если вы уже знакомы с OpenGL, является сохранение ориентации в виде полной матрицы. Вы накапливаете вращение высоты тона и рыскания, применяя их по мере их появления к матрице. Вы передаете эту матрицу в OpenGL через glMultMatrix для выполнения рисования.

Это не оптимальное решение, но решение для быстрого исправления будет состоять в том, чтобы использовать glLoadMatrix и glGet для применения преобразований, загружая вашу матрицу и затем извлекая ее из стека матрицы OpenGL, отдельно от вашего чертежа. Это не совсем то, для чего нужен стек, поэтому вы, вероятно, получите некоторые проблемы с производительностью, и со временем ошибки округления приведут к странному поведению, но вы можете исправить их, как только убедите подход. Справочные страницы OpenGL предоставляют формулы для всех матриц преобразования, и вам следует обратиться к нормализации матриц (вы, вероятно, будете использовать ортонормированную матрицу, понимаете ли вы это или нет, что должно помочь с Google), чтобы справиться с кумулятивным округлением.

РЕДАКТИРОВАТЬ: по отношению к коду, который вы опубликовали, пока я болтал, кватернионы - это еще один действительный способ представления ориентации и еще одна вещь, к которой вы можете безопасно применять инкрементные обновления. Они также компактны, их очень легко защитить от ошибок округления. Однако я думаю, что ваша проблема может заключаться в том, что вы не используете кватернионы в качестве хранилища для ориентации, а просто как промежуточный контейнер. Поэтому добавление их в цепочку не решит ни одной из ваших проблем.

РЕДАКТИРОВАТЬ 2: еще одно объяснение махания рукой, выдвигающее идею о том, что непосредственное сохранение высоты тона и рыскания недостаточно: представьте, что с точки зрения пилота вы применяете рывок 90 градусов, а затем шаг 30 градусов, затем рыскание -90 градусов. Тогда вы в конечном итоге, как если бы вы применили крен 30 градусов. Но если вы просто храните тангаж и рыскание, то у вас нет способа хранить рулон. Кроме того, если вы просто сложите общий рыск и общий шаг, вы в конечном итоге будете думать, что вы применили шаг 30 градусов, а не крен. Поэтому не имеет значения, в каком порядке вы применяете тангаж и рыскание или используете ли вы глобальные или локальные оси, вы получите неправильный результат.

1 голос
/ 09 ноября 2011

Вы должны рыскать, качаться и кататься, используя одно преобразование.Потому что, если вы этого не сделаете, вы будете подталкивать себя к карданному замку .Выдержка:

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

Рассмотрим этот пример самолета с подвесным карданом:

Gimbal locked airplane

Когда шаг) и вертикальные (пурпурные) карданы выравниваются, изменения крена (синие) и рыскания применяют одно и то же вращение к самолету

...