docs(math): added more documentation for bezier, matrix, noise, point, polynomial, quaternion and vector

This commit is contained in:
lisk77 2025-08-14 09:27:07 +02:00
parent 30c6327997
commit 5f97d3a881
8 changed files with 399 additions and 239 deletions

View file

@ -1,11 +1,13 @@
use crate::{InnerSpace, Point};
/// Representation of a Bezier curve of degree n in any (2-4) dimensions.
pub struct Bezier<V: InnerSpace> {
points: Vec<V>,
degree: usize,
}
impl<V: InnerSpace + Clone> Bezier<V> {
/// Creates a new Bezier curve with the given control points.
pub fn new(points: Vec<V>) -> Self {
let degree = points.len() - 1;

View file

@ -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 noise;
pub mod polynomial;
pub mod interpolation;
pub mod matrix;
pub mod noise;
pub mod point;
pub mod polynomial;
pub mod quaternion;
pub mod vector;

View file

@ -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<f32> {
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<v2> {
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<v2> {
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<f32> {
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<v3> {
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<v3> {
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<f32> {
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<v4> {
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<v4> {
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,

View file

@ -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<f32>`. Size of the vector is `width * height`.
pub fn generate(&self) -> Vec<f32> {
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<f32>`.
pub fn generate_with_octaves(&self, octaves: u32, persistence: f64) -> Vec<f32> {
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);

View file

@ -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
}

View file

@ -1,129 +1,152 @@
use std::ops::*;
/// Representation of a polynomial of degree `n`.
pub struct Polynomial {
coefficients: Vec<f32>,
degree: usize
coefficients: Vec<f32>,
degree: usize,
}
impl Polynomial {
pub fn new(coefficients: Vec<f32>) -> Self {
let degree = coefficients.len() - 1;
Self {
coefficients,
degree
}
}
/// Creates a new polynomial from a list of coefficients.
pub fn new(coefficients: Vec<f32>) -> 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<String> = 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(" + "))
}
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let terms: Vec<String> = 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(" + "))
}
}

View file

@ -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<Quat> 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<Quat> 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<f32> 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<f32> 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<Quat> 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<Quat> 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<f32> 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<f32> for Quat {
type Output = Quat;
type Output = Quat;
fn div(self, scalar: f32) -> Quat {
Quat {
s: self.s/scalar,
v: self.v/scalar,
}
}
fn div(self, scalar: f32) -> Quat {
Quat {
s: self.s / scalar,
v: self.v / scalar,
}
}
}

View file

@ -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<v2> 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<v3> 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<v3> 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;
}