Compare commits
3 Commits
f24280c866
...
5ca76b424a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ca76b424a | ||
|
|
6fd1eb49b7 | ||
|
|
c47d3448a3 |
@@ -8,3 +8,4 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
approx = "0.4"
|
approx = "0.4"
|
||||||
|
structs = { path = "../structs" }
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate approx;
|
extern crate approx;
|
||||||
|
|
||||||
|
use structs::Tuple;
|
||||||
|
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -14,6 +16,36 @@ impl Matrix {
|
|||||||
matrix: matrix,
|
matrix: matrix,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_array(matrix: [[f32; 4]; 4]) -> Matrix {
|
||||||
|
let mut m = Vec::with_capacity(4);
|
||||||
|
for row in 0..matrix.len() {
|
||||||
|
let mut r = Vec::with_capacity(4);
|
||||||
|
for col in 0..matrix[row].len() {
|
||||||
|
r.push(matrix[row][col]);
|
||||||
|
}
|
||||||
|
m.push(r);
|
||||||
|
}
|
||||||
|
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<usize> for Matrix {
|
impl Index<usize> for Matrix {
|
||||||
@@ -43,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<Matrix> 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<Tuple> 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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -66,6 +148,25 @@ mod tests {
|
|||||||
assert_eq!(15.5, matrix[3][2]);
|
assert_eq!(15.5, matrix[3][2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn matrix_4x4_array() {
|
||||||
|
let m = [
|
||||||
|
[1.0, 2.0, 3.0, 4.0],
|
||||||
|
[5.5, 6.5, 7.5, 8.5],
|
||||||
|
[9.0, 10.0, 11.0, 12.0],
|
||||||
|
[13.5, 14.5, 15.5, 16.5],
|
||||||
|
];
|
||||||
|
|
||||||
|
let matrix = Matrix::from_array(m);
|
||||||
|
assert_eq!(1.0, matrix[0][0]);
|
||||||
|
assert_eq!(4.0, matrix[0][3]);
|
||||||
|
assert_eq!(5.5, matrix[1][0]);
|
||||||
|
assert_eq!(7.5, matrix[1][2]);
|
||||||
|
assert_eq!(11.0, matrix[2][2]);
|
||||||
|
assert_eq!(13.5, matrix[3][0]);
|
||||||
|
assert_eq!(15.5, matrix[3][2]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn matrix_2x2() {
|
fn matrix_2x2() {
|
||||||
let m = vec![
|
let m = vec![
|
||||||
@@ -136,4 +237,44 @@ mod tests {
|
|||||||
|
|
||||||
assert_ne!(m_a, m_b);
|
assert_ne!(m_a, m_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multiply() {
|
||||||
|
let matrix_a = Matrix::from_array([
|
||||||
|
[1.0, 2.0, 3.0, 4.0,],
|
||||||
|
[5.0, 6.0, 7.0, 8.0,],
|
||||||
|
[9.0, 8.0, 7.0, 6.0,],
|
||||||
|
[5.0, 4.0, 3.0, 2.0,],
|
||||||
|
]);
|
||||||
|
let matrix_b = Matrix::from_array([
|
||||||
|
[-2.0, 1.0, 2.0, 3.0,],
|
||||||
|
[3.0, 2.0, 1.0, -1.0,],
|
||||||
|
[4.0, 3.0, 6.0, 5.0,],
|
||||||
|
[1.0, 2.0, 7.0, 8.0,],
|
||||||
|
]);
|
||||||
|
|
||||||
|
let expected = Matrix::from_array([
|
||||||
|
[20.0, 22.0, 50.0, 48.0],
|
||||||
|
[44.0, 54.0, 114.0, 108.0],
|
||||||
|
[40.0, 58.0, 110.0, 102.0,],
|
||||||
|
[16.0, 26.0, 46.0, 42.0],
|
||||||
|
]);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ impl Tuple {
|
|||||||
self.z
|
self.z
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn w(&self) -> f32 {
|
||||||
|
self.w
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_point(&self) -> bool {
|
pub fn is_point(&self) -> bool {
|
||||||
self.w == 1.0
|
self.w == 1.0
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user