From 5f97d3a881b4b2f6115688241de276ffc7355b83 Mon Sep 17 00:00:00 2001 From: lisk77 Date: Thu, 14 Aug 2025 09:27:07 +0200 Subject: [PATCH] docs(math): added more documentation for bezier, matrix, noise, point, polynomial, quaternion and vector --- crates/comet_math/src/bezier.rs | 2 + crates/comet_math/src/lib.rs | 21 +-- crates/comet_math/src/matrix.rs | 37 +++++ crates/comet_math/src/noise.rs | 40 +++-- crates/comet_math/src/point.rs | 13 +- crates/comet_math/src/polynomial.rs | 225 +++++++++++++++------------- crates/comet_math/src/quaternion.rs | 216 +++++++++++++------------- crates/comet_math/src/vector.rs | 84 ++++++++++- 8 files changed, 399 insertions(+), 239 deletions(-) diff --git a/crates/comet_math/src/bezier.rs b/crates/comet_math/src/bezier.rs index 6ca3ee3..89458c6 100644 --- a/crates/comet_math/src/bezier.rs +++ b/crates/comet_math/src/bezier.rs @@ -1,11 +1,13 @@ use crate::{InnerSpace, Point}; +/// Representation of a Bezier curve of degree n in any (2-4) dimensions. pub struct Bezier { points: Vec, degree: usize, } impl Bezier { + /// Creates a new Bezier curve with the given control points. pub fn new(points: Vec) -> Self { let degree = points.len() - 1; diff --git a/crates/comet_math/src/lib.rs b/crates/comet_math/src/lib.rs index be7742f..0a678ee 100644 --- a/crates/comet_math/src/lib.rs +++ b/crates/comet_math/src/lib.rs @@ -1,17 +1,20 @@ -pub use point::*; -pub use vector::*; -pub use matrix::*; +//! This crate provides a set of mathematical utilities for game development. +//! It includes definitions for points, vectors, matrices, quaternions, bezier curves, easing functions, noise generation, polynomials, and interpolation utilities. + pub use bezier::*; pub use easings::*; -pub use polynomial::*; pub use interpolation::*; +pub use matrix::*; +pub use point::*; +pub use polynomial::*; +pub use vector::*; -pub mod point; -pub mod vector; -pub mod matrix; -pub mod quaternion; pub mod bezier; pub mod easings; +pub mod interpolation; +pub mod matrix; pub mod noise; +pub mod point; pub mod polynomial; -pub mod interpolation; \ No newline at end of file +pub mod quaternion; +pub mod vector; diff --git a/crates/comet_math/src/matrix.rs b/crates/comet_math/src/matrix.rs index a7c2972..4a9c501 100644 --- a/crates/comet_math/src/matrix.rs +++ b/crates/comet_math/src/matrix.rs @@ -9,6 +9,7 @@ trait LinearTransformation { // # MATRIX 2D # // ################################################## +/// Representation of a 2x2 matrix. #[repr(C)] #[derive(Debug, PartialEq)] pub struct m2 { @@ -19,6 +20,7 @@ pub struct m2 { } impl m2 { + /// The zero matrix. pub const ZERO: Self = Self { x00: 0.0, x01: 0.0, @@ -26,6 +28,7 @@ impl m2 { x11: 0.0, }; + /// The identity matrix. pub const IDENTITY: Self = Self { x00: 1.0, x01: 0.0, @@ -33,10 +36,12 @@ impl m2 { x11: 1.0, }; + /// Creates a new 2x2 matrix with the given elements. pub fn new(x00: f32, x01: f32, x10: f32, x11: f32) -> Self { Self { x00, x01, x10, x11 } } + /// Creates a new 2x2 matrix with the given vectors as its columns. pub fn from_cols(col1: v2, col2: v2) -> Self { Self { x00: col1.x(), @@ -46,6 +51,7 @@ impl m2 { } } + /// Creates a new 2x2 matrix with the given vectors as its rows. pub fn from_rows(row1: v2, row2: v2) -> Self { Self { x00: row1.x(), @@ -55,6 +61,7 @@ impl m2 { } } + /// Gets the element at the specified row and column. pub fn get(&self, row: usize, col: usize) -> Option { match (row, col) { (0, 0) => Some(self.x00), @@ -65,6 +72,7 @@ impl m2 { } } + /// Sets the element at the specified row and column. pub fn set(&mut self, row: usize, col: usize, value: f32) { match (row, col) { (0, 0) => self.x00 = value, @@ -75,6 +83,7 @@ impl m2 { } } + /// Gets the entire column at the specified index. pub fn col(&self, index: usize) -> Option { match index { 0 => Some(v2::new(self.x00, self.x01)), @@ -83,6 +92,7 @@ impl m2 { } } + /// Gets the entire row at the specified index. pub fn row(&self, index: usize) -> Option { match index { 0 => Some(v2::new(self.x00, self.x10)), @@ -91,6 +101,7 @@ impl m2 { } } + /// Returns the transpose of the matrix. pub fn transpose(&self) -> Self { Self { x00: self.x00, @@ -100,6 +111,7 @@ impl m2 { } } + /// Returns a matrix with the same elements as the original matrix but in homogeneous form. pub fn to_homogeneous(&self) -> m3 { m3::new( self.x00, self.x01, 0.0, self.x10, self.x11, 0.0, 0.0, 0.0, 1.0, @@ -193,6 +205,7 @@ impl Into<[[f32; 2]; 2]> for m2 { // # MATRIX 3D # // ################################################## +/// Representation of a 3x3 matrix. #[repr(C)] #[derive(Debug, PartialEq)] pub struct m3 { @@ -208,6 +221,7 @@ pub struct m3 { } impl m3 { + /// The zero matrix. pub const ZERO: Self = Self { x00: 0.0, x01: 0.0, @@ -220,6 +234,7 @@ impl m3 { x22: 0.0, }; + /// The identity matrix. pub const IDENTITY: Self = Self { x00: 1.0, x01: 0.0, @@ -232,6 +247,7 @@ impl m3 { x22: 1.0, }; + /// Creates a new 3x3 matrix with the given elements. pub fn new( x00: f32, x01: f32, @@ -256,6 +272,7 @@ impl m3 { } } + /// Creates a new 3x3 matrix from the given columns. pub fn from_cols(col1: v3, col2: v3, col3: v3) -> Self { Self { x00: col1.x(), @@ -270,6 +287,7 @@ impl m3 { } } + /// Creates a new 3x3 matrix from the given rows. pub fn from_rows(row1: v3, row2: v3, row3: v3) -> Self { Self { x00: row1.x(), @@ -284,6 +302,7 @@ impl m3 { } } + /// Gets the element at the given row and column. pub fn get(&self, row: usize, col: usize) -> Option { match (row, col) { (0, 0) => Some(self.x00), @@ -299,6 +318,7 @@ impl m3 { } } + /// Sets the element at the given row and column. pub fn set(&mut self, row: usize, col: usize, value: f32) { match (row, col) { (0, 0) => self.x00 = value, @@ -314,6 +334,7 @@ impl m3 { } } + /// Gets the entire column at the given index. pub fn col(&self, index: usize) -> Option { match index { 0 => Some(v3::new(self.x00, self.x01, self.x02)), @@ -323,6 +344,7 @@ impl m3 { } } + /// Gets the entire row at the given index. pub fn row(&self, index: usize) -> Option { match index { 0 => Some(v3::new(self.x00, self.x10, self.x20)), @@ -332,6 +354,7 @@ impl m3 { } } + /// Returns the transpose of the matrix. pub fn transpose(&self) -> Self { Self { x00: self.x00, @@ -346,6 +369,7 @@ impl m3 { } } + /// Returns a matrix with the same elements as the original matrix but in homogeneous form. pub fn to_homogeneous(&self) -> m4 { m4::new( self.x00, self.x01, self.x02, 0.0, self.x10, self.x11, self.x12, 0.0, self.x20, @@ -470,6 +494,7 @@ impl Into<[[f32; 3]; 3]> for m3 { // # MATRIX 4D # // ################################################## +/// Representation of a 4x4 matrix. #[repr(C)] #[derive(Debug, PartialEq)] pub struct m4 { @@ -492,6 +517,7 @@ pub struct m4 { } impl m4 { + /// The zero matrix. pub const ZERO: Self = Self { x00: 0.0, x01: 0.0, @@ -511,6 +537,7 @@ impl m4 { x33: 0.0, }; + /// The identity matrix. pub const IDENTITY: Self = Self { x00: 1.0, x01: 0.0, @@ -530,6 +557,7 @@ impl m4 { x33: 1.0, }; + /// The OpenGL conversion matrix. pub const OPENGL_CONV: Self = Self { x00: 1.0, x01: 0.0, @@ -549,6 +577,7 @@ impl m4 { x33: 1.0, }; + /// Creates a new matrix with the given elements. pub fn new( x00: f32, x01: f32, @@ -587,6 +616,7 @@ impl m4 { } } + /// Creates a new matrix from the given columns. pub fn from_cols(col1: v4, col2: v4, col3: v4, col4: v4) -> Self { Self { x00: col1.x(), @@ -608,6 +638,7 @@ impl m4 { } } + /// Creates a new matrix from the given rows. pub fn from_rows(row1: v4, row2: v4, row3: v4, row4: v4) -> Self { Self { x00: row1.x(), @@ -629,6 +660,7 @@ impl m4 { } } + /// Gets the element at the given row and column. pub fn get(&self, row: usize, col: usize) -> Option { match (row, col) { (0, 0) => Some(self.x00), @@ -651,6 +683,7 @@ impl m4 { } } + /// Sets the element at the given row and column. pub fn set(&mut self, row: usize, col: usize, value: f32) { match (row, col) { (0, 0) => self.x00 = value, @@ -673,6 +706,7 @@ impl m4 { } } + /// Gets the entire column at the given index. pub fn col(&self, index: usize) -> Option { match index { 0 => Some(v4::new(self.x00, self.x01, self.x02, self.x03)), @@ -683,6 +717,7 @@ impl m4 { } } + /// Gets the entire row at the given index. pub fn row(&self, index: usize) -> Option { match index { 0 => Some(v4::new(self.x00, self.x10, self.x20, self.x30)), @@ -693,6 +728,7 @@ impl m4 { } } + /// Returns the transpose of the matrix. pub fn transpose(&self) -> Self { Self { x00: self.x00, @@ -714,6 +750,7 @@ impl m4 { } } + /// Generates the orthographic projection matrix. pub fn orthographic_projection( left: f32, right: f32, diff --git a/crates/comet_math/src/noise.rs b/crates/comet_math/src/noise.rs index f8107ca..f6ddbea 100644 --- a/crates/comet_math/src/noise.rs +++ b/crates/comet_math/src/noise.rs @@ -32,26 +32,30 @@ pub trait NoiseGenerator { fn generate_image(&self) -> DynamicImage; } +/// White noise generator. pub struct WhiteNoise { size: (usize, usize), } impl WhiteNoise { - /// Creates a white noise generator ideal for multiple uses. + /// Creates a white noise generator with the given parameters. pub fn new(width: usize, height: usize) -> Self { Self { size: (width, height), } } + /// Sets the width of the noise image. pub fn set_width(&mut self, width: usize) { self.size.0 = width; } + /// Sets the height of the noise image. pub fn set_height(&mut self, height: usize) { self.size.1 = height; } + /// Sets the size of the noise image. pub fn set_size(&mut self, width: usize, height: usize) { self.size = (width, height); } @@ -113,6 +117,7 @@ impl NoiseGenerator for WhiteNoise { } } +/// Perlin noise generator. pub struct PerlinNoise { size: (usize, usize), frequency: f64, @@ -120,6 +125,7 @@ pub struct PerlinNoise { } impl PerlinNoise { + /// Create a new Perlin noise generator with the given parameters. pub fn new(width: usize, height: usize, frequency: f64, seed: u32) -> Self { Self { size: (width, height), @@ -128,22 +134,27 @@ impl PerlinNoise { } } + /// Set the width of the noise image. pub fn set_width(&mut self, width: usize) { self.size.0 = width; } + /// Set the height of the noise image. pub fn set_height(&mut self, height: usize) { self.size.1 = height; } + /// Set the size of the noise image. pub fn set_size(&mut self, width: usize, height: usize) { self.size = (width, height); } + /// Set the frequency of the noise. pub fn set_frequency(&mut self, frequency: f64) { self.frequency = frequency; } + /// Set the seed for the random number generator. pub fn set_seed(&mut self, seed: u32) { self.seed = seed; } @@ -169,7 +180,7 @@ impl PerlinNoise { let mut noise = vec![0.0; self.size.0 * self.size.1]; let mut amplitude = 1.0; let mut frequency = self.frequency; - let mut max_value = 0.0; // Used for normalization + let mut max_value = 0.0; for _ in 0..octaves { for y in 0..self.size.1 { @@ -181,11 +192,10 @@ impl PerlinNoise { } } max_value += amplitude; - amplitude *= persistence; // Reduce amplitude for next octave - frequency *= 2.0; // Double frequency for next octave + amplitude *= persistence; + frequency *= 2.0; } - // Normalize the noise to the range [0, 1] noise .iter_mut() .for_each(|value| *value /= max_value as f32); @@ -250,6 +260,7 @@ impl PerlinNoise { } } +/// Value noise generator. pub struct ValueNoise { size: (usize, usize), frequency: f64, @@ -257,6 +268,7 @@ pub struct ValueNoise { } impl ValueNoise { + /// Create a new Perlin noise generator with the given parameters. pub fn new(width: usize, height: usize, frequency: f64, seed: u32) -> Self { Self { size: (width, height), @@ -290,12 +302,12 @@ impl ValueNoise { ) } + /// Generates value noise as a `Vec`. Size of the vector is `width * height`. pub fn generate(&self) -> Vec { let mut noise = Vec::with_capacity(self.size.0 * self.size.1); let mut max_amplitude = 0.0; let mut amplitude = 0.5; - // Calculate max amplitude for normalization for _ in 0..4 { max_amplitude += amplitude; amplitude *= 0.5; @@ -311,17 +323,9 @@ impl ValueNoise { let mut f = 0.0; let mut amplitude = 0.5; - /*for _ in 0..4 { // 4 octaves*/ f += amplitude * self.noise(uv); - - // Double frequency for next octave uv = (uv.0 * 2.0, uv.1 * 2.0); - - // Reduce amplitude (persistence) amplitude *= 0.5; - /*}*/ - - // Normalize and convert to [0, 1] f = ((f / max_amplitude) + 1.0) * 0.5; noise.push(f); @@ -331,12 +335,12 @@ impl ValueNoise { noise } + /// Generates value noise with multiple octaves as a `Vec`. pub fn generate_with_octaves(&self, octaves: u32, persistence: f64) -> Vec { let mut noise = Vec::with_capacity(self.size.0 * self.size.1); let mut max_amplitude = 0.0; let mut amplitude = 1.0; - // Calculate max amplitude for normalization for _ in 0..octaves { max_amplitude += amplitude; amplitude *= persistence; @@ -344,7 +348,6 @@ impl ValueNoise { for y in 0..self.size.1 { for x in 0..self.size.0 { - // Convert to UV space and scale by frequency let mut uv = ( x as f32 / self.size.0 as f32 * self.frequency as f32, y as f32 / self.size.1 as f32 * self.frequency as f32, @@ -355,15 +358,10 @@ impl ValueNoise { for _ in 0..octaves { f += amplitude * self.noise(uv); - - // Double frequency for next octave uv = (uv.0 * 2.0, uv.1 * 2.0); - - // Reduce amplitude (persistence) amplitude *= persistence as f32; } - // Normalize and convert to [0, 1] f = ((f / max_amplitude as f32) + 1.0) * 0.5; noise.push(f); diff --git a/crates/comet_math/src/point.rs b/crates/comet_math/src/point.rs index b90943c..51ef279 100644 --- a/crates/comet_math/src/point.rs +++ b/crates/comet_math/src/point.rs @@ -1,5 +1,3 @@ -use rand::seq::index::IndexVecIntoIter; - use crate::vector::{v2, v3}; use crate::InnerSpace; @@ -8,6 +6,7 @@ pub trait Point { fn to_vec(&self) -> impl InnerSpace; } +/// Representation of a 2D point. #[derive(Debug, Clone, Copy, PartialEq)] pub struct p2 { x: f32, @@ -15,23 +14,28 @@ pub struct p2 { } impl p2 { + /// Creates a new 2D point with the given elements. pub fn new(x: f32, y: f32) -> Self { p2 { x, y } } + /// Creates a new 2D point from a 2D vector. pub fn from_vec(v: v2) -> Self { Self { x: v.x(), y: v.y() } } + /// Returns the x-component of the point. pub fn x(&self) -> f32 { self.x } + /// Returns the y-component of the point. pub fn y(&self) -> f32 { self.y } } +/// Representation of a 3D point. #[derive(Debug, Clone, Copy, PartialEq)] pub struct p3 { x: f32, @@ -40,10 +44,12 @@ pub struct p3 { } impl p3 { + /// Creates a new 3D point with the given elements. pub fn new(x: f32, y: f32, z: f32) -> Self { p3 { x, y, z } } + /// Creates a new 3D point from a 3D vector. pub fn from_vec(v: v3) -> Self { Self { x: v.x(), @@ -52,14 +58,17 @@ impl p3 { } } + /// Returns the x-component of the point. pub fn x(&self) -> f32 { self.x } + /// Returns the y-component of the point. pub fn y(&self) -> f32 { self.y } + /// Returns the z-component of the point. pub fn z(&self) -> f32 { self.z } diff --git a/crates/comet_math/src/polynomial.rs b/crates/comet_math/src/polynomial.rs index d78df45..eaf1f09 100644 --- a/crates/comet_math/src/polynomial.rs +++ b/crates/comet_math/src/polynomial.rs @@ -1,129 +1,152 @@ use std::ops::*; +/// Representation of a polynomial of degree `n`. pub struct Polynomial { - coefficients: Vec, - degree: usize + coefficients: Vec, + degree: usize, } impl Polynomial { - pub fn new(coefficients: Vec) -> Self { - let degree = coefficients.len() - 1; - Self { - coefficients, - degree - } - } + /// Creates a new polynomial from a list of coefficients. + pub fn new(coefficients: Vec) -> Self { + let degree = coefficients.len() - 1; + Self { + coefficients, + degree, + } + } - pub fn evaluate(&self, x: f32) -> f32 { - let mut result = 0.0; - for c in &self.coefficients { - result = result * x + c; - } - result - } + /// Evaluates the polynomial at a given point. + pub fn evaluate(&self, x: f32) -> f32 { + let mut result = 0.0; + for c in &self.coefficients { + result = result * x + c; + } + result + } - pub fn differentiate(&self) -> Self { - let mut new_coefficients = Vec::new(); - for (i, &c) in self.coefficients.iter().enumerate() { - if i != 0 { - new_coefficients.push(c * i as f32); - } - } - Self::new(new_coefficients) - } + /// Differentiates the polynomial. + pub fn differentiate(&self) -> Self { + let mut new_coefficients = Vec::new(); + for (i, &c) in self.coefficients.iter().enumerate() { + if i != 0 { + new_coefficients.push(c * i as f32); + } + } + Self::new(new_coefficients) + } - pub fn integrate(&self) -> Self { - let mut new_coefficients = Vec::new(); - new_coefficients.push(0.0); - for (i, &c) in self.coefficients.iter().enumerate() { - new_coefficients.push(c / (i + 1) as f32); - } - Self::new(new_coefficients) - } + /// Integrates the polynomial. + pub fn integrate(&self) -> Self { + let mut new_coefficients = Vec::new(); + new_coefficients.push(0.0); + for (i, &c) in self.coefficients.iter().enumerate() { + new_coefficients.push(c / (i + 1) as f32); + } + Self::new(new_coefficients) + } } impl Add for Polynomial { - type Output = Self; + type Output = Self; - fn add(self, other: Self) -> Self { - let mut new_coefficients = Vec::new(); - let mut i = 0; - while i < self.coefficients.len() || i < other.coefficients.len() { - let a = if i < self.coefficients.len() { self.coefficients[i] } else { 0.0 }; - let b = if i < other.coefficients.len() { other.coefficients[i] } else { 0.0 }; - new_coefficients.push(a + b); - i += 1; - } - Self::new(new_coefficients) - } + fn add(self, other: Self) -> Self { + let mut new_coefficients = Vec::new(); + let mut i = 0; + while i < self.coefficients.len() || i < other.coefficients.len() { + let a = if i < self.coefficients.len() { + self.coefficients[i] + } else { + 0.0 + }; + let b = if i < other.coefficients.len() { + other.coefficients[i] + } else { + 0.0 + }; + new_coefficients.push(a + b); + i += 1; + } + Self::new(new_coefficients) + } } impl Sub for Polynomial { - type Output = Self; + type Output = Self; - fn sub(self, other: Self) -> Self { - let mut new_coefficients = Vec::new(); - let mut i = 0; - while i < self.coefficients.len() || i < other.coefficients.len() { - let a = if i < self.coefficients.len() { self.coefficients[i] } else { 0.0 }; - let b = if i < other.coefficients.len() { other.coefficients[i] } else { 0.0 }; - new_coefficients.push(a - b); - i += 1; - } - Self::new(new_coefficients) - } + fn sub(self, other: Self) -> Self { + let mut new_coefficients = Vec::new(); + let mut i = 0; + while i < self.coefficients.len() || i < other.coefficients.len() { + let a = if i < self.coefficients.len() { + self.coefficients[i] + } else { + 0.0 + }; + let b = if i < other.coefficients.len() { + other.coefficients[i] + } else { + 0.0 + }; + new_coefficients.push(a - b); + i += 1; + } + Self::new(new_coefficients) + } } impl Mul for Polynomial { - type Output = Self; + type Output = Self; - fn mul(self, other: Self) -> Self { - let mut new_coefficients = vec![0.0; self.degree + other.degree + 1]; - for (i, &a) in self.coefficients.iter().enumerate() { - for (j, &b) in other.coefficients.iter().enumerate() { - new_coefficients[i + j] += a * b; - } - } - Self::new(new_coefficients) - } + fn mul(self, other: Self) -> Self { + let mut new_coefficients = vec![0.0; self.degree + other.degree + 1]; + for (i, &a) in self.coefficients.iter().enumerate() { + for (j, &b) in other.coefficients.iter().enumerate() { + new_coefficients[i + j] += a * b; + } + } + Self::new(new_coefficients) + } } impl Div for Polynomial { - type Output = Self; + type Output = Self; - fn div(self, other: Self) -> Self { - let mut new_coefficients = vec![0.0; self.degree - other.degree + 1]; - let mut dividend = self.coefficients.clone(); - let divisor = other.coefficients.clone(); - while dividend.len() >= divisor.len() { - let mut quotient = vec![0.0; dividend.len() - divisor.len() + 1]; - let mut i = dividend.len() - divisor.len(); - quotient[i] = dividend.last().unwrap() / divisor.last().unwrap(); - for (j, &d) in divisor.iter().enumerate() { - dividend[i + j] -= quotient[i] * d; - } - new_coefficients[i] = quotient[i]; - dividend.pop(); - } - Self::new(new_coefficients) - } + fn div(self, other: Self) -> Self { + let mut new_coefficients = vec![0.0; self.degree - other.degree + 1]; + let mut dividend = self.coefficients.clone(); + let divisor = other.coefficients.clone(); + while dividend.len() >= divisor.len() { + let mut quotient = vec![0.0; dividend.len() - divisor.len() + 1]; + let mut i = dividend.len() - divisor.len(); + quotient[i] = dividend.last().unwrap() / divisor.last().unwrap(); + for (j, &d) in divisor.iter().enumerate() { + dividend[i + j] -= quotient[i] * d; + } + new_coefficients[i] = quotient[i]; + dividend.pop(); + } + Self::new(new_coefficients) + } } impl std::fmt::Display for Polynomial { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let terms: Vec = self.coefficients.iter() - .enumerate() - .filter(|(_, &c)| c != 0.0) - .map(|(i, &c)| { - if i == 0 { - format!("{}", c) - } else if i == 1 { - format!("{}x", c) - } else { - format!("{}x^{}", c, i) - } - }) - .collect(); - write!(f, "{}", terms.join(" + ")) - } -} \ No newline at end of file + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let terms: Vec = self + .coefficients + .iter() + .enumerate() + .filter(|(_, &c)| c != 0.0) + .map(|(i, &c)| { + if i == 0 { + format!("{}", c) + } else if i == 1 { + format!("{}x", c) + } else { + format!("{}x^{}", c, i) + } + }) + .collect(); + write!(f, "{}", terms.join(" + ")) + } +} diff --git a/crates/comet_math/src/quaternion.rs b/crates/comet_math/src/quaternion.rs index 132aa94..1183b9c 100644 --- a/crates/comet_math/src/quaternion.rs +++ b/crates/comet_math/src/quaternion.rs @@ -1,149 +1,161 @@ -use std::ops::*; -use std::ops::Mul; use crate::vector::v3; +use std::ops::Mul; +use std::ops::*; /// Representation of a quaternion in scalar/vector form #[derive(Debug, Clone, Copy, PartialEq)] pub struct Quat { - pub s: f32, - pub v: v3, + pub s: f32, + pub v: v3, } impl Quat { - pub const fn zero() -> Self { - Self { - s: 0.0, - v: v3 { - x: 0.0, - y: 0.0, - z: 0.0, - }, - } - } - pub const fn new(s: f32, v: v3) -> Self { - Self { s, v } - } + /// The zero quaternion. + const ZERO: Self = Self { + s: 0.0, + v: v3 { + x: 0.0, + y: 0.0, + z: 0.0, + }, + }; - pub fn conjugate(&self) -> Self { - Self { - s: self.s, - v: self.v * (-1.0), - } - } + /// Creates a new quaternion from a scalar and a vector. + pub const fn new(s: f32, v: v3) -> Self { + Self { s, v } + } - pub fn normalize(&self) -> Self { - let inverse_squareroot = 1.0/(self.s*self.s + self.v.x*self.v.x + self.v.y*self.v.y + self.v.z*self.v.z).sqrt(); - Self::new(self.s*inverse_squareroot, self.v*inverse_squareroot) - } + /// Returns the conjugate of the quaternion. + pub fn conjugate(&self) -> Self { + Self { + s: self.s, + v: self.v * (-1.0), + } + } - pub fn into_vec(&self) -> v3 { - v3 { - x: self.v.x, - y: self.v.y, - z: self.v.z, - } - } + /// Returns the normalized version of the quaternion. + pub fn normalize(&self) -> Self { + let inverse_squareroot = 1.0 + / (self.s * self.s + self.v.x * self.v.x + self.v.y * self.v.y + self.v.z * self.v.z) + .sqrt(); + Self::new(self.s * inverse_squareroot, self.v * inverse_squareroot) + } + + /// Converts the quaternion into a vector. + pub fn into_vec(&self) -> v3 { + v3 { + x: self.v.x, + y: self.v.y, + z: self.v.z, + } + } } impl Add for Quat { - type Output = Quat; + type Output = Quat; - fn add(self, other: Quat) -> Quat { - Quat { - s: self.s + other.s, - v: self.v + other.v, - } - } + fn add(self, other: Quat) -> Quat { + Quat { + s: self.s + other.s, + v: self.v + other.v, + } + } } impl Sub for Quat { - type Output = Quat; + type Output = Quat; - fn sub(self, other: Quat) -> Quat { - Quat { - s: self.s - other.s, - v: self.v - other.v, - } - } + fn sub(self, other: Quat) -> Quat { + Quat { + s: self.s - other.s, + v: self.v - other.v, + } + } } impl Neg for Quat { - type Output = Quat; + type Output = Quat; - fn neg(self) -> Quat { - Quat { - s: -self.s, - v: -self.v, - } - } + fn neg(self) -> Quat { + Quat { + s: -self.s, + v: -self.v, + } + } } impl Add for Quat { - type Output = Quat; + type Output = Quat; - fn add(self, scalar: f32) -> Quat { - Quat { - s: self.s + scalar, - v: self.v, - } - } + fn add(self, scalar: f32) -> Quat { + Quat { + s: self.s + scalar, + v: self.v, + } + } } impl Sub for Quat { - type Output = Quat; + type Output = Quat; - fn sub(self, scalar: f32) -> Quat { - Quat { - s: self.s - scalar, - v: self.v, - } - } + fn sub(self, scalar: f32) -> Quat { + Quat { + s: self.s - scalar, + v: self.v, + } + } } impl Mul for f32 { - type Output = Quat; + type Output = Quat; - fn mul(self, quat: Quat) -> Quat { - Quat { - s: self*quat.s, - v: self*quat.v, - } - } + fn mul(self, quat: Quat) -> Quat { + Quat { + s: self * quat.s, + v: self * quat.v, + } + } } impl Mul for Quat { - type Output = Quat; + type Output = Quat; - fn mul(self, other: Quat) -> Quat { - Quat { - s: self.s*other.s - self.v.x*other.v.x - self.v.y*other.v.y - self.v.z*other.v.z, - v: v3 { - x: self.s*other.v.x + self.v.x*other.s + self.v.y*other.v.z - self.v.z*other.v.y, - y: self.s*other.v.y + self.v.y*other.s + self.v.z*other.v.x - self.v.x*other.v.z, - z: self.s*other.v.z + self.v.z*other.s + self.v.x*other.v.y - self.v.y*other.v.x, - } - } - } + fn mul(self, other: Quat) -> Quat { + Quat { + s: self.s * other.s + - self.v.x * other.v.x + - self.v.y * other.v.y + - self.v.z * other.v.z, + v: v3 { + x: self.s * other.v.x + self.v.x * other.s + self.v.y * other.v.z + - self.v.z * other.v.y, + y: self.s * other.v.y + self.v.y * other.s + self.v.z * other.v.x + - self.v.x * other.v.z, + z: self.s * other.v.z + self.v.z * other.s + self.v.x * other.v.y + - self.v.y * other.v.x, + }, + } + } } impl Mul for Quat { - type Output = Quat; + type Output = Quat; - fn mul(self, scalar: f32) -> Quat { - Quat { - s: self.s*scalar, - v: self.v*scalar, - } - } + fn mul(self, scalar: f32) -> Quat { + Quat { + s: self.s * scalar, + v: self.v * scalar, + } + } } impl Div for Quat { - type Output = Quat; + type Output = Quat; - fn div(self, scalar: f32) -> Quat { - Quat { - s: self.s/scalar, - v: self.v/scalar, - } - } -} \ No newline at end of file + fn div(self, scalar: f32) -> Quat { + Quat { + s: self.s / scalar, + v: self.v / scalar, + } + } +} diff --git a/crates/comet_math/src/vector.rs b/crates/comet_math/src/vector.rs index f05c694..011e788 100644 --- a/crates/comet_math/src/vector.rs +++ b/crates/comet_math/src/vector.rs @@ -29,7 +29,7 @@ pub trait InnerSpace: // # VECTOR 2D # // ################################################## -/// Representation of a 2D Vector +/// Representation of a 2D vector #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -40,30 +40,39 @@ pub struct v2 { } impl v2 { + /// The unit vector along the x-axis. pub const X: v2 = v2 { x: 1.0, y: 0.0 }; + /// The unit vector along the y-axis. pub const Y: v2 = v2 { x: 0.0, y: 1.0 }; + /// The zero vector. pub const ZERO: v2 = v2 { x: 0.0, y: 0.0 }; + /// Creates a new vector with the given components. pub const fn new(x: f32, y: f32) -> Self { v2 { x, y } } + /// Creates a new vector from a point. pub fn from_point(p: p2) -> Self { Self { x: p.x(), y: p.y() } } + /// Gets the x-component of the vector. pub fn x(&self) -> f32 { self.x } + /// Gets the y-component of the vector. pub fn y(&self) -> f32 { self.y } + /// Sets the x-component of the vector. pub fn set_x(&mut self, new_x: f32) { self.x = new_x; } + /// Sets the y-component of the vector. pub fn set_y(&mut self, new_y: f32) { self.y = new_y; } @@ -164,7 +173,7 @@ impl Into for [f32; 2] { } } -/// Representation of a 2D integer Vector +/// Representation of a 2D integer vector #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -175,14 +184,19 @@ pub struct v2i { } impl v2i { + /// The unit vector in the x direction. pub const X: v2i = v2i { x: 1, y: 0 }; + /// The unit vector in the y direction. pub const Y: v2i = v2i { x: 0, y: 1 }; + /// The zero vector. pub const ZERO: v2i = v2i { x: 0, y: 0 }; + /// Creates a new vector with the given components. pub const fn new(x: i64, y: i64) -> Self { v2i { x, y } } + /// Creates a new vector from a point. pub fn from_point(p: p2) -> Self { Self { x: p.x() as i64, @@ -190,10 +204,12 @@ impl v2i { } } + /// Creates a 2D point from the vector. pub fn as_point(&self) -> p2 { p2::new(self.x as f32, self.y as f32) } + /// Creates a integer 2D vector from a floating point 2D vector. pub fn from_vec2(v: v2) -> Self { Self { x: v.x as i64, @@ -201,6 +217,7 @@ impl v2i { } } + /// Creates a floating point 2D vector from the integer vector. pub fn as_vec2(&self) -> v2 { v2 { x: self.x as f32, @@ -208,26 +225,32 @@ impl v2i { } } + /// Gets the x component of the vector. pub fn x(&self) -> i64 { self.x } + /// Gets the y component of the vector. pub fn y(&self) -> i64 { self.y } + /// Sets the x component of the vector. pub fn set_x(&mut self, new_x: i64) { self.x = new_x; } + /// Sets the y component of the vector. pub fn set_y(&mut self, new_y: i64) { self.y = new_y; } + /// Gets the length of the vector. pub fn length(&self) -> i64 { ((self.x * self.x + self.y * self.y) as f32).sqrt() as i64 } + /// Calculates the normalized version of the vector. pub fn normalize(&self) -> Self { let factor = 1.0 / self.length() as f32; v2i { @@ -236,6 +259,8 @@ impl v2i { } } + /// Swizzles the vector components. + /// (x,y) -> (x,x) pub fn xx(&self) -> Self { Self { x: self.x, @@ -243,6 +268,8 @@ impl v2i { } } + /// Swizzles the vector components. + /// (x,y) -> (x,y) pub fn xy(&self) -> Self { Self { x: self.x, @@ -250,6 +277,8 @@ impl v2i { } } + /// Swizzles the vector components. + /// (x,y) -> (y,x) pub fn yx(&self) -> Self { Self { x: self.y, @@ -257,6 +286,8 @@ impl v2i { } } + /// Swizzles the vector components. + /// (x,y) -> (y,y) pub fn yy(&self) -> Self { Self { x: self.y, @@ -390,7 +421,7 @@ impl Into<[f32; 2]> for v2i { // # VECTOR 3D # // ################################################## -/// Representation of a 3D Vector +/// Representation of a 3D vector #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -402,31 +433,37 @@ pub struct v3 { } impl v3 { + /// The unit vector along the x-axis. pub const X: v3 = v3 { x: 1.0, y: 0.0, z: 0.0, }; + /// The unit vector along the y-axis. pub const Y: v3 = v3 { x: 0.0, y: 1.0, z: 0.0, }; + /// The unit vector along the z-axis. pub const Z: v3 = v3 { x: 0.0, y: 0.0, z: 1.0, }; + /// The zero vector. pub const ZERO: v3 = v3 { x: 0.0, y: 0.0, z: 0.0, }; + /// Creates a new vector with the given components. pub const fn new(x: f32, y: f32, z: f32) -> Self { v3 { x, y, z } } + /// Creates a new vector from a point. pub fn from_point(p: p3) -> Self { Self { x: p.x(), @@ -435,30 +472,37 @@ impl v3 { } } + /// Creates a new point from a vector. pub fn as_point(&self) -> p3 { p3::new(self.x as f32, self.y as f32, self.z as f32) } + /// Gets the x-component of the vector. pub fn x(&self) -> f32 { self.x } + /// Gets the y-component of the vector. pub fn y(&self) -> f32 { self.y } + /// Gets the z-component of the vector. pub fn z(&self) -> f32 { self.z } + /// Sets the x-component of the vector. pub fn set_x(&mut self, new_x: f32) { self.x = new_x; } + /// Sets the y-component of the vector. pub fn set_y(&mut self, new_y: f32) { self.y = new_y; } + /// Sets the z-component of the vector. pub fn set_z(&mut self, new_z: f32) { self.z = new_z; } @@ -574,6 +618,7 @@ impl Into for [f32; 3] { } } +/// Representation of a 3D integer vector #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -585,15 +630,21 @@ pub struct v3i { } impl v3i { + /// The unit vector in the x-direction. pub const X: v3i = v3i { x: 1, y: 0, z: 0 }; + /// The unit vector in the y-direction. pub const Y: v3i = v3i { x: 0, y: 1, z: 0 }; + /// The unit vector in the z-direction. pub const Z: v3i = v3i { x: 0, y: 0, z: 1 }; + /// The zero vector. pub const ZERO: v3i = v3i { x: 0, y: 0, z: 0 }; + /// Creates a new vector with the given components. pub const fn new(x: i64, y: i64, z: i64) -> Self { v3i { x, y, z } } + /// Creates a new vector from a point. pub fn from_point(p: p3) -> Self { Self { x: p.x() as i64, @@ -602,34 +653,42 @@ impl v3i { } } + /// Gets the x-component of the vector. pub fn x(&self) -> i64 { self.x } + /// Gets the y-component of the vector. pub fn y(&self) -> i64 { self.y } + /// Gets the z-component of the vector. pub fn z(&self) -> i64 { self.z } + /// Sets the x-component of the vector. pub fn set_x(&mut self, new_x: i64) { self.x = new_x; } + /// Sets the y-component of the vector. pub fn set_y(&mut self, new_y: i64) { self.y = new_y; } + /// Sets the z-component of the vector. pub fn set_z(&mut self, new_z: i64) { self.z = new_z; } + /// Calculates the length of the vector. pub fn length(&self) -> i64 { ((self.x * self.x + self.y * self.y + self.z * self.z) as f32).sqrt() as i64 } + /// Normalizes the vector. pub fn normalize(&self) -> Self { let factor = 1 / self.length(); v3i { @@ -763,7 +822,7 @@ impl From for v3i { // # VECTOR 4D # // ################################################## -/// Representation of a 4D Vector +/// Representation of a 4D vector #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -776,24 +835,31 @@ pub struct v4 { } impl v4 { + /// The unit vector along the x-axis. pub const X: v4 = v4 { x: 1.0, y: 0.0, z: 0.0, w: 0.0, }; + + /// The unit vector along the y-axis. pub const Y: v4 = v4 { x: 0.0, y: 1.0, z: 0.0, w: 0.0, }; + + /// The unit vector along the z-axis. pub const Z: v4 = v4 { x: 0.0, y: 0.0, z: 1.0, w: 0.0, }; + + /// The unit vector along the w-axis. pub const W: v4 = v4 { x: 0.0, y: 0.0, @@ -801,6 +867,7 @@ impl v4 { w: 1.0, }; + /// The zero vector. pub const ZERO: v4 = v4 { x: 0.0, y: 0.0, @@ -808,38 +875,47 @@ impl v4 { w: 0.0, }; + /// Creates a new vector with the given components. pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self { v4 { x, y, z, w } } + /// Gets the x-component of the vector. pub fn x(&self) -> f32 { self.x } + /// Gets the y-component of the vector. pub fn y(&self) -> f32 { self.y } + /// Gets the z-component of the vector. pub fn z(&self) -> f32 { self.z } + /// Gets the w-component of the vector. pub fn w(&self) -> f32 { self.w } + /// Sets the x-component of the vector. pub fn set_x(&mut self, new_x: f32) { self.x = new_x; } + /// Sets the y-component of the vector. pub fn set_y(&mut self, new_y: f32) { self.y = new_y; } + /// Sets the z-component of the vector. pub fn set_z(&mut self, new_z: f32) { self.z = new_z; } + /// Sets the w-component of the vector. pub fn set_w(&mut self, new_w: f32) { self.w = new_w; }