Skip to main content

vexil_runtime/
geometric.rs

1//! Geometric types for Vexil runtime.
2//!
3//! Vec2, Vec3, Vec4, Quat, Mat3, Mat4 with basic operations and Pack/Unpack support.
4
5use core::ops::{Add, Div, Mul, Neg, Sub};
6
7use crate::bit_reader::BitReader;
8use crate::bit_writer::BitWriter;
9use crate::error::{DecodeError, EncodeError};
10use crate::traits::{Pack, Unpack};
11
12/// 2-component vector.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14#[repr(C)]
15pub struct Vec2<T> {
16    pub x: T,
17    pub y: T,
18}
19
20/// 3-component vector.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22#[repr(C)]
23pub struct Vec3<T> {
24    pub x: T,
25    pub y: T,
26    pub z: T,
27}
28
29/// 4-component vector.
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
31#[repr(C)]
32pub struct Vec4<T> {
33    pub x: T,
34    pub y: T,
35    pub z: T,
36    pub w: T,
37}
38
39/// Quaternion.
40#[derive(Debug, Clone, Copy, PartialEq)]
41#[repr(C)]
42pub struct Quat<T> {
43    pub x: T,
44    pub y: T,
45    pub z: T,
46    pub w: T,
47}
48
49/// 3x3 matrix (column-major).
50#[derive(Debug, Clone, Copy, PartialEq)]
51#[repr(C)]
52pub struct Mat3<T> {
53    pub cols: [Vec3<T>; 3],
54}
55
56/// 4x4 matrix (column-major).
57#[derive(Debug, Clone, Copy, PartialEq)]
58#[repr(C)]
59pub struct Mat4<T> {
60    pub cols: [Vec4<T>; 4],
61}
62
63// ==================== Vec2 Implementations ====================
64
65impl<T> Vec2<T> {
66    /// Create a new Vec2.
67    pub const fn new(x: T, y: T) -> Self {
68        Self { x, y }
69    }
70}
71
72impl<T: Add<Output = T>> Add for Vec2<T> {
73    type Output = Self;
74    fn add(self, other: Self) -> Self {
75        Self {
76            x: self.x + other.x,
77            y: self.y + other.y,
78        }
79    }
80}
81
82impl<T: Sub<Output = T>> Sub for Vec2<T> {
83    type Output = Self;
84    fn sub(self, other: Self) -> Self {
85        Self {
86            x: self.x - other.x,
87            y: self.y - other.y,
88        }
89    }
90}
91
92impl<T: Mul<Output = T> + Copy> Mul<T> for Vec2<T> {
93    type Output = Self;
94    fn mul(self, scalar: T) -> Self {
95        Self {
96            x: self.x * scalar,
97            y: self.y * scalar,
98        }
99    }
100}
101
102impl<T: Div<Output = T> + Copy> Div<T> for Vec2<T> {
103    type Output = Self;
104    fn div(self, scalar: T) -> Self {
105        Self {
106            x: self.x / scalar,
107            y: self.y / scalar,
108        }
109    }
110}
111
112impl<T: Neg<Output = T>> Neg for Vec2<T> {
113    type Output = Self;
114    fn neg(self) -> Self {
115        Self {
116            x: -self.x,
117            y: -self.y,
118        }
119    }
120}
121
122impl<T: Pack> Pack for Vec2<T> {
123    fn pack(&self, w: &mut BitWriter) -> Result<(), EncodeError> {
124        self.x.pack(w)?;
125        self.y.pack(w)
126    }
127}
128
129impl<T: Unpack> Unpack for Vec2<T> {
130    fn unpack(r: &mut BitReader<'_>) -> Result<Self, DecodeError> {
131        Ok(Self {
132            x: T::unpack(r)?,
133            y: T::unpack(r)?,
134        })
135    }
136}
137
138// ==================== Vec3 Implementations ====================
139
140impl<T> Vec3<T> {
141    /// Create a new Vec3.
142    pub const fn new(x: T, y: T, z: T) -> Self {
143        Self { x, y, z }
144    }
145}
146
147impl<T: Add<Output = T>> Add for Vec3<T> {
148    type Output = Self;
149    fn add(self, other: Self) -> Self {
150        Self {
151            x: self.x + other.x,
152            y: self.y + other.y,
153            z: self.z + other.z,
154        }
155    }
156}
157
158impl<T: Sub<Output = T>> Sub for Vec3<T> {
159    type Output = Self;
160    fn sub(self, other: Self) -> Self {
161        Self {
162            x: self.x - other.x,
163            y: self.y - other.y,
164            z: self.z - other.z,
165        }
166    }
167}
168
169impl<T: Mul<Output = T> + Copy> Mul<T> for Vec3<T> {
170    type Output = Self;
171    fn mul(self, scalar: T) -> Self {
172        Self {
173            x: self.x * scalar,
174            y: self.y * scalar,
175            z: self.z * scalar,
176        }
177    }
178}
179
180impl<T: Div<Output = T> + Copy> Div<T> for Vec3<T> {
181    type Output = Self;
182    fn div(self, scalar: T) -> Self {
183        Self {
184            x: self.x / scalar,
185            y: self.y / scalar,
186            z: self.z / scalar,
187        }
188    }
189}
190
191impl<T: Neg<Output = T>> Neg for Vec3<T> {
192    type Output = Self;
193    fn neg(self) -> Self {
194        Self {
195            x: -self.x,
196            y: -self.y,
197            z: -self.z,
198        }
199    }
200}
201
202impl<T: Pack> Pack for Vec3<T> {
203    fn pack(&self, w: &mut BitWriter) -> Result<(), EncodeError> {
204        self.x.pack(w)?;
205        self.y.pack(w)?;
206        self.z.pack(w)
207    }
208}
209
210impl<T: Unpack> Unpack for Vec3<T> {
211    fn unpack(r: &mut BitReader<'_>) -> Result<Self, DecodeError> {
212        Ok(Self {
213            x: T::unpack(r)?,
214            y: T::unpack(r)?,
215            z: T::unpack(r)?,
216        })
217    }
218}
219
220// ==================== Vec4 Implementations ====================
221
222impl<T> Vec4<T> {
223    /// Create a new Vec4.
224    pub const fn new(x: T, y: T, z: T, w: T) -> Self {
225        Self { x, y, z, w }
226    }
227}
228
229impl<T: Add<Output = T>> Add for Vec4<T> {
230    type Output = Self;
231    fn add(self, other: Self) -> Self {
232        Self {
233            x: self.x + other.x,
234            y: self.y + other.y,
235            z: self.z + other.z,
236            w: self.w + other.w,
237        }
238    }
239}
240
241impl<T: Sub<Output = T>> Sub for Vec4<T> {
242    type Output = Self;
243    fn sub(self, other: Self) -> Self {
244        Self {
245            x: self.x - other.x,
246            y: self.y - other.y,
247            z: self.z - other.z,
248            w: self.w - other.w,
249        }
250    }
251}
252
253impl<T: Mul<Output = T> + Copy> Mul<T> for Vec4<T> {
254    type Output = Self;
255    fn mul(self, scalar: T) -> Self {
256        Self {
257            x: self.x * scalar,
258            y: self.y * scalar,
259            z: self.z * scalar,
260            w: self.w * scalar,
261        }
262    }
263}
264
265impl<T: Div<Output = T> + Copy> Div<T> for Vec4<T> {
266    type Output = Self;
267    fn div(self, scalar: T) -> Self {
268        Self {
269            x: self.x / scalar,
270            y: self.y / scalar,
271            z: self.z / scalar,
272            w: self.w / scalar,
273        }
274    }
275}
276
277impl<T: Neg<Output = T>> Neg for Vec4<T> {
278    type Output = Self;
279    fn neg(self) -> Self {
280        Self {
281            x: -self.x,
282            y: -self.y,
283            z: -self.z,
284            w: -self.w,
285        }
286    }
287}
288
289impl<T: Pack> Pack for Vec4<T> {
290    fn pack(&self, w: &mut BitWriter) -> Result<(), EncodeError> {
291        self.x.pack(w)?;
292        self.y.pack(w)?;
293        self.z.pack(w)?;
294        self.w.pack(w)
295    }
296}
297
298impl<T: Unpack> Unpack for Vec4<T> {
299    fn unpack(r: &mut BitReader<'_>) -> Result<Self, DecodeError> {
300        Ok(Self {
301            x: T::unpack(r)?,
302            y: T::unpack(r)?,
303            z: T::unpack(r)?,
304            w: T::unpack(r)?,
305        })
306    }
307}
308
309// ==================== Quat Implementations ====================
310
311impl<T> Quat<T> {
312    /// Create a new Quaternion.
313    pub const fn new(x: T, y: T, z: T, w: T) -> Self {
314        Self { x, y, z, w }
315    }
316}
317
318impl<T: Add<Output = T>> Add for Quat<T> {
319    type Output = Self;
320    fn add(self, other: Self) -> Self {
321        Self {
322            x: self.x + other.x,
323            y: self.y + other.y,
324            z: self.z + other.z,
325            w: self.w + other.w,
326        }
327    }
328}
329
330impl<T: Sub<Output = T>> Sub for Quat<T> {
331    type Output = Self;
332    fn sub(self, other: Self) -> Self {
333        Self {
334            x: self.x - other.x,
335            y: self.y - other.y,
336            z: self.z - other.z,
337            w: self.w - other.w,
338        }
339    }
340}
341
342impl<T: Mul<Output = T> + Copy> Mul<T> for Quat<T> {
343    type Output = Self;
344    fn mul(self, scalar: T) -> Self {
345        Self {
346            x: self.x * scalar,
347            y: self.y * scalar,
348            z: self.z * scalar,
349            w: self.w * scalar,
350        }
351    }
352}
353
354impl<T: Div<Output = T> + Copy> Div<T> for Quat<T> {
355    type Output = Self;
356    fn div(self, scalar: T) -> Self {
357        Self {
358            x: self.x / scalar,
359            y: self.y / scalar,
360            z: self.z / scalar,
361            w: self.w / scalar,
362        }
363    }
364}
365
366impl<T: Neg<Output = T>> Neg for Quat<T> {
367    type Output = Self;
368    fn neg(self) -> Self {
369        Self {
370            x: -self.x,
371            y: -self.y,
372            z: -self.z,
373            w: -self.w,
374        }
375    }
376}
377
378impl<T: Pack> Pack for Quat<T> {
379    fn pack(&self, w: &mut BitWriter) -> Result<(), EncodeError> {
380        self.x.pack(w)?;
381        self.y.pack(w)?;
382        self.z.pack(w)?;
383        self.w.pack(w)
384    }
385}
386
387impl<T: Unpack> Unpack for Quat<T> {
388    fn unpack(r: &mut BitReader<'_>) -> Result<Self, DecodeError> {
389        Ok(Self {
390            x: T::unpack(r)?,
391            y: T::unpack(r)?,
392            z: T::unpack(r)?,
393            w: T::unpack(r)?,
394        })
395    }
396}
397
398// ==================== Mat3 Implementations ====================
399
400impl<T> Mat3<T> {
401    /// Create a new Mat3 from three column vectors.
402    pub const fn new(c0: Vec3<T>, c1: Vec3<T>, c2: Vec3<T>) -> Self {
403        Self { cols: [c0, c1, c2] }
404    }
405
406    /// Create an identity matrix (requires T: Default + From<u8>).
407    pub fn identity() -> Self
408    where
409        T: Default + From<u8>,
410    {
411        Self {
412            cols: [
413                Vec3::new(T::from(1), T::default(), T::default()),
414                Vec3::new(T::default(), T::from(1), T::default()),
415                Vec3::new(T::default(), T::default(), T::from(1)),
416            ],
417        }
418    }
419}
420
421impl<T: Pack> Pack for Mat3<T> {
422    fn pack(&self, w: &mut BitWriter) -> Result<(), EncodeError> {
423        self.cols[0].pack(w)?;
424        self.cols[1].pack(w)?;
425        self.cols[2].pack(w)
426    }
427}
428
429impl<T: Unpack> Unpack for Mat3<T> {
430    fn unpack(r: &mut BitReader<'_>) -> Result<Self, DecodeError> {
431        Ok(Self {
432            cols: [Vec3::unpack(r)?, Vec3::unpack(r)?, Vec3::unpack(r)?],
433        })
434    }
435}
436
437// ==================== Mat4 Implementations ====================
438
439impl<T> Mat4<T> {
440    /// Create a new Mat4 from four column vectors.
441    pub const fn new(c0: Vec4<T>, c1: Vec4<T>, c2: Vec4<T>, c3: Vec4<T>) -> Self {
442        Self {
443            cols: [c0, c1, c2, c3],
444        }
445    }
446
447    /// Create an identity matrix (requires T: Default + From<u8>).
448    pub fn identity() -> Self
449    where
450        T: Default + From<u8>,
451    {
452        Self {
453            cols: [
454                Vec4::new(T::from(1), T::default(), T::default(), T::default()),
455                Vec4::new(T::default(), T::from(1), T::default(), T::default()),
456                Vec4::new(T::default(), T::default(), T::from(1), T::default()),
457                Vec4::new(T::default(), T::default(), T::default(), T::from(1)),
458            ],
459        }
460    }
461}
462
463impl<T: Pack> Pack for Mat4<T> {
464    fn pack(&self, w: &mut BitWriter) -> Result<(), EncodeError> {
465        self.cols[0].pack(w)?;
466        self.cols[1].pack(w)?;
467        self.cols[2].pack(w)?;
468        self.cols[3].pack(w)
469    }
470}
471
472impl<T: Unpack> Unpack for Mat4<T> {
473    fn unpack(r: &mut BitReader<'_>) -> Result<Self, DecodeError> {
474        Ok(Self {
475            cols: [
476                Vec4::unpack(r)?,
477                Vec4::unpack(r)?,
478                Vec4::unpack(r)?,
479                Vec4::unpack(r)?,
480            ],
481        })
482    }
483}
484
485#[cfg(test)]
486mod tests {
487    use super::*;
488
489    #[test]
490    fn vec2_new() {
491        let v = Vec2::new(1.0f32, 2.0f32);
492        assert_eq!(v.x, 1.0);
493        assert_eq!(v.y, 2.0);
494    }
495
496    #[test]
497    fn vec2_add() {
498        let a = Vec2::new(1, 2);
499        let b = Vec2::new(3, 4);
500        let c = a + b;
501        assert_eq!(c.x, 4);
502        assert_eq!(c.y, 6);
503    }
504
505    #[test]
506    fn vec2_sub() {
507        let a = Vec2::new(5, 7);
508        let b = Vec2::new(2, 3);
509        let c = a - b;
510        assert_eq!(c.x, 3);
511        assert_eq!(c.y, 4);
512    }
513
514    #[test]
515    fn vec2_mul_scalar() {
516        let a = Vec2::new(2.0f32, 3.0f32);
517        let b = a * 2.0f32;
518        assert_eq!(b.x, 4.0);
519        assert_eq!(b.y, 6.0);
520    }
521
522    #[test]
523    fn vec2_neg() {
524        let a = Vec2::new(1.0f32, -2.0f32);
525        let b = -a;
526        assert_eq!(b.x, -1.0);
527        assert_eq!(b.y, 2.0);
528    }
529
530    #[test]
531    fn vec3_new() {
532        let v = Vec3::new(1.0f32, 2.0f32, 3.0f32);
533        assert_eq!(v.x, 1.0);
534        assert_eq!(v.y, 2.0);
535        assert_eq!(v.z, 3.0);
536    }
537
538    #[test]
539    fn vec3_add() {
540        let a = Vec3::new(1, 2, 3);
541        let b = Vec3::new(4, 5, 6);
542        let c = a + b;
543        assert_eq!(c.x, 5);
544        assert_eq!(c.y, 7);
545        assert_eq!(c.z, 9);
546    }
547
548    #[test]
549    fn vec4_new() {
550        let v = Vec4::new(1.0f32, 2.0f32, 3.0f32, 4.0f32);
551        assert_eq!(v.x, 1.0);
552        assert_eq!(v.y, 2.0);
553        assert_eq!(v.z, 3.0);
554        assert_eq!(v.w, 4.0);
555    }
556
557    #[test]
558    fn quat_new() {
559        let q = Quat::new(1.0f32, 2.0f32, 3.0f32, 4.0f32);
560        assert_eq!(q.x, 1.0);
561        assert_eq!(q.y, 2.0);
562        assert_eq!(q.z, 3.0);
563        assert_eq!(q.w, 4.0);
564    }
565
566    #[test]
567    fn mat3_identity() {
568        let m = Mat3::<f32>::identity();
569        assert_eq!(m.cols[0].x, 1.0);
570        assert_eq!(m.cols[0].y, 0.0);
571        assert_eq!(m.cols[0].z, 0.0);
572        assert_eq!(m.cols[1].x, 0.0);
573        assert_eq!(m.cols[1].y, 1.0);
574        assert_eq!(m.cols[1].z, 0.0);
575        assert_eq!(m.cols[2].x, 0.0);
576        assert_eq!(m.cols[2].y, 0.0);
577        assert_eq!(m.cols[2].z, 1.0);
578    }
579
580    #[test]
581    fn mat4_identity() {
582        let m = Mat4::<f32>::identity();
583        assert_eq!(m.cols[0].x, 1.0);
584        assert_eq!(m.cols[0].y, 0.0);
585        assert_eq!(m.cols[0].z, 0.0);
586        assert_eq!(m.cols[0].w, 0.0);
587        assert_eq!(m.cols[1].x, 0.0);
588        assert_eq!(m.cols[1].y, 1.0);
589        assert_eq!(m.cols[2].z, 1.0);
590        assert_eq!(m.cols[3].w, 1.0);
591    }
592
593    #[test]
594    fn vec2_pack_unpack() {
595        let v = Vec2::new(1.0f32, 2.0f32);
596        let mut w = BitWriter::new();
597        v.pack(&mut w).unwrap();
598        let buf = w.finish();
599        let mut r = BitReader::new(&buf);
600        let v2 = Vec2::<f32>::unpack(&mut r).unwrap();
601        assert_eq!(v, v2);
602    }
603
604    #[test]
605    fn vec3_pack_unpack() {
606        let v = Vec3::new(1.0f32, 2.0f32, 3.0f32);
607        let mut w = BitWriter::new();
608        v.pack(&mut w).unwrap();
609        let buf = w.finish();
610        let mut r = BitReader::new(&buf);
611        let v2 = Vec3::<f32>::unpack(&mut r).unwrap();
612        assert_eq!(v, v2);
613    }
614
615    #[test]
616    fn vec4_pack_unpack() {
617        let v = Vec4::new(1.0f32, 2.0f32, 3.0f32, 4.0f32);
618        let mut w = BitWriter::new();
619        v.pack(&mut w).unwrap();
620        let buf = w.finish();
621        let mut r = BitReader::new(&buf);
622        let v2 = Vec4::<f32>::unpack(&mut r).unwrap();
623        assert_eq!(v, v2);
624    }
625
626    #[test]
627    fn quat_pack_unpack() {
628        let q = Quat::new(1.0f32, 2.0f32, 3.0f32, 4.0f32);
629        let mut w = BitWriter::new();
630        q.pack(&mut w).unwrap();
631        let buf = w.finish();
632        let mut r = BitReader::new(&buf);
633        let q2 = Quat::<f32>::unpack(&mut r).unwrap();
634        assert_eq!(q, q2);
635    }
636
637    #[test]
638    fn mat3_pack_unpack() {
639        let m = Mat3::new(
640            Vec3::new(1.0f32, 0.0f32, 0.0f32),
641            Vec3::new(0.0f32, 1.0f32, 0.0f32),
642            Vec3::new(0.0f32, 0.0f32, 1.0f32),
643        );
644        let mut w = BitWriter::new();
645        m.pack(&mut w).unwrap();
646        let buf = w.finish();
647        let mut r = BitReader::new(&buf);
648        let m2 = Mat3::<f32>::unpack(&mut r).unwrap();
649        assert_eq!(m, m2);
650    }
651
652    #[test]
653    fn mat4_pack_unpack() {
654        let m = Mat4::new(
655            Vec4::new(1.0f32, 0.0f32, 0.0f32, 0.0f32),
656            Vec4::new(0.0f32, 1.0f32, 0.0f32, 0.0f32),
657            Vec4::new(0.0f32, 0.0f32, 1.0f32, 0.0f32),
658            Vec4::new(0.0f32, 0.0f32, 0.0f32, 1.0f32),
659        );
660        let mut w = BitWriter::new();
661        m.pack(&mut w).unwrap();
662        let buf = w.finish();
663        let mut r = BitReader::new(&buf);
664        let m2 = Mat4::<f32>::unpack(&mut r).unwrap();
665        assert_eq!(m, m2);
666    }
667
668    #[test]
669    fn vec2_int_pack_unpack() {
670        let v = Vec2::new(10i32, 20i32);
671        let mut w = BitWriter::new();
672        v.pack(&mut w).unwrap();
673        let buf = w.finish();
674        let mut r = BitReader::new(&buf);
675        let v2 = Vec2::<i32>::unpack(&mut r).unwrap();
676        assert_eq!(v, v2);
677    }
678
679    #[test]
680    fn vec3_int_pack_unpack() {
681        let v = Vec3::new(1i16, 2i16, 3i16);
682        let mut w = BitWriter::new();
683        v.pack(&mut w).unwrap();
684        let buf = w.finish();
685        let mut r = BitReader::new(&buf);
686        let v2 = Vec3::<i16>::unpack(&mut r).unwrap();
687        assert_eq!(v, v2);
688    }
689}