1use std::ops::{Add, Div, Mul, Neg, Sub};
5
6#[derive(Debug, Clone, Copy, PartialEq)]
8pub struct Vector2 {
9 pub x: f64,
10 pub y: f64,
11}
12
13#[derive(Debug, Clone, Copy, PartialEq)]
15pub struct Vector3 {
16 pub x: f64,
17 pub y: f64,
18 pub z: f64,
19}
20
21#[derive(Debug, Clone, Copy, PartialEq)]
23pub struct Vector4 {
24 pub x: f64,
25 pub y: f64,
26 pub z: f64,
27 pub w: f64,
28}
29
30impl Vector3 {
35 #[inline]
37 pub const fn new(x: f64, y: f64, z: f64) -> Self {
38 Self { x, y, z }
39 }
40
41 #[inline]
43 pub const fn zero() -> Self {
44 Self::new(0.0, 0.0, 0.0)
45 }
46
47 #[inline]
49 pub const fn one() -> Self {
50 Self::new(1.0, 1.0, 1.0)
51 }
52
53 #[inline]
55 pub const fn unit_x() -> Self {
56 Self::new(1.0, 0.0, 0.0)
57 }
58 #[inline]
59 pub const fn unit_y() -> Self {
60 Self::new(0.0, 1.0, 0.0)
61 }
62 #[inline]
63 pub const fn unit_z() -> Self {
64 Self::new(0.0, 0.0, 1.0)
65 }
66
67 #[inline]
69 pub const fn up() -> Self {
70 Self::unit_y()
71 }
72 #[inline]
73 pub const fn down() -> Self {
74 Self::new(0.0, -1.0, 0.0)
75 }
76 #[inline]
77 pub const fn left() -> Self {
78 Self::new(-1.0, 0.0, 0.0)
79 }
80 #[inline]
81 pub const fn right() -> Self {
82 Self::unit_x()
83 }
84 #[inline]
85 pub const fn forward() -> Self {
86 Self::new(0.0, 0.0, -1.0)
87 }
88 #[inline]
89 pub const fn back() -> Self {
90 Self::unit_z()
91 }
92
93 #[inline]
95 pub fn dot(self, other: Self) -> f64 {
96 self.x * other.x + self.y * other.y + self.z * other.z
97 }
98
99 #[inline]
101 pub fn cross(self, other: Self) -> Self {
102 Self {
103 x: self.y * other.z - self.z * other.y,
104 y: self.z * other.x - self.x * other.z,
105 z: self.x * other.y - self.y * other.x,
106 }
107 }
108
109 #[inline]
111 pub fn length(self) -> f64 {
112 self.dot(self).sqrt()
113 }
114
115 #[inline]
117 pub fn length_squared(self) -> f64 {
118 self.dot(self)
119 }
120
121 #[inline]
123 pub fn normalize(self) -> Self {
124 let len = self.length();
125 if len > 0.0 {
126 self / len
127 } else {
128 Self::zero()
129 }
130 }
131
132 #[inline]
134 pub fn distance(self, other: Self) -> f64 {
135 (self - other).length()
136 }
137
138 #[inline]
140 pub fn distance_squared(self, other: Self) -> f64 {
141 (self - other).length_squared()
142 }
143
144 #[inline]
146 pub fn lerp(self, other: Self, t: f64) -> Self {
147 self * (1.0 - t) + other * t
148 }
149
150 #[inline]
152 pub fn reflect(self, normal: Self) -> Self {
153 self - normal * (2.0 * self.dot(normal))
154 }
155
156 #[inline]
158 pub fn project_onto(self, onto: Self) -> Self {
159 onto * (self.dot(onto) / onto.dot(onto))
160 }
161
162 #[inline]
164 pub fn min(self, other: Self) -> Self {
165 Self {
166 x: self.x.min(other.x),
167 y: self.y.min(other.y),
168 z: self.z.min(other.z),
169 }
170 }
171
172 #[inline]
174 pub fn max(self, other: Self) -> Self {
175 Self {
176 x: self.x.max(other.x),
177 y: self.y.max(other.y),
178 z: self.z.max(other.z),
179 }
180 }
181
182 #[inline]
184 pub fn to_vector4_dir(self) -> Vector4 {
185 Vector4::new(self.x, self.y, self.z, 0.0)
186 }
187
188 #[inline]
190 pub fn to_vector4_point(self) -> Vector4 {
191 Vector4::new(self.x, self.y, self.z, 1.0)
192 }
193}
194
195impl Add for Vector3 {
197 type Output = Self;
198 fn add(self, rhs: Self) -> Self {
199 Self::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
200 }
201}
202
203impl Sub for Vector3 {
204 type Output = Self;
205 fn sub(self, rhs: Self) -> Self {
206 Self::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
207 }
208}
209
210impl Mul<f64> for Vector3 {
211 type Output = Self;
212 fn mul(self, rhs: f64) -> Self {
213 Self::new(self.x * rhs, self.y * rhs, self.z * rhs)
214 }
215}
216
217impl Div<f64> for Vector3 {
218 type Output = Self;
219 fn div(self, rhs: f64) -> Self {
220 Self::new(self.x / rhs, self.y / rhs, self.z / rhs)
221 }
222}
223
224impl Neg for Vector3 {
225 type Output = Self;
226 fn neg(self) -> Self {
227 Self::new(-self.x, -self.y, -self.z)
228 }
229}
230
231impl Vector4 {
236 #[inline]
238 pub const fn new(x: f64, y: f64, z: f64, w: f64) -> Self {
239 Self { x, y, z, w }
240 }
241
242 #[inline]
244 pub const fn zero() -> Self {
245 Self::new(0.0, 0.0, 0.0, 0.0)
246 }
247
248 #[inline]
250 pub fn to_vector3(self) -> Vector3 {
251 Vector3::new(self.x, self.y, self.z)
252 }
253
254 #[inline]
256 pub fn dot(self, other: Self) -> f64 {
257 self.x * other.x + self.y * other.y + self.z * other.z + self.w * other.w
258 }
259
260 #[inline]
262 pub fn length(self) -> f64 {
263 self.dot(self).sqrt()
264 }
265
266 #[inline]
268 pub fn normalize(self) -> Self {
269 let len = self.length();
270 if len > 0.0 {
271 self / len
272 } else {
273 Self::zero()
274 }
275 }
276}
277
278impl Add for Vector4 {
280 type Output = Self;
281 fn add(self, rhs: Self) -> Self {
282 Self::new(
283 self.x + rhs.x,
284 self.y + rhs.y,
285 self.z + rhs.z,
286 self.w + rhs.w,
287 )
288 }
289}
290
291impl Sub for Vector4 {
292 type Output = Self;
293 fn sub(self, rhs: Self) -> Self {
294 Self::new(
295 self.x - rhs.x,
296 self.y - rhs.y,
297 self.z - rhs.z,
298 self.w - rhs.w,
299 )
300 }
301}
302
303impl Mul<f64> for Vector4 {
304 type Output = Self;
305 fn mul(self, rhs: f64) -> Self {
306 Self::new(self.x * rhs, self.y * rhs, self.z * rhs, self.w * rhs)
307 }
308}
309
310impl Div<f64> for Vector4 {
311 type Output = Self;
312 fn div(self, rhs: f64) -> Self {
313 Self::new(self.x / rhs, self.y / rhs, self.z / rhs, self.w / rhs)
314 }
315}
316
317#[cfg(test)]
318mod tests {
319 use super::*;
320
321 #[test]
322 fn test_vector3_basic() {
323 let v = Vector3::new(1.0, 2.0, 3.0);
324 assert_eq!(v.x, 1.0);
325 assert_eq!(v.y, 2.0);
326 assert_eq!(v.z, 3.0);
327 }
328
329 #[test]
330 fn test_vector3_arithmetic() {
331 let v1 = Vector3::new(1.0, 2.0, 3.0);
332 let v2 = Vector3::new(4.0, 5.0, 6.0);
333 let sum = v1 + v2;
334 assert_eq!(sum, Vector3::new(5.0, 7.0, 9.0));
335 }
336
337 #[test]
338 fn test_vector3_dot() {
339 let v1 = Vector3::new(1.0, 2.0, 3.0);
340 let v2 = Vector3::new(4.0, 5.0, 6.0);
341 assert_eq!(v1.dot(v2), 32.0);
342 }
343
344 #[test]
345 fn test_vector3_cross() {
346 let v1 = Vector3::unit_x();
347 let v2 = Vector3::unit_y();
348 let cross = v1.cross(v2);
349 assert!((cross.x - 0.0).abs() < 1e-10);
350 assert!((cross.y - 0.0).abs() < 1e-10);
351 assert!((cross.z - 1.0).abs() < 1e-10);
352 }
353
354 #[test]
355 fn test_vector3_normalize() {
356 let v = Vector3::new(3.0, 4.0, 0.0);
357 let normalized = v.normalize();
358 assert!((normalized.length() - 1.0).abs() < 1e-10);
359 }
360}