Zakładamy, że nasz układ współrzędnych jest lewoskrętny.
Macierz wynikowa będzie złożeniem 5 macierzy:
- obrót wokół wybranej osi sprowadzający wektor →A do płaszczyzny osi układu współrzędnych (np. wokół osi Z do płaszczyzny XZ)
- obrót wokół osi układu współrzędnych tak by sprowadzić wektor →A do jednej z osi układ współrzędnych (np. wokół osi Y do osi Z)
- obrót wokół tej osi (tym samym wokół wektora w jego lokalnym układzie współrzędnych od którego sprowadziliśmy go obrotami) o kąt θ
- obrót odwrotny do 2
- obrót odwrotny do 1
Najpierw robimy obrót o kąt −α wokół osi Z sprowadzając wektor →A do płaszczyzny XY.
α=−arctan(vu)
Teraz robimy obrót o kąt −β wokół osi Y sprowadzając wektor →A do osi Z.
s=√v2+u2
β=−arctan(sw)
Teraz nie pozostaje nam nic innego jak dokonać obrotu o kąt θ wokół osi Z. β=−arctan(sw)
Kompletna macierz ma postać:
M=M−1Z(α)M−1Y(β)MZ(θ)MY(β)MZ(α)
Zakładając, że wektor →A jest wektorem jednostkowym (co znacząco upraszcza i przyspiesza obliczenia), po wytrwałym mnożeniu powinniśmy dostać:t=1−cosθ
M=[tuu+cosθtuv−wsinθtuw+vsinθ0tuv+wsinθtvv+cosθtvw−usinθ0tuw−vsinθtvw+usinθtww+cosθ00001]
Przykład w C# prosto z definicji:M=[tuu+cosθtuv−wsinθtuw+vsinθ0tuv+wsinθtvv+cosθtvw−usinθ0tuw−vsinθtvw+usinθtww+cosθ00001]
public static Matrix4 CreateRotateAroundVector(Vector3 a_rotate_around, double a_angle) { a_rotate_around = a_rotate_around.Normalized; double u = a_rotate_around.X; double v = a_rotate_around.Y; double w = a_rotate_around.Z; var m_alpha = Matrix4.CreateRotateZ(-Math.Atan2(v, u)); var m_beta = Matrix4.CreateRotateY( -Math.Atan2(Math.Sqrt(v*v + u*u), w))); var m_angle = Matrix4.CreateRotateZ(a_angle); return m_alpha.Inverted * m_beta.Inverted * m_angle * m_beta * m_alpha; }I wersja szybka:
public static Matrix4 CreateRotateAroundVector(Vector3 a_rotate_around, double a_angle) { a_rotate_around = a_rotate_around.Normalized; double cos = Math.Cos(a_angle); double sin = Math.Sin(a_angle); double t = 1 - cos; double u = a_rotate_around.X; double v = a_rotate_around.Y; double w = a_rotate_around.Z; return new Matrix4( t * u * u + cos, t * u * v - sin * w, t * u * w + sin * v, 0, t * u * v + sin * w, t * v * v + cos, t * v * w - sin * u, 0, t * u * w - sin * v, t * v * w + sin * u, t * w * w + cos, 0, 0, 0, 0, 1 ); }
Brak komentarzy:
Prześlij komentarz