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}