rapier2d/utils/
orthonormal_basis.rs1#[cfg(feature = "dim3")]
4use crate::math::Real;
5use crate::math::Vector;
6#[cfg(not(target_arch = "spirv"))]
7use crate::utils::{CopySign, SimdRealCopy};
8#[cfg(not(target_arch = "spirv"))]
9use na::{Vector2, Vector3};
10
11pub trait OrthonormalBasis: Sized {
13 type Basis;
15 fn orthonormal_basis(self) -> Self::Basis;
17 fn orthonormal_vector(self) -> Self;
19}
20
21#[cfg(not(target_arch = "spirv"))]
22impl<N: SimdRealCopy> OrthonormalBasis for Vector2<N> {
23 type Basis = [Vector2<N>; 1];
24 fn orthonormal_basis(self) -> [Vector2<N>; 1] {
25 [Vector2::new(-self.y, self.x)]
26 }
27 fn orthonormal_vector(self) -> Vector2<N> {
28 Vector2::new(-self.y, self.x)
29 }
30}
31
32#[cfg(not(target_arch = "spirv"))]
33impl<N: SimdRealCopy + CopySign<N>> OrthonormalBasis for Vector3<N> {
34 type Basis = [Vector3<N>; 2];
35 fn orthonormal_basis(self) -> [Vector3<N>; 2] {
38 let sign = self.z.copy_sign_to(N::one());
39 let a = -N::one() / (sign + self.z);
40 let b = self.x * self.y * a;
41
42 [
43 Vector3::new(
44 N::one() + sign * self.x * self.x * a,
45 sign * b,
46 -sign * self.x,
47 ),
48 Vector3::new(b, sign + self.y * self.y * a, -self.y),
49 ]
50 }
51
52 fn orthonormal_vector(self) -> Vector3<N> {
53 let sign = self.z.copy_sign_to(N::one());
54 let a = -N::one() / (sign + self.z);
55 let b = self.x * self.y * a;
56 Vector3::new(b, sign + self.y * self.y * a, -self.y)
57 }
58}
59
60#[cfg(feature = "dim2")]
62impl OrthonormalBasis for Vector {
63 type Basis = [Vector; 1];
64 fn orthonormal_basis(self) -> [Vector; 1] {
65 [Vector::new(-self.y, self.x)]
66 }
67 fn orthonormal_vector(self) -> Vector {
68 Vector::new(-self.y, self.x)
69 }
70}
71
72#[cfg(feature = "dim3")]
73impl OrthonormalBasis for Vector {
74 type Basis = [Vector; 2];
75 fn orthonormal_basis(self) -> [Vector; 2] {
78 let sign = Real::copysign(1.0, self.z);
79 let a = -1.0 / (sign + self.z);
80 let b = self.x * self.y * a;
81
82 [
83 Vector::new(1.0 + sign * self.x * self.x * a, sign * b, -sign * self.x),
84 Vector::new(b, sign + self.y * self.y * a, -self.y),
85 ]
86 }
87
88 fn orthonormal_vector(self) -> Vector {
89 let sign = Real::copysign(1.0, self.z);
90 let a = -1.0 / (sign + self.z);
91 let b = self.x * self.y * a;
92 Vector::new(b, sign + self.y * self.y * a, -self.y)
93 }
94}