Матрица угла поворота ZYX Эйлера определяется как
R_ZYX(dz, dy, dx) = R(Z, dz) * R(Y, dy) * R(X, dx)
Существует два разных способа определения порядка поворотов: слева направо или справа налево. При чтении слева направо повороты вокруг локальных осей системы координат , как вы правильно делаете . Только при чтении с справа налево вращения происходят вокруг фиксированной системы координат.
Теперь, чтобы ответить на вопрос, давайте вычислим угол, с которым dy
вы должны вращаться, если хотите, чтобы все координаты повернутого вектора имели одинаковое абсолютное значение.
Пусть r
будет длиной v
, а a
будет абсолютным значением координаты. По Пифогору, a^2 + a^2 + a^2 = r^2
, следовательно, a = r / sqrt(3)
. Угол поворота вектора относительно плоскости XY составляет dy = asin(a / r) = asin(1 / sqrt(3))
, что составляет около 35,3 градуса. Этот угол отличается от 45 градусов (или asin(1 / sqrt(2))
в радианах), которые вы используете в настоящее время.
Тест (с использованием Python и gameobjects library):
from gameobjects import *
from math import *
import random
V = vector3.Vector3
T = matrix44.Matrix44
def R_x(dx): return T.x_rotation(dx)
def R_y(dy): return T.y_rotation(dy)
def R_z(dz): return T.z_rotation(dz)
def fmt(v): return "(%.3f, %.3f, %.3f)" % (v[0], v[1], v[2])
dx = 0
dy = asin(1 / sqrt(3.0))
dz = pi / 4
v = V(10, 0, 0)
print "ZYX Euler angle transformations:"
print fmt((R_z(dz) * R_y(dy) * R_x(dx)).transform(v))
dy = pi / 4
print fmt((R_z(dz) * R_y(dy) * R_x(dx)).transform(v))
Выход:
ZYX Euler angle transformations:
(5.774, 5.774, -5.774)
(5.000, 5.000, -7.071)
Последняя строка для dz = dy = pi / 4
показывает, что программа согласуется с вашей реализацией угла Эйлера.