1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//! Safe wrappers for working with matrix and vector types provided by `citro3d`.

// TODO: bench FFI calls into `inline statics` generated by bindgen, vs
// reimplementing some of those calls. Many of them are pretty trivial impls

mod fvec;
mod matrix;
mod ops;
mod projection;

pub use fvec::{FVec, FVec3, FVec4};
pub use matrix::Matrix4;
pub use projection::{
    AspectRatio, ClipPlanes, CoordinateOrientation, Orthographic, Perspective, Projection,
    ScreenOrientation, StereoDisplacement,
};

/// A 4-vector of `u8`s.
///
/// # Layout
/// Uses the PICA layout of WZYX
#[doc(alias = "C3D_IVec")]
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct IVec(citro3d_sys::C3D_IVec);

impl IVec {
    pub fn new(x: u8, y: u8, z: u8, w: u8) -> Self {
        Self(unsafe { citro3d_sys::IVec_Pack(x, y, z, w) })
    }
    pub fn as_raw(&self) -> &citro3d_sys::C3D_IVec {
        &self.0
    }
    pub fn x(self) -> u8 {
        self.0 as u8
    }
    pub fn y(self) -> u8 {
        (self.0 >> 8) as u8
    }
    pub fn z(self) -> u8 {
        (self.0 >> 16) as u8
    }
    pub fn w(self) -> u8 {
        (self.0 >> 24) as u8
    }
}

/// A quaternion, internally represented the same way as [`FVec`].
#[allow(dead_code)]
#[doc(alias = "C3D_FQuat")]
pub struct FQuat(citro3d_sys::C3D_FQuat);

#[cfg(test)]
mod tests {
    use super::IVec;

    #[test]
    fn ivec_getters_work() {
        let iv = IVec::new(1, 2, 3, 4);
        assert_eq!(iv.x(), 1);
        assert_eq!(iv.y(), 2);
        assert_eq!(iv.z(), 3);
        assert_eq!(iv.w(), 4);
    }
}