#math #vector #3d #transform #coordinate-transformation
#математика #вектор #3D #преобразование #преобразование координат
Вопрос:
Я пытаюсь выровнять систему координат по нормальному направлению, таким образом, я ввожу только X, Y, Z и направление нормали и Y-вращение координаты, чтобы получить новые X, Y, Z из новой выровненной системы координат.
Функция, которая будет выглядеть следующим образом:
func transform(coordinate: XYZposition, to: XYZnormal, withY:Radians){
//missing mathematic
//rotate coordinates
return XYZpositionOfNewSystem
}
Вот изображение, представляющее визуализацию того, чего я хочу достичь. Ось — это представление системы координат. Первая система координат — исходная, а 2 справа — повернутые.
Почему 2 примера справа?
Как вы можете видеть, при выравнивании по нормали к грани остается одна свободная ось. Ось Y может принимать любое вращение и при этом оставаться выровненной по грани.
Вот почему функции необходимо задать вращение, чтобы она также применяла это вращение по оси Y.
Я нашел некоторые математические расчеты на сайте Mathematics Stack Exchange (поверните систему координат 3D так, чтобы ось Z была параллельна заданному вектору), но я потерялся, если это то, что мне нужно, и я немного запутался в применяемой математике и используемых символах.
Ответ №1:
Вот ответ, который вы процитировали, реализованный с использованием python и numpy и обмен ролями y
и z
в соответствии с вашими потребностями:
from numpy import array, dot, cross, arccos, sin, cos
from scipy.spatial.distance import cosine
def angle(u,v):
return arccos(1 - cosine(u,v))
# assumes all four vectors are normalized
def get_transform_matrix(orig_system, n):
j = orig_system[:,1]
b = cross(j, n)
theta = angle(j, n)
q0 = cos(theta/2)
q1,q2,q3 = sin(theta/2) * b
Q = array([
[q0**2 q1**2 - q2**2 - q3**2, 2*(q1*q3 q0*q2), 2*(q1*q2-q0*q3)],
[2*(q3*q1-q0*q2), q0**2 - q1**2 - q2**2 q3**2, 2*(q3*q2 q0*q1)],
[2*(q2*q1 q0*q3), 2*(q2*q3-q0*q1), q0**2 - q1**2 q2**2 - q3**2]
])
return Q
Чтобы преобразовать вектор p
в новую систему, просто вычислите Q @ p
:
from numpy import eye, sqrt
orig_system = eye(3)
n = array([0,1,1]) / sqrt(2)
Q = get_transform_matrix(orig_system, n)
print(Q)
# [[ 0.9267767 0. 0. ]
# [ 0. 0.78033009 0.5 ]
# [ 0. -0.5 0.78033009]]
p = array([10, 20, 30])
print(Q @ p)
# [ 9.26776695 30.60660172 13.40990258]
Пожалуйста, протестируйте это тщательно!! Я тестировал с несколькими разными векторами, и все выглядело нормально, но я не могу гарантировать, что ошибок нет.
Комментарии:
1. Протестируем это прямо сейчас! Позволит вам, если это сработает, сначала мне нужно будет перевести в Metal, я использую его в шейдере для вычисления UV-координат.