mirror of
https://github.com/lisk77/comet.git
synced 2025-10-24 13:58:49 +00:00
initial commit
This commit is contained in:
commit
6154c72b0e
55 changed files with 9481 additions and 0 deletions
145
crates/comet_math/src/bezier.rs
Normal file
145
crates/comet_math/src/bezier.rs
Normal 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
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
132
crates/comet_math/src/easings.rs
Normal file
132
crates/comet_math/src/easings.rs
Normal 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 }
|
||||
}
|
||||
14
crates/comet_math/src/lib.rs
Normal file
14
crates/comet_math/src/lib.rs
Normal 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;
|
||||
732
crates/comet_math/src/matrix.rs
Normal file
732
crates/comet_math/src/matrix.rs
Normal 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()
|
||||
}
|
||||
62
crates/comet_math/src/point.rs
Normal file
62
crates/comet_math/src/point.rs
Normal 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
|
||||
}
|
||||
}
|
||||
60
crates/comet_math/src/quaternion.rs
Normal file
60
crates/comet_math/src/quaternion.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
177
crates/comet_math/src/utilities.rs
Normal file
177
crates/comet_math/src/utilities.rs
Normal 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 #
|
||||
// ##################################################
|
||||
2640
crates/comet_math/src/vector.rs
Normal file
2640
crates/comet_math/src/vector.rs
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue