Из вектора направления (вперед) f и вектора вверх u вы можете получить боковой вектор s , выполнив векторное перекрестное произведение ( s = fxu ). Все три вектора теперь ортогональны. Вы также должны сделать их ортонормированными, нормализуя каждый из них. Взятые вместе, эти векторы образуют ортонормированный базис.
Теперь у вас есть два таких основания: одно из вашей первоначальной ориентации камеры и одно из вашей конечной ориентации камеры. Обе основы могут быть представлены в виде матрицы вращения. Матрица вращения - это просто матрица 3х3, где 3 строки соответственно:
- Вектор вперед
- Вектор вверх
- Боковой вектор
Например, матрица:
[[1 0 0]
[0 1 0]
[0 0 1]]
может быть вашей первоначальной ориентацией камеры при запуске с вектором вперед, вектором вверх и боковым вектором, указывающим на положительную ось x, ось y и ось z соответственно.
Теперь вы можете преобразовать эти два базиса (M1 и M2) в два единичных кватерниона (Q1 и Q2), используя этот алгоритм , который заботится о потенциальных проблемах, таких как деление на ноль.
На данный момент у вас есть два единичных кватерниона, представляющих вашу начальную и конечную ориентацию камеры. Теперь вы должны найти кватернион qT, который преобразует Q1 в Q2, то есть:
q2 = qT * q1
q2 * q1^-1 = qT * (q1 * q1^-1) = qT
=> qT = q2 * q1^-1
Знание того, что обратный элемент кватерниона равен его сопряженному :
q1^-1 = q1* iif ||q1|| = 1
qT = q2 * q1^-1 = q2 * q1*
Остался один шаг: извлечение оси и угла из кватерниона qT:
angle = 2 * acos(qw)
x = qx / sqrt(1-qw*qw)
y = qy / sqrt(1-qw*qw)
z = qz / sqrt(1-qw*qw)
Угол, конечно, дан в радианах. Остерегайтесь деления на ноль при расчете x, y и z. Такая ситуация может возникнуть, если нет вращения или очень маленькое, поэтому вам следует проверить, если угол> эпсилон, где вы бы выбрали эпсилон достаточно малым углом (скажем, 1/10 градуса), а не вычислять вектор, если это это случай.