Если я игнорирую грязные детали алгебры кватернионов, я думаю, что я понимаю математику, стоящую за вращением и трансляционными преобразованиями.Но все равно не понимаю, что я делаю неправильно.
Почему моя камера вращается раз и навсегда!? :)
И, если быть более конкретным,как мне вычислить матрицу вида камеры по ее ориентации (матрица вращения)?
Я пишу минималистичный трехмерный движок на Python с классом Node сцены, который обрабатывает механику вращения и перемещения трехмерных объектов.У него есть методы, которые предоставляют матрицы вращения и трансляции, а также матрицу модели.
Существует также класс CameraNode, подкласс Node, который также предоставляет матрицы просмотра и проекции (проекция не является проблемой,поэтому мы можем игнорировать это).
Матрица модели
Чтобы правильно применить преобразования, я умножаю матрицы следующим образом:
PxVxM x v
т.е. сначала Модель, затемВид и, наконец, Проекция.
Где М вычисляется сначала путем применения поворота, а затем перевода:
M = TxR
Вот код:
class Node():
# ...
def model_mat(self):
return self.translation_mat() @ self.rotation_mat() @ self.scaling_mat()
def translation_mat(self):
translation = np.eye(4, dtype=np.float32)
translation[:-1, -1] = self.position # self.position is an ndarray
return translation
def rotation_mat(self):
rotation = np.eye(4, dtype=np.float32)
rotation[:-1, :-1] = qua.as_rotation_matrix(self.orientation) # self.orientation is a quaternion object
return rotation
ПросмотрМатрица
Я вычисляю матрицу просмотра на основе положения и ориентации камеры следующим образом:
class CameraNode(Node):
# ...
def view_mat(self):
trans = self.translation_mat()
rot = self.rotation_mat()
trans[:-1, 3] = -trans[:-1, 3] # <-- efficient matrix inversion
rot = rot.T # <-- efficient matrix inversion
self.view = rot @ trans
return self.view
Пожалуйста, исправьте меня, если я ошибаюсь.Так как мы можем только перемещать и вращать геометрию мира (в отличие от перемещения / вращения камеры), я должен умножить матрицы в обратном порядке, а также преобразование опозита (фактически обратное каждой матрице преобразования).Другими словами, перемещение камеры от объекта также можно рассматривать как перемещение объекта от камеры.
Ввод во вращение
Теперь вот как я преобразую ввод с клавиатуры в поворот камеры,Когда я нажимаю клавиши со стрелками вправо / влево / вверх / вниз, я вызываю следующие методы с некоторым углом тангажа / рыскания:
def rotate_in_xx(self, pitch):
rot = qua.from_rotation_vector((pitch, 0.0, 0.0))
self.orientation *= rot
def rotate_in_yy(self, yaw):
rot = qua.from_rotation_vector((0.0, yaw, 0.0))
self.orientation *= rot
ведет себя неправильно, но матрица вращения верна
И этовот что я получаю:
![behaves wrong but rot matrix is correct](https://i.stack.imgur.com/8EMCv.gif)
![behaves wrong but rot matrix is correct](https://i.stack.imgur.com/vAfge.png)
Теперь, если я изменю вышеприведенноеСпособы:
class CameraNode(Node):
def view_mat(self):
view = np.eye(4)
trans = self.translation_mat()
rot = self.rotation_mat()
trans[:-1, 3] = -trans[:-1, 3]
# rot = rot.T # <-- COMMENTED OUT
self.view = rot @ trans
return self.view
def rotate_in_xx(self, pitch):
rot = qua.from_rotation_vector((pitch, 0.0, 0.0))
self.orientation = rot * self.orientation # <-- CHANGE
Я могу заставить камеру вести себя корректно, как FPS-камера, но матрица вращения кажется неправильной.
![behaves well but rot matrix is wrong](https://i.stack.imgur.com/mBO36.gif)
![enter image description here](https://i.stack.imgur.com/ffYuv.png)
Пожалуйста, кто-нибудь может пролить свет?Заранее спасибо.