rssn/numerical/
computer_graphics.rs

1//! # Numerical 3D Computer Graphics
2//!
3//! This module provides fundamental structs and functions for 3D computer graphics,
4//! including representations for points and vectors, standard vector operations
5//! (dot product, cross product), and functions to generate 4x4 transformation
6//! matrices for translation, scaling, and rotation.
7use crate::numerical::matrix::Matrix;
8use std::ops::{Add, Div, Mul, Sub};
9#[derive(Debug, Clone, Copy, PartialEq)]
10pub struct Point3D {
11    pub x: f64,
12    pub y: f64,
13    pub z: f64,
14}
15#[derive(Debug, Clone, Copy, PartialEq)]
16pub struct Vector3D {
17    pub x: f64,
18    pub y: f64,
19    pub z: f64,
20}
21impl Vector3D {
22    /// Computes the magnitude (length) of the vector.
23    ///
24    /// # Returns
25    /// The magnitude as an `f64`.
26    pub fn magnitude(&self) -> f64 {
27        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
28    }
29    /// Normalizes the vector to have a magnitude of 1.
30    ///
31    /// If the vector's magnitude is zero, it returns the original vector unchanged.
32    ///
33    /// # Returns
34    /// A new `Vector3D` representing the normalized vector.
35    #[must_use]
36    pub fn normalize(&self) -> Self {
37        let mag = self.magnitude();
38        if mag == 0.0 {
39            *self
40        } else {
41            *self / mag
42        }
43    }
44}
45impl Add for Vector3D {
46    type Output = Self;
47    /// Performs vector addition component-wise.
48    fn add(self, rhs: Self) -> Self {
49        Vector3D {
50            x: self.x + rhs.x,
51            y: self.y + rhs.y,
52            z: self.z + rhs.z,
53        }
54    }
55}
56impl Sub for Vector3D {
57    type Output = Self;
58    /// Performs vector subtraction component-wise.
59    fn sub(self, rhs: Self) -> Self {
60        Vector3D {
61            x: self.x - rhs.x,
62            y: self.y - rhs.y,
63            z: self.z - rhs.z,
64        }
65    }
66}
67impl Mul<f64> for Vector3D {
68    type Output = Self;
69    /// Performs scalar multiplication of the vector.
70    fn mul(self, rhs: f64) -> Self {
71        Vector3D {
72            x: self.x * rhs,
73            y: self.y * rhs,
74            z: self.z * rhs,
75        }
76    }
77}
78impl Div<f64> for Vector3D {
79    type Output = Self;
80    /// Performs scalar division of the vector.
81    fn div(self, rhs: f64) -> Self {
82        Vector3D {
83            x: self.x / rhs,
84            y: self.y / rhs,
85            z: self.z / rhs,
86        }
87    }
88}
89/// Computes the dot product of two `Vector3D`s.
90///
91/// The dot product (or scalar product) is a scalar value that represents
92/// the projection of one vector onto another. It is defined as `v1.x*v2.x + v1.y*v2.y + v1.z*v2.z`.
93///
94/// # Arguments
95/// * `v1` - The first vector.
96/// * `v2` - The second vector.
97///
98/// # Returns
99/// The scalar dot product as an `f64`.
100pub fn dot_product(v1: &Vector3D, v2: &Vector3D) -> f64 {
101    v1.x * v2.x + v1.y * v2.y + v1.z * v2.z
102}
103/// Computes the cross product of two `Vector3D`s.
104///
105/// The cross product (or vector product) results in a new vector that is
106/// perpendicular to both input vectors. Its magnitude is equal to the area
107/// of the parallelogram that the two vectors form.
108///
109/// # Arguments
110/// * `v1` - The first vector.
111/// * `v2` - The second vector.
112///
113/// # Returns
114/// A new `Vector3D` representing the cross product.
115pub fn cross_product(v1: &Vector3D, v2: &Vector3D) -> Vector3D {
116    Vector3D {
117        x: v1.y * v2.z - v1.z * v2.y,
118        y: v1.z * v2.x - v1.x * v2.z,
119        z: v1.x * v2.y - v1.y * v2.x,
120    }
121}
122/// Generates a 4x4 translation matrix.
123///
124/// This matrix can be used to move objects in 3D space by `dx`, `dy`, and `dz`.
125///
126/// # Arguments
127/// * `dx` - Translation along the x-axis.
128/// * `dy` - Translation along the y-axis.
129/// * `dz` - Translation along the z-axis.
130///
131/// # Returns
132/// A `Matrix<f64>` representing the translation transformation.
133pub fn translation_matrix(dx: f64, dy: f64, dz: f64) -> Matrix<f64> {
134    Matrix::new(
135        4,
136        4,
137        vec![
138            1.0, 0.0, 0.0, dx, 0.0, 1.0, 0.0, dy, 0.0, 0.0, 1.0, dz, 0.0, 0.0, 0.0, 1.0,
139        ],
140    )
141}
142/// Generates a 4x4 scaling matrix.
143///
144/// This matrix can be used to scale objects in 3D space by `sx`, `sy`, and `sz`.
145///
146/// # Arguments
147/// * `sx` - Scaling factor along the x-axis.
148/// * `sy` - Scaling factor along the y-axis.
149/// * `sz` - Scaling factor along the z-axis.
150///
151/// # Returns
152/// A `Matrix<f64>` representing the scaling transformation.
153pub fn scaling_matrix(sx: f64, sy: f64, sz: f64) -> Matrix<f64> {
154    Matrix::new(
155        4,
156        4,
157        vec![
158            sx, 0.0, 0.0, 0.0, 0.0, sy, 0.0, 0.0, 0.0, 0.0, sz, 0.0, 0.0, 0.0, 0.0, 1.0,
159        ],
160    )
161}
162/// Generates a 4x4 rotation matrix around the X-axis.
163///
164/// # Arguments
165/// * `angle_rad` - The rotation angle in radians.
166///
167/// # Returns
168/// A `Matrix<f64>` representing the rotation transformation around the X-axis.
169pub fn rotation_matrix_x(angle_rad: f64) -> Matrix<f64> {
170    let (s, c) = angle_rad.sin_cos();
171    Matrix::new(
172        4,
173        4,
174        vec![
175            1.0, 0.0, 0.0, 0.0, 0.0, c, -s, 0.0, 0.0, s, c, 0.0, 0.0, 0.0, 0.0, 1.0,
176        ],
177    )
178}