half-baked linear algebra module; gonna switch to Glam
This commit is contained in:
parent
534b332a7e
commit
cc56a34155
2 changed files with 322 additions and 0 deletions
320
src/linalg.rs
Normal file
320
src/linalg.rs
Normal file
|
@ -0,0 +1,320 @@
|
|||
use std::ops::{Add, Deref, Mul};
|
||||
|
||||
use crate::point::Point3f;
|
||||
|
||||
pub type Float = f32;
|
||||
|
||||
//-************************************************************************
|
||||
// Vectors
|
||||
//-************************************************************************
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
|
||||
#[repr(transparent)]
|
||||
pub struct Vek<const N: usize> {
|
||||
pub vec: [Float; N],
|
||||
}
|
||||
|
||||
pub type Vec3 = Vek<3>;
|
||||
pub type Vec4 = Vek<4>;
|
||||
|
||||
//-************************************************************************
|
||||
// Matrices
|
||||
//-************************************************************************
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
|
||||
#[repr(transparent)]
|
||||
pub struct Mat<const N: usize> {
|
||||
pub rows: [Vek<N>; N],
|
||||
}
|
||||
|
||||
pub type Mat3 = Mat<3>;
|
||||
pub type Mat4 = Mat<4>;
|
||||
|
||||
//-************************************************************************
|
||||
// inherent impls
|
||||
//-************************************************************************
|
||||
|
||||
// Vec3
|
||||
impl Vec3 {
|
||||
pub fn new(x: Float, y: Float, z: Float) -> Self {
|
||||
Self { vec: [x, y, z] }
|
||||
}
|
||||
|
||||
pub fn x(&self) -> Float {
|
||||
self.vec[0]
|
||||
}
|
||||
|
||||
pub fn y(&self) -> Float {
|
||||
self.vec[1]
|
||||
}
|
||||
|
||||
pub fn z(&self) -> Float {
|
||||
self.vec[2]
|
||||
}
|
||||
|
||||
pub fn dot(&self, rhs: &Self) -> Float {
|
||||
self.x() * rhs.x() + self.y() * rhs.y() + self.z() * rhs.z()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> Float {
|
||||
self.len_squared().sqrt()
|
||||
}
|
||||
|
||||
pub fn len_squared(&self) -> Float {
|
||||
self.x().powi(2) + self.y().powi(2) + self.z().powi(2)
|
||||
}
|
||||
|
||||
pub fn scale(self, factor: Float) -> Self {
|
||||
self * factor
|
||||
}
|
||||
}
|
||||
|
||||
// Vec4
|
||||
impl Vec4 {
|
||||
pub fn new(x: Float, y: Float, z: Float, w: Float) -> Self {
|
||||
Self { vec: [x, y, z, w] }
|
||||
}
|
||||
|
||||
pub fn x(&self) -> Float {
|
||||
self.vec[0]
|
||||
}
|
||||
|
||||
pub fn y(&self) -> Float {
|
||||
self.vec[1]
|
||||
}
|
||||
|
||||
pub fn z(&self) -> Float {
|
||||
self.vec[2]
|
||||
}
|
||||
|
||||
pub fn w(&self) -> Float {
|
||||
self.vec[3]
|
||||
}
|
||||
pub fn dot(&self, rhs: &Self) -> Float {
|
||||
self.x() * rhs.x() + self.y() * rhs.y() + self.z() * rhs.z() + self.w() * rhs.w()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> Float {
|
||||
self.len_squared().sqrt()
|
||||
}
|
||||
|
||||
pub fn len_squared(&self) -> Float {
|
||||
self.x().powi(2) + self.y().powi(2) + self.z().powi(2) + self.w().powi(2)
|
||||
}
|
||||
|
||||
pub fn scale(self, factor: Float) -> Self {
|
||||
self * factor
|
||||
}
|
||||
}
|
||||
|
||||
// Mat3
|
||||
impl Mat3 {
|
||||
pub fn new(rows: [Vec3; 3]) -> Self {
|
||||
Self { rows }
|
||||
}
|
||||
|
||||
pub fn identity() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// panics if `row` is > 2
|
||||
pub fn row(&self, row: usize) -> Vec3 {
|
||||
self[row]
|
||||
}
|
||||
|
||||
pub fn a(&self) -> Vec3 {
|
||||
self[0]
|
||||
}
|
||||
|
||||
pub fn b(&self) -> Vec3 {
|
||||
self[1]
|
||||
}
|
||||
|
||||
pub fn c(&self) -> Vec3 {
|
||||
self[2]
|
||||
}
|
||||
|
||||
pub fn transpose(&self) -> Self {
|
||||
let a = [self[0][0], self[1][0], self[2][0]].into();
|
||||
let b = [self[0][1], self[1][1], self[2][1]].into();
|
||||
let c = [self[0][2], self[1][2], self[2][2]].into();
|
||||
Self { rows: [a, b, c] }
|
||||
}
|
||||
|
||||
pub fn invert(&self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
//-************************************************************************
|
||||
// trait impls
|
||||
//-************************************************************************
|
||||
|
||||
// Vec3
|
||||
impl Default for Vec3 {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
vec: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[Float; 3]> for Vec3 {
|
||||
fn from(vec: [Float; 3]) -> Self {
|
||||
Self { vec }
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Vec3 {
|
||||
type Target = [Float; 3];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.vec
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Float> for Vec3 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: Float) -> Self::Output {
|
||||
let [x, y, z] = self.vec;
|
||||
Self {
|
||||
vec: [x * rhs, y * rhs, z * rhs],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Vec3> for Float {
|
||||
type Output = Vec3;
|
||||
|
||||
fn mul(self, rhs: Vec3) -> Self::Output {
|
||||
rhs * self
|
||||
}
|
||||
}
|
||||
|
||||
/// Adding a vector to a point like "point + vec"
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
impl Add<Vec3> for Point3f {
|
||||
type Output = Point3f;
|
||||
|
||||
fn add(self, v: Vec3) -> Self::Output {
|
||||
Point3f::new(
|
||||
(self.x() as Float + v.x()) as f32,
|
||||
(self.y() as Float + v.y()) as f32,
|
||||
(self.z() as Float + v.z()) as f32,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Vec4
|
||||
impl Default for Vec4 {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
vec: [0., 0., 0., 1.],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[Float; 4]> for Vec4 {
|
||||
fn from(vec: [Float; 4]) -> Self {
|
||||
Self { vec }
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Vec4 {
|
||||
type Target = [Float; 4];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.vec
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Float> for Vec4 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: Float) -> Self::Output {
|
||||
let [x, y, z, w] = self.vec;
|
||||
Self {
|
||||
vec: [x * rhs, y * rhs, z * rhs, w * rhs],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Vec4> for Float {
|
||||
type Output = Vec4;
|
||||
|
||||
fn mul(self, rhs: Vec4) -> Self::Output {
|
||||
rhs * self
|
||||
}
|
||||
}
|
||||
|
||||
// Mat3
|
||||
impl Default for Mat3 {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
rows: [
|
||||
[1., 0., 0.].into(),
|
||||
[0., 1., 0.].into(),
|
||||
[0., 0., 1.].into(),
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Mat3 {
|
||||
type Target = [Vec3; 3];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.rows
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Vec3> for Mat3 {
|
||||
type Output = Vec3;
|
||||
|
||||
fn mul(self, rhs: Vec3) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Mat4 {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
rows: [
|
||||
[1., 0., 0., 0.].into(),
|
||||
[0., 1., 0., 0.].into(),
|
||||
[0., 0., 1., 0.].into(),
|
||||
[0., 0., 0., 1.].into(),
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Mat4 {
|
||||
type Target = [Vec4; 4];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.rows
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn mat3_transpose() {
|
||||
// identity doesn't change under transpose
|
||||
let m = Mat3::default();
|
||||
assert_eq!(1.0, m[0][0]);
|
||||
assert_eq!(0.0, m[0][1]);
|
||||
assert_eq!(m, m.transpose());
|
||||
|
||||
let m = Mat3::new([[1.; 3].into(), [2.; 3].into(), [3.; 3].into()]);
|
||||
assert_eq!(m.a(), [1., 1., 1.].into());
|
||||
|
||||
let mt = m.transpose();
|
||||
assert_ne!(m, mt);
|
||||
assert_eq!(mt.a(), [1., 2., 3.].into());
|
||||
}
|
||||
}
|
|
@ -12,6 +12,8 @@ mod model;
|
|||
mod triangle;
|
||||
use triangle::*;
|
||||
|
||||
mod linalg;
|
||||
|
||||
use crate::model::Model;
|
||||
|
||||
const BLACK: TGAColor = TGAColor { bgra: [0u8; 4] };
|
||||
|
|
Loading…
Reference in a new issue