Накопительные вращения будут страдать от блокировки карданного подвеса.Посмотрите на это так: предположим, вы находитесь в самолете, летите ровно.Вы применяете поворот на 90 градусов против часовой стрелки.Затем вы применяете поворот на 90 градусов по часовой стрелке.Затем вы применяете поворот на 90 градусов по часовой стрелке.
Теперь ваша плоскость направлена прямо вниз - общий эффект составляет шаг 90 градусов по часовой стрелке.Но если вы просто попытаетесь сложить различные повороты, то в итоге вы получите крен в 90 градусов, и никакого шага вообще не будет, потому что вы нигде не применили шаг к плоскости.
Попытка сохранить и обновитьвращение как три отдельных угла не работает.
Наиболее часто цитируемые решения - использовать кватернион или сохранять ориентацию объекта непосредственно в виде матрицы.Матричное решение легче построить, потому что вы можете создать его с помощью встроенных матричных стеков OpenGL.Большинству людей кажется, что матрицы проще для понимания, чем кватернионы.
Итак, если вы хотите перейти к матрице, ваш прототип может сделать что-то вроде: (пожалуйста, простите мне отсутствие приличных знаний Java; я собираюсь написатьC по существу):
GLfloat myOrientation[16];
// to draw the object:
glMultMatrixf(myOrientation);
/* drawing here */
// to apply roll, assuming the modelview stack is active:
glPushMatrix(); // backup what's already on the stack
glLoadIdentity(); // start with the identity
glRotatef(angle, 0, 0, 1);
glMultMatrixf(myOrientation); // premultiply the current orientation by the roll
// update our record of orientation
glGetFloatv(GL_MODELVIEW_MATRIX, myOrientation);
glPopMatrix();
Возможно, вы не хотите использовать стек OpenGL в отгрузочном коде, потому что он на самом деле не предназначен для такого рода использования, и поэтому производительность может быть сомнительной.Но вы можете создать прототип и профиль, а не делать предположения.Вам также нужно учитывать проблемы точности с плавающей точкой - на самом деле вы должны применить шаг, который гарантирует, что myOrientation все еще ортонормирован после того, как он был настроен.
Вероятно, это проще всего проверить в Google, но вкратце выиспользуйте точечное произведение, чтобы удалить ошибочные перекрестные помехи от двух осей до третьей, затем удалить одну из первых двух осей от второй, а затем перенормировать все три.