1use core::{
25 marker::PhantomData,
26 ops::{Add, Index, IndexMut, Mul, Neg, Sub},
27};
28
29pub trait Ops {
33 fn sqrt(x: f32) -> f32;
39
40 fn acos(x: f32) -> f32;
44}
45
46pub(crate) struct Vec3<O: Ops> {
47 pub(crate) x: f32,
48 pub(crate) y: f32,
49 pub(crate) z: f32,
50 pub(crate) _phantom: PhantomData<O>,
51}
52
53impl<O: Ops> Copy for Vec3<O> {}
54
55impl<O: Ops> Clone for Vec3<O> {
56 fn clone(&self) -> Self {
57 *self
58 }
59}
60
61impl<O: Ops> From<[f32; 3]> for Vec3<O> {
62 fn from([x, y, z]: [f32; 3]) -> Self {
63 Self {
64 x,
65 y,
66 z,
67 ..Self::ZERO
68 }
69 }
70}
71
72impl<O: Ops> From<Vec3<O>> for [f32; 3] {
73 fn from(Vec3 { x, y, z, .. }: Vec3<O>) -> Self {
74 [x, y, z]
75 }
76}
77
78impl<O: Ops> Vec3<O> {
79 pub(crate) const ZERO: Vec3<O> = Vec3 {
80 x: 0.,
81 y: 0.,
82 z: 0.,
83 _phantom: PhantomData,
84 };
85
86 pub(crate) fn dot(self, rhs: Self) -> f32 {
87 self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
88 }
89
90 pub(crate) fn normalize_or_zero(&mut self) {
91 if not_zero(self.x) || not_zero(self.y) || not_zero(self.z) {
93 *self = *self * self.length().recip();
94 }
95 }
96
97 pub(crate) fn normalized_or_zero(mut self) -> Self {
98 self.normalize_or_zero();
99 self
100 }
101
102 pub(crate) fn length_squared(self) -> f32 {
103 self.dot(self)
104 }
105
106 pub(crate) fn length(self) -> f32 {
107 O::sqrt(self.length_squared())
108 }
109}
110
111impl<O: Ops> Index<usize> for Vec3<O> {
112 type Output = f32;
113
114 fn index(&self, index: usize) -> &Self::Output {
115 match index {
116 0 => &self.x,
117 1 => &self.y,
118 2 => &self.z,
119 _ => panic!(),
120 }
121 }
122}
123
124impl<O: Ops> IndexMut<usize> for Vec3<O> {
125 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
126 match index {
127 0 => &mut self.x,
128 1 => &mut self.y,
129 2 => &mut self.z,
130 _ => panic!(),
131 }
132 }
133}
134
135impl<O: Ops> Add for Vec3<O> {
136 type Output = Vec3<O>;
137
138 fn add(self, rhs: Self) -> Self::Output {
139 Vec3 {
140 x: self.x + rhs.x,
141 y: self.y + rhs.y,
142 z: self.z + rhs.z,
143 _phantom: PhantomData,
144 }
145 }
146}
147
148impl<O: Ops> Sub for Vec3<O> {
149 type Output = Vec3<O>;
150
151 fn sub(self, rhs: Self) -> Self::Output {
152 Vec3 {
153 x: self.x - rhs.x,
154 y: self.y - rhs.y,
155 z: self.z - rhs.z,
156 _phantom: PhantomData,
157 }
158 }
159}
160
161impl<O: Ops> Mul<f32> for Vec3<O> {
162 type Output = Vec3<O>;
163
164 fn mul(self, rhs: f32) -> Self::Output {
165 Vec3 {
166 x: rhs * self.x,
167 y: rhs * self.y,
168 z: rhs * self.z,
169 _phantom: PhantomData,
170 }
171 }
172}
173
174impl<O: Ops> Mul<Vec3<O>> for f32 {
175 type Output = Vec3<O>;
176
177 fn mul(self, rhs: Vec3<O>) -> Self::Output {
178 rhs * self
179 }
180}
181
182impl<O: Ops> PartialEq for Vec3<O> {
183 fn eq(&self, other: &Self) -> bool {
184 self.x == other.x && self.y == other.y && self.z == other.z
185 }
186}
187
188impl<O: Ops> Neg for Vec3<O> {
189 type Output = Vec3<O>;
190
191 fn neg(self) -> Self::Output {
192 Self {
193 x: -self.x,
194 y: -self.y,
195 z: -self.z,
196 _phantom: PhantomData,
197 }
198 }
199}
200
201pub(crate) fn fabsf(x: f32) -> f32 {
202 if x.is_sign_negative() { -x } else { x }
203}
204
205pub(crate) fn not_zero(x: f32) -> bool {
206 fabsf(x) > f32::MIN_POSITIVE
208}