Ответ 1
Учитывая старый нормальный N
и новый нормальный N'
, вы можете получить поворот на:
RotationAxis = cross(N, N')
RotationAngle = arccos(dot(N, N') / (|N| * |N'|))
Где
-
cross(x, y)
является поперечным произведением векторовx
иy
-
dot(x, y)
является точечным произведением векторовx
иy
-
|x|
- длина вектораx
Это приведет к повороту старого нормального на новый с помощью кратчайшего пути.
Примечания
-
RotationAngle
будет в радианах (если arccos возвращает радианы, как это происходит в большинстве реализаций) -
arccos
является обратным косинусоидальной функции. Это необходимо, потому чтоdot(N, N') = |N| * |N'| * cos(RotationAngle)
гдеRotationAngle
- угол между векторами. -
RotationAxis
не нормируется - Если нормали нормализованы, деление на
(|N| * |N'|)
становится ненужным (фактически, еслиN
нормализовано, вы можете оставить|N|
продукта, а еслиN'
нормализовано, оставьте|N'|
) - Этот метод завершится с ошибкой, если
N' = -N
(так как существует бесконечное множество кратчайших путей)
Как это работает?
Первое замечание состоит в том, что две нормали всегда будут определять (по крайней мере) одну плоскость, в которой оба лежат. Наименьший угол, который их части, будет измеряться и внутри этой плоскости.Таким образом, вектор RotationAxis
будет нормалью плоскости, которая охватывает как N
, так и N'
, а RotationAngle
- наименьший угол между двумя упомянутыми ранее.
Итак, вращаясь вокруг RotationAxis
с помощью RotationAngle
, старый нормальный N
поворачивается внутри плоскости на кратчайший путь к N'
.