Ian Chamberlain
1 year ago
4 changed files with 191 additions and 73 deletions
@ -0,0 +1,87 @@ |
|||||||
|
//! Safe wrappers for working with matrix and vector types provided by `citro3d`.
|
||||||
|
|
||||||
|
use std::mem::MaybeUninit; |
||||||
|
|
||||||
|
use crate::AspectRatio; |
||||||
|
|
||||||
|
/// A 4-vector of [`u8`]s.
|
||||||
|
pub struct IntVec(citro3d_sys::C3D_IVec); |
||||||
|
|
||||||
|
/// A 4-vector of [`f32`]s.
|
||||||
|
pub struct FloatVec(citro3d_sys::C3D_FVec); |
||||||
|
|
||||||
|
/// A quaternion, internally represented the same way as [`FVec`].
|
||||||
|
pub struct Quaternion(citro3d_sys::C3D_FQuat); |
||||||
|
|
||||||
|
/// A 4x4 row-major matrix of [`f32`]s.
|
||||||
|
pub struct Matrix(citro3d_sys::C3D_Mtx); |
||||||
|
|
||||||
|
/// Whether to use left-handed or right-handed coordinates for calculations.
|
||||||
|
#[derive(Clone, Copy, Debug)] |
||||||
|
#[non_exhaustive] // This probably is exhaustive, but just in case
|
||||||
|
pub enum CoordinateSystem { |
||||||
|
LeftHanded, |
||||||
|
RightHanded, |
||||||
|
} |
||||||
|
|
||||||
|
impl Matrix { |
||||||
|
// TODO: this could probably be generalized with something like builder or options
|
||||||
|
// pattern. Should look and see what the different citro3d implementations look like
|
||||||
|
pub fn perspective_stereo_tilt( |
||||||
|
fov_y: f32, |
||||||
|
aspect_ratio: AspectRatio, |
||||||
|
near: f32, |
||||||
|
far: f32, |
||||||
|
interocular_distance: f32, |
||||||
|
/* better name ?? */ screen_depth: f32, |
||||||
|
coordinates: CoordinateSystem, |
||||||
|
) -> Self { |
||||||
|
let mut result = MaybeUninit::uninit(); |
||||||
|
|
||||||
|
let inner = unsafe { |
||||||
|
citro3d_sys::Mtx_PerspStereoTilt( |
||||||
|
result.as_mut_ptr(), |
||||||
|
fov_y, |
||||||
|
aspect_ratio.into(), |
||||||
|
near, |
||||||
|
far, |
||||||
|
interocular_distance, |
||||||
|
screen_depth, |
||||||
|
matches!(coordinates, CoordinateSystem::LeftHanded), |
||||||
|
); |
||||||
|
|
||||||
|
result.assume_init() |
||||||
|
}; |
||||||
|
|
||||||
|
Self(inner) |
||||||
|
} |
||||||
|
|
||||||
|
pub fn perspective_tilt( |
||||||
|
fov_y: f32, |
||||||
|
aspect_ratio: AspectRatio, |
||||||
|
near: f32, |
||||||
|
far: f32, |
||||||
|
coordinates: CoordinateSystem, |
||||||
|
) -> Self { |
||||||
|
let mut result = MaybeUninit::uninit(); |
||||||
|
|
||||||
|
let inner = unsafe { |
||||||
|
citro3d_sys::Mtx_PerspTilt( |
||||||
|
result.as_mut_ptr(), |
||||||
|
fov_y, |
||||||
|
aspect_ratio.into(), |
||||||
|
near, |
||||||
|
far, |
||||||
|
matches!(coordinates, CoordinateSystem::LeftHanded), |
||||||
|
); |
||||||
|
|
||||||
|
result.assume_init() |
||||||
|
}; |
||||||
|
|
||||||
|
Self(inner) |
||||||
|
} |
||||||
|
|
||||||
|
pub(crate) fn as_raw(&self) -> *const citro3d_sys::C3D_Mtx { |
||||||
|
&self.0 |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue