initial commit

This commit is contained in:
lisk77 2024-10-26 02:15:26 +02:00
commit 6154c72b0e
55 changed files with 9481 additions and 0 deletions

View file

@ -0,0 +1,145 @@
use num_traits::Pow;
use crate::point::{Point2, Point3};
use crate::vector::{Vec2, Vec3};
use crate::utilities::{lerp2, lerp3, fac};
pub trait ParameterCurve2 {
//fn arcLen(&self) -> f32;
fn getPoint(&self, t: f32) -> Point2;
}
pub trait ParameterCurve3 {
//fn arcLen(&self) -> f32;
fn getPoint(&self, t: f32) -> Point3;
}
/// A general Bézier Curve in 2D
/// WORK IN PROGRESS: DOES NOT WORK (use cBezier2 instead)
#[repr(C)]
pub struct Bezier2 {
points: Vec<Point2>,
degree: u8
}
impl Bezier2 {
pub fn new(points: Vec<Point2>) -> Self {
let n = points.len() as u8;
Self { points: points, degree: n }
}
}
/// A general Bézier Curve in 3D
/// WORK IN PROGRESS: DOES NOT WORK (use cBezier3 instead)
#[repr(C)]
pub struct Bezier3 {
points: Vec<Point3>,
degree: u8
}
impl Bezier3 {
pub fn new(points: Vec<Point3>) -> Self {
let n = points.len() as u8;
Self { points: points, degree: n }
}
}
/// A cubic Bézier Curve in 2D
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct cBezier2 {
p0: Point2,
p1: Point2,
p2: Point2,
p3: Point2
}
impl cBezier2 {
pub fn new(p0: Point2, p1: Point2, p2: Point2, p3: Point2) -> Self {
Self { p0, p1, p2, p3 }
}
}
impl ParameterCurve2 for cBezier2 {
fn getPoint(&self, t: f32) -> Point2 {
let tSquared = t * t;
let tCubed = tSquared * t;
let vP0 = Vec2::from_point(self.p0);
let vP1 = Vec2::from_point(self.p1);
let vP2 = Vec2::from_point(self.p2);
let vP3 = Vec2::from_point(self.p3);
Point2::from_vec(
vP0 * (-tCubed + 3.0 * tSquared - 3.0 * t + 1.0 ) +
vP1 * (3.0 * tCubed - 6.0 * tSquared + 3.0 * t ) +
vP2 * (-3.0 * tCubed + 3.0 * tSquared ) +
vP3 * tCubed
)
}
}
/// A cubic Bézier Curve in 3D
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct cBezier3 {
p0: Point3,
p1: Point3,
p2: Point3,
p3: Point3
}
impl cBezier3 {
pub fn new(p0: Point3, p1: Point3, p2: Point3, p3: Point3) -> Self {
Self { p0, p1, p2, p3 }
}
}
impl ParameterCurve2 for Bezier2 {
fn getPoint(&self, t: f32) -> Point2 {
let n = self.points.len();
let mut points = self.points.clone();
for k in 1..n {
for i in 0..n - k {
points[i] = Point2::from_vec(lerp2(Vec2::from_point(points[i]), Vec2::from_point(points[i + 1]), t));
}
}
points[0]
}
}
impl ParameterCurve3 for Bezier3 {
fn getPoint(&self, t: f32) -> Point3 {
let n = self.points.len();
let mut points = self.points.clone();
for k in 1..n {
for i in 0..n - k {
points[i] = Point3::from_vec(lerp3(Vec3::from_point(points[i]), Vec3::from_point(points[i + 1]), t));
}
}
points[0]
}
}
impl ParameterCurve3 for cBezier3 {
fn getPoint(&self, t: f32) -> Point3 {
let tSquared = t * t;
let tCubed = tSquared * t;
let vP0 = Vec3::from_point(self.p0);
let vP1 = Vec3::from_point(self.p1);
let vP2 = Vec3::from_point(self.p2);
let vP3 = Vec3::from_point(self.p3);
Point3::from_vec(
vP0 * (-tCubed + 3.0 * tSquared - 3.0 * t + 1.0 ) +
vP1 * (3.0 * tCubed - 6.0 * tSquared + 3.0 * t ) +
vP2 * (-3.0 * tCubed + 3.0 * tSquared ) +
vP3 * tCubed
)
}
}

View file

@ -0,0 +1,132 @@
use crate::utilities::{PI, sin, cos, sqrt};
pub fn ease_in_sine(x: f32) -> f32 {
1.0 - cos((x * PI) / 2.0)
}
pub fn ease_out_sine(x: f32) -> f32 {
sin((x * PI) / 2.0)
}
pub fn ease_in_out_sine(x: f32) -> f32 {
-(cos(PI * x) - 1.0) / 2.0
}
pub fn ease_in_quad(x: f32) -> f32 {
x * x
}
pub fn ease_out_quad(x: f32) -> f32 {
1.0 - (1.0 - x) * (1.0 - x)
}
pub fn ease_in_out_quad(x: f32) -> f32 {
if x < 0.5 { 2.0 * x * x } else { 1.0 - (-2.0 * x + 2.0).powf(2.0) / 2.0 }
}
pub fn ease_in_cubic(x: f32) -> f32 {
x * x * x
}
pub fn ease_out_cubic(x: f32) -> f32 {
1.0 - (1.0 - x).powf(3.0)
}
pub fn ease_in_out_cubic(x: f32) -> f32 {
if x < 0.5 { 4.0 * x * x * x } else { 1.0 - (-2.0 * x + 2.0).powf(3.0) / 2.0 }
}
pub fn ease_in_quart(x: f32) -> f32 {
x * x * x * x
}
pub fn ease_out_quart(x: f32) -> f32 {
1.0 - (1.0 - x).powf(4.0)
}
pub fn ease_in_out_quart(x: f32) -> f32 {
if x < 0.5 { 8.0 * x * x * x * x } else { 1.0 - (-2.0 * x + 2.0).powf(4.0) / 2.0 }
}
pub fn ease_in_quint(x: f32) -> f32 {
x * x * x * x * x
}
pub fn ease_out_quint(x: f32) -> f32 {
1.0 - (1.0 - x).powf(5.0)
}
pub fn ease_in_out_quint(x: f32) -> f32 {
if x < 0.5 { 16.0 * x * x * x * x * x } else { 1.0 - (-2.0 * x + 2.0).powf(5.0) / 2.0 }
}
pub fn ease_in_expo(x: f32) -> f32 {
if x == 0.0 { 0.0 } else { 2.0_f32.powf(10.0 * x - 10.0) }
}
pub fn ease_out_expo(x: f32) -> f32 {
if x == 1.0 { 1.0 } else { 1.0 - 2.0_f32.powf(-10.0 * x) }
}
pub fn ease_in_out_expo(x: f32) -> f32 {
if x == 0.0 { 0.0 } else if x == 1.0 { 1.0 } else if x < 0.5 { 2.0_f32.powf(20.0 * x - 10.0) / 2.0 } else { (2.0 - 2.0_f32.powf(-20.0 * x + 10.0)) / 2.0 }
}
pub fn ease_in_circ(x: f32) -> f32 {
1.0 - sqrt(1.0 - x * x)
}
pub fn ease_out_circ(x: f32) -> f32 {
sqrt(1.0 - (x - 1.0).powf(2.0))
}
pub fn ease_in_out_circ(x: f32) -> f32 {
if x < 0.5 { sqrt(1.0 - (1.0 - 2.0 * x).powf(2.0)) / 2.0 } else { (sqrt(1.0 - (-2.0 * x + 2.0).powf(2.0)) + 1.0) / 2.0 }
}
pub fn ease_in_back(x: f32) -> f32 {
let c1 = 1.70158;
let c3 = c1 + 1.0;
c3 * x * x * x - c1 * x * x
}
pub fn ease_out_back(x: f32) -> f32 {
let c1 = 1.70158;
let c3 = c1 + 1.0;
1.0 + c3 * (x - 1.0).powf(3.0) + c1 * (x - 1.0).powf(2.0)
}
pub fn ease_in_out_back(x: f32) -> f32 {
let c1 = 1.70158;
let c2 = c1 * 1.525;
if x < 0.5 { (2.0 * x).powf(2.0) * ((c2 + 1.0) * 2.0 * x - c2) / 2.0 } else { ((2.0 * x - 2.0).powf(2.0) * ((c2 + 1.0) * (2.0 * x - 2.0) + c2) + 2.0) / 2.0 }
}
pub fn ease_in_elastic(x: f32) -> f32 {
let c4 = (2.0 * PI) / 3.0;
if x == 0.0 { 0.0 } else if x == 1.0 { 1.0 } else { -2.0_f32.powf(10.0 * x - 10.0) * sin((x * 10.0 - 10.75) * c4) }
}
pub fn ease_out_elastic(x: f32) -> f32 {
let c4 = (2.0 * PI) / 3.0;
if x == 0.0 { 0.0 } else if x == 1.0 { 1.0 } else { 2.0_f32.powf(-10.0 * x) * sin((x * 10.0 - 0.75) * c4) + 1.0 }
}
pub fn ease_in_out_elastic(x: f32) -> f32 {
let c5 = (2.0 * PI) / 4.5;
if x == 0.0 { 0.0 } else if x == 1.0 { 1.0 } else if x < 0.5 { -(2.0_f32.powf(20.0 * x - 10.0) * sin((20.0 * x - 11.125) * c5)) / 2.0 } else { (2.0_f32.powf(-20.0 * x + 10.0) * sin((20.0 * x - 11.125) * c5)) / 2.0 + 1.0 }
}
pub fn ease_in_bounce(x: f32) -> f32 {
1.0 - ease_out_bounce(1.0 - x)
}
pub fn ease_out_bounce(x: f32) -> f32 {
let n1 = 7.5625;
let d1 = 2.75;
if x < 1.0 / d1 { n1 * x * x } else if x < 2.0 / d1 { n1 * (x - 1.5 / d1) * (x - 1.5 / d1) + 0.75 } else if x < 2.5 / d1 { n1 * (x - 2.25 / d1) * (x - 2.25 / d1) + 0.9375 } else { n1 * (x - 2.625 / d1) * (x - 2.625 / d1) + 0.984375 }
}
pub fn ease_in_out_bounce(x: f32) -> f32 {
if x < 0.5 { (1.0 - ease_out_bounce(1.0 - 2.0 * x)) / 2.0 } else { (1.0 + ease_out_bounce(2.0 * x - 1.0)) / 2.0 }
}

View file

@ -0,0 +1,14 @@
pub(crate) use utilities::*;
pub use point::*;
pub use vector::*;
pub use matrix::*;
pub use bezier::*;
pub use easings::*;
mod utilities;
pub mod point;
pub mod vector;
pub mod matrix;
pub mod quaternion;
pub mod bezier;
pub mod easings;

View file

@ -0,0 +1,732 @@
use std::ops::{Add, Sub, Mul, Div};
use crate::{cross, dot, Point3};
use crate::vector::{Vec2, Vec3, Vec4};
trait LinearTransformation {
fn det(&self) -> f32;
}
// ##################################################
// # MATRIX 2D #
// ##################################################
/// Representation of a 2x2 Matrix in row major
#[repr(C)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq)]
pub struct Mat2 {
x00: f32,
x01: f32,
x10: f32,
x11: f32,
}
impl Mat2 {
pub const ZERO: Mat2 = Mat2 {
x00: 0.0, x01: 0.0,
x10: 0.0, x11: 0.0
};
pub const IDENTITY: Mat2 = Mat2 {
x00: 1.0, x01: 0.0,
x10: 0.0, x11: 1.0
};
pub const fn new(x00: f32, x01: f32, x10: f32, x11: f32) -> Self {
Self {
x00, x01,
x10, x11
}
}
pub fn from_vec(row1: Vec2, row2: Vec2) -> Self {
Self {
x00: row1.x(), x01: row1.y(),
x10: row2.x(), x11: row2.y()
}
}
pub fn get(&self, row: usize, col: usize) -> Option<f32> {
assert!(row <= 1, "This row ({}) is out of bounds! Bounds: 0..1", row);
assert!(col <= 1, "This row ({}) is out of bounds! Bounds: 0..1", col);
match (row, col) {
(0, 0) => Some(self.x00),
(0, 1) => Some(self.x01),
(1, 0) => Some(self.x10),
(1, 1) => Some(self.x11),
_ => None,
}
}
pub fn get_row(&self, row: usize) -> Option<Vec2> {
assert!(row <= 1, "This row ({}) is out of bounds! Bounds: 0..1", row);
match row {
0 => Some(Vec2::new(self.x00, self.x01)),
1 => Some(Vec2::new(self.x10, self.x11)),
_ => None
}
}
pub fn set(&mut self, row: usize, col: usize, element: f32) {
assert!(row <= 1, "This row ({}) is out of bounds! Bounds: 0..1", row);
assert!(col <= 1, "This row ({}) is out of bounds! Bounds: 0..1", col);
match (row, col) {
(0,0) => self.x00 = element,
(0,1) => self.x01 = element,
(1,0) => self.x10 = element,
(1,1) => self.x11 = element,
_ => {}
}
}
pub fn set_row(&mut self, row: usize, row_content: Vec2) {
assert!(row <= 1, "This row ({}) is out of bounds! Bounds: 0..1", row);
match row {
0 => { self.x00 = row_content.x(); self.x01 = row_content.y(); },
1 => { self.x10 = row_content.x(); self.x11 = row_content.y(); },
_ => {}
}
}
pub fn det(&self) -> f32 {
self.x00 * self.x11
- self.x01 * self.x10
}
pub fn transpose(&self) -> Self {
Self {
x00: self.x00, x01: self.x10,
x10: self.x01, x11: self.x11
}
}
pub fn swap_rows(&mut self, row1: usize, row2: usize) {
let tmp = self.get_row(row1).expect(format!("This row ({}) is out of bounds! Bounds: 0..1", row1).as_str());
self.set_row(row1, self.get_row(row2).expect(format!("This row ({}) is out of bounds! Bounds: 0..1", row2).as_str()));
self.set_row(row2, tmp);
}
}
impl Add<Mat2> for Mat2 {
type Output = Self;
fn add(self, other: Mat2) -> Self {
Self {
x00: self.x00 + other.x00, x01: self.x01 + other.x01,
x10: self.x10 + other.x10, x11: self.x11 + other.x11
}
}
}
impl Sub<Mat2> for Mat2 {
type Output = Self;
fn sub(self, other: Mat2) -> Self {
Self {
x00: self.x00 - other.x00, x01: self.x01 - other.x01,
x10: self.x10 - other.x10, x11: self.x11 - other.x11
}
}
}
impl Mul<f32> for Mat2 {
type Output = Self;
fn mul(self, other: f32) -> Self {
Self {
x00: self.x00 * other, x01: self.x01 * other,
x10: self.x10 * other, x11: self.x11 * other
}
}
}
impl Mul<Mat2> for f32 {
type Output = Mat2;
fn mul(self, other: Mat2) -> Mat2 {
Mat2 {
x00: self * other.x00, x01: self * other.x01,
x10: self * other.x10, x11: self * other.x11
}
}
}
impl Mul<Mat2> for Mat2 {
type Output = Self;
fn mul(self, other: Mat2) -> Self {
Self {
x00: self.x00 * other.x00 + self.x01 * other.x10,
x01: self.x00 * other.x01 + self.x01 * other.x11,
x10: self.x10 * other.x00 + self.x11 * other.x10,
x11: self.x10 * other.x01 + self.x11 * other.x11
}
}
}
impl Mul<Vec2> for Mat2 {
type Output = Vec2;
fn mul(self, other: Vec2) -> Vec2 {
Vec2::new(
self.x00 * other.x() + self.x01 * other.y(),
self.x10 * other.x() + self.x11 * other.y()
)
}
}
impl Div<f32> for Mat2 {
type Output = Self;
fn div(self, other: f32) -> Self {
let inv = 1.0 / other;
inv * self
}
}
impl Into<[[f32; 2]; 2]> for Mat2 {
fn into(self) -> [[f32; 2]; 2] {
[
[self.x00, self.x01],
[self.x10, self.x11],
]
}
}
// ##################################################
// # MATRIX 3D #
// ##################################################
/// Representation of a 3x3 Matrix
#[repr(C)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq)]
pub struct Mat3 {
x00: f32,
x01: f32,
x02: f32,
x10: f32,
x11: f32,
x12: f32,
x20: f32,
x21: f32,
x22: f32
}
impl Mat3 {
pub const ZERO: Mat3 = Mat3 {
x00: 0.0, x01: 0.0, x02: 0.0,
x10: 0.0, x11: 0.0, x12: 0.0,
x20: 0.0, x21: 0.0, x22: 0.0
};
pub const IDENTITY: Mat3 = Mat3 {
x00: 1.0, x01: 0.0, x02: 0.0,
x10: 0.0, x11: 1.0, x12: 0.0,
x20: 0.0, x21: 0.0, x22: 1.0
};
pub const fn new(x00: f32, x01: f32, x02: f32, x10: f32, x11: f32, x12: f32, x20: f32, x21: f32, x22: f32) -> Self {
Self {
x00, x01, x02,
x10, x11, x12,
x20, x21, x22
}
}
pub fn from_vec(row1: Vec3, row2: Vec3, row3: Vec3) -> Self {
Self {
x00: row1.x(), x01: row1.y(), x02: row1.z(),
x10: row2.x(), x11: row2.y(), x12: row2.z(),
x20: row3.x(), x21: row3.y(), x22: row3.z()
}
}
pub fn get(&self, row: usize, col: usize) -> Option<f32> {
assert!(row <= 2, "This row ({}) is out of bounds! Bounds: 0..2", row);
assert!(col <= 2, "This row ({}) is out of bounds! Bounds: 0..2", col);
match (row, col) {
(0, 0) => Some(self.x00),
(0, 1) => Some(self.x01),
(0, 2) => Some(self.x02),
(1, 0) => Some(self.x10),
(1, 1) => Some(self.x11),
(1, 2) => Some(self.x12),
(2, 0) => Some(self.x20),
(2, 1) => Some(self.x21),
(2, 2) => Some(self.x22),
_ => None,
}
}
pub fn get_row(&self, row: usize) -> Option<Vec3> {
assert!(row <= 2, "This row ({}) is out of bounds! Bounds: 0..2", row);
match row {
0 => Some(Vec3::new(self.x00, self.x01, self.x02)),
1 => Some(Vec3::new(self.x10, self.x11, self.x12)),
2 => Some(Vec3::new(self.x20, self.x21, self.x22)),
_ => None
}
}
pub fn set(&mut self, row: usize, col: usize, element: f32) {
assert!(row <= 2, "This row ({}) is out of bounds! Bounds: 0..2", row);
assert!(col <= 2, "This row ({}) is out of bounds! Bounds: 0..2", col);
match (row, col) {
(0,0) => self.x00 = element,
(0,1) => self.x01 = element,
(0,2) => self.x02 = element,
(1,0) => self.x10 = element,
(1,1) => self.x11 = element,
(1,2) => self.x12 = element,
(2,0) => self.x20 = element,
(2,1) => self.x21 = element,
(2,2) => self.x22 = element,
_ => {}
}
}
pub fn set_row(&mut self, row: usize, row_content: Vec3) {
assert!(row <= 2, "This row ({}) is out of bounds! Bounds: 0..2", row);
match row {
0 => { self.x00 = row_content.x; self.x01 = row_content.y; self.x02 = row_content.z; },
1 => { self.x10 = row_content.x; self.x11 = row_content.y; self.x12 = row_content.z; },
2 => { self.x20 = row_content.x; self.x21 = row_content.y; self.x22 = row_content.z; }
_ => {}
}
}
pub fn det(&self) -> f32 {
self.x00 * self.x11 * self.x22
+ self.x01 * self.x12 * self.x20
+ self.x02 * self.x10 * self.x21
- self.x02 * self.x11 * self.x20
- self.x01 * self.x10 * self.x22
- self.x00 * self.x12 * self.x21
}
pub fn transpose(&self) -> Self {
Self {
x00: self.x00, x01: self.x10, x02: self.x20,
x10: self.x01, x11: self.x11, x12: self.x21,
x20: self.x02, x21: self.x12, x22: self.x22
}
}
pub fn swap_rows(&mut self, row1: usize, row2: usize) {
let tmp = self.get_row(row1).expect(format!("This row ({}) is out of bounds! Bounds: 0..2", row1).as_str());
self.set_row(row1, self.get_row(row2).expect(format!("This row ({}) is out of bounds! Bounds: 0..2", row2).as_str()));
self.set_row(row2, tmp);
}
}
impl Add<Mat3> for Mat3 {
type Output = Self;
fn add(self, other: Mat3) -> Self {
Self {
x00: self.x00 + other.x00, x01: self.x01 + other.x01, x02: self.x02 + other.x02,
x10: self.x10 + other.x10, x11: self.x11 + other.x11, x12: self.x12 + other.x12,
x20: self.x20 + other.x20, x21: self.x21 + other.x21, x22: self.x22 + other.x22
}
}
}
impl Sub<Mat3> for Mat3 {
type Output = Self;
fn sub(self, other: Mat3) -> Self {
Self {
x00: self.x00 - other.x00, x01: self.x01 - other.x01, x02: self.x02 - other.x02,
x10: self.x10 - other.x10, x11: self.x11 - other.x11, x12: self.x12 - other.x12,
x20: self.x20 - other.x20, x21: self.x21 - other.x21, x22: self.x22 - other.x22
}
}
}
impl Mul<f32> for Mat3 {
type Output = Self;
fn mul(self, other: f32) -> Self {
Self {
x00: self.x00 * other, x01: self.x01 * other, x02: self.x02 * other,
x10: self.x10 * other, x11: self.x11 * other, x12: self.x12 * other,
x20: self.x20 * other, x21: self.x21 * other, x22: self.x22 * other
}
}
}
impl Mul<Mat3> for f32 {
type Output = Mat3;
fn mul(self, other: Mat3) -> Mat3 {
Mat3 {
x00: self * other.x00, x01: self * other.x01, x02: self * other.x02,
x10: self * other.x10, x11: self * other.x11, x12: self * other.x12,
x20: self * other.x20, x21: self * other.x21, x22: self * other.x22
}
}
}
impl Mul<Mat3> for Mat3 {
type Output = Self;
fn mul(self, other: Mat3) -> Self {
Self {
x00: self.x00 * other.x00 + self.x01 * other.x10 + self.x02 * other.x20,
x01: self.x00 * other.x01 + self.x01 * other.x11 + self.x02 * other.x21,
x02: self.x00 * other.x02 + self.x01 * other.x12 + self.x02 * other.x22,
x10: self.x10 * other.x00 + self.x11 * other.x10 + self.x12 * other.x20,
x11: self.x10 * other.x01 + self.x11 * other.x11 + self.x12 * other.x21,
x12: self.x10 * other.x02 + self.x11 * other.x12 + self.x12 * other.x22,
x20: self.x20 * other.x00 + self.x21 * other.x10 + self.x22 * other.x20,
x21: self.x20 * other.x01 + self.x21 * other.x11 + self.x22 * other.x21,
x22: self.x20 * other.x02 + self.x21 * other.x12 + self.x22 * other.x22
}
}
}
impl Mul<Vec3> for Mat3 {
type Output = Vec3;
fn mul(self, other: Vec3) -> Vec3 {
Vec3::new(
self.x00 * other.x() + self.x01 * other.y() + self.x02 * other.z(),
self.x10 * other.x() + self.x11 * other.y() + self.x12 * other.z(),
self.x20 * other.x() + self.x21 * other.y() + self.x22 * other.z()
)
}
}
impl Div<f32> for Mat3 {
type Output = Self;
fn div(self, other: f32) -> Self {
let inv = 1.0 / other;
inv * self
}
}
impl Into<[[f32; 3]; 3]> for Mat3 {
fn into(self) -> [[f32; 3]; 3] {
[
[self.x00, self.x01, self.x02],
[self.x10, self.x11, self.x12],
[self.x20, self.x21, self.x22],
]
}
}
// ##################################################
// # MATRIX 4D #
// ##################################################
/// Representation of a 4x4 Matrix
#[repr(C)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Mat4 {
x00: f32,
x01: f32,
x02: f32,
x03: f32,
x10: f32,
x11: f32,
x12: f32,
x13: f32,
x20: f32,
x21: f32,
x22: f32,
x23: f32,
x30: f32,
x31: f32,
x32: f32,
x33: f32
}
impl Mat4 {
pub const ZERO: Mat4 = Mat4 {
x00: 0.0, x01: 0.0, x02: 0.0, x03: 0.0,
x10: 0.0, x11: 0.0, x12: 0.0, x13: 0.0,
x20: 0.0, x21: 0.0, x22: 0.0, x23: 0.0,
x30: 0.0, x31: 0.0, x32: 0.0, x33: 0.0
};
pub const IDENTITY: Mat4 = Mat4 {
x00: 1.0, x01: 0.0, x02: 0.0, x03: 0.0,
x10: 0.0, x11: 1.0, x12: 0.0, x13: 0.0,
x20: 0.0, x21: 0.0, x22: 1.0, x23: 0.0,
x30: 0.0, x31: 0.0, x32: 0.0, x33: 1.0
};
pub const fn new(x00: f32, x01: f32,x02: f32,x03: f32,x10: f32,x11: f32,x12: f32,x13: f32,x20: f32,x21: f32,x22: f32,x23: f32,x30: f32, x31: f32, x32: f32,x33: f32) -> Self {
Self {
x00, x01, x02, x03,
x10, x11, x12, x13,
x20, x21, x22, x23,
x30, x31, x32, x33
}
}
pub fn from_vec(row1: Vec4, row2: Vec4, row3: Vec4, row4: Vec4) -> Self {
Self {
x00: row1.x(), x01: row1.y(), x02: row1.z(), x03: row1.w(),
x10: row2.x(), x11: row2.y(), x12: row2.z(), x13: row2.w(),
x20: row3.x(), x21: row3.y(), x22: row3.z(), x23: row3.w(),
x30: row4.x(), x31: row4.y(), x32: row4.z(), x33: row4.w()
}
}
pub fn rh_look_to(camera: Point3, dir: Vec3, up: Vec3) -> Self {
let f = dir.normalize();
let s = cross(f, up).normalize();
let u = cross(s,f);
let cam = camera.to_vec();
/*Mat4::new(
s.x().clone(), u.x().clone(), -f.x().clone(), 0.0,
s.y().clone(), u.y().clone(), -f.y().clone(), 0.0,
s.z().clone(), u.z().clone(), -f.z().clone(), 0.0,
-dot(&cam, &s), -dot(&cam, &u), dot(&cam, &f),1.0
)*/
Mat4::new(
s.x().clone(), s.y().clone(), s.z().clone(), 0.0,
u.x().clone(), u.y().clone(), u.z().clone(), 0.0,
-f.x().clone(), -f.y().clone(), -f.z().clone(), 0.0,
-dot(&cam, &s), -dot(&cam, &u), dot(&cam, &f), 1.0
)
}
pub fn lh_look_to(camera: Point3, dir: Vec3, up: Vec3) -> Self {
Self::lh_look_to(camera, dir * -1.0, up)
}
pub fn look_at_rh(camera: Point3, center: Point3, up: Vec3) -> Mat4 {
Self::rh_look_to(camera, (center.to_vec() - camera.to_vec()), up)
}
pub fn look_at_lh(camera: Point3, center: Point3, up: Vec3) -> Self {
Self::lh_look_to(camera, (center.to_vec() - camera.to_vec()), up)
}
pub fn perspective_matrix(fovy: f32, aspect: f32, near: f32, far: f32) -> Self {
let angle = fovy * 0.5;
let ymax = near * angle.tan();
let xmax = ymax * aspect;
let left = -xmax;
let right = xmax;
let bottom = -ymax;
let top = ymax;
/*Mat4::new(
(2.0 * near) / (right - left), 0.0, (right + left) / (right - left), 0.0,
0.0, (2.0 * near) / (top - bottom), (top + bottom) / (top - bottom), 0.0,
0.0, 0.0, -(far + near) / (far - near), -(2.0 * far * near) / (far - near),
0.0, 0.0, -1.0, 0.0
)*/
Mat4::new(
(2.0 * near) / (right - left), 0.0, 0.0, 0.0,
0.0, (2.0 * near) / (top - bottom), 0.0, 0.0,
(right + left) / (right - left), (top + bottom) / (top - bottom), -(far + near) / (far - near), -1.0,
0.0, 0.0, -(2.0 * far * near) / (far - near), 0.0
)
}
pub fn get(&self, row: usize, col: usize) -> Option<f32> {
assert!(row <= 3, "This row ({}) is out of bounds! Bounds: 0..3", row);
assert!(col <= 3, "This row ({}) is out of bounds! Bounds: 0..3", col);
match (row, col) {
(0, 0) => Some(self.x00),
(0, 1) => Some(self.x01),
(0, 2) => Some(self.x02),
(0, 3) => Some(self.x03),
(1, 0) => Some(self.x10),
(1, 1) => Some(self.x11),
(1, 2) => Some(self.x12),
(1, 3) => Some(self.x13),
(2, 0) => Some(self.x20),
(2, 1) => Some(self.x21),
(2, 2) => Some(self.x22),
(2, 3) => Some(self.x23),
(3, 0) => Some(self.x30),
(3, 1) => Some(self.x31),
(3, 2) => Some(self.x32),
(3, 3) => Some(self.x33),
_ => None,
}
}
pub fn get_row(&self, row: usize) -> Option<Vec4> {
assert!(row <= 3, "This row ({}) is out of bounds! Bounds: 0..3", row);
match row {
0 => Some(Vec4::new(self.x00, self.x01, self.x02, self.x03)),
1 => Some(Vec4::new(self.x10, self.x11, self.x12, self.x13)),
2 => Some(Vec4::new(self.x20, self.x21, self.x22, self.x23)),
3 => Some(Vec4::new(self.x30, self.x31, self.x32, self.x33)),
_ => None
}
}
pub fn set(&mut self, row: usize, col: usize, element: f32) {
assert!(row <= 3, "The given row ({}) is out of bounds! Bounds: 0..3", row);
assert!(col <= 3, "The given column ({}) is out of bounds! Bounds: 0..3", col);
match (row, col) {
(0,0) => self.x00 = element,
(0,1) => self.x01 = element,
(0,2) => self.x02 = element,
(0,3) => self.x03 = element,
(1,0) => self.x10 = element,
(1,1) => self.x11 = element,
(1,2) => self.x12 = element,
(1,3) => self.x13 = element,
(2,0) => self.x20 = element,
(2,1) => self.x21 = element,
(2,2) => self.x22 = element,
(2,3) => self.x23 = element,
(3,0) => self.x30 = element,
(3,1) => self.x31 = element,
(3,2) => self.x32 = element,
(3,3) => self.x33 = element,
_ => {}
}
}
pub fn set_row(&mut self, row: usize, row_content: Vec4) {
assert!(row <= 3, "This row ({}) is out of bounds: Bounds: 0..3", row);
match row {
0 => { self.x00 = row_content.x(); self.x01 = row_content.y(); self.x02 = row_content.z(); self.x03 = row_content.w(); },
1 => { self.x10 = row_content.x(); self.x11 = row_content.y(); self.x12 = row_content.z(); self.x13 = row_content.w(); },
2 => { self.x20 = row_content.x(); self.x21 = row_content.y(); self.x22 = row_content.z(); self.x23 = row_content.w(); },
3 => { self.x30 = row_content.x(); self.x31 = row_content.y(); self.x32 = row_content.z(); self.x33 = row_content.w(); }
_ => {}
}
}
pub fn det(&self) -> f32 {
self.x00 * (self.x11 * (self.x22* self.x33 - self.x23 * self.x32)
- self.x21 * (self.x12 * self.x33 - self.x13 * self.x32)
+ self.x31 * (self.x12 * self.x23 - self.x13 * self.x22))
- self.x10 * (self.x01 * (self.x22* self.x33 - self.x23 * self.x32)
- self.x21 * (self.x02 * self.x33 - self.x32 * self.x03)
+ self.x31 * (self.x02 * self.x23 - self.x22 * self.x03))
+ self.x20 * (self.x01 * (self.x12 * self.x33 - self.x13 * self.x32)
- self.x11 * (self.x02 * self.x33 - self.x03 * self.x32)
+ self.x31 * (self.x02 * self.x13 - self.x03 * self.x12))
- self.x30 * (self.x01 * (self.x12 * self.x23 - self.x22 * self.x13)
- self.x11 * (self.x02 * self.x23 - self.x22 * self.x03)
+ self.x21 * (self.x02 * self.x13 - self.x03 * self.x12))
}
pub fn transpose(&self) -> Self {
Self {
x00: self.x00, x01: self.x10, x02: self.x20, x03: self.x30,
x10: self.x01, x11: self.x11, x12: self.x21, x13: self.x31,
x20: self.x02, x21: self.x12, x22: self.x22, x23: self.x32,
x30: self.x03, x31: self.x13, x32: self.x23, x33: self.x33
}
}
}
impl Add<Mat4> for Mat4 {
type Output = Self;
fn add(self, other: Mat4) -> Self {
Self {
x00: self.x00 + other.x00, x01: self.x01 + other.x01, x02: self.x02 + other.x02, x03: self.x03 + other.x03,
x10: self.x10 + other.x10, x11: self.x11 + other.x11, x12: self.x12 + other.x12, x13: self.x13 + other.x13,
x20: self.x20 + other.x20, x21: self.x21 + other.x21, x22: self.x22 + other.x22, x23: self.x23 + other.x23,
x30: self.x30 + other.x30, x31: self.x31 + other.x31, x32: self.x32 + other.x32, x33: self.x33 + other.x33
}
}
}
impl Sub<Mat4> for Mat4 {
type Output = Self;
fn sub(self, other: Mat4) -> Self {
Self {
x00: self.x00 - other.x00, x01: self.x01 - other.x01, x02: self.x02 - other.x02, x03: self.x03 - other.x03,
x10: self.x10 - other.x10, x11: self.x11 - other.x11, x12: self.x12 - other.x12, x13: self.x13 - other.x13,
x20: self.x20 - other.x20, x21: self.x21 - other.x21, x22: self.x22 - other.x22, x23: self.x23 - other.x23,
x30: self.x30 - other.x30, x31: self.x31 - other.x31, x32: self.x32 - other.x32, x33: self.x33 - other.x33
}
}
}
impl Mul<f32> for Mat4 {
type Output = Self;
fn mul(self, other: f32) -> Self {
Self {
x00: self.x00 * other, x01: self.x01 * other, x02: self.x02 * other, x03: self.x03 * other,
x10: self.x10 * other, x11: self.x11 * other, x12: self.x12 * other, x13: self.x13 * other,
x20: self.x20 * other, x21: self.x21 * other, x22: self.x22 * other, x23: self.x23 * other,
x30: self.x30 * other, x31: self.x31 * other, x32: self.x32 * other, x33: self.x33 * other
}
}
}
impl Div<f32> for Mat4 {
type Output = Self;
fn div(self, other: f32) -> Self {
Self {
x00: self.x00 / other, x01: self.x01 / other, x02: self.x02 / other, x03: self.x03 / other,
x10: self.x10 / other, x11: self.x11 / other, x12: self.x12 / other, x13: self.x13 / other,
x20: self.x20 / other, x21: self.x21 / other, x22: self.x22 / other, x23: self.x23 / other,
x30: self.x30 / other, x31: self.x31 / other, x32: self.x32 / other, x33: self.x33 / other
}
}
}
impl Mul<Mat4> for Mat4 {
type Output = Self;
fn mul(self, other: Mat4) -> Self {
Self {
x00: self.x00 * other.x00 + self.x01 * other.x10 + self.x02 * other.x20 + self.x03 * other.x30,
x01: self.x00 * other.x01 + self.x01 * other.x11 + self.x02 * other.x21 + self.x03 * other.x31,
x02: self.x00 * other.x02 + self.x01 * other.x12 + self.x02 * other.x22 + self.x03 * other.x32,
x03: self.x00 * other.x03 + self.x01 * other.x13 + self.x02 * other.x23 + self.x03 * other.x33,
x10: self.x10 * other.x00 + self.x11 * other.x10 + self.x12 * other.x20 + self.x13 * other.x30,
x11: self.x10 * other.x01 + self.x11 * other.x11 + self.x12 * other.x21 + self.x13 * other.x31,
x12: self.x10 * other.x02 + self.x11 * other.x12 + self.x12 * other.x22 + self.x13 * other.x32,
x13: self.x10 * other.x03 + self.x11 * other.x13 + self.x12 * other.x23 + self.x13 * other.x33,
x20: self.x20 * other.x00 + self.x21 * other.x10 + self.x22 * other.x20 + self.x23 * other.x30,
x21: self.x20 * other.x01 + self.x21 * other.x11 + self.x22 * other.x21 + self.x23 * other.x31,
x22: self.x20 * other.x02 + self.x21 * other.x12 + self.x22 * other.x22 + self.x23 * other.x32,
x23: self.x20 * other.x03 + self.x21 * other.x13 + self.x22 * other.x23 + self.x23 * other.x33,
x30: self.x30 * other.x00 + self.x31 * other.x10 + self.x32 * other.x20 + self.x33 * other.x30,
x31: self.x30 * other.x01 + self.x31 * other.x11 + self.x32 * other.x21 + self.x33 * other.x31,
x32: self.x30 * other.x02 + self.x31 * other.x12 + self.x32 * other.x22 + self.x33 * other.x32,
x33: self.x30 * other.x03 + self.x31 * other.x13 + self.x32 * other.x23 + self.x33 * other.x33
}
}
}
impl Into<[[f32; 4]; 4]> for Mat4 {
fn into(self) -> [[f32; 4]; 4] {
[
[self.x00, self.x01, self.x02, self.x03],
[self.x10, self.x11, self.x12, self.x13],
[self.x20, self.x21, self.x22, self.x23],
[self.x30, self.x31, self.x32, self.x33],
]
}
}
// ##################################################
// # MATRIX FUNCTIONS #
// ##################################################
pub fn det<T: LinearTransformation>(mat: &T) -> f32 {
mat.det()
}

View file

@ -0,0 +1,62 @@
use crate::vector::{Vec2, Vec3};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Point2 {
x: f32,
y: f32
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Point3 {
x: f32,
y: f32,
z: f32
}
impl Point2 {
pub fn new(x: f32, y: f32) -> Self {
Point2 { x, y }
}
pub fn from_vec(v: Vec2) -> Self {
Self { x: v.x(), y: v.y() }
}
pub fn to_vec(&self) -> Vec2 {
Vec2::new(self.x, self.y)
}
pub fn x(&self) -> f32 {
self.x
}
pub fn y(&self) -> f32 {
self.y
}
}
impl Point3 {
pub fn new(x: f32, y: f32, z: f32) -> Self {
Point3 { x, y, z }
}
pub fn from_vec(v: Vec3) -> Self {
Self { x: v.x(), y: v.y(), z: v.z() }
}
pub fn to_vec(&self) -> Vec3 {
Vec3::new(self.x, self.y, self.z)
}
pub fn x(&self) -> f32 {
self.x
}
pub fn y(&self) -> f32 {
self.y
}
pub fn z(&self) -> f32 {
self.z
}
}

View file

@ -0,0 +1,60 @@
use std::ops::Mul;
use crate::vector::Vec3;
/// Representation of a quaternion in scalar/vector form
pub struct Quat {
pub s: f32,
pub v: Vec3,
}
impl Quat {
pub const fn zero() -> Self {
Self {
s: 0.0,
v: Vec3 {
x: 0.0,
y: 0.0,
z: 0.0,
},
}
}
pub const fn new(s: f32, v: Vec3) -> Self {
Self { s, v }
}
pub fn conjugate(&self) -> Self {
Self {
s: self.s,
v: self.v * (-1.0),
}
}
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)
}
pub fn into_vec(&self) -> Vec3 {
Vec3 {
x: self.v.x,
y: self.v.y,
z: self.v.z,
}
}
}
impl Mul<Quat> for 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: Vec3 {
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,
}
}
}
}

View file

@ -0,0 +1,177 @@
use crate::point::{Point2, Point3};
use crate::vector::{Vec2, Vec3, Vec4, InnerSpace};
// ##################################################
// # CONSTANTS #
// ##################################################
static FAC: [i64; 21] = [
1,1,2,6,24,120,720,5040,40320,362880,3628800,
39916800,479001600,6227020800,87178291200,1307674368000,
20922789888000,355687428096000,6402373705728000,
121645100408832000,2432902008176640000
];
static iFAC: [f32; 6] = [
1.0,1.0,0.5,0.1666666666666666667,0.04166666666666666667,0.00833333333333333334
];
pub static PI: f32 = std::f32::consts::PI;
// ##################################################
// # GENERAL PURPOSE #
// ##################################################
pub fn fac(n: i64) -> i64 {
match n {
_ if n <= 21 => { FAC[n as usize] }
_ => n * fac(n-1)
}
}
pub fn sqrt(x: f32) -> f32 {
x.sqrt()
}
pub fn ln(x: f32) -> f32 {
x.ln()
}
pub fn log(x: f32) -> f32 {
ln(x)/2.30258509299
}
pub fn log2(x: f32) -> f32 {
ln(x)/0.69314718056
}
pub fn sin(x: f32) -> f32 {
x.sin()
}
pub fn asin(x: f32) -> f32 {
x.asin()
}
pub fn cos(x: f32) -> f32 {
x.cos()
}
pub fn acos(x: f32) -> f32 {
x.acos()
}
pub fn tan(x: f32) -> f32 {
x.tan()
}
pub fn atan(x: f32) -> f32 {
x.atan()
}
pub fn atan2(p: Point2) -> f32 {
p.y().atan2(p.x())
}
pub fn sinh(x: f32) -> f32 {
x.sinh()
}
pub fn cosh(x: f32) -> f32 {
x.cosh()
}
pub fn tanh(x: f32) -> f32 {
x.tanh()
}
pub fn clamp(start: f32, end: f32, value: f32) -> f32 {
match value {
_ if value > end => end,
_ if start > value => start,
_ => value
}
}
pub fn pointDerivative(func: fn(f32) -> f32, x: f32, h: f32) -> f32 {
(func(x+h) - func(x-h))/(2.0 * h)
}
// ##################################################
// # INTERPOLATION #
// ##################################################
pub fn lerp(a: f32, b: f32, t: f32) -> f32 {
(1.0 - t) * a + t * b
}
pub fn invLerp(a: f32, b:f32, value: f32) -> f32 {
(value - a) / (b - a)
}
pub fn lerp2(a: Vec2, b: Vec2, t: f32) -> Vec2 {
a * (1.0 - t) + b * t
}
pub fn invLerp2(a: Vec2, b: Vec2, value: Vec2) -> Option<f32> {
let tx = (value.x() - a.x()) / (b.x() - a.x());
let ty = (value.y() - a.y()) / (b.y() - a.y());
if tx == ty {
return Some(tx);
}
None
}
pub fn lerp3(a: Vec3, b: Vec3, t: f32) -> Vec3 {
a * (1.0 - t) + b * t
}
pub fn invLerp3(a: Vec3, b: Vec3, value: Vec3) -> Option<f32> {
let tx = (value.x() - a.x())/(b.x() - a.x());
let ty = (value.y() - a.y())/(b.y() - a.y());
let tz = (value.z() - a.z())/(b.z() - a.z());
if (tx == ty) && (ty == tz) {
return Some(tx);
}
None
}
// ##################################################
// # BEZIER CURVES #
// ##################################################
/// Cubic Bézier Curve in R²
pub fn bezier2(p0: Point2, p1: Point2, p2: Point2, p3: Point2, t: f32) -> Point2 {
let tSquared = t * t;
let tCubed = tSquared * t;
let vP0 = Vec2::from_point(p0);
let vP1 = Vec2::from_point(p1);
let vP2 = Vec2::from_point(p2);
let vP3 = Vec2::from_point(p3);
Point2::from_vec(vP0 * (-tCubed + 3.0 * tSquared - 3.0 * t + 1.0 ) +
vP1 * (3.0 * tCubed - 6.0 * tSquared + 3.0 * t ) +
vP2 * (-3.0 * tCubed + 3.0 * tSquared ) +
vP3 * tCubed)
}
/// Cubic Bézier Curve in R³
pub fn bezier3(p0: Point3, p1: Point3, p2: Point3, p3: Point3, t: f32) -> Point3 {
let tSquared = t * t;
let tCubed = tSquared * t;
let vP0 = Vec3::from_point(p0);
let vP1 = Vec3::from_point(p1);
let vP2 = Vec3::from_point(p2);
let vP3 = Vec3::from_point(p3);
Point3::from_vec(vP0 * (-tCubed + 3.0 * tSquared - 3.0 * t + 1.0 ) +
vP1 * (3.0 * tCubed - 6.0 * tSquared + 3.0 * t ) +
vP2 * (-3.0 * tCubed + 3.0 * tSquared ) +
vP3 * tCubed)
}
// ##################################################
// # SPLINES #
// ##################################################

File diff suppressed because it is too large Load diff