Я работал над игровой движок и недавно дошел до того, что я мог легко создать класс Camera для управления матрицей вида (или позволить легкий переход на другой). Я концептуально знаю, что он должен делать, но у меня возникают проблемы с выяснением того, как вращаться вокруг локального источника (для матрицы представления это будет то же самое, что и матрица перевода, которая умножается на матрицу вращения).
Я знаю, что в прямом режиме вы бы
glTranslatef(x, y, z); //move back to origin
glRotatef(angle, x_rot, y_rot, z_rot); //turn using a quaternion
glTranslatef(-x, -y, -z); //move back to original location
но я не уверен, как это переведет на более современное приложение. Сделаете ли вы по сути то же самое, создадите матрицу перевода обратно в исходное положение, поверните и переведите обратно? Для каждого объекта, который вы хотите вращать? Из того, что я тестировал до сих пор, этот метод работает для просмотра, но управлять им в трехмерном пространстве неудобно (я не уверен, как постоянно регулировать вращение. Преобразуйте компоненты движения в один vec4, умножьте на вращение, применить к переводу, а затем сделать фактическое вращение?)
Кажется, что есть более эффективный способ, чем три или более умножения матрицы 4х4, которые я пропускаю.
Вот конкретный раздел после опробования предложенного решения.
Вы можете сделать в основном то же самое, что и последовательность, которую вы разместили, не делая полных матричных умножений во время выполнения. Поскольку матрицы перевода очень просты, вы можете умножать вручную. С R
будучи матрицей вращения 3х3, и p
будучи позицией, которую вы хотите вращать, вы можете построить матрицу 4×4:
R
в поворотной части матрицы 4х4.p - R * p
и сохраните результат в части перевода матрицы 4×4.Это уменьшит его до умножения одной матрицы * на вектор и вычитания вектора. Вы можете перепроверить мою математику, так как я только что вывел ее на бумаге.
Другой подход заключается в том, что вы храните повороты и переводы отдельно в коде вашего ЦП, обновляете их по мере необходимости и объединяете их только в матрицу 4х4 при обновлении униформы.
Поскольку у вас есть контроль над кодом шейдера, вам даже не нужно использовать матрицу 4×4, чтобы содержать все преобразования. Например, если вам удобнее применять переводы перед поворотами, вы можете подать матрицу вращения mat3 и вектор перевода vec3 в свой шейдер и добавить вектор перевода в позицию перед умножением на матрицу вращения. Хранение двух отдельных также может быть полезным, если вы обновляете один из них гораздо чаще, чем другой.
Я думаю, что вы слишком усложняете это, думая о старом трубопроводе.
Сформируйте вашу новую матрицу преобразования, T. Предположим, у вас есть существующая матрица камеры, C. Вы хотите C ‘, модифицированную матрицу камеры.
Там действительно только два варианта. Или:
C' = CT, or
C' = TC
Потому что какая другая информация у вас есть?
На практике то, что вы выбираете, — это новое преобразование, действующее «до» существующей матрицы камеры, в этом случае оно будет действовать в мировых координатах, или «после», и в этом случае оно будет иметь место в координатах камеры.
Вы, кажется, хотите предварительного умножения. Так что используйте это. Преобразование вступит в силу в глобальном координатном пространстве.
Старые подпрограммы OpenGL всегда публикуются умноженными.