Я думаю, ты имеешь в виду блокировку карданного подвеса? Вы правы, что каждое вращение изменяет оси, вокруг которых будут происходить последующие локальные вращения. В вашем случае это влияет на рыскание, потому что стек матрицы OpenGL работает так, что каждая вещь, которую вы добавляете к нему, происходит концептуально перед тем, что уже находится в стеке (т. Е. После умножения в матричных терминах).
Однако ваше решение не решит проблему, даже если оно будет реализовано правильно. То, что вы пытаетесь сделать, это получить глобальную ось y в локальном координатном пространстве, чтобы вы могли вращаться вокруг глобального y даже после того, как вы повернули вокруг глобального z, сдвигая локальные оси. Но это просто доставляет вам те же проблемы, как если бы вы застряли с глобальными осями и применили повороты в другом порядке. Второе вращение теперь будет мешать первому, а не наоборот.
Еще один способ убедить себя в том, что вы делаете неправильно, - посмотреть, сколько информации у вас есть. Вы пытаетесь описать ориентацию объекта двумя числами. Двух чисел недостаточно для описания какого-либо поворота, поэтому, очевидно, существует другое правило для преобразования двух чисел в полную ориентацию. Что бы вы ни делали, чтобы изменить это правило, вы в конечном итоге ограничите ориентацию, которую можете достичь. Но с самолетом вы действительно хотите достичь любой ориентации, так что это фундаментальное противоречие.
Путаница возникает из-за того, что, если у вас есть подходящий способ сохранения ориентации, то совершенно справедливо продолжить работу, сказав: «Какова ориентация, если я изменю ее, вращая вокруг локального y на 5, а затем вокруг локального z на 10? 'И т. Д. Проблема состоит в том, чтобы объединить все эти преобразования в одну пару вращений. Это невозможно.
Самым простым решением, если вы уже знакомы с OpenGL, является сохранение ориентации в виде полной матрицы. Вы накапливаете вращение высоты тона и рыскания, применяя их по мере их появления к матрице. Вы передаете эту матрицу в OpenGL через glMultMatrix
для выполнения рисования.
Это не оптимальное решение, но решение для быстрого исправления будет состоять в том, чтобы использовать glLoadMatrix
и glGet
для применения преобразований, загружая вашу матрицу и затем извлекая ее из стека матрицы OpenGL, отдельно от вашего чертежа. Это не совсем то, для чего нужен стек, поэтому вы, вероятно, получите некоторые проблемы с производительностью, и со временем ошибки округления приведут к странному поведению, но вы можете исправить их, как только убедите подход. Справочные страницы OpenGL предоставляют формулы для всех матриц преобразования, и вам следует обратиться к нормализации матриц (вы, вероятно, будете использовать ортонормированную матрицу, понимаете ли вы это или нет, что должно помочь с Google), чтобы справиться с кумулятивным округлением.
РЕДАКТИРОВАТЬ: по отношению к коду, который вы опубликовали, пока я болтал, кватернионы - это еще один действительный способ представления ориентации и еще одна вещь, к которой вы можете безопасно применять инкрементные обновления. Они также компактны, их очень легко защитить от ошибок округления. Однако я думаю, что ваша проблема может заключаться в том, что вы не используете кватернионы в качестве хранилища для ориентации, а просто как промежуточный контейнер. Поэтому добавление их в цепочку не решит ни одной из ваших проблем.
РЕДАКТИРОВАТЬ 2: еще одно объяснение махания рукой, выдвигающее идею о том, что непосредственное сохранение высоты тона и рыскания недостаточно: представьте, что с точки зрения пилота вы применяете рывок 90 градусов, а затем шаг 30 градусов, затем рыскание -90 градусов. Тогда вы в конечном итоге, как если бы вы применили крен 30 градусов. Но если вы просто храните тангаж и рыскание, то у вас нет способа хранить рулон. Кроме того, если вы просто сложите общий рыск и общий шаг, вы в конечном итоге будете думать, что вы применили шаг 30 градусов, а не крен. Поэтому не имеет значения, в каком порядке вы применяете тангаж и рыскание или используете ли вы глобальные или локальные оси, вы получите неправильный результат.