Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite the maths & uniform API #43

Merged
merged 15 commits into from
Feb 18, 2024
5 changes: 4 additions & 1 deletion citro3d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
glam = { version = "0.24.2", optional = true }
approx = { version = "0.5.1", optional = true }
bitflags = "1.3.2"
bytemuck = { version = "1.10.0", features = ["extern_crate_std"] }
Expand All @@ -17,9 +18,11 @@ document-features = "0.2.7"
libc = "0.2.125"

[features]
default = []
default = ["glam"]
## Enable this feature to use the `approx` crate for comparing vectors and matrices.
approx = ["dep:approx"]
## Enable for glam support in uniforms
glam = ["dep:glam"]

[dev-dependencies]
test-runner = { git = "https://github.com/rust3ds/test-runner.git" }
Expand Down
8 changes: 4 additions & 4 deletions citro3d/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ impl Instance {
/// let mtx = Matrix::identity();
/// instance.bind_vertex_uniform(idx, &mtx);
/// ```
pub fn bind_vertex_uniform(&mut self, index: uniform::Index, uniform: impl Uniform) {
uniform.bind(self, shader::Type::Vertex, index);
pub fn bind_vertex_uniform(&mut self, index: uniform::Index, uniform: impl Into<Uniform>) {
uniform.into().bind(self, shader::Type::Vertex, index);
}

/// Bind a uniform to the given `index` in the geometry shader for the next draw call.
Expand All @@ -210,8 +210,8 @@ impl Instance {
/// let mtx = Matrix::identity();
/// instance.bind_geometry_uniform(idx, &mtx);
/// ```
pub fn bind_geometry_uniform(&mut self, index: uniform::Index, uniform: impl Uniform) {
uniform.bind(self, shader::Type::Geometry, index);
pub fn bind_geometry_uniform(&mut self, index: uniform::Index, uniform: impl Into<Uniform>) {
uniform.into().bind(self, shader::Type::Geometry, index);
}

/// Retrieve the [`TexEnv`] for the given stage, initializing it first if necessary.
Expand Down
42 changes: 41 additions & 1 deletion citro3d/src/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,56 @@ mod ops;
mod projection;

pub use fvec::{FVec, FVec3, FVec4};
pub use matrix::{Matrix, Matrix3, Matrix4};
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`].
#[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);
}
}
38 changes: 38 additions & 0 deletions citro3d/src/math/fvec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@
use std::fmt;

/// A vector of `f32`s.
///
/// # Layout
/// Note that this matches the PICA layout so is actually WZYX, this means using it
/// in vertex data as an attribute it will be reversed
///
/// It is guaranteed to have the same layout as [`citro3d_sys::C3D_FVec`] in memory
#[derive(Clone, Copy)]
#[doc(alias = "C3D_FVec")]
#[repr(transparent)]
pub struct FVec<const N: usize>(pub(crate) citro3d_sys::C3D_FVec);

/// A 3-vector of `f32`s.
Expand Down Expand Up @@ -48,6 +55,11 @@ impl FVec4 {
unsafe { self.0.__bindgen_anon_1.w }
}

/// Wrap a raw [`citro3d_sys::C3D_FVec`]
pub fn from_raw(raw: citro3d_sys::C3D_FVec) -> Self {
Self(raw)
}

/// Create a new [`FVec4`] from its components.
///
/// # Example
Expand Down Expand Up @@ -243,6 +255,32 @@ impl FVec3 {
}
}

#[cfg(feature = "glam")]
impl From<glam::Vec4> for FVec4 {
fn from(value: glam::Vec4) -> Self {
Self::new(value.x, value.y, value.z, value.w)
}
}
#[cfg(feature = "glam")]
impl From<glam::Vec3> for FVec3 {
fn from(value: glam::Vec3) -> Self {
Self::new(value.x, value.y, value.z)
}
}
#[cfg(feature = "glam")]
impl From<FVec4> for glam::Vec4 {
fn from(value: FVec4) -> Self {
glam::Vec4::new(value.x(), value.y(), value.z(), value.w())
}
}

#[cfg(feature = "glam")]
impl From<FVec3> for glam::Vec3 {
fn from(value: FVec3) -> Self {
glam::Vec3::new(value.x(), value.y(), value.z())
}
}

#[cfg(test)]
mod tests {
use approx::assert_abs_diff_eq;
Expand Down
Loading
Loading