From 5ca76b424a6bf27b3fafc3efa4cbeee6953eb244 Mon Sep 17 00:00:00 2001 From: Jon Janzen Date: Sun, 28 Mar 2021 19:16:14 -0600 Subject: [PATCH] multiple matrix by tuple --- matrix/Cargo.toml | 1 + matrix/src/lib.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++++ structs/src/lib.rs | 4 +++ 3 files changed, 88 insertions(+) diff --git a/matrix/Cargo.toml b/matrix/Cargo.toml index 2f6e9d1..e9fa596 100644 --- a/matrix/Cargo.toml +++ b/matrix/Cargo.toml @@ -8,3 +8,4 @@ edition = "2018" [dependencies] approx = "0.4" +structs = { path = "../structs" } diff --git a/matrix/src/lib.rs b/matrix/src/lib.rs index c5dfbc9..a559e63 100644 --- a/matrix/src/lib.rs +++ b/matrix/src/lib.rs @@ -1,6 +1,8 @@ #[macro_use] extern crate approx; +use structs::Tuple; + use std::ops::Index; #[derive(Debug)] @@ -28,6 +30,22 @@ impl Matrix { matrix: m, } } + + pub fn new_empty(row_count: usize, col_count: usize) -> Matrix { + let mut rows = Vec::with_capacity(row_count); + for _ in 0..row_count { + let mut col = Vec::with_capacity(col_count); + for _ in 0..col_count { + col.push(0.0); + } + rows.push(col); + } + Matrix::new(rows) + } + + pub fn new_empty_4() -> Matrix { + Matrix::new_empty(4, 4) + } } impl Index for Matrix { @@ -57,6 +75,56 @@ impl PartialEq for Matrix { } } +impl Matrix { + fn calc_val_for_mul(&self, row: usize, rhs: &Matrix, col: usize) -> f32 { + let mut sum = 0.0; + for i in 0..self.matrix.len() { + sum += self.matrix[row][i] * rhs.matrix[i][col]; + } + sum + } + + fn calc_val_for_mul_tuple(&self, row: usize, tuple: &Tuple) -> f32 { + (self.matrix[row][0] * tuple.x()) + + (self.matrix[row][1] * tuple.y()) + + (self.matrix[row][2] * tuple.z()) + + (self.matrix[row][3] * tuple.w()) + } +} + +impl std::ops::Mul for Matrix { + type Output = Matrix; + + fn mul(self, _rhs: Matrix) -> Matrix { + let row_count = self.matrix.len(); + let col_count = self.matrix[0].len(); + let mut rows = Vec::with_capacity(row_count); + for row in 0..row_count { + let mut cols = Vec::with_capacity(col_count); + for col in 0..col_count { + cols.push(self.calc_val_for_mul(row, &_rhs, col)); + } + rows.push(cols); + } + Matrix::new(rows) + } + +} + +impl std::ops::Mul for Matrix { + type Output = Tuple; + + fn mul(self, _rhs: Tuple) -> Tuple { + Tuple::new( + self.calc_val_for_mul_tuple(0, &_rhs), + self.calc_val_for_mul_tuple(1, &_rhs), + self.calc_val_for_mul_tuple(2, &_rhs), + self.calc_val_for_mul_tuple(3, &_rhs), + ) + } + +} + #[cfg(test)] mod tests { use super::*; @@ -194,4 +262,19 @@ mod tests { assert_eq!(matrix_a * matrix_b, expected); } + + #[test] + fn multiply_by_tuple() { + let matrix = Matrix::from_array([ + [1.0, 2.0, 3.0, 4.0], + [2.0, 4.0, 4.0, 2.0], + [8.0, 6.0, 4.0, 1.0], + [0.0, 0.0, 0.0, 1.0], + ]); + + let tuple = Tuple::new(1.0, 2.0, 3.0, 1.0); + let expected = Tuple::new(18.0, 24.0, 33.0, 1.0); + + assert_eq!(matrix * tuple, expected); + } } diff --git a/structs/src/lib.rs b/structs/src/lib.rs index 9e73153..420918d 100644 --- a/structs/src/lib.rs +++ b/structs/src/lib.rs @@ -55,6 +55,10 @@ impl Tuple { self.z } + pub fn w(&self) -> f32 { + self.w + } + pub fn is_point(&self) -> bool { self.w == 1.0 }