rs_math3d/
basis.rs

1// Copyright 2020-Present (c) Raja Lehtihet & Wael El Oraiby
2//
3// Redistribution and use in source and binary forms, with or without
4// modification, are permitted provided that the following conditions are met:
5//
6// 1. Redistributions of source code must retain the above copyright notice,
7// this list of conditions and the following disclaimer.
8//
9// 2. Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12//
13// 3. Neither the name of the copyright holder nor the names of its contributors
14// may be used to endorse or promote products derived from this software without
15// specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27// POSSIBILITY OF SUCH DAMAGE.
28use crate::matrix::*;
29use crate::scalar::*;
30use crate::vector::*;
31
32#[derive(Debug, Clone, Copy)]
33pub enum BasisPlane {
34    YZ,
35    ZX,
36    XY,
37}
38
39impl BasisPlane {
40    pub fn to_id(&self) -> usize {
41        match self {
42            BasisPlane::YZ => 0,
43            BasisPlane::ZX => 1,
44            BasisPlane::XY => 2,
45        }
46    }
47
48    pub fn of_id(id: usize) -> Self {
49        match id {
50            0 => BasisPlane::YZ,
51            1 => BasisPlane::ZX,
52            2 => BasisPlane::XY,
53            _ => panic!("invalid id"),
54        }
55    }
56}
57
58#[derive(Debug, Clone, Copy)]
59#[repr(C)]
60pub struct Basis<T: Scalar> {
61    pub x_axis: Vector3<T>,
62    pub y_axis: Vector3<T>,
63    pub z_axis: Vector3<T>,
64    pub center: Vector3<T>,
65}
66
67impl<T: Scalar> Basis<T> {
68    pub fn center(&self) -> &Vector3<T> {
69        &self.center
70    }
71
72    pub fn center_mut(&mut self) -> &mut Vector3<T> {
73        &mut self.center
74    }
75
76    pub fn to_mat4(&self) -> Matrix4<T> {
77        Matrix4::new(
78            self.x_axis.x,
79            self.x_axis.y,
80            self.x_axis.z,
81            T::zero(),
82            self.y_axis.x,
83            self.y_axis.y,
84            self.y_axis.z,
85            T::zero(),
86            self.z_axis.x,
87            self.z_axis.y,
88            self.z_axis.z,
89            T::zero(),
90            self.center.x,
91            self.center.y,
92            self.center.z,
93            T::one(),
94        )
95    }
96
97    pub fn of_mat4(mat: &Matrix4<T>) -> Self {
98        let col0 = mat.col[0];
99        let col1 = mat.col[1];
100        let col2 = mat.col[2];
101        let col3 = mat.col[3];
102        Self {
103            center: col3.xyz(),
104            x_axis: col0.xyz(),
105            y_axis: col1.xyz(),
106            z_axis: col2.xyz(),
107        }
108    }
109
110    pub fn default() -> Self {
111        Self {
112            center: Vector3::new(T::zero(), T::zero(), T::zero()),
113            x_axis: Vector3::new(T::one(), T::zero(), T::zero()),
114            y_axis: Vector3::new(T::zero(), T::one(), T::zero()),
115            z_axis: Vector3::new(T::zero(), T::zero(), T::one()),
116        }
117    }
118
119    pub fn default_with_center(center: &Vector3<T>) -> Self {
120        Self {
121            center: *center,
122            x_axis: Vector3::new(T::one(), T::zero(), T::zero()),
123            y_axis: Vector3::new(T::zero(), T::one(), T::zero()),
124            z_axis: Vector3::new(T::zero(), T::zero(), T::one()),
125        }
126    }
127
128    pub fn plane_axis(&self, plane: BasisPlane) -> (&Vector3<T>, &Vector3<T>) {
129        match plane {
130            BasisPlane::YZ => (&self.y_axis, &self.z_axis),
131            BasisPlane::ZX => (&self.z_axis, &self.x_axis),
132            BasisPlane::XY => (&self.x_axis, &self.y_axis),
133        }
134    }
135
136    pub fn plane_axis_mut(&mut self, plane: BasisPlane) -> (&mut Vector3<T>, &mut Vector3<T>) {
137        match plane {
138            BasisPlane::YZ => (&mut self.y_axis, &mut self.z_axis),
139            BasisPlane::ZX => (&mut self.z_axis, &mut self.x_axis),
140            BasisPlane::XY => (&mut self.x_axis, &mut self.y_axis),
141        }
142    }
143
144    pub fn to_mat3(&self) -> Matrix3<T> {
145        Matrix3::new(
146            self.x_axis.x,
147            self.x_axis.y,
148            self.x_axis.z,
149            self.y_axis.x,
150            self.y_axis.y,
151            self.y_axis.z,
152            self.z_axis.x,
153            self.z_axis.y,
154            self.z_axis.z,
155        )
156    }
157
158    pub fn of_center_mat3(center: &Vector3<T>, m: Matrix3<T>) -> Self {
159        Self {
160            center: *center,
161            x_axis: m.col[0],
162            y_axis: m.col[1],
163            z_axis: m.col[2],
164        }
165    }
166}