├── .github └── workflows │ ├── build.yml │ └── publish.yml ├── .gitignore ├── Cargo.toml ├── conv.py ├── license.md ├── readme.md ├── src ├── lib.rs ├── mat.rs ├── num.rs ├── quat.rs ├── swizz.rs └── vec.rs └── tests └── tests.rs /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | on: 3 | push: 4 | branches: ["master"] 5 | pull_request: 6 | branches: ["master"] 7 | 8 | env: 9 | CARGO_TERM_COLOR: always 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: build 17 | run: cargo build --verbose 18 | - name: test 19 | run: cargo test --verbose --features serde 20 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: publish 2 | on: 3 | push: 4 | tags: 5 | - '*' 6 | env: 7 | CARGO_TERM_COLOR: always 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v3 13 | - name: build 14 | run: cargo build --verbose 15 | - name: test 16 | run: cargo test --verbose 17 | - name: create_release 18 | id: create_release 19 | uses: actions/create-release@v1 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | with: 23 | tag_name: ${{ github.ref }} 24 | release_name: Release ${{ github.ref }} 25 | draft: false 26 | prerelease: false 27 | - name: bump_version 28 | run: | 29 | export REFS_VERSION=${{ github.ref }} 30 | export VERSION=$(echo $REFS_VERSION| cut -d'/' -f 3) 31 | echo $VERSION 32 | sed -i -E "1,/[0-9]+.[0-9]+.[0-9]+/ s/[0-9]+.[0-9]+.[0-9]+/$VERSION/g" Cargo.toml 33 | git config user.name github-actions 34 | git config user.email github-actions@github.com 35 | git add . 36 | git commit -m "- bump Cargo.toml version to $VERSION for publish" 37 | git push origin HEAD:master 38 | - name: publish 39 | run: | 40 | cargo login ${{ secrets.CARGO_REGISTRY_TOKEN }} 41 | cargo publish --dry-run 42 | cargo publish 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "maths-rs" 3 | version = "0.2.7" 4 | edition = "2021" 5 | authors = ["polymonster "] 6 | description = "A linear algebra library for gamedev and graphics" 7 | readme = "readme.md" 8 | homepage = "https://github.com/polymonster/maths-rs" 9 | repository = "https://github.com/polymonster/maths-rs" 10 | keywords = ["linear-algebra", "math", "vector", "matrix", "quaternion"] 11 | categories = ["mathematics", "game-development", "graphics"] 12 | license-file = "license.md" 13 | 14 | [features] 15 | short_hand_constructors = [] 16 | lhs_scalar_vec_ops = [] 17 | casts = [] 18 | short_types = [] 19 | serde = ["dep:serde", "serde_json"] 20 | hash = [] 21 | default = ["short_hand_constructors", "lhs_scalar_vec_ops", "casts", "short_types"] 22 | 23 | [dependencies] 24 | serde = {version = "1.0", features = ["derive"], optional=true} 25 | serde_json = {version = "1.0.81", optional=true} -------------------------------------------------------------------------------- /conv.py: -------------------------------------------------------------------------------- 1 | from dataclasses import replace 2 | 3 | import sys 4 | 5 | # converts c++ test code to rust, with some caveats 6 | def conv(str): 7 | str = str.replace("const vec3f", "let") 8 | str = str.replace("const mat4", "let") 9 | str = str.replace("vec3f", "let") 10 | str = str.replace("(f32)", "") 11 | str = str.replace("f32", "let") 12 | str = str.replace("bool(1)", "true") 13 | str = str.replace("bool(0)", "false") 14 | str = str.replace("bool", "let") 15 | str = str.replace("u32(0)", "Classification::Intersects") 16 | str = str.replace("u32(1)", "Classification::Behind") 17 | str = str.replace("u32(2)", "Classification::Infront") 18 | str = str.replace("u32", "let") 19 | str = str.replace("{", "vec3f(") 20 | str = str.replace("}", ")") 21 | str = str.replace("REQUIRE", "assert_eq!") 22 | str = str.replace("require_func", "") 23 | str = str.replace("((", "(") 24 | str = str.replace("))", ")") 25 | print(str) 26 | 27 | 28 | if __name__ == "__main__": 29 | conv(sys.argv[1]) -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Alex Dixon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Maths 2 | 3 | [![build](https://github.com/polymonster/maths-rs/actions/workflows/build.yml/badge.svg)](https://github.com/polymonster/maths-rs/actions/workflows/build.yml) 4 | [![publish](https://github.com/polymonster/maths-rs/actions/workflows/publish.yml/badge.svg)](https://github.com/polymonster/maths-rs/actions/workflows/build.yml) 5 | [![docs](https://img.shields.io/docsrs/maths-rs/latest)](https://docs.rs/maths-rs/latest/maths_rs/index.html) 6 | [![crates](https://img.shields.io/crates/v/maths-rs)](https://crates.io/crates/maths-rs) 7 | 8 | Maths is a linear algebra library which aims to be ergonmic and fun to use for gamedev and graphics. If you like writing shaders you should feel right at home. In addition to the usual implementation of vectors, matrices and quaternions it includes a comprehensive collection of utility functions, vector swizzling, intersection tests, point tests, distance functions, trig functions, graphs and signal processing functions. 9 | 10 | Most features of the crate are enabled by default, you can choose to opt out if you wish. `serde` and `hash` support is optional and disabled by default they can be enabled with: 11 | 12 | ```text 13 | features = ["serde", "hash"] 14 | ``` 15 | 16 | Most of this code was ported from my C++ [maths library](https://github.com/polymonster/maths), there is a live [WebGL demo](https://www.polymonster.co.uk/pmtech/examples/maths_functions.html) which showcases a lot of the features in an interactive way and was used to generate test data and verify the functions work correctly. 17 | 18 | ## Vector 19 | 20 | This is a narrow vector library with `Vec2`, `Vec3` and `Vec4` column-vector implementations. 21 | 22 | ```rust 23 | /// abbrivated types #[cfg(feature = "short_types")] 24 | pub type Vec2f = Vec2; 25 | pub type Vec3f = Vec3; 26 | pub type Vec4f = Vec4; 27 | pub type Vec4d = Vec4; 28 | /// ... etc 29 | 30 | // construct a vector 31 | let v2 = Vec2f::new(2.0, 3.0); 32 | 33 | // the short way #[cfg(feature = "short_hand_constructors")] 34 | let v2_short = vec2f(5.0, 6.0); 35 | 36 | // splat a scalar #[cfg(feature = "short_hand_constructors")] 37 | let v3_splat = splat3f(9.0); 38 | 39 | // quick common constructors 40 | let y = Vec3f::unit_y(); 41 | let b = Vec3f::blue(); 42 | let z = Vec3f::zero(); 43 | let o = Vec3f::one(); 44 | let m = Vec3f::max_value(); 45 | // + more 46 | 47 | // default 48 | let vdefault = Vec3f::default(); // default is zero 49 | 50 | // arithmetic / operators 51 | let result = v2 * v2_short; 52 | let result = v2 + v2_short; 53 | let result = v2 / v2_short; 54 | let result = v2 - v2_short; 55 | let result = -v2; 56 | 57 | // arithmetic with values and refs so no need for dereferencing 58 | let v2ref = &v2; 59 | let result = v2ref * v2; // ref * value 60 | let result = v2 * v2ref; // value * ref 61 | let result = v2ref * v2ref; // ref * ref 62 | 63 | // construct from tuples and vectors of various sizes 64 | let v4 = Vec4f::from((v2, v2)); // vec4 from 2x v2's 65 | let v3 = Vec3f::from((v2, 1.0)); // vec3 from 1x v2 and 1x scalar 66 | let v2 = Vec2f::from((5.0, 6.0)); // vec2 from 2x scalars 67 | let v4 = Vec4f::from((v2, 0.0, 1.0)); // vec4 from 1x v2 and 2x scalars 68 | let v4 = Vec4f::from(v2); // vec4 from vec2 (splat 0's) 69 | let v2 = Vec2f::from(v4); // vec2 from vec4 (truncate) 70 | // .. and so on 71 | 72 | // swizzling 73 | let wxyz = v4.wxyz(); // swizzle 74 | let xyz = v4.xyz(); // truncate 75 | let xxx = v4.xxx(); // and so on.. 76 | let xy = v3.yx(); // .. 77 | 78 | // mutable swizzles 79 | let mut v = Vec4f::zero(); 80 | x.set_xwyz(v); // set swizzle 81 | x.set_xy(v.yx()); // assign truncated 82 | x.set_yzx(v.zzz()); // etc.. 83 | 84 | // type casts #[cfg(feature = "casts")] 85 | let veci = Vec3i::from(vec3f(1.0, 2.0, 3.0)); 86 | ``` 87 | 88 | ## Matrix 89 | 90 | Row-major matrices with `Mat2`, `Mat3`, `Mat34` and `Mat4` implementations. 91 | 92 | ```rust 93 | /// abbrivated types #[cfg(feature = "short_types")] 94 | pub type Mat2f = Mat2; 95 | pub type Mat3f = Mat3; 96 | pub type Mat34f = Mat34; 97 | pub type Mat4f = Mat4; 98 | 99 | // identity 100 | let mat_ident = Mat4f::identity(); 101 | let mat_default = Mat4f::default(); // default is identity 102 | 103 | // construct from floats 104 | let m4 = Mat4f::new( 105 | 1.0, 0.0, 0.0, 0.0, 106 | 0.0, 1.0, 0.0, 0.0, 107 | 0.0, 0.0, 1.0, 0.0, 108 | 0.0, 0.0, 0.0, 1.0 109 | ); 110 | 111 | // construct from common matrices 112 | let m34 = Mat34f::from_translation(vec3f(50.0, -10.0, 20.0)); 113 | let m4 = Mat4f::from_z_rotation(f32::deg_to_rad(90.0)); 114 | let m4 = Mat4f::from_scale(vec3f(10.0, 2.0, 30.0)); 115 | let m3 = Mat34f::from_scale(vec3f(10.0, 2.0, 30.0)); 116 | 117 | // arithmetic 118 | // matrix multiplication 119 | let result = x4 * m4; 120 | 121 | // vector transformation 122 | let v4 = vec4f(0.0, 1.0, 0.0, 1.0); 123 | let result = m4 * v4; 124 | 125 | // arithmetic with values and refs so no need for dereferencing 126 | let v4ref = &v4; 127 | let m4ref = &m4; 128 | let result = m4ref * v4; // ref * value 129 | let result = m4 * v4ref; // value * ref 130 | let result = m4ref * v4ref; // ref * ref 131 | 132 | // functions 133 | let det = m4.determinant(); 134 | let inv = m4.inverse(); 135 | 136 | // construct rows from tuples 137 | let m3v = Mat3f::from(( 138 | vec3f(1.0, 2.0, 3.0), 139 | vec3f(4.0, 5.0, 6.0), 140 | vec3f(7.0, 8.0, 9.0) 141 | )); 142 | 143 | let m4v = Mat4f::from(( 144 | vec4f(1.0, 2.0, 3.0, 4.0), 145 | vec4f(5.0, 6.0, 7.0, 8.0), 146 | vec4f(9.0, 10.0, 11.0, 12.0), 147 | vec4f(13.0, 14.0, 15.0, 16.0), 148 | )); 149 | 150 | let m4_rot = Mat4f::from(m3v); // mat4 from mat3 151 | let m4r = Mat3f::from(quat); // from quaternion 152 | 153 | // type casts #[cfg(feature = "casts")] 154 | let matd = Mat4d::from(m4v); 155 | ``` 156 | 157 | ## Quaternion 158 | 159 | Generic floating-point quaternion. 160 | 161 | ```rust 162 | // abbrivated types #[cfg(feature = "short_types")] 163 | pub type Quatf = Quat; 164 | pub type Quatd = Quat; 165 | 166 | // construct from euler angles 167 | let q = Quatf::from_euler_angles(x, y, z); 168 | 169 | // construct from axis angle 170 | let q2 = Quatf::from_axis_angle(axis, angle); 171 | 172 | // identity 173 | let qident = Quatf::identity(); 174 | let qdefault = Quat::default(); // default is identity 175 | 176 | // arithmetic 177 | let q3 = q * q2; 178 | let q4 = q + q2; 179 | let q5 = q - q2; 180 | let q6 = -q; 181 | 182 | // quat * vec 183 | let v = vec3f(1.0, 0.0, 0.0); 184 | let vv = q * v3; 185 | 186 | // multiply with refs or values without need to deref 187 | let qref = &q; 188 | let vref = &v3; 189 | 190 | let qr = qref * v3; 191 | let qr = q * v3ref; 192 | let qr = qref * vref; 193 | 194 | // functions 195 | let rev = q.reverse(); 196 | let inv = q.inverse(); 197 | 198 | // type casts #[cfg(feature = "casts")] 199 | let quatd = Quatd::from(q2); 200 | ``` 201 | 202 | ## Generic Functions 203 | 204 | You can use generic functions on different sized vectors or scalars: `min, max, clamp, step, signum, copysign, abs, deg_to_rad, rad_to_deg, floor, ceil, round, approx, sqrt, powi, powf, sqrt, frac, trunc, modf, rsqrt, recip lerp, nlerp, slerp, smoothstep, dot, perp, cross, mag, mag2, length, distance, dist, dist2, normalize, chebyshev_normalize` 205 | 206 | ```rust 207 | // numeric ops 208 | let int_abs = abs(-1); 209 | let float_abs = abs(-1.0); 210 | let int_max = max(5, 6); 211 | let float_max = max(1.0, 2.0); 212 | let vec_max = max(vec3f(1.0, 1.0, 1.0), vec3f(2.0, 2.0, 2.0)); 213 | let vec_min = min(vec4f(8.0, 7.0, 6.0, 5.0), vec4f(-8.0, -7.0, -6.0, -5.0)); 214 | 215 | // float ops 216 | let fsat = saturate(22.0); 217 | let vsat = saturate(vec3f(22.0, 22.0, 22.0)); 218 | let f = floor(5.5); 219 | let vc = ceil(vec3f(5.0, 5.0, 5.0)); 220 | 221 | // vector ops 222 | let dp = dot(vec2, vec2); 223 | let dp = dot(vec3, vec3); 224 | let cp = cross(vec3, Vec3::unit_y()); 225 | let n = normalize(vec3); 226 | let qn = normalize(quat); 227 | let m = mag(vec4); 228 | let d = dist(vec31, vec32); 229 | 230 | // interpolation 231 | let fi : f32 = lerp(10.0, 2.0, 0.2); 232 | let vi = lerp(vec2, vec2, 0.5); 233 | let qi = lerp(quat1, quat2, 0.75); 234 | let qs = slerp(quat1, quat2, 0.1); 235 | let vn = nlerp(vec2, vec2, 0.3); 236 | let f = smoothstep(5.0, 1.0, f); 237 | ``` 238 | 239 | ## Trigonometry and Logarithmic Functions 240 | 241 | These functions are availble for all floating point scalar or vector types: `cos, sin, tan, acos, asin, atan, cosh, sinh, tanh, sin_cos, atan2, exp, exp2, log2, log10`. 242 | 243 | ```rust 244 | // trig functions 245 | let s = sin(vec2); 246 | let x = cos(vec3); 247 | let f = acos(x); 248 | let d = atan2(y, x); 249 | 250 | // exp / log 251 | let d = exp(y); 252 | let l = log2(x); 253 | ``` 254 | 255 | ### Functions 256 | 257 | Plane Classification: `point_vs_plane, aabb_vs_plane, sphere_vs_plane, capsule_vs_plane, cone_vs_plane`. 258 | 259 | Overlaps: `sphere_vs_sphere, sphere_vs_aabb, sphere_vs_obb, aabb_vs_aabb, aabb_vs_frustum, sphere_vs_frustum, sphere_vs_capsule, capsule_vs_capsule, obb_vs_obb, aabb_vs_obb, convex_hull_vs_convex_hull, gjk_2d, gjk_3d`. 260 | 261 | Point Inside: `point_inside_aabb, point_inside_sphere, point_inside_obb, point_inside_triangle, point_inside_cone, point_inside_convex_hull, point_inside_poly, point_inside_frustum`. 262 | 263 | Closest Point: `closest_point_on_aabb, closest_point_on_line, closest_point_on_plane, closest_point_on_obb, closest_point_on_sphere, closest_point_on_ray, closest_point_on_triangle, closest_point_on_polygon, closest_point_on_convex_hull, closest_point_on_cone`. 264 | 265 | Point Distance: `point_aabb_distance, point_segment_distance, point_triangle_distance, distance_on_line, point_plane_distance, plane_distance, point_sphere_distance, point_polygon_distance, point_convex_hull_distance, point_cone_distance, point_obb_distance`. 266 | 267 | Ray / Line: `ray_vs_plane, ray_vs_triangle, ray_vs_sphere, ray_vs_line_segment, ray_vs_aabb, ray_vs_obb, ray_vs_capsule, ray_vs_cylinder, line_vs_line, line_vs_poly, shortest_line_segment_between_lines, shortest_line_segment_between_line_segments`. 268 | 269 | Shader Style Functions: `dot, cross, normalize, mag, mag2, dist, dist2, triple, vector_triple, lerp, nlerp, slerp, saturate, clamp, normalize, chebyshev_normalize, all, any, min, max, smoothstep, step, round, floor, ceil, abs, frac, trunc, exp, exp2, log, log2, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh`. 270 | 271 | Graph Functions: `smooth_start, smooth_stop, impulse, cubic_pulse, exp_step, parabola, pcurve, exp_sustained_impulse, sinc, gain, almost_identity, integral_smoothstep, quad_impulse, poly_impulse`. 272 | 273 | \+ More included! 274 | -------------------------------------------------------------------------------- /src/mat.rs: -------------------------------------------------------------------------------- 1 | 2 | use crate::vec::*; 3 | use crate::num::*; 4 | use crate::quat::*; 5 | 6 | use std::ops::Index; 7 | use std::ops::IndexMut; 8 | use std::ops::Mul; 9 | use std::ops::MulAssign; 10 | use std::ops::Deref; 11 | use std::ops::DerefMut; 12 | 13 | use std::cmp::PartialEq; 14 | 15 | use std::fmt::Display; 16 | use std::fmt::Formatter; 17 | 18 | /// row major matrix index layouts 19 | /// 20 | /// Mat2: 21 | /// 00 01 22 | /// 02 03 23 | /// 24 | /// Mat3: 25 | /// 00 01 02 26 | /// 03 04 05 27 | /// 06 07 08 28 | /// 29 | /// Mat34: 30 | /// 00 01 02 03 31 | /// 04 05 06 07 32 | /// 08 09 10 11 33 | /// 34 | /// Mat44: 35 | /// 00 01 02 03 36 | /// 04 05 06 07 37 | /// 08 09 10 11 38 | /// 12 13 14 15 39 | 40 | /// creates the basic generic traits for row-major matrices 41 | macro_rules! mat_impl { 42 | ($MatN:ident, $rows:expr, $cols:expr, $elems:expr, 43 | $RowVecN:ident { $($row_field:ident, $row_field_index:expr),* }, 44 | $ColVecN:ident { $($col_field:ident, $col_field_index:expr),* } ) => { 45 | 46 | #[cfg_attr(feature="serde", derive(serde::Serialize, serde::Deserialize))] 47 | #[cfg_attr(feature="hash", derive(Hash))] 48 | #[derive(Debug, Copy, Clone)] 49 | #[repr(C)] 50 | pub struct $MatN { 51 | pub m: [T; $elems] 52 | } 53 | 54 | /// index into matrix with tuple \[(row, column)\] 55 | impl Index<(usize, usize)> for $MatN { 56 | type Output = T; 57 | fn index(&self, rc: (usize, usize)) -> &Self::Output { 58 | &self.m[rc.0 * $cols + rc.1] 59 | } 60 | } 61 | 62 | /// mutably index into matrix with tuple \[(row, column)\] 63 | impl IndexMut<(usize, usize)> for $MatN { 64 | fn index_mut(&mut self, rc: (usize, usize)) -> &mut Self::Output { 65 | &mut self.m[rc.0 * $cols + rc.1] 66 | } 67 | } 68 | 69 | /// index into matrix raw array single \[index\] 70 | impl Index for $MatN { 71 | type Output = T; 72 | fn index(&self, index: usize) -> &Self::Output { 73 | &self.m[index] 74 | } 75 | } 76 | 77 | /// mutably index into matrix raw array with single \[index\] 78 | impl IndexMut for $MatN { 79 | fn index_mut(&mut self, index: usize) -> &mut Self::Output { 80 | &mut self.m[index] 81 | } 82 | } 83 | 84 | /// deref matrix as a slice of T 85 | impl Deref for $MatN where T: Number { 86 | type Target = [T]; 87 | fn deref(&self) -> &Self::Target { 88 | unsafe { 89 | std::slice::from_raw_parts(&self.m[0], $elems) 90 | } 91 | } 92 | } 93 | 94 | /// mutably deref matrix as a slice of T 95 | impl DerefMut for $MatN where T: Number { 96 | fn deref_mut(&mut self) -> &mut [T] { 97 | unsafe { 98 | std::slice::from_raw_parts_mut(&mut self.m[0], $elems) 99 | } 100 | } 101 | } 102 | 103 | /// displays like: 104 | /// [1.0, 0.0, 0.0] 105 | /// [0.0, 1.0, 1.0] 106 | /// [0.0, 0.0, 1.0] 107 | impl Display for $MatN where T: Display { 108 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 109 | let mut output = String::from(""); 110 | for r in 0..$rows { 111 | output += &String::from("["); 112 | for c in 0..$cols { 113 | output += &self[(r, c)].to_string(); 114 | if c < $cols-1 { 115 | output += &String::from(", "); 116 | } 117 | 118 | } 119 | output += "]"; 120 | if r < $rows-1 { 121 | output += "\n"; 122 | } 123 | } 124 | write!(f, "{}", output) 125 | } 126 | } 127 | 128 | /// default to identity matrix 129 | impl Default for $MatN where T: Number { 130 | fn default() -> Self { 131 | Self::identity() 132 | } 133 | } 134 | 135 | impl Eq for $MatN where T: Eq {} 136 | impl PartialEq for $MatN where T: PartialEq { 137 | fn eq(&self, other: &Self) -> bool { 138 | for i in 0..$elems { 139 | if self.m[i] != other.m[i] { 140 | return false; 141 | } 142 | } 143 | true 144 | } 145 | } 146 | 147 | impl $MatN where T: Float + FloatOps { 148 | /// compare if matrices are approximately equal to account for floating point precision 149 | pub fn approx(lhs: Self, rhs: Self, eps: T) -> bool { 150 | for i in 0..$elems { 151 | if !T::approx(lhs.m[i], rhs.m[i], eps) { 152 | return false; 153 | } 154 | } 155 | true 156 | } 157 | } 158 | 159 | impl $MatN where T: Number { 160 | /// initialise matrix to all zero's 161 | pub fn zero() -> $MatN { 162 | $MatN { 163 | m: [T::zero(); $elems] 164 | } 165 | } 166 | 167 | /// initialise matrix to identity 168 | pub fn identity() -> $MatN { 169 | unsafe { 170 | let mut mat : $MatN = std::mem::zeroed(); 171 | for r in 0..$rows { 172 | for c in 0..$cols { 173 | if c == r { 174 | mat.set(r, c, T::one()); 175 | } 176 | } 177 | } 178 | mat 179 | } 180 | } 181 | 182 | pub const fn get_num_rows(&self) -> usize { 183 | $rows 184 | } 185 | 186 | pub const fn get_num_columns(&self) -> usize { 187 | $cols 188 | } 189 | 190 | /// get single element from the matrix at row, column index 191 | pub fn at(self, row: u32, column: u32) -> T { 192 | let urow = row as usize; 193 | let ucol = column as usize; 194 | self.m[urow * $cols + ucol] 195 | } 196 | 197 | /// set a single element of the matrix at row, column index 198 | pub fn set(&mut self, row: u32, column: u32, value: T) { 199 | let urow = row as usize; 200 | let ucol = column as usize; 201 | self.m[urow * $cols + ucol] = value 202 | } 203 | 204 | /// gets a single row of the matrix in n sized vec where in is the column count of the matrix 205 | pub fn get_row(self, row: u32) -> $RowVecN { 206 | let urow = row as usize; 207 | $RowVecN { 208 | $($row_field: self.m[urow * $cols + $row_field_index],)+ 209 | } 210 | } 211 | 212 | // sets a single row of the matrix by an n sized vec, where n is the column count of the matrix 213 | pub fn set_row(&mut self, row: u32, value: $RowVecN) { 214 | let urow = row as usize; 215 | $(self.m[urow * $cols + $row_field_index] = value.$row_field;)+ 216 | } 217 | 218 | /// gets a single column of the matrix in n sized vec where in is the row count of the matrix 219 | pub fn get_column(self, column: u32) -> $ColVecN { 220 | let ucol = column as usize; 221 | $ColVecN { 222 | $($col_field: self.m[$col_field_index * $cols + ucol],)+ 223 | } 224 | } 225 | 226 | /// sets a single column of the matrix by an n sized vec, where n is the row count of the matrix 227 | pub fn set_column(&mut self, column: u32, value: $ColVecN) { 228 | let ucol = column as usize; 229 | $(self.m[$col_field_index * $cols + ucol] = value.$col_field;)+ 230 | } 231 | 232 | /// returns a slice T of the matrix 233 | pub fn as_slice(&self) -> &[T] { 234 | unsafe { 235 | std::slice::from_raw_parts(&self.m[0], $elems) 236 | } 237 | } 238 | 239 | /// returns a mutable slice T of the matrix 240 | pub fn as_mut_slice(&mut self) -> &mut [T] { 241 | unsafe { 242 | std::slice::from_raw_parts_mut(&mut self.m[0], $elems) 243 | } 244 | } 245 | 246 | /// returns a slice of bytes for the matrix 247 | pub fn as_u8_slice(&self) -> &[u8] { 248 | unsafe { 249 | std::slice::from_raw_parts((&self.m[0] as *const T) as *const u8, std::mem::size_of::<$MatN>()) 250 | } 251 | } 252 | } 253 | } 254 | } 255 | 256 | macro_rules! mat_cast { 257 | ($MatN:ident, $count:expr, $t:ident, $u:ident) => { 258 | impl From<$MatN<$u>> for $MatN<$t> { 259 | /// cast matrix from type u to type t 260 | fn from(other: $MatN<$u>) -> $MatN<$t> { 261 | unsafe { 262 | let mut mm : $MatN<$t> = std::mem::zeroed(); 263 | for i in 0..$count { 264 | mm.m[i] = other.m[i] as $t; 265 | } 266 | mm 267 | } 268 | } 269 | } 270 | 271 | impl From<$MatN<$t>> for $MatN<$u> { 272 | /// cast matrix from type t to type u 273 | fn from(other: $MatN<$t>) -> $MatN<$u> { 274 | unsafe { 275 | let mut mm : $MatN<$u> = std::mem::zeroed(); 276 | for i in 0..$count { 277 | mm.m[i] = other.m[i] as $u; 278 | } 279 | mm 280 | } 281 | } 282 | } 283 | } 284 | } 285 | 286 | #[cfg(feature = "casts")] 287 | mat_cast!(Mat2, 4, f32, f64); 288 | mat_cast!(Mat3, 9, f32, f64); 289 | mat_cast!(Mat34, 12, f32, f64); 290 | mat_cast!(Mat4, 16, f32, f64); 291 | 292 | // 293 | // From 294 | // 295 | 296 | /// intialse matrix from tuple of 4 elements 297 | impl From<(T, T, T, T)> for Mat2 where T: Number { 298 | fn from(other: (T, T, T, T)) -> Mat2 { 299 | Mat2 { 300 | m: [ 301 | other.0, other.1, 302 | other.2, other.3 303 | ] 304 | } 305 | } 306 | } 307 | 308 | /// constructs Mat3 from tuple of 2 2D row vectors 309 | impl From<(Vec2, Vec2)> for Mat2 where T: Number { 310 | fn from(other: (Vec2, Vec2)) -> Mat2 { 311 | Mat2 { 312 | m: [ 313 | other.0.x, other.0.y, 314 | other.1.x, other.1.y 315 | ] 316 | } 317 | } 318 | } 319 | 320 | /// constructs Mat3 from 3x3 matrix truncating the 3rd row and column 321 | impl From> for Mat2 where T: Number { 322 | fn from(other: Mat3) -> Mat2 { 323 | Mat2 { 324 | m: [ 325 | other.m[0], other.m[1], 326 | other.m[3], other.m[4], 327 | ] 328 | } 329 | } 330 | } 331 | 332 | /// constructs Mat3 from 3x4 matrix truncating the 3rd row and 3rd and 4th column 333 | impl From> for Mat2 where T: Number { 334 | fn from(other: Mat34) -> Mat2 { 335 | Mat2 { 336 | m: [ 337 | other.m[0], other.m[1], 338 | other.m[4], other.m[5], 339 | ] 340 | } 341 | } 342 | } 343 | 344 | /// constructs Mat3 from 3x4 matrix truncating the 3rd and 4th row and 3rd and 4th column 345 | impl From> for Mat2 where T: Number { 346 | fn from(other: Mat4) -> Mat2 { 347 | Mat2 { 348 | m: [ 349 | other.m[0], other.m[1], 350 | other.m[4], other.m[5], 351 | ] 352 | } 353 | } 354 | } 355 | 356 | /// constructs Mat3 from a Mat2 initialising the 2x2 part and setting the 3rd column and row to identity 357 | impl From> for Mat3 where T: Number { 358 | fn from(other: Mat2) -> Mat3 { 359 | Mat3 { 360 | m: [ 361 | other.m[0], other.m[1], T::zero(), 362 | other.m[2], other.m[3], T::zero(), 363 | T::zero(), T::zero(), T::one() 364 | ] 365 | } 366 | } 367 | } 368 | 369 | /// construct a Mat3 from a Mat34 initialising the 3x3 part and truncation the 4th column 370 | impl From> for Mat3 where T: Number { 371 | fn from(other: Mat34) -> Mat3 { 372 | Mat3 { 373 | m: [ 374 | other.m[0], other.m[1], other.m[2], 375 | other.m[4], other.m[5], other.m[6], 376 | other.m[8], other.m[9], other.m[10], 377 | ] 378 | } 379 | } 380 | } 381 | 382 | /// construct a Mat3 from a Mat44 initialising the 3x3 part and truncation the 4th row and column 383 | impl From> for Mat3 where T: Number { 384 | fn from(other: Mat4) -> Mat3 { 385 | Mat3 { 386 | m: [ 387 | other.m[0], other.m[1], other.m[2], 388 | other.m[4], other.m[5], other.m[6], 389 | other.m[8], other.m[9], other.m[10], 390 | ] 391 | } 392 | } 393 | } 394 | 395 | /// construct a Mat3 from tuple of 9 elements 396 | impl From<(T, T, T, T, T, T, T, T, T)> for Mat3 where T: Number { 397 | fn from(other: (T, T, T, T, T, T, T, T, T)) -> Mat3 { 398 | Mat3 { 399 | m: [ 400 | other.0, other.1, other.2, 401 | other.3, other.4, other.5, 402 | other.6, other.7, other.8, 403 | ] 404 | } 405 | } 406 | } 407 | 408 | /// constructs Mat3 from tuple of 3 3D row vectors 409 | impl From<(Vec3, Vec3, Vec3)> for Mat3 where T: Number { 410 | fn from(other: (Vec3, Vec3, Vec3)) -> Mat3 { 411 | Mat3 { 412 | m: [ 413 | other.0.x, other.0.y, other.0.z, 414 | other.1.x, other.1.y, other.1.z, 415 | other.2.x, other.2.y, other.2.z, 416 | ] 417 | } 418 | } 419 | } 420 | 421 | /// constucts a mat3 rotation matrix from quaternion 422 | impl From> for Mat3 where T: Float + SignedNumber + FloatOps + NumberOps + SignedNumberOps { 423 | fn from(other: Quat) -> Mat3 { 424 | other.get_matrix() 425 | } 426 | } 427 | 428 | /// construct a Mat34 from a Mat2 initialising the 2x2 part and setting the 3rd row to identity 429 | impl From> for Mat34 where T: Number { 430 | fn from(other: Mat2) -> Mat34 { 431 | Mat34 { 432 | m: [ 433 | other.m[0], other.m[1], T::zero(), T::zero(), 434 | other.m[2], other.m[3], T::zero(), T::zero(), 435 | T::zero(), T::zero(), T::one(), T::zero(), 436 | ] 437 | } 438 | } 439 | } 440 | 441 | /// construct a Mat34 from a Mat3 initialising the 3x3 part and setting the 4th row to zero 442 | impl From> for Mat34 where T: Number { 443 | fn from(other: Mat3) -> Mat34 { 444 | Mat34 { 445 | m: [ 446 | other.m[0], other.m[1], other.m[2], T::zero(), 447 | other.m[3], other.m[4], other.m[5], T::zero(), 448 | other.m[6], other.m[7], other.m[8], T::zero(), 449 | ] 450 | } 451 | } 452 | } 453 | 454 | /// constucts a mat34 rotation matrix from quaternion 455 | impl From> for Mat34 where T: Float + SignedNumber + FloatOps + NumberOps + SignedNumberOps { 456 | fn from(other: Quat) -> Mat34 { 457 | Mat34::from(other.get_matrix()) 458 | } 459 | } 460 | 461 | /// construct a Mat34 from a Mat4 initialising the 3x4 part and truncating the 4th row 462 | impl From> for Mat34 where T: Number { 463 | fn from(other: Mat4) -> Mat34 { 464 | Mat34 { 465 | m: [ 466 | other.m[0], other.m[1], other.m[2], other.m[3], 467 | other.m[4], other.m[5], other.m[6], other.m[7], 468 | other.m[8], other.m[9], other.m[10], other.m[11], 469 | ] 470 | } 471 | } 472 | } 473 | 474 | /// construct a Mat34 from tuple of 12 elements 475 | impl From<(T, T, T, T, T, T, T, T, T, T, T, T)> for Mat34 where T: Number { 476 | fn from(other: (T, T, T, T, T, T, T, T, T, T, T, T)) -> Mat34 { 477 | Mat34 { 478 | m: [ 479 | other.0, other.1, other.2, other.3, 480 | other.4, other.5, other.6, other.7, 481 | other.8, other.9, other.10, other.11 482 | ] 483 | } 484 | } 485 | } 486 | 487 | /// constructs Mat34 from tuple of 3 4D row vectors 488 | impl From<(Vec4, Vec4, Vec4)> for Mat34 where T: Number { 489 | fn from(other: (Vec4, Vec4, Vec4)) -> Mat34 { 490 | Mat34 { 491 | m: [ 492 | other.0.x, other.0.y, other.0.z, other.0.w, 493 | other.1.x, other.1.y, other.1.z, other.1.w, 494 | other.2.x, other.2.y, other.2.z, other.2.w, 495 | ] 496 | } 497 | } 498 | } 499 | 500 | /// construct a Mat4 from a Mat2 initialising the 2x2 part and setting the 3rd and 4th rows to identity 501 | impl From> for Mat4 where T: Number { 502 | fn from(other: Mat2) -> Mat4 { 503 | Mat4 { 504 | m: [ 505 | other.m[0], other.m[1], T::zero(), T::zero(), 506 | other.m[2], other.m[3], T::zero(), T::zero(), 507 | T::zero(), T::zero(), T::one(), T::zero(), 508 | T::zero(), T::zero(), T::zero(), T::one() 509 | ] 510 | } 511 | } 512 | } 513 | 514 | /// construct a Mat4 from a Mat3 initialising the 3x3 part and setting the 4th row/column to identity 515 | impl From> for Mat4 where T: Number { 516 | fn from(other: Mat3) -> Mat4 { 517 | Mat4 { 518 | m: [ 519 | other.m[0], other.m[1], other.m[2], T::zero(), 520 | other.m[3], other.m[4], other.m[5], T::zero(), 521 | other.m[6], other.m[7], other.m[8], T::zero(), 522 | T::zero(), T::zero(), T::zero(), T::one() 523 | ] 524 | } 525 | } 526 | } 527 | 528 | /// construct a Mat4 from a Mat34 initialising the 3x4 part and setting the 4th row to identity 529 | impl From> for Mat4 where T: Number { 530 | fn from(other: Mat34) -> Mat4 { 531 | Mat4 { 532 | m: [ 533 | other.m[0], other.m[1], other.m[2], other.m[3], 534 | other.m[4], other.m[5], other.m[6], other.m[7], 535 | other.m[8], other.m[9], other.m[10], other.m[11], 536 | T::zero(), T::zero(), T::zero(), T::one() 537 | ] 538 | } 539 | } 540 | } 541 | 542 | /// construct a Mat4 from tuple of 16 elements 543 | impl From<(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T)> for Mat4 where T: Number { 544 | fn from(other: (T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T)) -> Mat4 { 545 | Mat4 { 546 | m: [ 547 | other.0, other.1, other.2, other.3, 548 | other.4, other.5, other.6, other.7, 549 | other.8, other.9, other.10, other.11, 550 | other.12, other.13, other.14, other.15 551 | ] 552 | } 553 | } 554 | } 555 | 556 | /// constructs Mat4 from tuple of 4 4D row vectors 557 | impl From<(Vec4, Vec4, Vec4, Vec4)> for Mat4 where T: Number { 558 | fn from(other: (Vec4, Vec4, Vec4, Vec4)) -> Mat4 { 559 | Mat4 { 560 | m: [ 561 | other.0.x, other.0.y, other.0.z, other.0.w, 562 | other.1.x, other.1.y, other.1.z, other.1.w, 563 | other.2.x, other.2.y, other.2.z, other.2.w, 564 | other.3.x, other.3.y, other.3.z, other.3.w, 565 | ] 566 | } 567 | } 568 | } 569 | 570 | /// constucts a mat4 rotation matrix from quaternion 571 | impl From> for Mat4 where T: Float + SignedNumber + FloatOps + NumberOps + SignedNumberOps { 572 | fn from(other: Quat) -> Mat4 { 573 | Mat4::from(other.get_matrix()) 574 | } 575 | } 576 | 577 | // 578 | // Mat2 Mul 579 | // 580 | 581 | /// multiply 2x2 * 2x2 matrix 582 | fn mul2x2(lhs: Mat2, rhs: Mat2) -> Mat2 { 583 | Mat2 { 584 | m: [ 585 | lhs.m[0] * rhs.m[0] + lhs.m[1] * rhs.m[2], 586 | lhs.m[0] * rhs.m[1] + lhs.m[1] * rhs.m[3], 587 | lhs.m[2] * rhs.m[0] + lhs.m[3] * rhs.m[2], 588 | lhs.m[2] * rhs.m[1] + lhs.m[3] * rhs.m[3], 589 | ] 590 | } 591 | } 592 | 593 | impl Mul for Mat2 where T: Number { 594 | type Output = Self; 595 | fn mul(self, rhs: Mat2) -> Self::Output { 596 | mul2x2(self, rhs) 597 | } 598 | } 599 | 600 | impl MulAssign for Mat2 where T: Number { 601 | fn mul_assign(&mut self, rhs: Mat2) { 602 | *self = mul2x2(*self, rhs); 603 | } 604 | } 605 | 606 | impl MulAssign<&Self> for Mat2 where T: Number { 607 | fn mul_assign(&mut self, rhs: &Self) { 608 | *self = mul2x2(*self, *rhs); 609 | } 610 | } 611 | 612 | impl Mul> for Mat2 where T: Number { 613 | type Output = Vec2; 614 | fn mul(self, rhs: Vec2) -> Self::Output { 615 | Vec2 { 616 | x: self.m[0] * rhs.x + self.m[1] * rhs.y, 617 | y: self.m[2] * rhs.x + self.m[3] * rhs.y 618 | } 619 | } 620 | } 621 | 622 | // mul refs 623 | impl Mul<&Self> for Mat2 where T: Number { 624 | type Output = Self; 625 | fn mul(self, rhs: &Self) -> Self::Output { 626 | mul2x2(self, *rhs) 627 | } 628 | } 629 | 630 | impl Mul> for &Mat2 where T: Number { 631 | type Output = Mat2; 632 | fn mul(self, rhs: Mat2) -> Self::Output { 633 | mul2x2(*self, rhs) 634 | } 635 | } 636 | 637 | impl Mul for &Mat2 where T: Number { 638 | type Output = Mat2; 639 | fn mul(self, rhs: Self) -> Self::Output { 640 | mul2x2(*self, *rhs) 641 | } 642 | } 643 | 644 | impl Mul<&Vec2> for Mat2 where T: Number { 645 | type Output = Vec2; 646 | fn mul(self, rhs: &Vec2) -> Self::Output { 647 | Vec2 { 648 | x: self.m[0] * rhs.x + self.m[1] * rhs.y, 649 | y: self.m[2] * rhs.x + self.m[3] * rhs.y 650 | } 651 | } 652 | } 653 | 654 | impl Mul> for &Mat2 where T: Number { 655 | type Output = Vec2; 656 | fn mul(self, rhs: Vec2) -> Self::Output { 657 | Vec2 { 658 | x: self.m[0] * rhs.x + self.m[1] * rhs.y, 659 | y: self.m[2] * rhs.x + self.m[3] * rhs.y 660 | } 661 | } 662 | } 663 | 664 | impl Mul<&Vec2> for &Mat2 where T: Number { 665 | type Output = Vec2; 666 | fn mul(self, rhs: &Vec2) -> Self::Output { 667 | Vec2 { 668 | x: self.m[0] * rhs.x + self.m[1] * rhs.y, 669 | y: self.m[2] * rhs.x + self.m[3] * rhs.y 670 | } 671 | } 672 | } 673 | 674 | // 675 | // Mat3 Mul 676 | // 677 | 678 | /// multiply 3x3 * 3x3 matrix 679 | fn mul3x3(lhs: Mat3, rhs: Mat3) -> Mat3 { 680 | Mat3 { 681 | m: [ 682 | lhs.m[0] * rhs.m[0] + lhs.m[1] * rhs.m[3] + lhs.m[2] * rhs.m[6], 683 | lhs.m[0] * rhs.m[1] + lhs.m[1] * rhs.m[4] + lhs.m[2] * rhs.m[7], 684 | lhs.m[0] * rhs.m[2] + lhs.m[1] * rhs.m[5] + lhs.m[2] * rhs.m[8], 685 | 686 | lhs.m[3] * rhs.m[0] + lhs.m[4] * rhs.m[3] + lhs.m[5] * rhs.m[6], 687 | lhs.m[3] * rhs.m[1] + lhs.m[4] * rhs.m[4] + lhs.m[5] * rhs.m[7], 688 | lhs.m[3] * rhs.m[2] + lhs.m[4] * rhs.m[5] + lhs.m[5] * rhs.m[8], 689 | 690 | lhs.m[6] * rhs.m[0] + lhs.m[7] * rhs.m[3] + lhs.m[8] * rhs.m[6], 691 | lhs.m[6] * rhs.m[1] + lhs.m[7] * rhs.m[4] + lhs.m[8] * rhs.m[7], 692 | lhs.m[6] * rhs.m[2] + lhs.m[7] * rhs.m[5] + lhs.m[8] * rhs.m[8], 693 | ] 694 | } 695 | } 696 | 697 | impl Mul for Mat3 where T: Number { 698 | type Output = Self; 699 | fn mul(self, rhs: Mat3) -> Self::Output { 700 | mul3x3(self, rhs) 701 | } 702 | } 703 | 704 | impl MulAssign for Mat3 where T: Number { 705 | fn mul_assign(&mut self, rhs: Mat3) { 706 | *self = mul3x3(*self, rhs); 707 | } 708 | } 709 | 710 | impl Mul> for Mat3 where T: Number { 711 | type Output = Vec3; 712 | fn mul(self, rhs: Vec3) -> Self::Output { 713 | Vec3 { 714 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z, 715 | y: self.m[3] * rhs.x + self.m[4] * rhs.y + self.m[5] * rhs.z, 716 | z: self.m[6] * rhs.x + self.m[7] * rhs.y + self.m[8] * rhs.z, 717 | } 718 | } 719 | } 720 | 721 | // mul refs 722 | impl Mul<&Self> for Mat3 where T: Number { 723 | type Output = Self; 724 | fn mul(self, rhs: &Self) -> Self::Output { 725 | mul3x3(self, *rhs) 726 | } 727 | } 728 | 729 | impl Mul> for &Mat3 where T: Number { 730 | type Output = Mat3; 731 | fn mul(self, rhs: Mat3) -> Self::Output { 732 | mul3x3(*self, rhs) 733 | } 734 | } 735 | 736 | impl Mul for &Mat3 where T: Number { 737 | type Output = Mat3; 738 | fn mul(self, rhs: Self) -> Self::Output { 739 | mul3x3(*self, *rhs) 740 | } 741 | } 742 | 743 | impl Mul<&Vec3> for Mat3 where T: Number { 744 | type Output = Vec3; 745 | fn mul(self, rhs: &Vec3) -> Self::Output { 746 | Vec3 { 747 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z, 748 | y: self.m[3] * rhs.x + self.m[4] * rhs.y + self.m[5] * rhs.z, 749 | z: self.m[6] * rhs.x + self.m[7] * rhs.y + self.m[8] * rhs.z, 750 | } 751 | } 752 | } 753 | 754 | impl Mul> for &Mat3 where T: Number { 755 | type Output = Vec3; 756 | fn mul(self, rhs: Vec3) -> Self::Output { 757 | Vec3 { 758 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z, 759 | y: self.m[3] * rhs.x + self.m[4] * rhs.y + self.m[5] * rhs.z, 760 | z: self.m[6] * rhs.x + self.m[7] * rhs.y + self.m[8] * rhs.z, 761 | } 762 | } 763 | } 764 | 765 | impl Mul<&Vec3> for &Mat3 where T: Number { 766 | type Output = Vec3; 767 | fn mul(self, rhs: &Vec3) -> Self::Output { 768 | Vec3 { 769 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z, 770 | y: self.m[3] * rhs.x + self.m[4] * rhs.y + self.m[5] * rhs.z, 771 | z: self.m[6] * rhs.x + self.m[7] * rhs.y + self.m[8] * rhs.z, 772 | } 773 | } 774 | } 775 | 776 | // 777 | // Mat34 Mul 778 | // 779 | 780 | /// multiply 3x4 * 3x4 matrix 781 | fn mul3x4(lhs: Mat34, rhs: Mat34) -> Mat34 { 782 | Mat34 { 783 | m: [ 784 | lhs.m[0] * rhs.m[0] + lhs.m[1] * rhs.m[4] + lhs.m[2] * rhs.m[8], 785 | lhs.m[0] * rhs.m[1] + lhs.m[1] * rhs.m[5] + lhs.m[2] * rhs.m[9], 786 | lhs.m[0] * rhs.m[2] + lhs.m[1] * rhs.m[6] + lhs.m[2] * rhs.m[10], 787 | lhs.m[0] * rhs.m[3] + lhs.m[1] * rhs.m[7] + lhs.m[2] * rhs.m[11] + lhs.m[3], 788 | 789 | lhs.m[4] * rhs.m[0] + lhs.m[5] * rhs.m[4] + lhs.m[6] * rhs.m[8], 790 | lhs.m[4] * rhs.m[1] + lhs.m[5] * rhs.m[5] + lhs.m[6] * rhs.m[9], 791 | lhs.m[4] * rhs.m[2] + lhs.m[5] * rhs.m[6] + lhs.m[6] * rhs.m[10], 792 | lhs.m[4] * rhs.m[3] + lhs.m[5] * rhs.m[7] + lhs.m[6] * rhs.m[11] + lhs.m[7], 793 | 794 | lhs.m[8] * rhs.m[0] + lhs.m[9] * rhs.m[4] + lhs.m[10] * rhs.m[8], 795 | lhs.m[8] * rhs.m[1] + lhs.m[9] * rhs.m[5] + lhs.m[10] * rhs.m[9], 796 | lhs.m[8] * rhs.m[2] + lhs.m[9] * rhs.m[6] + lhs.m[10] * rhs.m[10], 797 | lhs.m[8] * rhs.m[3] + lhs.m[9] * rhs.m[7] + lhs.m[10] * rhs.m[11] + lhs.m[11], 798 | ] 799 | } 800 | } 801 | 802 | impl Mul for Mat34 where T: Number { 803 | type Output = Self; 804 | fn mul(self, rhs: Mat34) -> Self::Output { 805 | mul3x4(self, rhs) 806 | } 807 | } 808 | 809 | impl MulAssign for Mat34 where T: Number { 810 | fn mul_assign(&mut self, rhs: Mat34) { 811 | *self = mul3x4(*self, rhs) 812 | } 813 | } 814 | 815 | impl Mul> for Mat34 where T: Number { 816 | type Output = Vec3; 817 | fn mul(self, rhs: Vec3) -> Self::Output { 818 | Vec3 { 819 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3], 820 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7], 821 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11] 822 | } 823 | } 824 | } 825 | 826 | /// multiples vector with implicit 4th row in matrix 0,0,0,1 827 | impl Mul> for Mat34 where T: Number { 828 | type Output = Vec4; 829 | fn mul(self, rhs: Vec4) -> Self::Output { 830 | Vec4 { 831 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3] * rhs.w, 832 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7] * rhs.w, 833 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11] * rhs.w, 834 | w: rhs.w, 835 | } 836 | } 837 | } 838 | 839 | // mul refs 840 | impl Mul<&Self> for Mat34 where T: Number { 841 | type Output = Self; 842 | fn mul(self, rhs: &Self) -> Self::Output { 843 | mul3x4(self, *rhs) 844 | } 845 | } 846 | 847 | impl Mul> for &Mat34 where T: Number { 848 | type Output = Mat34; 849 | fn mul(self, rhs: Mat34) -> Self::Output { 850 | mul3x4(*self, rhs) 851 | } 852 | } 853 | 854 | impl Mul for &Mat34 where T: Number { 855 | type Output = Mat34; 856 | fn mul(self, rhs: Self) -> Self::Output { 857 | mul3x4(*self, *rhs) 858 | } 859 | } 860 | 861 | impl Mul<&Vec3> for Mat34 where T: Number { 862 | type Output = Vec3; 863 | fn mul(self, rhs: &Vec3) -> Self::Output { 864 | Vec3 { 865 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3], 866 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7], 867 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11] 868 | } 869 | } 870 | } 871 | 872 | impl Mul> for &Mat34 where T: Number { 873 | type Output = Vec3; 874 | fn mul(self, rhs: Vec3) -> Self::Output { 875 | Vec3 { 876 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3], 877 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7], 878 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11] 879 | } 880 | } 881 | } 882 | 883 | impl Mul<&Vec3> for &Mat34 where T: Number { 884 | type Output = Vec3; 885 | fn mul(self, rhs: &Vec3) -> Self::Output { 886 | Vec3 { 887 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3], 888 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7], 889 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11] 890 | } 891 | } 892 | } 893 | 894 | impl Mul<&Vec4> for Mat34 where T: Number { 895 | type Output = Vec4; 896 | fn mul(self, rhs: &Vec4) -> Self::Output { 897 | Vec4 { 898 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3] * rhs.w, 899 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7] * rhs.w, 900 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11] * rhs.w, 901 | w: rhs.w, 902 | } 903 | } 904 | } 905 | 906 | impl Mul> for &Mat34 where T: Number { 907 | type Output = Vec4; 908 | fn mul(self, rhs: Vec4) -> Self::Output { 909 | Vec4 { 910 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3] * rhs.w, 911 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7] * rhs.w, 912 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11] * rhs.w, 913 | w: rhs.w, 914 | } 915 | } 916 | } 917 | 918 | impl Mul<&Vec4> for &Mat34 where T: Number { 919 | type Output = Vec4; 920 | fn mul(self, rhs: &Vec4) -> Self::Output { 921 | Vec4 { 922 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3] * rhs.w, 923 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7] * rhs.w, 924 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11] * rhs.w, 925 | w: rhs.w, 926 | } 927 | } 928 | } 929 | 930 | // 931 | // Mat4 Mul 932 | // 933 | 934 | /// multiply 4x4 * 4x4 matrix 935 | fn mul4x4(lhs: Mat4, rhs: Mat4) -> Mat4 { 936 | Mat4 { 937 | m: [ 938 | lhs.m[0] * rhs.m[0] + lhs.m[1] * rhs.m[4] + lhs.m[2] * rhs.m[8] + lhs.m[3] * rhs.m[12], 939 | lhs.m[0] * rhs.m[1] + lhs.m[1] * rhs.m[5] + lhs.m[2] * rhs.m[9] + lhs.m[3] * rhs.m[13], 940 | lhs.m[0] * rhs.m[2] + lhs.m[1] * rhs.m[6] + lhs.m[2] * rhs.m[10] + lhs.m[3] * rhs.m[14], 941 | lhs.m[0] * rhs.m[3] + lhs.m[1] * rhs.m[7] + lhs.m[2] * rhs.m[11] + lhs.m[3] * rhs.m[15], 942 | 943 | lhs.m[4] * rhs.m[0] + lhs.m[5] * rhs.m[4] + lhs.m[6] * rhs.m[8] + lhs.m[7] * rhs.m[12], 944 | lhs.m[4] * rhs.m[1] + lhs.m[5] * rhs.m[5] + lhs.m[6] * rhs.m[9] + lhs.m[7] * rhs.m[13], 945 | lhs.m[4] * rhs.m[2] + lhs.m[5] * rhs.m[6] + lhs.m[6] * rhs.m[10] + lhs.m[7] * rhs.m[14], 946 | lhs.m[4] * rhs.m[3] + lhs.m[5] * rhs.m[7] + lhs.m[6] * rhs.m[11] + lhs.m[7] * rhs.m[15], 947 | 948 | lhs.m[8] * rhs.m[0] + lhs.m[9] * rhs.m[4] + lhs.m[10] * rhs.m[8] + lhs.m[11] * rhs.m[12], 949 | lhs.m[8] * rhs.m[1] + lhs.m[9] * rhs.m[5] + lhs.m[10] * rhs.m[9] + lhs.m[11] * rhs.m[13], 950 | lhs.m[8] * rhs.m[2] + lhs.m[9] * rhs.m[6] + lhs.m[10] * rhs.m[10] + lhs.m[11] * rhs.m[14], 951 | lhs.m[8] * rhs.m[3] + lhs.m[9] * rhs.m[7] + lhs.m[10] * rhs.m[11] + lhs.m[11] * rhs.m[15], 952 | 953 | lhs.m[12] * rhs.m[0] + lhs.m[13] * rhs.m[4] + lhs.m[14] * rhs.m[8] + lhs.m[15] * rhs.m[12], 954 | lhs.m[12] * rhs.m[1] + lhs.m[13] * rhs.m[5] + lhs.m[14] * rhs.m[9] + lhs.m[15] * rhs.m[13], 955 | lhs.m[12] * rhs.m[2] + lhs.m[13] * rhs.m[6] + lhs.m[14] * rhs.m[10] + lhs.m[15] * rhs.m[14], 956 | lhs.m[12] * rhs.m[3] + lhs.m[13] * rhs.m[7] + lhs.m[14] * rhs.m[11] + lhs.m[15] * rhs.m[15], 957 | ] 958 | } 959 | } 960 | 961 | impl Mul for Mat4 where T: Number { 962 | type Output = Self; 963 | fn mul(self, rhs: Mat4) -> Self::Output { 964 | mul4x4(self, rhs) 965 | } 966 | } 967 | 968 | impl MulAssign for Mat4 where T: Number { 969 | fn mul_assign(&mut self, rhs: Mat4) { 970 | *self = mul4x4(*self, rhs); 971 | } 972 | } 973 | 974 | impl Mul> for Mat4 where T: Number { 975 | type Output = Vec4; 976 | fn mul(self, rhs: Vec4) -> Self::Output { 977 | Vec4 { 978 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3] * rhs.w, 979 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7] * rhs.w, 980 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11] * rhs.w, 981 | w: self.m[12] * rhs.x + self.m[13] * rhs.y + self.m[14] * rhs.z + self.m[15] * rhs.w, 982 | } 983 | } 984 | } 985 | 986 | /// performs multiplication on vec3 with implicit w = 1.0, returning Vec3 which has been divided by w 987 | impl Mul> for Mat4 where T: Number { 988 | type Output = Vec3; 989 | fn mul(self, rhs: Vec3) -> Self::Output { 990 | let w = self.m[12] * rhs.x + self.m[13] * rhs.y + self.m[14] * rhs.z + self.m[15]; 991 | Vec3 { 992 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3], 993 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7], 994 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11], 995 | } / w 996 | } 997 | } 998 | 999 | // mat34 implicit last row 1000 | // 12 13 14 15 1001 | // 00 00 00 01 1002 | 1003 | /// multiply 3x4 * 4x4 matrix 1004 | fn mul3x4_4x4(lhs: Mat34, rhs: Mat4) -> Mat4 { 1005 | Mat4 { 1006 | m: [ 1007 | lhs.m[0] * rhs.m[0] + lhs.m[1] * rhs.m[4] + lhs.m[2] * rhs.m[8] + lhs.m[3] * rhs.m[12], 1008 | lhs.m[0] * rhs.m[1] + lhs.m[1] * rhs.m[5] + lhs.m[2] * rhs.m[9] + lhs.m[3] * rhs.m[13], 1009 | lhs.m[0] * rhs.m[2] + lhs.m[1] * rhs.m[6] + lhs.m[2] * rhs.m[10] + lhs.m[3] * rhs.m[14], 1010 | lhs.m[0] * rhs.m[3] + lhs.m[1] * rhs.m[7] + lhs.m[2] * rhs.m[11] + lhs.m[3] * rhs.m[15], 1011 | 1012 | lhs.m[4] * rhs.m[0] + lhs.m[5] * rhs.m[4] + lhs.m[6] * rhs.m[8] + lhs.m[7] * rhs.m[12], 1013 | lhs.m[4] * rhs.m[1] + lhs.m[5] * rhs.m[5] + lhs.m[6] * rhs.m[9] + lhs.m[7] * rhs.m[13], 1014 | lhs.m[4] * rhs.m[2] + lhs.m[5] * rhs.m[6] + lhs.m[6] * rhs.m[10] + lhs.m[7] * rhs.m[14], 1015 | lhs.m[4] * rhs.m[3] + lhs.m[5] * rhs.m[7] + lhs.m[6] * rhs.m[11] + lhs.m[7] * rhs.m[15], 1016 | 1017 | lhs.m[8] * rhs.m[0] + lhs.m[9] * rhs.m[4] + lhs.m[10] * rhs.m[8] + lhs.m[11] * rhs.m[12], 1018 | lhs.m[8] * rhs.m[1] + lhs.m[9] * rhs.m[5] + lhs.m[10] * rhs.m[9] + lhs.m[11] * rhs.m[13], 1019 | lhs.m[8] * rhs.m[2] + lhs.m[9] * rhs.m[6] + lhs.m[10] * rhs.m[10] + lhs.m[11] * rhs.m[14], 1020 | lhs.m[8] * rhs.m[3] + lhs.m[9] * rhs.m[7] + lhs.m[10] * rhs.m[11] + lhs.m[11] * rhs.m[15], 1021 | 1022 | rhs.m[12], 1023 | rhs.m[13], 1024 | rhs.m[14], 1025 | rhs.m[15], 1026 | ] 1027 | } 1028 | } 1029 | 1030 | impl Mul> for Mat34 where T: Number { 1031 | type Output = Mat4; 1032 | fn mul(self, rhs: Mat4) -> Self::Output { 1033 | mul3x4_4x4(self, rhs) 1034 | } 1035 | } 1036 | 1037 | // mat34 implicit last row 1038 | // 12 13 14 15 1039 | // 00 00 00 01 1040 | 1041 | /// multiply 4x4 * 3x4 matrix 1042 | fn mul4x4_3x4(lhs: Mat4, rhs: Mat34) -> Mat4 { 1043 | Mat4 { 1044 | m: [ 1045 | lhs.m[0] * rhs.m[0] + lhs.m[1] * rhs.m[4] + lhs.m[2] * rhs.m[8], 1046 | lhs.m[0] * rhs.m[1] + lhs.m[1] * rhs.m[5] + lhs.m[2] * rhs.m[9], 1047 | lhs.m[0] * rhs.m[2] + lhs.m[1] * rhs.m[6] + lhs.m[2] * rhs.m[10], 1048 | lhs.m[0] * rhs.m[3] + lhs.m[1] * rhs.m[7] + lhs.m[2] * rhs.m[11] + lhs.m[3], 1049 | 1050 | lhs.m[4] * rhs.m[0] + lhs.m[5] * rhs.m[4] + lhs.m[6] * rhs.m[8], 1051 | lhs.m[4] * rhs.m[1] + lhs.m[5] * rhs.m[5] + lhs.m[6] * rhs.m[9], 1052 | lhs.m[4] * rhs.m[2] + lhs.m[5] * rhs.m[6] + lhs.m[6] * rhs.m[10], 1053 | lhs.m[4] * rhs.m[3] + lhs.m[5] * rhs.m[7] + lhs.m[6] * rhs.m[11] + lhs.m[7], 1054 | 1055 | lhs.m[8] * rhs.m[0] + lhs.m[9] * rhs.m[4] + lhs.m[10] * rhs.m[8], 1056 | lhs.m[8] * rhs.m[1] + lhs.m[9] * rhs.m[5] + lhs.m[10] * rhs.m[9], 1057 | lhs.m[8] * rhs.m[2] + lhs.m[9] * rhs.m[6] + lhs.m[10] * rhs.m[10], 1058 | lhs.m[8] * rhs.m[3] + lhs.m[9] * rhs.m[7] + lhs.m[10] * rhs.m[11] + lhs.m[11], 1059 | 1060 | lhs.m[12] * rhs.m[0] + lhs.m[13] * rhs.m[4] + lhs.m[14] * rhs.m[8], 1061 | lhs.m[12] * rhs.m[1] + lhs.m[13] * rhs.m[5] + lhs.m[14] * rhs.m[9], 1062 | lhs.m[12] * rhs.m[2] + lhs.m[13] * rhs.m[6] + lhs.m[14] * rhs.m[10], 1063 | lhs.m[12] * rhs.m[3] + lhs.m[13] * rhs.m[7] + lhs.m[14] * rhs.m[11] + lhs.m[15], 1064 | ] 1065 | } 1066 | } 1067 | 1068 | impl Mul> for Mat4 where T: Number { 1069 | type Output = Self; 1070 | fn mul(self, rhs: Mat34) -> Self::Output { 1071 | mul4x4_3x4(self, rhs) 1072 | } 1073 | } 1074 | 1075 | impl MulAssign> for Mat4 where T: Number { 1076 | fn mul_assign(&mut self, rhs: Mat34) { 1077 | *self = mul4x4_3x4(*self, rhs) 1078 | } 1079 | } 1080 | 1081 | // mul refs 1082 | impl Mul<&Self> for Mat4 where T: Number { 1083 | type Output = Self; 1084 | fn mul(self, rhs: &Self) -> Self::Output { 1085 | mul4x4(self, *rhs) 1086 | } 1087 | } 1088 | 1089 | impl Mul> for &Mat4 where T: Number { 1090 | type Output = Mat4; 1091 | fn mul(self, rhs: Mat4) -> Self::Output { 1092 | mul4x4(*self, rhs) 1093 | } 1094 | } 1095 | 1096 | impl Mul for &Mat4 where T: Number { 1097 | type Output = Mat4; 1098 | fn mul(self, rhs: Self) -> Self::Output { 1099 | mul4x4(*self, *rhs) 1100 | } 1101 | } 1102 | 1103 | // 4 x 34 1104 | impl Mul<&Mat34> for Mat4 where T: Number { 1105 | type Output = Self; 1106 | fn mul(self, rhs: &Mat34) -> Self::Output { 1107 | mul4x4_3x4(self, *rhs) 1108 | } 1109 | } 1110 | 1111 | impl Mul> for &Mat4 where T: Number { 1112 | type Output = Mat4; 1113 | fn mul(self, rhs: Mat34) -> Self::Output { 1114 | mul4x4_3x4(*self, rhs) 1115 | } 1116 | } 1117 | 1118 | impl Mul<&Mat34> for &Mat4 where T: Number { 1119 | type Output = Mat4; 1120 | fn mul(self, rhs: &Mat34) -> Self::Output { 1121 | mul4x4_3x4(*self, *rhs) 1122 | } 1123 | } 1124 | 1125 | // 34 x 4 1126 | 1127 | impl Mul<&Mat4> for Mat34 where T: Number { 1128 | type Output = Mat4; 1129 | fn mul(self, rhs: &Mat4) -> Self::Output { 1130 | mul3x4_4x4(self, *rhs) 1131 | } 1132 | } 1133 | 1134 | impl Mul> for &Mat34 where T: Number { 1135 | type Output = Mat4; 1136 | fn mul(self, rhs: Mat4) -> Self::Output { 1137 | mul3x4_4x4(*self, rhs) 1138 | } 1139 | } 1140 | 1141 | impl Mul<&Mat4> for &Mat34 where T: Number { 1142 | type Output = Mat4; 1143 | fn mul(self, rhs: &Mat4) -> Self::Output { 1144 | mul3x4_4x4(*self, *rhs) 1145 | } 1146 | } 1147 | 1148 | impl Mul<&Vec4> for Mat4 where T: Number { 1149 | type Output = Vec4; 1150 | fn mul(self, rhs: &Vec4) -> Self::Output { 1151 | Vec4 { 1152 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3] * rhs.w, 1153 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7] * rhs.w, 1154 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11] * rhs.w, 1155 | w: self.m[12] * rhs.x + self.m[13] * rhs.y + self.m[14] * rhs.z + self.m[15] * rhs.w, 1156 | } 1157 | } 1158 | } 1159 | 1160 | impl Mul> for &Mat4 where T: Number { 1161 | type Output = Vec4; 1162 | fn mul(self, rhs: Vec4) -> Self::Output { 1163 | Vec4 { 1164 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3] * rhs.w, 1165 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7] * rhs.w, 1166 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11] * rhs.w, 1167 | w: self.m[12] * rhs.x + self.m[13] * rhs.y + self.m[14] * rhs.z + self.m[15] * rhs.w, 1168 | } 1169 | } 1170 | } 1171 | 1172 | impl Mul<&Vec4> for &Mat4 where T: Number { 1173 | type Output = Vec4; 1174 | fn mul(self, rhs: &Vec4) -> Self::Output { 1175 | Vec4 { 1176 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3] * rhs.w, 1177 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7] * rhs.w, 1178 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11] * rhs.w, 1179 | w: self.m[12] * rhs.x + self.m[13] * rhs.y + self.m[14] * rhs.z + self.m[15] * rhs.w, 1180 | } 1181 | } 1182 | } 1183 | 1184 | impl Mul<&Vec3> for Mat4 where T: Number { 1185 | type Output = Vec3; 1186 | fn mul(self, rhs: &Vec3) -> Self::Output { 1187 | let w = self.m[12] * rhs.x + self.m[13] * rhs.y + self.m[14] * rhs.z + self.m[15]; 1188 | Vec3 { 1189 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3], 1190 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7], 1191 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11], 1192 | } / w 1193 | } 1194 | } 1195 | 1196 | impl Mul> for &Mat4 where T: Number { 1197 | type Output = Vec3; 1198 | fn mul(self, rhs: Vec3) -> Self::Output { 1199 | let w = self.m[12] * rhs.x + self.m[13] * rhs.y + self.m[14] * rhs.z + self.m[15]; 1200 | Vec3 { 1201 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3], 1202 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7], 1203 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11], 1204 | } / w 1205 | } 1206 | } 1207 | 1208 | impl Mul<&Vec3> for &Mat4 where T: Number { 1209 | type Output = Vec3; 1210 | fn mul(self, rhs: &Vec3) -> Self::Output { 1211 | let w = self.m[12] * rhs.x + self.m[13] * rhs.y + self.m[14] * rhs.z + self.m[15]; 1212 | Vec3 { 1213 | x: self.m[0] * rhs.x + self.m[1] * rhs.y + self.m[2] * rhs.z + self.m[3], 1214 | y: self.m[4] * rhs.x + self.m[5] * rhs.y + self.m[6] * rhs.z + self.m[7], 1215 | z: self.m[8] * rhs.x + self.m[9] * rhs.y + self.m[10] * rhs.z + self.m[11], 1216 | } / w 1217 | } 1218 | } 1219 | 1220 | /// base matrix trait for arithmetic ops 1221 | pub trait MatN>: 1222 | Sized + Display + Copy + Clone + 1223 | Mul + Mul + MulAssign + 1224 | { 1225 | } 1226 | 1227 | impl MatN> for Mat2 where T: Number {} 1228 | impl MatN> for Mat3 where T: Number {} 1229 | impl MatN> for Mat34 where T: Number {} 1230 | impl MatN> for Mat4 where T: Number {} 1231 | impl MatN> for Mat4 where T: Number {} 1232 | 1233 | 1234 | /// trait for minimum of 4 column matrices to create translation 1235 | pub trait MatTranslate { 1236 | /// create a translation matrix from 3-dimensional vector `t` 1237 | fn from_translation(t: V) -> Self; 1238 | } 1239 | 1240 | impl MatTranslate> for Mat4 where T: Number { 1241 | fn from_translation(t: Vec3) -> Self { 1242 | let mut m = Mat4::identity(); 1243 | m.set_column(3, Vec4::from(t)); 1244 | m.m[15] = T::one(); 1245 | m 1246 | } 1247 | } 1248 | 1249 | impl MatTranslate> for Mat34 where T: Number { 1250 | fn from_translation(t: Vec3) -> Self { 1251 | let mut m = Mat34::identity(); 1252 | m.set_column(3, t); 1253 | m 1254 | } 1255 | } 1256 | 1257 | /// trait for all matrices to cerate a scaling matrix 1258 | pub trait MatScale { 1259 | /// create a scale matrix from n-dimensional vector `t` 1260 | fn from_scale(t: V) -> Self; 1261 | } 1262 | 1263 | impl MatScale> for Mat4 where T: Number { 1264 | fn from_scale(t: Vec3) -> Self { 1265 | let mut m = Mat4::identity(); 1266 | m.set(0, 0, t.x); 1267 | m.set(1, 1, t.y); 1268 | m.set(2, 2, t.z); 1269 | m 1270 | } 1271 | } 1272 | 1273 | impl MatScale> for Mat34 where T: Number { 1274 | fn from_scale(t: Vec3) -> Self { 1275 | let mut m = Mat34::identity(); 1276 | m.set(0, 0, t.x); 1277 | m.set(1, 1, t.y); 1278 | m.set(2, 2, t.z); 1279 | m 1280 | } 1281 | } 1282 | 1283 | impl MatScale> for Mat3 where T: Number { 1284 | fn from_scale(t: Vec3) -> Self { 1285 | let mut m = Mat3::identity(); 1286 | m.set(0, 0, t.x); 1287 | m.set(1, 1, t.y); 1288 | m.set(2, 2, t.z); 1289 | m 1290 | } 1291 | } 1292 | 1293 | impl MatScale> for Mat2 where T: Number { 1294 | fn from_scale(t: Vec2) -> Self { 1295 | let mut m = Mat2::identity(); 1296 | m.set(0, 0, t.x); 1297 | m.set(1, 1, t.y); 1298 | m 1299 | } 1300 | } 1301 | 1302 | /// trait for minimum of 2x2 matrices applying rotation in z-axis 1303 | pub trait MatRotate2D { 1304 | /// create rotation about the z axis by `theta` radians 1305 | fn from_z_rotation(theta: T) -> Self; 1306 | } 1307 | 1308 | impl MatRotate2D for Mat2 where T: Float + FloatOps { 1309 | fn from_z_rotation(theta: T) -> Self { 1310 | let mut m = Mat2::identity(); 1311 | let cos_theta = T::cos(theta); 1312 | let sin_theta = T::sin(theta); 1313 | m.set(0, 0, cos_theta); 1314 | m.set(0, 1, -sin_theta); 1315 | m.set(1, 0, sin_theta); 1316 | m.set(1, 1, cos_theta); 1317 | m 1318 | } 1319 | } 1320 | 1321 | impl MatRotate2D for Mat3 where T: Float + FloatOps { 1322 | fn from_z_rotation(theta: T) -> Self { 1323 | let mut m = Mat3::identity(); 1324 | let cos_theta = T::cos(theta); 1325 | let sin_theta = T::sin(theta); 1326 | m.set(0, 0, cos_theta); 1327 | m.set(0, 1, -sin_theta); 1328 | m.set(1, 0, sin_theta); 1329 | m.set(1, 1, cos_theta); 1330 | m 1331 | } 1332 | } 1333 | 1334 | impl MatRotate2D for Mat4 where T: Float + FloatOps { 1335 | fn from_z_rotation(theta: T) -> Self { 1336 | let mut m = Mat4::identity(); 1337 | let cos_theta = T::cos(theta); 1338 | let sin_theta = T::sin(theta); 1339 | m.set(0, 0, cos_theta); 1340 | m.set(0, 1, -sin_theta); 1341 | m.set(1, 0, sin_theta); 1342 | m.set(1, 1, cos_theta); 1343 | m 1344 | } 1345 | } 1346 | 1347 | impl MatRotate2D for Mat34 where T: Float + FloatOps { 1348 | fn from_z_rotation(theta: T) -> Self { 1349 | let mut m = Mat34::identity(); 1350 | let cos_theta = T::cos(theta); 1351 | let sin_theta = T::sin(theta); 1352 | m.set(0, 0, cos_theta); 1353 | m.set(0, 1, -sin_theta); 1354 | m.set(1, 0, sin_theta); 1355 | m.set(1, 1, cos_theta); 1356 | m 1357 | } 1358 | } 1359 | 1360 | /// given the normalised vector `n`, constructs an orthonormal basis returned as tuple 1361 | pub fn get_orthonormal_basis_hughes_moeller + FloatOps>(n: Vec3) -> (Vec3, Vec3) { 1362 | // choose a vector orthogonal to n as the direction of b2. 1363 | let b2 = if T::abs(n.x) > T::abs(n.z) { 1364 | Vec3::new(-n.y, n.x, T::zero()) 1365 | } 1366 | else { 1367 | Vec3::new(T::zero(), -n.z, n.y) 1368 | }; 1369 | 1370 | // normalise b2 1371 | let b2 = b2 * T::rsqrt(Vec3::dot(b2, b2)); 1372 | 1373 | // construct b1 using cross product 1374 | let b1 = Vec3::cross(b2, n); 1375 | 1376 | (b1, b2) 1377 | } 1378 | 1379 | /// given the normalised vector `n` construct an orthonormal basis without sqrt.. 1380 | pub fn get_orthonormal_basis_frisvad + FloatOps + From>(n: Vec3) -> (Vec3, Vec3) { 1381 | let epsilon = T::from(-0.99999999); 1382 | if n.z < epsilon { 1383 | (-Vec3::unit_y(), -Vec3::unit_x()) 1384 | } 1385 | else { 1386 | let a = T::one()/(T::one() + n.z); 1387 | let b = -n.x * n.y * a; 1388 | (Vec3::new(T::one() - n.x * n.x * a, b, -n.x), Vec3::new(b, T::one() - n.y * n.y * a, -n.y)) 1389 | } 1390 | } 1391 | 1392 | 1393 | /// trait for minimum of 3x3 matrices applying rotation to x, y or aribtrary 3D axes 1394 | pub trait MatRotate3D { 1395 | /// create rotation about the x axis by `theta` radians 1396 | fn from_x_rotation(theta: T) -> Self; 1397 | /// create rotation about the y axis by `theta` radians 1398 | fn from_y_rotation(theta: T) -> Self; 1399 | /// create rotation about the abitrary `axis` by `theta` radians 1400 | fn from_rotation(axis: V, theta: T) -> Self; 1401 | /// create an othonormal basis from the `normal` vector 1402 | fn from_orthonormal_basis(normal: Vec3) -> Self; 1403 | } 1404 | 1405 | impl MatRotate3D> for Mat3 where T: Float + FloatOps + SignedNumberOps { 1406 | fn from_x_rotation(theta: T) -> Self { 1407 | let mut m = Mat3::identity(); 1408 | let cos_theta = T::cos(theta); 1409 | let sin_theta = T::sin(theta); 1410 | m.set(1, 1, cos_theta); 1411 | m.set(1, 2, -sin_theta); 1412 | m.set(2, 1, sin_theta); 1413 | m.set(2, 2, cos_theta); 1414 | m 1415 | } 1416 | 1417 | fn from_y_rotation(theta: T) -> Self { 1418 | let mut m = Mat3::identity(); 1419 | let cos_theta = T::cos(theta); 1420 | let sin_theta = T::sin(theta); 1421 | m.set(0, 0, cos_theta); 1422 | m.set(0, 2, sin_theta); 1423 | m.set(2, 0, -sin_theta); 1424 | m.set(2, 2, cos_theta); 1425 | m 1426 | } 1427 | 1428 | fn from_rotation(axis: Vec3, theta: T) -> Self { 1429 | let cos_theta = T::cos(theta); 1430 | let sin_theta = T::sin(theta); 1431 | let inv_cos_theta = T::one() - cos_theta; 1432 | Mat3::from(( 1433 | Vec3::new( 1434 | inv_cos_theta * axis.x * axis.x + cos_theta, 1435 | inv_cos_theta * axis.x * axis.y - sin_theta * axis.z, 1436 | inv_cos_theta * axis.x * axis.z + sin_theta * axis.y 1437 | ), 1438 | Vec3::new( 1439 | inv_cos_theta * axis.x * axis.y + sin_theta * axis.z, 1440 | inv_cos_theta * axis.y * axis.y + cos_theta, 1441 | inv_cos_theta * axis.y * axis.z - sin_theta * axis.x 1442 | ), 1443 | Vec3::new( 1444 | inv_cos_theta * axis.x * axis.z - sin_theta * axis.y, 1445 | inv_cos_theta * axis.y * axis.z + sin_theta * axis.x, 1446 | inv_cos_theta * axis.z * axis.z + cos_theta 1447 | ) 1448 | )) 1449 | } 1450 | 1451 | fn from_orthonormal_basis(normal: Vec3) -> Self { 1452 | let (b1, b2) = get_orthonormal_basis_hughes_moeller(normal); 1453 | Mat3::from(( 1454 | b1, 1455 | normal, 1456 | b2 1457 | )) 1458 | } 1459 | } 1460 | 1461 | impl MatRotate3D> for Mat34 where T: Float + FloatOps + SignedNumberOps { 1462 | fn from_x_rotation(theta: T) -> Self { 1463 | Mat34::from(Mat3::from_x_rotation(theta)) 1464 | } 1465 | 1466 | fn from_y_rotation(theta: T) -> Self { 1467 | Mat34::from(Mat3::from_y_rotation(theta)) 1468 | } 1469 | 1470 | fn from_rotation(axis: Vec3, theta: T) -> Self { 1471 | Mat34::from(Mat3::from_rotation(axis, theta)) 1472 | } 1473 | 1474 | fn from_orthonormal_basis(normal: Vec3) -> Self { 1475 | Mat34::from(Mat3::from_orthonormal_basis(normal)) 1476 | } 1477 | } 1478 | 1479 | impl MatRotate3D> for Mat4 where T: Float + FloatOps + SignedNumberOps { 1480 | fn from_x_rotation(theta: T) -> Self { 1481 | Mat4::from(Mat3::from_x_rotation(theta)) 1482 | } 1483 | 1484 | fn from_y_rotation(theta: T) -> Self { 1485 | Mat4::from(Mat3::from_y_rotation(theta)) 1486 | } 1487 | 1488 | fn from_rotation(axis: Vec3, theta: T) -> Self { 1489 | Mat4::from(Mat3::from_rotation(axis, theta)) 1490 | } 1491 | 1492 | fn from_orthonormal_basis(normal: Vec3) -> Self { 1493 | Mat4::from(Mat3::from_orthonormal_basis(normal)) 1494 | } 1495 | } 1496 | 1497 | /// trait for square matrices to compute determinant 1498 | pub trait MatDeterminant { 1499 | /// return the determinant of the matrix as scalar `T` 1500 | fn determinant(&self) -> T; 1501 | } 1502 | 1503 | impl MatDeterminant for Mat2 where T: Number { 1504 | fn determinant(&self) -> T { 1505 | self.m[0] * self.m[3] - self.m[1] * self.m[2] 1506 | } 1507 | } 1508 | 1509 | impl MatDeterminant for Mat3 where T: Number { 1510 | fn determinant(&self) -> T { 1511 | self.m[0] * (self.m[4] * self.m[8] - self.m[5] * self.m[7]) - 1512 | self.m[1] * (self.m[3] * self.m[8] - self.m[5] * self.m[6]) + 1513 | self.m[2] * (self.m[3] * self.m[7] - self.m[4] * self.m[6]) 1514 | } 1515 | } 1516 | 1517 | /// returns the 4x4 determinant using laplace expansion theorum 1518 | #[allow(clippy::zero_prefixed_literal)] 1519 | impl MatDeterminant for Mat4 where T: Number { 1520 | fn determinant(&self) -> T { 1521 | let s0 = (self.m[00] * self.m[05]) - (self.m[01] * self.m[04]); 1522 | let s1 = (self.m[00] * self.m[06]) - (self.m[02] * self.m[04]); 1523 | let s2 = (self.m[00] * self.m[07]) - (self.m[03] * self.m[04]); 1524 | let s3 = (self.m[01] * self.m[06]) - (self.m[02] * self.m[05]); 1525 | let s4 = (self.m[01] * self.m[07]) - (self.m[03] * self.m[05]); 1526 | let s5 = (self.m[02] * self.m[07]) - (self.m[03] * self.m[06]); 1527 | let c5 = (self.m[10] * self.m[15]) - (self.m[11] * self.m[14]); 1528 | let c4 = (self.m[09] * self.m[15]) - (self.m[11] * self.m[13]); 1529 | let c3 = (self.m[09] * self.m[14]) - (self.m[10] * self.m[13]); 1530 | let c2 = (self.m[08] * self.m[15]) - (self.m[11] * self.m[12]); 1531 | let c1 = (self.m[08] * self.m[14]) - (self.m[10] * self.m[12]); 1532 | let c0 = (self.m[08] * self.m[13]) - (self.m[09] * self.m[12]); 1533 | (s0 * c5) - (s1 * c4) + (s2 * c3) + (s3 * c2) - (s4 * c1) + (s5 * c0) 1534 | } 1535 | } 1536 | 1537 | /// trait for all kinds of matrices to calculate inverse 1538 | pub trait MatInverse { 1539 | /// returns the inverse of the matrix 1540 | fn inverse(&self) -> Self; 1541 | } 1542 | 1543 | impl MatInverse for Mat2 where T: SignedNumber { 1544 | fn inverse(&self) -> Self { 1545 | let det = self.determinant(); 1546 | let inv_det = T::one()/det; 1547 | Mat2 { 1548 | m: [ 1549 | inv_det * self.m[3], inv_det * -self.m[1], 1550 | inv_det * -self.m[2], inv_det * self.m[0], 1551 | ] 1552 | } 1553 | } 1554 | } 1555 | 1556 | impl MatInverse for Mat3 where T: SignedNumber { 1557 | fn inverse(&self) -> Self { 1558 | let det = self.determinant(); 1559 | let inv_det = T::one() / det; 1560 | Mat3 { 1561 | m: [ 1562 | (self.m[4] * self.m[8] - self.m[5] * self.m[7]) * inv_det, 1563 | -(self.m[1] * self.m[8] - self.m[2] * self.m[7]) * inv_det, 1564 | (self.m[1] * self.m[5] - self.m[2] * self.m[4]) * inv_det, 1565 | 1566 | -(self.m[3] * self.m[8] - self.m[5] * self.m[6]) * inv_det, 1567 | (self.m[0] * self.m[8] - self.m[2] * self.m[6]) * inv_det, 1568 | -(self.m[0] * self.m[5] - self.m[2] * self.m[3]) * inv_det, 1569 | 1570 | (self.m[3] * self.m[7] - self.m[4] * self.m[6]) * inv_det, 1571 | -(self.m[0] * self.m[7] - self.m[1] * self.m[6]) * inv_det, 1572 | (self.m[0] * self.m[4] - self.m[1] * self.m[3]) * inv_det 1573 | ] 1574 | } 1575 | } 1576 | } 1577 | 1578 | impl MatInverse for Mat34 where T: SignedNumber { 1579 | fn inverse(&self) -> Self { 1580 | let m3_inv = Mat3::::from(*self).inverse(); 1581 | let mut m34 = Mat34::::from(m3_inv); 1582 | let t = Vec3::::from((-self.m[3], -self.m[7], -self.m[11])); 1583 | let inv_t = Vec3:: { 1584 | x: t.x * m3_inv.m[0] + t.y * m3_inv.m[1] + t.z * m3_inv.m[2], 1585 | y: t.x * m3_inv.m[3] + t.y * m3_inv.m[4] + t.z * m3_inv.m[5], 1586 | z: t.x * m3_inv.m[6] + t.y * m3_inv.m[7] + t.z * m3_inv.m[8], 1587 | }; 1588 | m34.set_column(3, inv_t); 1589 | m34 1590 | } 1591 | } 1592 | 1593 | #[allow(clippy::zero_prefixed_literal)] 1594 | impl MatInverse for Mat4 where T: SignedNumber { 1595 | fn inverse(&self) -> Self { 1596 | let s0 = (self.m[00] * self.m[05]) - (self.m[01] * self.m[04]); 1597 | let s1 = (self.m[00] * self.m[06]) - (self.m[02] * self.m[04]); 1598 | let s2 = (self.m[00] * self.m[07]) - (self.m[03] * self.m[04]); 1599 | let s3 = (self.m[01] * self.m[06]) - (self.m[02] * self.m[05]); 1600 | let s4 = (self.m[01] * self.m[07]) - (self.m[03] * self.m[05]); 1601 | let s5 = (self.m[02] * self.m[07]) - (self.m[03] * self.m[06]); 1602 | let c5 = (self.m[10] * self.m[15]) - (self.m[11] * self.m[14]); 1603 | let c4 = (self.m[09] * self.m[15]) - (self.m[11] * self.m[13]); 1604 | let c3 = (self.m[09] * self.m[14]) - (self.m[10] * self.m[13]); 1605 | let c2 = (self.m[08] * self.m[15]) - (self.m[11] * self.m[12]); 1606 | let c1 = (self.m[08] * self.m[14]) - (self.m[10] * self.m[12]); 1607 | let c0 = (self.m[08] * self.m[13]) - (self.m[09] * self.m[12]); 1608 | let det = (s0 * c5) - (s1 * c4) + (s2 * c3) + (s3 * c2) - (s4 * c1) + (s5 * c0); 1609 | let inv_det = T::one() / det; 1610 | Mat4 { 1611 | m: [ 1612 | (self.m[5] * c5 - self.m[6] * c4 + self.m[7] * c3) * inv_det, 1613 | -(self.m[1] * c5 - self.m[2] * c4 + self.m[3] * c3) * inv_det, 1614 | (self.m[13] * s5 - self.m[14] * s4 + self.m[15] * s3) * inv_det, 1615 | -(self.m[9] * s5 - self.m[10] * s4 + self.m[11] * s3) * inv_det, 1616 | -(self.m[4] * c5 - self.m[6] * c2 + self.m[7] * c1) * inv_det, 1617 | (self.m[0] * c5 - self.m[2] * c2 + self.m[3] * c1) * inv_det, 1618 | -(self.m[12] * s5 - self.m[14] * s2 + self.m[15] * s1) * inv_det, 1619 | (self.m[8] * s5 - self.m[10] * s2 + self.m[11] * s1) * inv_det, 1620 | (self.m[4] * c4 - self.m[5] * c2 + self.m[7] * c0) * inv_det, 1621 | -(self.m[0] * c4 - self.m[1] * c2 + self.m[3] * c0) * inv_det, 1622 | (self.m[12] * s4 - self.m[13] * s2 + self.m[15] * s0) * inv_det, 1623 | -(self.m[8] * s4 - self.m[9] * s2 + self.m[11] * s0) * inv_det, 1624 | -(self.m[4] * c3 - self.m[5] * c1 + self.m[6] * c0) * inv_det, 1625 | (self.m[0] * c3 - self.m[1] * c1 + self.m[2] * c0) * inv_det, 1626 | -(self.m[12] * s3 - self.m[13] * s1 + self.m[14] * s0) * inv_det, 1627 | (self.m[8] * s3 - self.m[9] * s1 + self.m[10] * s0) * inv_det, 1628 | ] 1629 | } 1630 | } 1631 | } 1632 | 1633 | /// trait for matrix transpose 1634 | pub trait MatTranspose { 1635 | fn transpose(&self) -> Other; 1636 | } 1637 | 1638 | impl MatTranspose for Mat2 where T: Number { 1639 | fn transpose(&self) -> Self { 1640 | let mut t = *self; 1641 | for r in 0..t.get_num_rows() as u32 { 1642 | for c in 0..t.get_num_columns() as u32 { 1643 | t.set(c, r, self.at(r, c)); 1644 | } 1645 | } 1646 | t 1647 | } 1648 | } 1649 | 1650 | impl MatTranspose for Mat3 where T: Number { 1651 | fn transpose(&self) -> Self { 1652 | let mut t = *self; 1653 | for r in 0..t.get_num_rows() as u32 { 1654 | for c in 0..t.get_num_columns() as u32 { 1655 | t.set(c, r, self.at(r, c)); 1656 | } 1657 | } 1658 | t 1659 | } 1660 | } 1661 | 1662 | impl MatTranspose for Mat4 where T: Number { 1663 | fn transpose(&self) -> Self { 1664 | let mut t = *self; 1665 | for r in 0..t.get_num_rows() as u32 { 1666 | for c in 0..t.get_num_columns() as u32 { 1667 | t.set(c, r, self.at(r, c)); 1668 | } 1669 | } 1670 | t 1671 | } 1672 | } 1673 | 1674 | impl MatTranspose> for Mat34 where T: Number { 1675 | fn transpose(&self) -> Mat43 { 1676 | let mut t = Mat43 { 1677 | m: [T::zero(); 12] 1678 | }; 1679 | for r in 0..3 { 1680 | for c in 0..4 { 1681 | let i = c * 3 + r; 1682 | let v = self.at(r as u32, c as u32); 1683 | t.m[i] = v; 1684 | } 1685 | } 1686 | t 1687 | } 1688 | } 1689 | 1690 | impl MatTranspose> for Mat43 where T: Number { 1691 | fn transpose(&self) -> Mat34 { 1692 | let mut t = Mat34 { 1693 | m: [T::zero(); 12] 1694 | }; 1695 | for r in 0..4 { 1696 | for c in 0..3 { 1697 | let i = r * 3 + c; 1698 | t.set(c, r, self.m[i as usize]); 1699 | } 1700 | } 1701 | t 1702 | } 1703 | } 1704 | 1705 | /// trait for the minor of a matrix 1706 | /// the minor is the determinant of the matrix without the given row and column 1707 | pub trait MatMinor { 1708 | fn minor(&self, row: u32, column: u32) -> T; 1709 | } 1710 | 1711 | impl MatMinor for Mat2 where T: Number { 1712 | fn minor(&self, row: u32, column: u32) -> T { 1713 | self.at(1 - row, 1 - column) 1714 | } 1715 | } 1716 | 1717 | impl MatMinor> for Mat3 where T: Number { 1718 | fn minor(&self, row: u32, column: u32) -> T { 1719 | let mut m = Mat2::zero(); 1720 | let mut pos = 0; 1721 | 1722 | for l in 0..3 { 1723 | for k in 0..3 { 1724 | if l != row && k != column { 1725 | m.set(pos / 2, pos % 2, self.at(l, k)); 1726 | pos += 1; 1727 | } 1728 | } 1729 | } 1730 | 1731 | m.determinant() 1732 | } 1733 | } 1734 | 1735 | impl MatMinor> for Mat4 where T: Number { 1736 | fn minor(&self, row: u32, column: u32) -> T { 1737 | let mut m = Mat3::zero(); 1738 | let mut pos = 0; 1739 | 1740 | for l in 0..4 { 1741 | for k in 0..4 { 1742 | if l != row && k != column { 1743 | m.set(pos / 3, pos % 3, self.at(l, k)); 1744 | pos += 1; 1745 | } 1746 | } 1747 | } 1748 | 1749 | m.determinant() 1750 | } 1751 | } 1752 | 1753 | /// trait for the cofactor of a matrix 1754 | /// the cofactor is the minor with an alternating sign, multiplied by (-1)^(row+column) 1755 | pub trait MatCofactor { 1756 | fn cofactor(&self, row: u32, column: u32) -> T; 1757 | } 1758 | 1759 | impl MatCofactor for Mat2 where T: SignedNumber { 1760 | fn cofactor(&self, row: u32, column: u32) -> T { 1761 | let sign = if (row + column & 1) == 1 { T::minus_one() } else { T::one() }; 1762 | sign * self.minor(row, column) 1763 | } 1764 | } 1765 | 1766 | impl MatCofactor for Mat3 where T: SignedNumber { 1767 | fn cofactor(&self, row: u32, column: u32) -> T { 1768 | let sign = if (row + column & 1) == 1 { T::minus_one() } else { T::one() }; 1769 | sign * self.minor(row, column) 1770 | } 1771 | } 1772 | 1773 | impl MatCofactor for Mat4 where T: SignedNumber { 1774 | fn cofactor(&self, row: u32, column: u32) -> T { 1775 | let sign = if (row + column & 1) == 1 { T::minus_one() } else { T::one() }; 1776 | sign * self.minor(row, column) 1777 | } 1778 | } 1779 | 1780 | /// trait for the adjugate of a matrix 1781 | /// the adjugate is the transpose of the cofactor matrix 1782 | /// the cofactor matrix is the matrix where each element is replaced by its cofactor 1783 | pub trait MatAdjugate { 1784 | fn adjugate(&self) -> Self; 1785 | } 1786 | 1787 | impl MatAdjugate for Mat2 where T: SignedNumber { 1788 | fn adjugate(&self) -> Self { 1789 | let mut output = Mat2::zero(); 1790 | output.set(0, 0, self.cofactor(0, 0)); 1791 | output.set(0, 1, self.cofactor(1, 0)); 1792 | output.set(1, 0, self.cofactor(0, 1)); 1793 | output.set(1, 1, self.cofactor(1, 1)); 1794 | 1795 | output 1796 | } 1797 | } 1798 | 1799 | impl MatAdjugate for Mat3 where T: SignedNumber { 1800 | fn adjugate(&self) -> Self { 1801 | let mut output = Mat3::zero(); 1802 | for j in 0..3 { 1803 | for i in 0..3 { 1804 | output.set(i, j, self.cofactor(i, j)); 1805 | } 1806 | } 1807 | 1808 | output.transpose() 1809 | } 1810 | } 1811 | 1812 | impl MatAdjugate for Mat4 where T: SignedNumber { 1813 | fn adjugate(&self) -> Self { 1814 | let mut output = Mat4::zero(); 1815 | for j in 0..4 { 1816 | for i in 0..4 { 1817 | output.set(i, j, self.cofactor(i, j)); 1818 | } 1819 | } 1820 | 1821 | output.transpose() 1822 | } 1823 | } 1824 | 1825 | /// trait for 4x4 projection matrices 1826 | pub trait MatProjection { 1827 | /// returns 6 frustum planes as `Vec4`'s in the form `.xyz = normal, .w = plane distance` 1828 | fn get_frustum_planes(&self) -> [Vec4; 6]; 1829 | /// returns 8 points which are the corners of the frustum first 4 near, second 4 far 1830 | fn get_frustum_corners(&self) -> [Vec3; 8]; 1831 | /// returns an orthogrpahic projection matrix defined by `left`, `right`, `top`, `bottom` edges and `near` - `far` depth range 1832 | fn create_ortho_matrix(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Self; 1833 | /// returns a perespective projection matrix (left hand coordinate system with y-up) from `fov` (radians), `aspect` ratio and `near` - `far` depth 1834 | fn create_perspective_projection_lh_yup(fov: T, aspect: T, near: T, far: T) -> Self; 1835 | /// returns a perespective projection matrix (right hand coordinate system with y-up) from `fov` (radians), `aspect` ratio and `near` - `far` depth 1836 | fn create_perspective_projection_rh_yup(fov: T, aspect: T, near: T, far: T) -> Self; 1837 | } 1838 | 1839 | /// internal utility function to extract a plane in the form `.xyz=normal, w=constant` from plane corners (of a frustum) 1840 | fn plane_from_vectors>(plane_vectors: &[Vec3; 18], offset: usize) -> Vec4 { 1841 | let v1 = super::normalize(plane_vectors[offset + 1] - plane_vectors[offset]); 1842 | let v2 = super::normalize(plane_vectors[offset + 2] - plane_vectors[offset]); 1843 | let pn = super::cross(v1, v2); 1844 | let pd = super::plane_distance(plane_vectors[offset], pn); 1845 | Vec4::from((pn, pd)) 1846 | } 1847 | 1848 | fn create_perspective_matrix_internal_lh>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4 { 1849 | Mat4::from(( 1850 | Vec4::new((T::two() * near) / (right - left), T::zero(), (right + left) / (right - left), T::zero()), 1851 | Vec4::new(T::zero(), (T::two() * near) / (top - bottom), (top + bottom) / (top - bottom), T::zero()), 1852 | Vec4::new(T::zero(), T::zero(), (-far - near) / (far - near), (-(T::two() * near) * far) / (far - near)), 1853 | Vec4::new(T::zero(), T::zero(), T::minus_one(), T::zero()) 1854 | )) 1855 | } 1856 | 1857 | fn create_perspective_matrix_internal_rh>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4 { 1858 | Mat4::from(( 1859 | Vec4::new((T::two() * near) / (right - left), T::zero(), (right + left) / (right - left), T::zero()), 1860 | Vec4::new(T::zero(), (T::two() * near) / (top - bottom), (top + bottom) / (top - bottom), T::zero()), 1861 | Vec4::new(T::zero(), T::zero(), (-far - near) / (far - near), (-(T::two() * near) * far) / (far - near)), 1862 | Vec4::new(T::zero(), T::zero(), T::one(), T::zero()) 1863 | )) 1864 | } 1865 | 1866 | impl MatProjection for Mat4 where T: Float + FloatOps, Vec3: FloatOps { 1867 | fn get_frustum_planes(&self) -> [Vec4; 6] { 1868 | // unproject matrix to get frustum corners grouped as 4 near, 4 far. 1869 | let ndc_coords = [ 1870 | Vec2::::new(T::zero(), T::one()), 1871 | Vec2::::new(T::one(), T::one()), 1872 | Vec2::::new(T::zero(), T::zero()), 1873 | Vec2::::new(T::one(), T::zero()), 1874 | ]; 1875 | 1876 | // construct corner points 1877 | let corners = [[ 1878 | super::unproject_sc(Vec3::from((ndc_coords[0], T::zero())), *self, Vec2::one()), 1879 | super::unproject_sc(Vec3::from((ndc_coords[1], T::zero())), *self, Vec2::one()), 1880 | super::unproject_sc(Vec3::from((ndc_coords[2], T::zero())), *self, Vec2::one()), 1881 | super::unproject_sc(Vec3::from((ndc_coords[3], T::zero())), *self, Vec2::one()), 1882 | ], 1883 | [ 1884 | super::unproject_sc(Vec3::from((ndc_coords[0], T::one())), *self, Vec2::one()), 1885 | super::unproject_sc(Vec3::from((ndc_coords[1], T::one())), *self, Vec2::one()), 1886 | super::unproject_sc(Vec3::from((ndc_coords[2], T::one())), *self, Vec2::one()), 1887 | super::unproject_sc(Vec3::from((ndc_coords[3], T::one())), *self, Vec2::one()), 1888 | ]]; 1889 | 1890 | // construct vectors to obtain normals 1891 | let plane_vectors = [ 1892 | corners[0][0], corners[1][0], corners[0][2], // left 1893 | corners[0][0], corners[0][1], corners[1][0], // top 1894 | corners[0][1], corners[0][3], corners[1][1], // right 1895 | corners[0][2], corners[1][2], corners[0][3], // bottom 1896 | corners[0][0], corners[0][2], corners[0][1], // near 1897 | corners[1][0], corners[1][1], corners[1][2] // far 1898 | ]; 1899 | 1900 | // return array of planes 1901 | [ 1902 | plane_from_vectors(&plane_vectors, 0), 1903 | plane_from_vectors(&plane_vectors, 3), 1904 | plane_from_vectors(&plane_vectors, 6), 1905 | plane_from_vectors(&plane_vectors, 9), 1906 | plane_from_vectors(&plane_vectors, 12), 1907 | plane_from_vectors(&plane_vectors, 15), 1908 | ] 1909 | } 1910 | 1911 | fn get_frustum_corners(&self) -> [Vec3; 8] { 1912 | // unproject matrix to get frustum corners grouped as 4 near, 4 far. 1913 | let ndc_coords = [ 1914 | Vec2::::new(T::zero(), T::one()), 1915 | Vec2::::new(T::one(), T::one()), 1916 | Vec2::::new(T::zero(), T::zero()), 1917 | Vec2::::new(T::one(), T::zero()), 1918 | ]; 1919 | 1920 | // construct corner points 1921 | [ 1922 | super::unproject_sc(Vec3::from((ndc_coords[0], T::zero())), *self, Vec2::one()), 1923 | super::unproject_sc(Vec3::from((ndc_coords[1], T::zero())), *self, Vec2::one()), 1924 | super::unproject_sc(Vec3::from((ndc_coords[2], T::zero())), *self, Vec2::one()), 1925 | super::unproject_sc(Vec3::from((ndc_coords[3], T::zero())), *self, Vec2::one()), 1926 | super::unproject_sc(Vec3::from((ndc_coords[0], T::one())), *self, Vec2::one()), 1927 | super::unproject_sc(Vec3::from((ndc_coords[1], T::one())), *self, Vec2::one()), 1928 | super::unproject_sc(Vec3::from((ndc_coords[2], T::one())), *self, Vec2::one()), 1929 | super::unproject_sc(Vec3::from((ndc_coords[3], T::one())), *self, Vec2::one()), 1930 | ] 1931 | } 1932 | 1933 | fn create_ortho_matrix(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4 { 1934 | Mat4::from(( 1935 | Vec4::new(T::two() / (right - left), T::zero(), T::zero(), T::zero()), 1936 | Vec4::new(T::zero(), T::two() / (top - bottom), T::zero(), T::zero()), 1937 | Vec4::new(T::zero(), T::zero(), T::one() / (near - far), T::zero()), 1938 | Vec4::new((right + left) / (left - right), (top + bottom) / (bottom - top), near / (near - far), T::one()), 1939 | )) 1940 | } 1941 | 1942 | fn create_perspective_projection_lh_yup(fov: T, aspect: T, near: T, far: T) -> Mat4 { 1943 | let tfov = T::tan(fov * T::point_five()); 1944 | let right = tfov * aspect * near; 1945 | let left = -right; 1946 | let top = tfov * near; 1947 | let bottom = -top; 1948 | create_perspective_matrix_internal_lh(left, right, bottom, top, near, far) 1949 | } 1950 | 1951 | fn create_perspective_projection_rh_yup(fov: T, aspect: T, near: T, far: T) -> Mat4 { 1952 | let tfov = T::tan(fov * T::point_five()); 1953 | let right = tfov * aspect * near; 1954 | let left = -right; 1955 | let top = tfov * near; 1956 | let bottom = -top; 1957 | create_perspective_matrix_internal_rh(left, right, bottom, top, near, far) 1958 | } 1959 | } 1960 | 1961 | /// trait to construct matrix from 4 scalars 1962 | pub trait MatNew2 { 1963 | fn new( 1964 | m00: T, m01: T, 1965 | m10: T, m11: T 1966 | ) -> Self; 1967 | } 1968 | 1969 | impl MatNew2 for Mat2 where T: Number { 1970 | fn new( 1971 | m00: T, m01: T, 1972 | m10: T, m11: T 1973 | ) -> Self { 1974 | Self { 1975 | m: [ 1976 | m00, m01, 1977 | m10, m11 1978 | ] 1979 | } 1980 | } 1981 | } 1982 | 1983 | #[allow(clippy::too_many_arguments)] 1984 | /// trait to construct matrix from 9 scalars 1985 | pub trait MatNew3 { 1986 | fn new( 1987 | m00: T, m01: T, m02: T, 1988 | m10: T, m11: T, m12: T, 1989 | m20: T, m21: T, m22: T, 1990 | ) -> Self; 1991 | } 1992 | 1993 | impl MatNew3 for Mat3 where T: Number { 1994 | fn new( 1995 | m00: T, m01: T, m02: T, 1996 | m10: T, m11: T, m12: T, 1997 | m20: T, m21: T, m22: T, 1998 | ) -> Self { 1999 | Self { 2000 | m: [ 2001 | m00, m01, m02, 2002 | m10, m11, m12, 2003 | m20, m21, m22, 2004 | ] 2005 | } 2006 | } 2007 | } 2008 | 2009 | #[allow(clippy::too_many_arguments)] 2010 | /// trait to construct matrix from 12 scalars 2011 | pub trait MatNew34 { 2012 | fn new( 2013 | m00: T, m01: T, m02: T, m03: T, 2014 | m10: T, m11: T, m12: T, m13: T, 2015 | m20: T, m21: T, m22: T, m23: T, 2016 | ) -> Self; 2017 | } 2018 | 2019 | impl MatNew34 for Mat34 where T: Number { 2020 | fn new( 2021 | m00: T, m01: T, m02: T, m03: T, 2022 | m10: T, m11: T, m12: T, m13: T, 2023 | m20: T, m21: T, m22: T, m23: T, 2024 | ) -> Self { 2025 | Self { 2026 | m: [ 2027 | m00, m01, m02, m03, 2028 | m10, m11, m12, m13, 2029 | m20, m21, m22, m23 2030 | ] 2031 | } 2032 | } 2033 | } 2034 | 2035 | #[allow(clippy::too_many_arguments)] 2036 | /// trait to construct matrix from 12 scalars 2037 | pub trait MatNew43 { 2038 | fn new( 2039 | m00: T, m01: T, m02: T, 2040 | m03: T, m10: T, m11: T, 2041 | m12: T, m13: T, m20: T, 2042 | m21: T, m22: T, m23: T, 2043 | ) -> Self; 2044 | } 2045 | 2046 | impl MatNew43 for Mat43 where T: Number { 2047 | fn new( 2048 | m00: T, m01: T, m02: T, 2049 | m03: T, m10: T, m11: T, 2050 | m12: T, m13: T, m20: T, 2051 | m21: T, m22: T, m23: T, 2052 | ) -> Self { 2053 | Self { 2054 | m: [ 2055 | m00, m01, m02, 2056 | m03, m10, m11, 2057 | m12, m13, m20, 2058 | m21, m22, m23 2059 | ] 2060 | } 2061 | } 2062 | } 2063 | 2064 | #[allow(clippy::too_many_arguments)] 2065 | /// trait to construct matrix from 16 scalars 2066 | pub trait MatNew4 { 2067 | fn new( 2068 | m00: T, m01: T, m02: T, m03: T, 2069 | m10: T, m11: T, m12: T, m13: T, 2070 | m20: T, m21: T, m22: T, m23: T, 2071 | m30: T, m31: T, m32: T, m33: T, 2072 | ) -> Self; 2073 | } 2074 | 2075 | impl MatNew4 for Mat4 where T: Number { 2076 | fn new( 2077 | m00: T, m01: T, m02: T, m03: T, 2078 | m10: T, m11: T, m12: T, m13: T, 2079 | m20: T, m21: T, m22: T, m23: T, 2080 | m30: T, m31: T, m32: T, m33: T, 2081 | ) -> Self { 2082 | Self { 2083 | m: [ 2084 | m00, m01, m02, m03, 2085 | m10, m11, m12, m13, 2086 | m20, m21, m22, m23, 2087 | m30, m31, m32, m33 2088 | ] 2089 | } 2090 | } 2091 | } 2092 | 2093 | mat_impl!(Mat2, 2, 2, 4, Vec2 {x, 0, y, 1}, Vec2 {x, 0, y, 1}); 2094 | mat_impl!(Mat3, 3, 3, 9, Vec3 {x, 0, y, 1, z, 2}, Vec3 {x, 0, y, 1, z, 2}); 2095 | mat_impl!(Mat4, 4, 4, 16, Vec4 {x, 0, y, 1, z, 2, w, 3}, Vec4 {x, 0, y, 1, z, 2, w, 3}); 2096 | mat_impl!(Mat34, 3, 4, 12, Vec4 {x, 0, y, 1, z, 2, w, 3}, Vec3 {x, 0, y, 1, z, 2}); 2097 | mat_impl!(Mat43, 4, 3, 12, Vec3 {x, 0, y, 1, z, 2}, Vec4 {x, 0, y, 1, z, 2, w, 3}); -------------------------------------------------------------------------------- /src/num.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Mul; 2 | use std::ops::MulAssign; 3 | use std::ops::Add; 4 | use std::ops::AddAssign; 5 | use std::ops::Sub; 6 | use std::ops::SubAssign; 7 | use std::ops::Div; 8 | use std::ops::DivAssign; 9 | use std::ops::Rem; 10 | use std::ops::RemAssign; 11 | use std::ops::Neg; 12 | use std::ops::Shl; 13 | use std::ops::ShlAssign; 14 | use std::ops::Shr; 15 | use std::ops::ShrAssign; 16 | use std::ops::BitOr; 17 | use std::ops::BitOrAssign; 18 | use std::ops::BitAnd; 19 | use std::ops::BitAndAssign; 20 | use std::ops::BitXor; 21 | use std::ops::BitXorAssign; 22 | 23 | use std::cmp::PartialEq; 24 | use std::cmp::PartialOrd; 25 | 26 | use std::fmt::Display; 27 | 28 | /// base trait for scalar and vector numerical operations, arithmetic and generic constants 29 | pub trait Base: 30 | Copy + Display + 31 | Add + AddAssign + 32 | Sub + SubAssign + 33 | Mul + MulAssign + 34 | Div + DivAssign + 35 | Rem + RemAssign 36 | where Self: Sized { 37 | /// returns `0` 38 | fn zero() -> Self; 39 | /// returns `1` 40 | fn one() -> Self; 41 | /// returns `2` 42 | fn two() -> Self; 43 | /// returns `3` 44 | fn three() -> Self; 45 | /// returns `4` 46 | fn four() -> Self; 47 | /// returns the smallest representable number with the available precision 48 | fn min_value() -> Self; 49 | /// returns the largest representable number with the available precision 50 | fn max_value() -> Self; 51 | } 52 | 53 | /// operations applicable to both floating point, integer and unsigned types 54 | pub trait NumberOps { 55 | /// returns the minimum value of `a` and `b` 56 | fn min(a: Self, b: Self) -> Self; 57 | /// returns the maximum value of `a` and `b` 58 | fn max(a: Self, b: Self) -> Self; 59 | /// returns value `x` clamped to the range `min` - `max` 60 | fn clamp(x: Self, min: Self, max: Self) -> Self; 61 | /// returns a vector stepped component wise; `1` if `a` is >= `b`, `0` otherwise 62 | fn step(a: Self, b: Self) -> Self; 63 | } 64 | 65 | /// operations applicable to signed types 66 | pub trait SignedNumberOps: Neg { 67 | /// returns sign value of `a`; `-1` = negative, `1` = positive or `0` (integers only) 68 | fn signum(a: Self) -> Self; 69 | /// returns the absolute (postive) value of `a` 70 | fn abs(a: Self) -> Self; 71 | } 72 | 73 | /// operations applicable to integer types 74 | pub trait IntegerOps { 75 | /// returns value `a` raised to unsigned integer power `exp` 76 | fn pow(a: Self, exp: u32) -> Self; 77 | } 78 | 79 | /// trait for performing linear interpolation on scalars, vectors or quaternions 80 | pub trait Lerp { 81 | /// returns linear interpolation of `t` between `e0` and `e1`, `t` specifies the ratio to interpolate between the values 82 | fn lerp(e0: Self, e1: Self, t: T) -> Self; 83 | } 84 | 85 | pub trait Cast where Self: Sized { 86 | fn from_f32(v: f32) -> Self; 87 | fn from_f64(v: f64) -> Self; 88 | fn from_u32(v: u32) -> Self; 89 | fn from_i32(v: i32) -> Self; 90 | fn from_u64(v: u64) -> Self; 91 | fn from_i64(v: i64) -> Self; 92 | fn from_usize(v: usize) -> Self; 93 | fn as_f32(&self) -> f32; 94 | fn as_f64(&self) -> f64; 95 | fn as_u32(&self) -> u32; 96 | fn as_i32(&self) -> i32; 97 | fn as_u64(&self) -> u64; 98 | fn as_i64(&self) -> i64; 99 | fn as_usize(&self) -> usize; 100 | } 101 | 102 | /// operations applicable to floating point types 103 | pub trait FloatOps: Lerp where Self: Sized { 104 | /// returns `0.5` 105 | fn point_five() -> Self; 106 | /// returns `pi` 107 | fn pi() -> Self; 108 | /// returns `2.0 * pi` 109 | fn two_pi() -> Self; 110 | /// returns `1.0 / pi` 111 | fn inv_pi() -> Self; 112 | /// returns `phi` (the golden constant) 113 | fn phi() -> Self; 114 | /// returns `1.0 / phi` inverse phi (the golden constant) 115 | fn inv_phi() -> Self; 116 | /// returns tau, which is ratio of the circumference of a circle to its radius 117 | fn tau() -> Self; 118 | /// returns square root of `a` 119 | fn sqrt(a: Self) -> Self; 120 | /// returns reciprocal square root of `a` (`1/sqrt(a)`) 121 | fn rsqrt(a: Self) -> Self; 122 | /// returns the reciprocal of `a` 123 | fn recip(a: Self) -> Self; 124 | /// returns `a` raised to integer power `exp` 125 | fn powi(a: Self, exp: i32) -> Self; 126 | /// returns `a` raised to float power `exp` 127 | fn powf(a: Self, exp: T) -> Self; 128 | /// returns fused multiply add `a * m + b` 129 | fn mad(m: Self, a: Self, b: Self) -> Self; 130 | /// returns true if `a` and `b` are approximately equal within the designated epsilon `eps` 131 | fn approx(a: Self, b: Self, eps: T) -> bool; 132 | /// returns the greatest integer which is less than or equal to a 133 | fn floor(a: Self) -> Self; 134 | /// returns the smallest integer which is greater than or equal to `a` 135 | fn ceil(a: Self) -> Self; 136 | /// returns value `a` with the same sign as the second parameter `sign` 137 | fn copysign(a: Self, sign: T) -> Self; 138 | /// returns hermite interpolation between `0-1` of `t` between edges `e0` and `e1` 139 | fn smoothstep(e0: Self, e1: Self, t: T) -> Self; 140 | /// returns `a` rounded component wise 141 | fn round(a: Self) -> Self; 142 | /// returns true if `a` is not a number (`nan`) 143 | fn is_nan(a: Self) -> Self; 144 | /// returns true if `a` is `inf` 145 | fn is_infinite(a: Self) -> Self; 146 | /// returns true is `a` is finite 147 | fn is_finite(a: Self) -> Self; 148 | /// returns the value of `a` saturated (clamped between `0-1`). equivalent to `clamp(x, 0, 1)` 149 | fn saturate(x: Self) -> Self; 150 | /// returns `theta` converted from degrees to radians 151 | fn deg_to_rad(theta: Self) -> Self; 152 | /// returns `theta` converted from radians to degrees 153 | fn rad_to_deg(theta: Self) -> Self; 154 | /// returns the floating-point remainder of `x/y` 155 | fn fmod(x: Self, y: Self) -> Self; 156 | /// returns the fractional part of floating point number `v` removing the integer part 157 | fn frac(v: Self) -> Self; 158 | /// returns the integer part of float value `v` truncating the decimal part 159 | fn trunc(v: Self) -> Self; 160 | /// returns a tuple containing `(frac(v), trunc(v))` breaking the float into 2 parts 161 | fn modf(v: Self) -> (Self, Self); 162 | /// returns the cosine of `v` where the value `v` is in radians 163 | fn cos(v: Self) -> Self; 164 | /// returns the sine of `v` where the value `v` is in radians 165 | fn sin(v: Self) -> Self; 166 | /// returns the tangent of `v` where the value `v` is in radians 167 | fn tan(v: Self) -> Self; 168 | /// returns the arc cosine of `v` where the value `v` is in radians 169 | fn acos(v: Self) -> Self; 170 | /// returns the arc sine of `v` where the value `v` is in radians 171 | fn asin(v: Self) -> Self; 172 | /// returns the arc tangent of `v` where the value `v` is in radians 173 | fn atan(v: Self) -> Self; 174 | /// returns the hyperbolic cosine of `v` where the value `v` is in radians 175 | fn cosh(v: Self) -> Self; 176 | /// returns the hyperbolic sine of `v` where the value `v` is in radians 177 | fn sinh(v: Self) -> Self; 178 | /// returns the hyperbolic tangent of `v` where the value `v` is in radians 179 | fn tanh(v: Self) -> Self; 180 | /// returns a tuple of `(sin(v), cos(v))` of `v` where the value `v` is in radians 181 | fn sin_cos(v: Self) -> (Self, Self); 182 | // returns the value of the arc tangent of `y/x`, expressed in radians 183 | fn atan2(y: Self, x: Self) -> Self; 184 | // returns the base-e exponential function of `v`, which is `e` raised to the power `v` 185 | fn exp(v: Self) -> Self; 186 | /// returns 2 raised to the given power `v` 187 | fn exp2(v: Self) -> Self; 188 | /// returns the binary (base-2) logarithm of `v` 189 | fn log2(v: Self) -> Self; 190 | /// returns the common (base-10) logarithm of `v` 191 | fn log10(v: Self) -> Self; 192 | /// returns the logarithm of `v` in base 193 | fn log(v: Self, base: T) -> Self; 194 | } 195 | 196 | macro_rules! number_trait_impl { 197 | ($($func:ident),*) => { 198 | /// base number trait for signed or unsigned, floating point or integer numbers. 199 | pub trait Number: Base + Default + PartialEq + PartialOrd {} 200 | number_impl!(f64 { $($func),* }, 0.0, 1.0); 201 | number_impl!(f32 { $($func),* }, 0.0, 1.0); 202 | number_impl!(usize { $($func),* }, 0, 1); 203 | number_impl!(isize { $($func),* }, 0, 1); 204 | number_impl!(i64 { $($func),* }, 0, 1); 205 | number_impl!(u64 { $($func),* }, 0, 1); 206 | number_impl!(i32 { $($func),* }, 0, 1); 207 | number_impl!(u32 { $($func),* }, 0, 1); 208 | number_impl!(i16 { $($func),* }, 0, 1); 209 | number_impl!(u16 { $($func),* }, 0, 1); 210 | number_impl!(i8 { $($func),* }, 0, 1); 211 | number_impl!(u8 { $($func),* }, 0, 1); 212 | } 213 | } 214 | 215 | macro_rules! number_impl { 216 | ($t:ident { $($func:ident),* }, $zero:literal, $one:literal) => { 217 | impl Base<$t> for $t { 218 | fn min_value() -> Self { 219 | $t::MIN 220 | } 221 | 222 | fn max_value() -> Self { 223 | $t::MAX 224 | } 225 | 226 | fn zero() -> Self { 227 | $zero 228 | } 229 | 230 | fn one() -> Self { 231 | $one 232 | } 233 | 234 | fn two() -> Self { 235 | 2 as Self 236 | } 237 | 238 | fn three() -> Self { 239 | 3 as Self 240 | } 241 | 242 | fn four() -> Self { 243 | 4 as Self 244 | } 245 | 246 | } 247 | 248 | impl Number for $t {} 249 | 250 | impl NumberOps<$t> for $t { 251 | fn min(a: Self, b: Self) -> Self { 252 | a.min(b) 253 | } 254 | 255 | fn max(a: Self, b: Self) -> Self { 256 | a.max(b) 257 | } 258 | 259 | fn clamp(x: Self, min: Self, max: Self) -> Self { 260 | NumberOps::max(NumberOps::min(x, max), min) 261 | } 262 | 263 | fn step(a: Self, b: Self) -> Self { 264 | if a >= b { 265 | Self::one() 266 | } 267 | else { 268 | Self::zero() 269 | } 270 | } 271 | } 272 | 273 | impl Cast<$t> for $t { 274 | fn from_f32(v: f32) -> Self { 275 | v as Self 276 | } 277 | 278 | fn from_f64(v: f64) -> Self { 279 | v as Self 280 | } 281 | 282 | fn from_u32(v: u32) -> Self { 283 | v as Self 284 | } 285 | 286 | fn from_i32(v: i32) -> Self { 287 | v as Self 288 | } 289 | 290 | fn from_u64(v: u64) -> Self { 291 | v as Self 292 | } 293 | 294 | fn from_i64(v: i64) -> Self { 295 | v as Self 296 | } 297 | 298 | fn from_usize(v: usize) -> Self { 299 | v as Self 300 | } 301 | 302 | fn as_f32(&self) -> f32 { 303 | *self as f32 304 | } 305 | 306 | fn as_f64(&self) -> f64 { 307 | *self as f64 308 | } 309 | 310 | fn as_u32(&self) -> u32 { 311 | *self as u32 312 | } 313 | 314 | fn as_i32(&self) -> i32 { 315 | *self as i32 316 | } 317 | 318 | fn as_u64(&self) -> u64 { 319 | *self as u64 320 | } 321 | 322 | fn as_i64(&self) -> i64 { 323 | *self as i64 324 | } 325 | 326 | fn as_usize(&self) -> usize { 327 | *self as usize 328 | } 329 | } 330 | } 331 | } 332 | 333 | macro_rules! signed_number_trait_impl { 334 | ($($func:ident),*) => { 335 | /// signed number trait for signed integers or floats. 336 | pub trait SignedNumber: Number + Neg { 337 | fn minus_one() -> Self; 338 | } 339 | signed_number_impl!(f64 { $($func),* }, -1.0); 340 | signed_number_impl!(f32 { $($func),* }, -1.0); 341 | signed_number_impl!(i64 { $($func),* }, -1); 342 | signed_number_impl!(i32 { $($func),* }, -1); 343 | signed_number_impl!(i16 { $($func),* }, -1); 344 | signed_number_impl!(i8 { $($func),* }, -1); 345 | } 346 | } 347 | 348 | macro_rules! signed_number_impl { 349 | ($t:ident { $($func:ident),* }, $minus_one:literal) => { 350 | impl SignedNumber for $t { 351 | fn minus_one() -> Self { 352 | $minus_one 353 | } 354 | } 355 | 356 | impl SignedNumberOps<$t> for $t { 357 | $( 358 | fn $func(v: Self) -> Self { 359 | v.$func() 360 | } 361 | )* 362 | } 363 | } 364 | } 365 | 366 | macro_rules! float_trait_impl { 367 | ($($func:ident),*) => { 368 | /// floating point trait for various levels of fp precision 369 | pub trait Float: SignedNumber { 370 | fn small_epsilon() -> Self; 371 | } 372 | float_impl!(f64 { $($func),* }); 373 | float_impl!(f32 { $($func),* }); 374 | } 375 | } 376 | 377 | macro_rules! float_impl { 378 | ($t:ident { $($func:ident),* } ) => { 379 | impl Float for $t { 380 | fn small_epsilon() -> Self { 381 | 1e-30 382 | } 383 | } 384 | 385 | impl Lerp<$t> for $t { 386 | fn lerp(e0: Self, e1: Self, t: Self) -> Self { 387 | e0 + t * (e1 - e0) 388 | } 389 | } 390 | 391 | impl FloatOps<$t> for $t { 392 | $( 393 | fn $func(v: Self) -> Self { 394 | v.$func() 395 | } 396 | )* 397 | 398 | fn point_five() -> Self { 399 | 0.5 as Self 400 | } 401 | 402 | #[allow(clippy::excessive_precision)] 403 | fn pi() -> Self { 404 | 3.14159265358979323846264338327950288 as Self 405 | } 406 | 407 | fn two_pi() -> Self { 408 | 2.0 as Self * Self::pi() as Self 409 | } 410 | 411 | fn inv_pi() -> Self { 412 | 1.0 as Self / Self::pi() as Self 413 | } 414 | 415 | #[allow(clippy::excessive_precision)] 416 | fn phi() -> Self { 417 | 1.618033988749894 as Self 418 | } 419 | 420 | fn inv_phi() -> Self { 421 | 1.0 as Self / Self::phi() as Self 422 | } 423 | 424 | #[allow(clippy::excessive_precision)] 425 | fn tau() -> Self { 426 | 6.2831853071795864 as Self 427 | } 428 | 429 | fn rsqrt(a: Self) -> Self { 430 | Self::one()/Self::sqrt(a) 431 | } 432 | 433 | fn approx(a: Self, b: Self, eps: Self) -> bool { 434 | Self::abs(a - b) < eps 435 | } 436 | 437 | fn mad(m: Self, a: Self, b: Self) -> Self { 438 | m.mul_add(a, b) 439 | } 440 | 441 | fn is_nan(v: Self) -> $t { 442 | if v.is_nan() { $t::one() } else { $t::zero() } 443 | } 444 | 445 | fn is_infinite(v: Self) -> $t { 446 | if v.is_infinite() { $t::one() } else { $t::zero() } 447 | } 448 | 449 | fn is_finite(v: Self) -> $t { 450 | if v.is_finite() { $t::one() } else { $t::zero() } 451 | } 452 | 453 | fn copysign(a: Self, sign: $t) -> Self { 454 | a.copysign(sign) 455 | } 456 | 457 | fn smoothstep(e0: Self, e1: Self, t: Self) -> Self { 458 | if t < e0 { return Self::zero(); } 459 | if (t >= e1) { return Self::one(); } 460 | let x = (t - e0) / (e1 - e0); 461 | x * x * (3 as Self - 2 as Self * x) 462 | } 463 | 464 | fn saturate(v: Self) -> Self { 465 | Self::max(Self::min(v, 1.0), 0.0) 466 | } 467 | 468 | fn powi(v: Self, exp: i32) -> Self { 469 | v.powi(exp) 470 | } 471 | 472 | fn powf(v: Self, exp: $t) -> Self { 473 | v.powf(exp) 474 | } 475 | 476 | fn fmod(x: Self, y: Self) -> Self { 477 | x % y 478 | } 479 | 480 | fn frac(v: Self) -> Self { 481 | v.fract() 482 | } 483 | 484 | fn trunc(v: Self) -> Self { 485 | v.trunc() 486 | } 487 | 488 | fn modf(v: Self) -> (Self, Self) { 489 | (Self::frac(v), Self::trunc(v)) 490 | } 491 | 492 | fn log(v: Self, base: Self) -> Self { 493 | v.log(base) 494 | } 495 | 496 | fn sin_cos(v: Self) -> (Self, Self) { 497 | (v.sin(), v.cos()) 498 | } 499 | 500 | fn atan2(y: Self, x: Self) -> Self { 501 | y.atan2(x) 502 | } 503 | 504 | fn deg_to_rad(theta: Self) -> Self { 505 | theta.to_radians() 506 | } 507 | 508 | fn rad_to_deg(theta: Self) -> Self { 509 | theta.to_degrees() 510 | } 511 | } 512 | } 513 | } 514 | 515 | macro_rules! integer_trait_impl { 516 | ($($func:ident),*) => { 517 | /// integer point trait for various sized integers 518 | pub trait Integer: Number + 519 | Shl + ShlAssign + 520 | Shr + ShrAssign + 521 | BitOr + BitOrAssign + 522 | BitAnd + BitAndAssign + 523 | BitXor + BitXorAssign { 524 | } 525 | integer_impl!(i8 { $($func),* }); 526 | integer_impl!(u8 { $($func),* }); 527 | integer_impl!(i16 { $($func),* }); 528 | integer_impl!(u16 { $($func),* }); 529 | integer_impl!(i32 { $($func),* }); 530 | integer_impl!(u32 { $($func),* }); 531 | integer_impl!(i64 { $($func),* }); 532 | integer_impl!(u64 { $($func),* }); 533 | } 534 | } 535 | 536 | macro_rules! integer_impl { 537 | ($t:ident { $($func:ident),* } ) => { 538 | impl Integer for $t { 539 | } 540 | 541 | impl IntegerOps<$t> for $t { 542 | fn pow(v: Self, exp: u32) -> Self { 543 | v.pow(exp) 544 | } 545 | } 546 | } 547 | } 548 | 549 | number_trait_impl!(); 550 | integer_trait_impl!(); 551 | 552 | signed_number_trait_impl!(signum, abs); 553 | float_trait_impl!( 554 | floor, ceil, round, sqrt, recip, 555 | cos, sin, tan, acos, asin, atan, cosh, sinh, tanh, 556 | exp, exp2, log2, log10 557 | ); -------------------------------------------------------------------------------- /src/quat.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Div; 2 | use std::ops::DivAssign; 3 | use std::ops::Mul; 4 | use std::ops::MulAssign; 5 | use std::ops::Neg; 6 | use std::ops::Add; 7 | use std::ops::AddAssign; 8 | use std::ops::Sub; 9 | use std::ops::SubAssign; 10 | use std::ops::Deref; 11 | use std::ops::DerefMut; 12 | 13 | use std::fmt::Display; 14 | use std::fmt::Formatter; 15 | 16 | use crate::num::*; 17 | use crate::vec::*; 18 | use crate::mat::*; 19 | use crate::swizz::*; 20 | use crate::dot; 21 | use crate::cross; 22 | 23 | #[cfg_attr(feature="serde", derive(serde::Serialize, serde::Deserialize))] 24 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 25 | #[repr(C)] 26 | pub struct Quat { 27 | x: T, 28 | y: T, 29 | z: T, 30 | w: T 31 | } 32 | 33 | impl Quat where T: Float + FloatOps + SignedNumberOps { 34 | /// constructs an identity quaternion which means no rotation and if multiplied with another quat it has no effect 35 | pub fn identity() -> Self { 36 | Self { 37 | x: T::zero(), 38 | y: T::zero(), 39 | z: T::zero(), 40 | w: T::one() 41 | } 42 | } 43 | 44 | /// construct a quaternion from 3 euler angles `x`, `y` and `z` 45 | pub fn from_euler_angles(x: T, y: T, z: T) -> Self { 46 | let half_z = T::point_five() * z; 47 | let half_x = T::point_five() * x; 48 | let half_y = T::point_five() * y; 49 | 50 | let cos_z_2 = T::cos(half_z); 51 | let cos_y_2 = T::cos(half_y); 52 | let cos_x_2 = T::cos(half_x); 53 | 54 | let sin_z_2 = T::sin(half_z); 55 | let sin_y_2 = T::sin(half_y); 56 | let sin_x_2 = T::sin(half_x); 57 | 58 | Self::normalize( Quat { 59 | w: cos_z_2 * cos_y_2 * cos_x_2 + sin_z_2 * sin_y_2 * sin_x_2, 60 | x: cos_z_2 * cos_y_2 * sin_x_2 - sin_z_2 * sin_y_2 * cos_x_2, 61 | y: cos_z_2 * sin_y_2 * cos_x_2 + sin_z_2 * cos_y_2 * sin_x_2, 62 | z: sin_z_2 * cos_y_2 * cos_x_2 - cos_z_2 * sin_y_2 * sin_x_2, 63 | }) 64 | } 65 | 66 | /// constructs quaternion from `axis` and `angle` representation where `angle` is in radians 67 | pub fn from_axis_angle(axis: Vec3, angle: T) -> Self { 68 | let half_angle = angle * T::point_five(); 69 | Self::normalize( Quat { 70 | w: T::cos(half_angle), 71 | x: axis.x * T::sin(half_angle), 72 | y: axis.y * T::sin(half_angle), 73 | z: axis.z * T::sin(half_angle) 74 | }) 75 | } 76 | 77 | /// constructs quaternion from matrix `m` 78 | pub fn from_matrix(m: Mat3) -> Self { 79 | // https://math.stackexchange.com/questions/893984/conversion-of-rotation-matrix-to-quaternion 80 | let m00 = m.m[0]; 81 | let m01 = m.m[3]; 82 | let m02 = m.m[6]; 83 | let m10 = m.m[1]; 84 | let m11 = m.m[4]; 85 | let m12 = m.m[7]; 86 | let m20 = m.m[2]; 87 | let m21 = m.m[5]; 88 | let m22 = m.m[8]; 89 | 90 | let t = T::zero(); 91 | let t0 = T::zero(); 92 | let t1 = T::one(); 93 | 94 | let (x, y, z, w) = if m22 < t0 { 95 | if m00 > m11 { 96 | let x = t1 + m00 -m11 -m22; 97 | let y = m01 + m10; 98 | let z = m20 + m02; 99 | let w = m12 - m21; 100 | (x, y, z, w) 101 | } 102 | else { 103 | let x = m01 + m10; 104 | let y = t1 -m00 + m11 -m22; 105 | let z = m12 + m21; 106 | let w = m20 - m02; 107 | (x, y, z, w) 108 | 109 | } 110 | } 111 | else if m00 < -m11 { 112 | let x = m20+m02; 113 | let y = m12+m21; 114 | let z = t1 -m00 -m11 + m22; 115 | let w = m01-m10; 116 | (x, y, z, w) 117 | } 118 | else { 119 | let x = m12-m21; 120 | let y = m20-m02; 121 | let z = m01-m10; 122 | let w = t1 + m00 + m11 + m22; 123 | (x, y, z, w) 124 | }; 125 | 126 | let sq = T::point_five() / T::sqrt(t); 127 | 128 | Quat { 129 | x: x * sq, 130 | y: y * sq, 131 | z: z * sq, 132 | w: w * sq 133 | } 134 | } 135 | 136 | /// returns euler angles as tuple `(x, y, z)` from quaternion 137 | pub fn to_euler_angles(self) -> (T, T, T) { 138 | let t2 = T::two(); 139 | let t1 = T::one(); 140 | 141 | // roll (x-axis rotation) 142 | let sinr = t2 * (self.w * self.x + self.y * self.z); 143 | let cosr = t1 - t2 * (self.x * self.x + self.y * self.y); 144 | let x = T::atan2(sinr, cosr); 145 | 146 | // pitch (y-axis rotation) 147 | let sinp = t2 * (self.w * self.y - self.z * self.x); 148 | let y = if T::abs(sinp) >= T::one() { 149 | // use 90 degrees if out of range 150 | T::copysign(T::pi() / t2, sinp) 151 | } 152 | else { 153 | T::asin(sinp) 154 | }; 155 | 156 | // yaw (z-axis rotation) 157 | let siny = t2 * (self.w * self.z + self.x * self.y); 158 | let cosy = t1 - t2 * (self.y * self.y + self.z * self.z); 159 | let z = T::atan2(siny, cosy); 160 | 161 | (x, y, z) 162 | } 163 | 164 | /// returns a 3x3 rotation matrix 165 | pub fn get_matrix(self) -> Mat3 { 166 | let t1 = T::one(); 167 | let t2 = T::two(); 168 | Mat3::new( 169 | // row 1 170 | t1 - t2 * self.y * self.y - t2 * self.z * self.z, 171 | t2 * self.x * self.y - t2 * self.z * self.w, 172 | t2 * self.x * self.z + t2 * self.y * self.w, 173 | // row 2 174 | t2 * self.x * self.y + t2 * self.z * self.w, 175 | t1 - t2 * self.x * self.x - t2 * self.z * self.z, 176 | t2 * self.y * self.z - t2 * self.x * self.w, 177 | // row 3 178 | t2 * self.x * self.z - t2 * self.y * self.w, 179 | t2 * self.y * self.z + t2 * self.x * self.w, 180 | t1 - t2 * self.x * self.x - t2 * self.y * self.y 181 | ) 182 | } 183 | 184 | /// returns a slice `T` of the quaternion 185 | pub fn as_slice(&self) -> &[T] { 186 | unsafe { 187 | std::slice::from_raw_parts(&self.x, 4) 188 | } 189 | } 190 | 191 | /// returns a mutable slice `T` of the quaternion 192 | pub fn as_mut_slice(&mut self) -> &mut [T] { 193 | unsafe { 194 | std::slice::from_raw_parts_mut(&mut self.x, 4) 195 | } 196 | } 197 | 198 | /// returns a slice of `u8` bytes for the quaternion 199 | pub fn as_u8_slice(&self) -> &[u8] { 200 | unsafe { 201 | std::slice::from_raw_parts((&self.x as *const T) as *const u8, std::mem::size_of::>()) 202 | } 203 | } 204 | 205 | /// returns a quationion which reverses the axis of rotation of self 206 | pub fn reverse(self) -> Self { 207 | Quat { 208 | x: -self.x, 209 | y: -self.y, 210 | z: -self.z, 211 | w: self.w 212 | } 213 | } 214 | 215 | /// returns a quaternion which is the inverse of self 216 | pub fn inverse(self) -> Self { 217 | self.reverse() / Self::mag2(self) 218 | } 219 | } 220 | 221 | impl Add for Quat where T: Float { 222 | type Output = Self; 223 | fn add(self, other: Self) -> Self { 224 | Quat { 225 | x: self.x + other.x, 226 | y: self.y + other.y, 227 | z: self.z + other.z, 228 | w: self.w + other.w, 229 | } 230 | } 231 | } 232 | 233 | impl AddAssign for Quat where T: Float { 234 | fn add_assign(&mut self, other: Self) { 235 | self.x += other.x; 236 | self.y += other.y; 237 | self.z += other.z; 238 | self.w += other.w; 239 | } 240 | } 241 | 242 | impl Sub for Quat where T: Float { 243 | type Output = Self; 244 | fn sub(self, other: Self) -> Self { 245 | Quat { 246 | x: self.x - other.x, 247 | y: self.y - other.y, 248 | z: self.z - other.z, 249 | w: self.w - other.w, 250 | } 251 | } 252 | } 253 | 254 | impl SubAssign for Quat where T: Float { 255 | fn sub_assign(&mut self, other: Self) { 256 | self.x -= other.x; 257 | self.y -= other.y; 258 | self.z -= other.z; 259 | self.w -= other.w; 260 | } 261 | } 262 | 263 | impl Div for Quat where T: Number { 264 | type Output = Self; 265 | fn div(self, other: T) -> Self { 266 | Quat { 267 | x: self.x / other, 268 | y: self.y / other, 269 | z: self.z / other, 270 | w: self.w / other, 271 | } 272 | } 273 | } 274 | 275 | impl DivAssign for Quat where T: Number { 276 | fn div_assign(&mut self, other: T) { 277 | self.x /= other; 278 | self.y /= other; 279 | self.z /= other; 280 | self.w /= other; 281 | } 282 | } 283 | 284 | impl Mul for Quat where T: Number { 285 | type Output = Self; 286 | fn mul(self, other: T) -> Self { 287 | Quat { 288 | x: self.x * other, 289 | y: self.y * other, 290 | z: self.z * other, 291 | w: self.w * other, 292 | } 293 | } 294 | } 295 | 296 | impl MulAssign for Quat where T: Number { 297 | fn mul_assign(&mut self, other: T) { 298 | self.x *= other; 299 | self.y *= other; 300 | self.z *= other; 301 | self.w *= other; 302 | } 303 | } 304 | 305 | // value * value 306 | impl Mul for Quat where T: Number { 307 | type Output = Self; 308 | fn mul(self, other: Self) -> Self { 309 | Quat { 310 | w: self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z, 311 | x: self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y, 312 | y: self.w * other.y - self.x * other.z + self.y * other.w + self.z * other.z, 313 | z: self.w * other.z + self.x * other.y - self.y * other.x + self.z * other.w 314 | } 315 | } 316 | } 317 | 318 | // ref * value 319 | impl Mul> for &Quat where T: Number { 320 | type Output = Quat; 321 | fn mul(self, other: Quat) -> Quat { 322 | Quat { 323 | w: self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z, 324 | x: self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y, 325 | y: self.w * other.y - self.x * other.z + self.y * other.w + self.z * other.z, 326 | z: self.w * other.z + self.x * other.y - self.y * other.x + self.z * other.w 327 | } 328 | } 329 | } 330 | 331 | // value * ref 332 | impl Mul<&Self> for Quat where T: Number { 333 | type Output = Self; 334 | fn mul(self, other: &Self) -> Self { 335 | Quat { 336 | w: self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z, 337 | x: self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y, 338 | y: self.w * other.y - self.x * other.z + self.y * other.w + self.z * other.z, 339 | z: self.w * other.z + self.x * other.y - self.y * other.x + self.z * other.w 340 | } 341 | } 342 | } 343 | 344 | // ref * ref 345 | impl Mul for &Quat where T: Number { 346 | type Output = Quat; 347 | fn mul(self, other: Self) -> Quat { 348 | Quat { 349 | w: self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z, 350 | x: self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y, 351 | y: self.w * other.y - self.x * other.z + self.y * other.w + self.z * other.z, 352 | z: self.w * other.z + self.x * other.y - self.y * other.x + self.z * other.w 353 | } 354 | } 355 | } 356 | 357 | impl MulAssign for Quat where T: Number { 358 | fn mul_assign(&mut self, other: Self) { 359 | *self = Self::mul(*self, other); 360 | } 361 | } 362 | 363 | impl Neg for Quat where T: Float { 364 | type Output = Self; 365 | fn neg(self) -> Self::Output { 366 | Quat { 367 | x: -self.x, 368 | y: -self.y, 369 | z: -self.z, 370 | w: -self.w, 371 | } 372 | } 373 | } 374 | 375 | /// mul with vec3 assumes quat is normalized 376 | impl Mul> for Quat where T: Number { 377 | type Output = Vec3; 378 | fn mul(self, other: Vec3) -> Vec3 { 379 | // https://gamedev.stackexchange.com/questions/28395/rotating-vector3-by-a-quaternion 380 | let u = Vec3::new(self.x, self.y, self.z); 381 | let v = other; 382 | let s = self.w; 383 | 384 | let r0 = u * T::two() * dot(u, v); 385 | let r1 = v * (s*s - dot(u, u)); 386 | let r2 = cross(u, v) * T::two() * s; 387 | 388 | r0 + r1 + r2 389 | } 390 | } 391 | 392 | // ref * value 393 | impl Mul> for &Quat where T: Number { 394 | type Output = Vec3; 395 | fn mul(self, other: Vec3) -> Vec3 { 396 | (*self).mul(other) 397 | } 398 | } 399 | 400 | // value * ref 401 | impl Mul<&Vec3> for Quat where T: Number { 402 | type Output = Vec3; 403 | fn mul(self, other: &Vec3) -> Vec3 { 404 | self.mul(*other) 405 | } 406 | } 407 | 408 | // ref * ref 409 | impl Mul<&Vec3> for &Quat where T: Number { 410 | type Output = Vec3; 411 | fn mul(self, other: &Vec3) -> Vec3 { 412 | (*self).mul(*other) 413 | } 414 | } 415 | 416 | /// default to identity quaternion 417 | impl Default for Quat where T: Float + FloatOps + SignedNumberOps { 418 | fn default() -> Self { 419 | Self::identity() 420 | } 421 | } 422 | 423 | impl Dot for Quat where T: Float + FloatOps { 424 | fn dot(a: Self, b: Self) -> T { 425 | a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w 426 | } 427 | } 428 | 429 | impl Magnitude for Quat where T: Float + FloatOps { 430 | fn length(a: Self) -> T { 431 | T::sqrt(Self::dot(a, a)) 432 | } 433 | 434 | fn mag(a: Self) -> T { 435 | T::sqrt(Self::dot(a, a)) 436 | } 437 | 438 | fn mag2(a: Self) -> T { 439 | Self::dot(a, a) 440 | } 441 | 442 | fn normalize(a: Self) -> Self { 443 | let m = Self::mag(a); 444 | a / m 445 | } 446 | } 447 | 448 | /// returns a quaternion spherically interpolated between `e0` and `e1` by percentage `t` 449 | impl Slerp for Quat where T: Float + FloatOps + NumberOps + From { 450 | fn slerp(e0: Self, e1: Self, t: T) -> Self { 451 | let q1 = e0; 452 | // reverse the sign of e1 if q1.q2 < 0. 453 | let q2 = if Self::dot(q1, e1) < T::zero() { 454 | -e1 455 | } 456 | else { 457 | e1 458 | }; 459 | 460 | let theta = T::acos(Self::dot(q1, q2)); 461 | let k_epsilon = T::from(0.000001); 462 | let (m1, m2) = if theta > k_epsilon { 463 | ( 464 | T::sin((T::one() - t) * theta) / T::sin(theta), 465 | T::sin(t * theta) / T::sin(theta) 466 | ) 467 | } 468 | else { 469 | ( 470 | T::one() - t, 471 | t 472 | ) 473 | }; 474 | 475 | Quat { 476 | w: m1 * q1.w + m2 * q2.w, 477 | x: m1 * q1.x + m2 * q2.x, 478 | y: m1 * q1.y + m2 * q2.y, 479 | z: m1 * q1.z + m2 * q2.z 480 | } 481 | } 482 | } 483 | 484 | /// returns a quaternion lineraly interpolated between `e0` and `e1` by percentage `t` 485 | impl Lerp for Quat where T: Float + FloatOps + NumberOps { 486 | fn lerp(e0: Self, e1: Self, t: T) -> Self { 487 | e0 * (T::one() - t) + e1 * t 488 | } 489 | } 490 | 491 | /// returns a quaternion lineraly interpolated between `e0` and `e1` by percentage `t` normalising the return value 492 | impl Nlerp for Quat where T: Float + FloatOps + NumberOps { 493 | fn nlerp(e0: Self, e1: Self, t: T) -> Self { 494 | Self::normalize(e0 * (T::one() - t) + e1 * t) 495 | } 496 | } 497 | 498 | /// constructs from a `Vec3`, assuming the `Vec3` is poulated with euler angles `(x, y, z)` where the angles are in radians 499 | impl From> for Quat where T: Float + FloatOps + SignedNumberOps { 500 | fn from(v: Vec3) -> Self { 501 | Quat::from_euler_angles(v.x, v.y, v.z) 502 | } 503 | } 504 | 505 | /// constructs from a `Vec4`, assuming the `Vec4` is an `axis` - `angle` representation. `xyz = axis, w = radian angle` 506 | impl From> for Quat where T: Float + FloatOps + SignedNumberOps { 507 | fn from(v: Vec4) -> Self { 508 | Quat::from_axis_angle(v.xyz(), v.w) 509 | } 510 | } 511 | 512 | /// constructs a quaternion from a 3x3 rotation matrix 513 | impl From> for Quat where T: Float + FloatOps + SignedNumberOps { 514 | fn from(m: Mat3) -> Self { 515 | Quat::from_matrix(m) 516 | } 517 | } 518 | 519 | /// dereference to a slice of `T` 520 | impl Deref for Quat where T: Float + FloatOps + SignedNumberOps { 521 | type Target = [T]; 522 | fn deref(&self) -> &[T] { 523 | self.as_slice() 524 | } 525 | } 526 | 527 | /// mutably dereference to a slice of `T` 528 | impl DerefMut for Quat where T: Float + FloatOps + SignedNumberOps { 529 | fn deref_mut(&mut self) -> &mut [T] { 530 | self.as_mut_slice() 531 | } 532 | } 533 | 534 | /// displays like [1.0, 2.0, 3.0, 4.0] 535 | impl Display for Quat where T: Display { 536 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 537 | write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) 538 | } 539 | } -------------------------------------------------------------------------------- /src/vec.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Index; 2 | use std::ops::IndexMut; 3 | use std::ops::Mul; 4 | use std::ops::MulAssign; 5 | use std::ops::Add; 6 | use std::ops::AddAssign; 7 | use std::ops::Sub; 8 | use std::ops::SubAssign; 9 | use std::ops::Div; 10 | use std::ops::DivAssign; 11 | use std::ops::Rem; 12 | use std::ops::RemAssign; 13 | use std::ops::Neg; 14 | use std::ops::Deref; 15 | use std::ops::DerefMut; 16 | 17 | use std::cmp::PartialEq; 18 | 19 | use std::fmt::Display; 20 | use std::fmt::Formatter; 21 | 22 | use crate::num::*; 23 | 24 | // 25 | // Vec Traits 26 | // 27 | 28 | /// generic vec trait to allow sized vectors to be treated generically 29 | pub trait VecN: 30 | Base + Dot + 31 | Index + IndexMut + 32 | Add + Sub + 33 | Mul + Div { 34 | /// returns the count of elements in the vector type 35 | fn len() -> usize; 36 | /// returns true if all elements in vector `a` are non-zero 37 | fn all(a: Self) -> bool; 38 | /// returns true if any element of the vector `a` is non-zero 39 | fn any(a: Self) -> bool; 40 | /// returns a vector initialised as a unit vector in the x-axis `[1, 0, 0, 0]` 41 | fn unit_x() -> Self; 42 | /// returns a vector initialised as a unit vector in the y-axis `[0, 1, 0, 0]` 43 | fn unit_y() -> Self; 44 | /// returns a vector initialised as a unit vector in the z-axis `[0, 0, 1, 0]` value will be truncated to 0 for vectors < 3 dimension 45 | fn unit_z() -> Self; 46 | /// returns a vector initialised as a unit vector in the w-axis `[0, 0, 0, 1]` value will be truncated to 0 for vectors < 4 dimension 47 | fn unit_w() -> Self; 48 | /// returns a vector initialised to red `[1, 0, 0, 1]` 49 | fn red() -> Self; 50 | /// returns a vector initialised to green `[0, 1, 0, 1]` 51 | fn green() -> Self; 52 | /// returns a vector initialised to blue `[0, 0, 1, 1]` value will be truncated to 0 for vectors < 3 dimension 53 | fn blue() -> Self; 54 | /// returns a vector initialised to cyan `[0, 1, 1, 1]` value will be truncated to green for vectors < 3 dimension 55 | fn cyan() -> Self; 56 | /// returns a vector initialised to magenta `[1, 0, 1, 1]` value will be truncated to red for vectors < 3 dimension 57 | fn magenta() -> Self; 58 | /// returns a vector initialised to yellow `[1, 1, 0, 0]` 59 | fn yellow() -> Self; 60 | /// returns a vector initialised to black (zero's) 61 | fn black() -> Self; 62 | /// returns a vector initialised to white (ones's) 63 | fn white() -> Self; 64 | /// returns a slice T of the vector 65 | fn as_slice(&self) -> &[T]; 66 | /// returns a mutable slice T of the vector 67 | fn as_mut_slice(&mut self) -> &mut [T]; 68 | /// returns a slice of bytes for the vector 69 | fn as_u8_slice(&self) -> &[u8]; 70 | /// returns the largest scalar value component contained in the vector `a` 71 | fn max_scalar(a: Self) -> T; 72 | /// returns the smallest scalar value component contained in the vector `a` 73 | fn min_scalar(a: Self) -> T; 74 | } 75 | 76 | /// trait for vectors of signed types to allow Neg 77 | pub trait SignedVecN: Neg { 78 | /// returns a vector initialised with -1 79 | fn minus_one() -> Self; 80 | } 81 | 82 | /// trait for operations involve vector magnitude or dot product 83 | pub trait Magnitude { 84 | /// returns scalar magnitude or length of vector `a` 85 | fn length(a: Self) -> T; 86 | /// returns scalar magnitude or length of vector `a` 87 | fn mag(a: Self) -> T; 88 | /// returns scalar magnitude or length of vector `a` squared to avoid using sqrt 89 | fn mag2(a: Self) -> T; 90 | /// returns a normalized unit vector of `a` 91 | fn normalize(a: Self) -> Self; 92 | } 93 | 94 | /// operations to apply to n-dimensional vectors 95 | pub trait VecFloatOps: SignedVecN + Magnitude { 96 | /// returns scalar distance between point `a` and `b` (magnitude of the vector between the 2 points) 97 | fn distance(a: Self, b: Self) -> T; 98 | /// returns scalar distance between point `a` and `b` (magnitude of the vector between the 2 points) 99 | fn dist(a: Self, b: Self) -> T; 100 | /// returns scalar squared distance between point `a` and `b` to avoid using sqrt 101 | fn dist2(a: Self, b: Self) -> T; 102 | /// returns a reflection vector using an incident ray `i` and a surface normal `n` 103 | fn reflect(i: Self, n: Self) -> Self; 104 | /// returns a refraction vector using an entering ray `i`, a surface normal `n`, and a refraction index `eta` 105 | fn refract(i: Self, n: Self, eta: T) -> Self; 106 | /// returns linear interpolation between `e0` and `e1`, `t` specifies the ratio to interpolate between the values, with component-wise `t` 107 | fn vlerp(e0: Self, e1: Self, t: Self) -> Self; 108 | /// returns vector with component wise hermite interpolation between `0-1`, with component-wise `t` 109 | fn vsmoothstep(e0: Self, e1: Self, t: Self) -> Self; 110 | /// returns vector `a` raised to component wise power `exp` 111 | fn powfn(a: Self, exp: Self) -> Self; 112 | } 113 | 114 | /// trait for dot product 115 | pub trait Dot { 116 | /// vector dot-product 117 | fn dot(a: Self, b: Self) -> T; 118 | } 119 | 120 | impl Dot for Vec2 where T: Number { 121 | fn dot(a: Self, b: Self) -> T { 122 | a.x * b.x + a.y * b.y 123 | } 124 | } 125 | 126 | impl Dot for Vec3 where T: Number { 127 | fn dot(a: Self, b: Self) -> T { 128 | a.x * b.x + a.y * b.y + a.z * b.z 129 | } 130 | } 131 | 132 | impl Dot for Vec4 where T: Number { 133 | fn dot(a: Self, b: Self) -> T { 134 | a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w 135 | } 136 | } 137 | 138 | /// trait for cross product, this is implemented for Vec3 139 | pub trait Cross { 140 | /// vector cross-product 141 | fn cross(a: Self, b: Self) -> Self; 142 | } 143 | 144 | impl Cross for Vec3 where T: Number { 145 | fn cross(a: Self, b: Self) -> Self { 146 | Vec3 { 147 | x: (a.y * b.z) - (a.z * b.y), 148 | y: (a.z * b.x) - (a.x * b.z), 149 | z: (a.x * b.y) - (a.y * b.x), 150 | } 151 | } 152 | } 153 | 154 | /// trait for scalar and vector triple products 155 | pub trait Triple { 156 | /// scalar triple product 157 | fn scalar_triple(a: Self, b: Self, c: Self) -> T; 158 | /// vector triple product 159 | fn vector_triple(a: Self, b: Self, c: Self) -> Self; 160 | } 161 | 162 | /// 3D triple products 163 | impl Triple for Vec3 where T: Number { 164 | fn scalar_triple(a: Self, b: Self, c: Self) -> T { 165 | a.x * (b.y * c.z - b.z * c.y) + a.y * (b.z * c.x - b.x * c.z) + a.z * (b.x * c.y - b.y * c.x) 166 | } 167 | 168 | fn vector_triple(a: Self, b: Self, c: Self) -> Self { 169 | Self::cross(Self::cross(a, b), c) 170 | } 171 | } 172 | 173 | /// 2D triple product specialisation, levearging z-axis 174 | impl Triple for Vec2 where T: Number + SignedNumber { 175 | fn scalar_triple(_a: Self, b: Self, c: Self) -> T { 176 | b.x * c.y - b.y * c.x 177 | } 178 | 179 | fn vector_triple(a: Self, b: Self, c: Self) -> Self { 180 | let a3 = Vec3::::new(a.x, a.y, T::zero()); 181 | let b3 = Vec3::::new(b.x, b.y, T::zero()); 182 | let c3 = Vec3::::new(c.x, c.y, T::zero()); 183 | let v3 = Vec3::::cross(Vec3::::cross(a3, b3), c3); 184 | Self { 185 | x: v3.x, 186 | y: v3.y 187 | } 188 | } 189 | } 190 | 191 | /// trait for spherical interpolation, which is applicable with vec and quat 192 | pub trait Slerp> { 193 | // spherically interpolate between edges `e0` and `e1` by percentage `t` 194 | fn slerp(e0: Self, e1: Self, t: T) -> Self; 195 | } 196 | 197 | /// trait for normalized interpolation, which is applicable with vec and quat 198 | pub trait Nlerp { 199 | // linearly interpolate between edges `e0` and `e1` by percentage `t` and return the normalized value 200 | fn nlerp(e0: Self, e1: Self, t: T) -> Self; 201 | } 202 | 203 | // 204 | // Macro Implementation 205 | // 206 | 207 | /// macro to stamp out various n-dimensional vectors, all of their ops and functions 208 | macro_rules! vec_impl { 209 | ($VecN:ident { $($field:ident, $field_index:expr),* }, $len:expr, $module:ident) => { 210 | 211 | #[cfg_attr(feature="serde", derive(serde::Serialize, serde::Deserialize))] 212 | #[cfg_attr(feature="hash", derive(Hash))] 213 | #[derive(Debug, Copy, Clone)] 214 | #[repr(C)] 215 | pub struct $VecN { 216 | $(pub $field: T,)+ 217 | } 218 | 219 | impl $VecN where T: Number { 220 | /// construct a new vector from scalar values 221 | pub fn new($($field: T,)+) -> $VecN { 222 | $VecN { 223 | $($field,)+ 224 | } 225 | } 226 | } 227 | 228 | impl VecN for $VecN where T: Number { 229 | fn len() -> usize { 230 | $len 231 | } 232 | 233 | fn all(a: Self) -> bool { 234 | $(a.$field != T::zero() &&)+ 235 | true 236 | } 237 | 238 | fn any(a: Self) -> bool { 239 | $(a.$field != T::zero() ||)+ 240 | false 241 | } 242 | 243 | fn max_scalar(a: Self) -> T { 244 | let mut max = a[0]; 245 | for i in 1..Self::len() { 246 | if a[i] > max { 247 | max = a[i]; 248 | } 249 | } 250 | max 251 | } 252 | 253 | fn min_scalar(a: Self) -> T { 254 | let mut min = a[0]; 255 | for i in 1..Self::len() { 256 | if a[i] < min { 257 | min = a[i]; 258 | } 259 | } 260 | min 261 | } 262 | 263 | fn unit_x() -> $VecN { 264 | let v = [T::one(), T::zero(), T::zero(), T::zero()]; 265 | Self { 266 | $($field: v[$field_index],)+ 267 | } 268 | } 269 | 270 | fn unit_y() -> $VecN { 271 | let v = [T::zero(), T::one(), T::zero(), T::zero()]; 272 | Self { 273 | $($field: v[$field_index],)+ 274 | } 275 | } 276 | 277 | fn unit_z() -> $VecN { 278 | let v = [T::zero(), T::zero(), T::one(), T::zero()]; 279 | Self { 280 | $($field: v[$field_index],)+ 281 | } 282 | } 283 | 284 | fn unit_w() -> $VecN { 285 | let v = [T::zero(), T::zero(), T::zero(), T::one()]; 286 | Self { 287 | $($field: v[$field_index],)+ 288 | } 289 | } 290 | 291 | fn red() -> $VecN { 292 | let v = [T::one(), T::zero(), T::zero(), T::one()]; 293 | Self { 294 | $($field: v[$field_index],)+ 295 | } 296 | } 297 | 298 | fn green() -> $VecN { 299 | let v = [T::zero(), T::one(), T::zero(), T::one()]; 300 | Self { 301 | $($field: v[$field_index],)+ 302 | } 303 | } 304 | 305 | fn blue() -> $VecN { 306 | let v = [T::zero(), T::zero(), T::one(), T::one()]; 307 | Self { 308 | $($field: v[$field_index],)+ 309 | } 310 | } 311 | 312 | fn cyan() -> $VecN { 313 | let v = [T::zero(), T::one(), T::one(), T::one()]; 314 | Self { 315 | $($field: v[$field_index],)+ 316 | } 317 | } 318 | 319 | fn magenta() -> $VecN { 320 | let v = [T::one(), T::zero(), T::one(), T::one()]; 321 | Self { 322 | $($field: v[$field_index],)+ 323 | } 324 | } 325 | 326 | fn yellow() -> $VecN { 327 | let v = [T::one(), T::one(), T::zero(), T::one()]; 328 | Self { 329 | $($field: v[$field_index],)+ 330 | } 331 | } 332 | 333 | fn black() -> $VecN { 334 | let v = [T::zero(), T::zero(), T::zero(), T::one()]; 335 | Self { 336 | $($field: v[$field_index],)+ 337 | } 338 | } 339 | 340 | fn white() -> $VecN { 341 | Self::one() 342 | } 343 | 344 | fn as_slice(&self) -> &[T] { 345 | unsafe { 346 | std::slice::from_raw_parts(&self.x, $len) 347 | } 348 | } 349 | 350 | fn as_mut_slice(&mut self) -> &mut [T] { 351 | unsafe { 352 | std::slice::from_raw_parts_mut(&mut self.x, $len) 353 | } 354 | } 355 | 356 | fn as_u8_slice(&self) -> &[u8] { 357 | unsafe { 358 | std::slice::from_raw_parts((&self.x as *const T) as *const u8, std::mem::size_of::<$VecN>()) 359 | } 360 | } 361 | } 362 | 363 | impl SignedVecN for $VecN where T: SignedNumber { 364 | fn minus_one() -> Self { 365 | $VecN { 366 | $($field: T::minus_one(),)+ 367 | } 368 | } 369 | } 370 | 371 | impl IntegerOps for $VecN where T: Integer + IntegerOps { 372 | fn pow(a: Self, exp: u32) -> Self { 373 | Self { 374 | $($field: T::pow(a.$field, exp),)+ 375 | } 376 | } 377 | } 378 | 379 | impl NumberOps for $VecN where T: Number + NumberOps { 380 | fn min(a: Self, b: Self) -> Self { 381 | Self { 382 | $($field: T::min(a.$field, b.$field),)+ 383 | } 384 | } 385 | 386 | fn max(a: Self, b: Self) -> Self { 387 | Self { 388 | $($field: T::max(a.$field, b.$field),)+ 389 | } 390 | } 391 | 392 | fn clamp(x: Self, min: Self, max: Self) -> Self { 393 | Self { 394 | $($field: T::max(T::min(x.$field, max.$field), min.$field),)+ 395 | } 396 | } 397 | 398 | fn step(a: Self, b: Self) -> Self { 399 | Self { 400 | $($field: T::step(a.$field, b.$field),)+ 401 | } 402 | } 403 | } 404 | 405 | impl SignedNumberOps for $VecN where T: SignedNumber + SignedNumberOps { 406 | fn signum(a: Self) -> Self { 407 | Self { 408 | $($field: T::signum(a.$field),)+ 409 | } 410 | } 411 | 412 | fn abs(a: Self) -> Self { 413 | Self { 414 | $($field: T::abs(a.$field),)+ 415 | } 416 | } 417 | } 418 | 419 | impl Magnitude for $VecN where T: Float + FloatOps { 420 | fn length(a: Self) -> T { 421 | T::sqrt(Self::dot(a, a)) 422 | } 423 | 424 | fn mag(a: Self) -> T { 425 | T::sqrt(Self::dot(a, a)) 426 | } 427 | 428 | fn mag2(a: Self) -> T { 429 | Self::dot(a, a) 430 | } 431 | 432 | fn normalize(a: Self) -> Self { 433 | let m = Self::mag(a); 434 | a / m 435 | } 436 | } 437 | 438 | impl VecFloatOps for $VecN where T: Float + FloatOps { 439 | fn distance(a: Self, b: Self) -> T { 440 | let c = a-b; 441 | T::sqrt(Self::dot(c, c)) 442 | } 443 | 444 | fn dist(a: Self, b: Self) -> T { 445 | Self::distance(a, b) 446 | } 447 | 448 | fn dist2(a: Self, b: Self) -> T { 449 | let c = a-b; 450 | Self::dot(c, c) 451 | } 452 | 453 | fn reflect(i: Self, n: Self) -> Self { 454 | // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-reflect 455 | (i - T::two()) * n * Self::dot(i, n) 456 | } 457 | 458 | fn refract(i: Self, n: Self, eta: T) -> Self { 459 | // https://asawicki.info/news_1301_reflect_and_refract_functions.html 460 | let n_dot_i = Self::dot(n, i); 461 | let k = T::one() - eta * eta * (T::one() - n_dot_i * n_dot_i); 462 | if k < T::zero() { 463 | Self::zero() 464 | } 465 | else { 466 | (i * eta) - n * ((n_dot_i + T::sqrt(k)) * eta) 467 | } 468 | } 469 | 470 | fn vlerp(e0: Self, e1: Self, t: Self) -> Self { 471 | Self { 472 | $($field: T::lerp(e0.$field, e1.$field, t.$field),)+ 473 | } 474 | } 475 | 476 | fn vsmoothstep(e0: Self, e1: Self, t: Self) -> Self { 477 | Self { 478 | $($field: T::smoothstep(e0.$field, e1.$field, t.$field),)+ 479 | } 480 | } 481 | 482 | fn powfn(a: Self, exp: Self) -> Self { 483 | Self { 484 | $($field: T::powf(a.$field, exp.$field),)+ 485 | } 486 | } 487 | } 488 | 489 | impl Slerp for $VecN where T: Float + FloatOps + NumberOps { 490 | fn slerp(e0: Self, e1: Self, t: T) -> Self { 491 | // https://blog.demofox.org/2016/02/19/normalized-vector-interpolation-tldr/ 492 | let dot = Self::dot(e0, e1); 493 | let dot = T::clamp(dot, T::minus_one(), T::one()); 494 | let theta = T::acos(dot) * t; 495 | let v = Self::normalize(e1 - e0 * dot); 496 | ((e0 * T::cos(theta)) + (v * T::sin(theta))) 497 | } 498 | } 499 | 500 | impl Nlerp for $VecN where T: Float + FloatOps + NumberOps { 501 | fn nlerp(e0: Self, e1: Self, t: T) -> Self { 502 | Self::normalize( Self { 503 | $($field: T::lerp(e0.$field, e1.$field, t),)+ 504 | }) 505 | } 506 | } 507 | 508 | impl Base for $VecN where T: Number { 509 | fn zero() -> Self { 510 | $VecN { 511 | $($field: T::zero(),)+ 512 | } 513 | } 514 | 515 | fn one() -> Self { 516 | $VecN { 517 | $($field: T::one(),)+ 518 | } 519 | } 520 | 521 | fn two() -> Self { 522 | $VecN { 523 | $($field: T::two(),)+ 524 | } 525 | } 526 | 527 | fn three() -> Self { 528 | $VecN { 529 | $($field: T::four(),)+ 530 | } 531 | } 532 | 533 | fn four() -> Self { 534 | $VecN { 535 | $($field: T::four(),)+ 536 | } 537 | } 538 | 539 | fn min_value() -> Self { 540 | $VecN { 541 | $($field: T::min_value(),)+ 542 | } 543 | } 544 | 545 | fn max_value() -> Self { 546 | $VecN { 547 | $($field: T::max_value(),)+ 548 | } 549 | } 550 | } 551 | 552 | impl Lerp for $VecN where T: Float + Lerp { 553 | fn lerp(e0: Self, e1: Self, t: T) -> Self { 554 | Self { 555 | $($field: T::lerp(e0.$field, e1.$field, t),)+ 556 | } 557 | } 558 | } 559 | 560 | impl FloatOps for $VecN where T: Float + SignedNumberOps + NumberOps + FloatOps { 561 | fn point_five() -> Self { 562 | $VecN { 563 | $($field: T::point_five(),)+ 564 | } 565 | } 566 | 567 | fn pi() -> Self { 568 | $VecN { 569 | $($field: T::pi(),)+ 570 | } 571 | } 572 | 573 | fn two_pi() -> Self { 574 | $VecN { 575 | $($field: T::two_pi(),)+ 576 | } 577 | } 578 | 579 | fn inv_pi() -> Self { 580 | $VecN { 581 | $($field: T::inv_pi(),)+ 582 | } 583 | } 584 | 585 | fn phi() -> Self { 586 | $VecN { 587 | $($field: T::phi(),)+ 588 | } 589 | } 590 | 591 | fn inv_phi() -> Self { 592 | $VecN { 593 | $($field: T::inv_phi(),)+ 594 | } 595 | } 596 | 597 | fn tau() -> Self { 598 | $VecN { 599 | $($field: T::tau(),)+ 600 | } 601 | } 602 | 603 | fn sqrt(a: Self) -> Self { 604 | Self { 605 | $($field: T::sqrt(a.$field),)+ 606 | } 607 | } 608 | 609 | fn rsqrt(a: Self) -> Self { 610 | Self { 611 | $($field: T::recip(T::sqrt(a.$field)),)+ 612 | } 613 | } 614 | 615 | fn recip(a: Self) -> Self { 616 | Self { 617 | $($field: T::recip(a.$field),)+ 618 | } 619 | } 620 | 621 | fn powi(a: Self, exp: i32) -> Self { 622 | Self { 623 | $($field: T::powi(a.$field, exp),)+ 624 | } 625 | } 626 | 627 | fn powf(a: Self, exp: T) -> Self { 628 | Self { 629 | $($field: T::powf(a.$field, exp),)+ 630 | } 631 | } 632 | 633 | fn mad(m: Self, a: Self, b: Self) -> Self { 634 | Self { 635 | $($field: T::mad(m.$field, a.$field, b.$field),)+ 636 | } 637 | } 638 | 639 | fn approx(a: Self, b: Self, eps: T) -> bool { 640 | $(T::abs(a.$field - b.$field) < eps &&)+ 641 | true 642 | } 643 | 644 | fn floor(a: Self) -> Self { 645 | Self { 646 | $($field: T::floor(a.$field),)+ 647 | } 648 | } 649 | 650 | fn ceil(a: Self) -> Self { 651 | Self { 652 | $($field: T::ceil(a.$field),)+ 653 | } 654 | } 655 | 656 | fn copysign(a: Self, sign: T) -> Self { 657 | Self { 658 | $($field: T::copysign(a.$field, sign),)+ 659 | } 660 | } 661 | 662 | fn smoothstep(e0: Self, e1: Self, t: T) -> Self { 663 | Self { 664 | $($field: T::smoothstep(e0.$field, e1.$field, t),)+ 665 | } 666 | } 667 | 668 | fn round(a: Self) -> Self { 669 | Self { 670 | $($field: T::round(a.$field),)+ 671 | } 672 | } 673 | 674 | fn is_nan(a: Self) -> Self { 675 | Self { 676 | $($field: T::is_nan(a.$field),)+ 677 | } 678 | } 679 | 680 | fn is_infinite(a: Self) -> Self { 681 | Self { 682 | $($field: T::is_infinite(a.$field),)+ 683 | } 684 | } 685 | 686 | fn is_finite(a: Self) -> Self { 687 | Self { 688 | $($field: T::is_finite(a.$field),)+ 689 | } 690 | } 691 | 692 | fn saturate(x: Self) -> Self { 693 | Self::clamp(x, Self::zero(), Self::one()) 694 | } 695 | 696 | fn deg_to_rad(a: Self) -> Self { 697 | Self { 698 | $($field: T::deg_to_rad(a.$field),)+ 699 | } 700 | } 701 | 702 | fn rad_to_deg(a: Self) -> Self { 703 | Self { 704 | $($field: T::rad_to_deg(a.$field),)+ 705 | } 706 | } 707 | 708 | fn fmod(x: Self, y: Self) -> Self { 709 | x % y 710 | } 711 | 712 | fn frac(v: Self) -> Self { 713 | Self { 714 | $($field: T::frac(v.$field),)+ 715 | } 716 | } 717 | 718 | fn trunc(v: Self) -> Self { 719 | Self { 720 | $($field: T::trunc(v.$field),)+ 721 | } 722 | } 723 | 724 | fn modf(v: Self) -> (Self, Self) { 725 | ( 726 | Self { 727 | $($field: T::frac(v.$field),)+ 728 | }, 729 | Self { 730 | $($field: T::trunc(v.$field),)+ 731 | } 732 | ) 733 | } 734 | 735 | fn cos(v: Self) -> Self { 736 | Self { 737 | $($field: T::cos(v.$field),)+ 738 | } 739 | } 740 | 741 | fn sin(v: Self) -> Self { 742 | Self { 743 | $($field: T::sin(v.$field),)+ 744 | } 745 | } 746 | 747 | fn tan(v: Self) -> Self { 748 | Self { 749 | $($field: T::tan(v.$field),)+ 750 | } 751 | } 752 | 753 | fn acos(v: Self) -> Self { 754 | Self { 755 | $($field: T::acos(v.$field),)+ 756 | } 757 | } 758 | 759 | fn asin(v: Self) -> Self { 760 | Self { 761 | $($field: T::asin(v.$field),)+ 762 | } 763 | } 764 | 765 | fn atan(v: Self) -> Self { 766 | Self { 767 | $($field: T::atan(v.$field),)+ 768 | } 769 | } 770 | 771 | fn cosh(v: Self) -> Self { 772 | Self { 773 | $($field: T::cosh(v.$field),)+ 774 | } 775 | } 776 | 777 | fn sinh(v: Self) -> Self { 778 | Self { 779 | $($field: T::sinh(v.$field),)+ 780 | } 781 | } 782 | 783 | fn tanh(v: Self) -> Self { 784 | Self { 785 | $($field: T::tanh(v.$field),)+ 786 | } 787 | } 788 | 789 | fn sin_cos(v: Self) -> (Self, Self) { 790 | ( 791 | Self { 792 | $($field: T::sin(v.$field),)+ 793 | }, 794 | Self { 795 | $($field: T::cos(v.$field),)+ 796 | } 797 | ) 798 | } 799 | 800 | fn atan2(y: Self, x: Self) -> Self { 801 | Self { 802 | $($field: T::atan2(y.$field, x.$field),)+ 803 | } 804 | } 805 | 806 | fn exp(v: Self) -> Self { 807 | Self { 808 | $($field: T::exp(v.$field),)+ 809 | } 810 | } 811 | 812 | fn exp2(v: Self) -> Self { 813 | Self { 814 | $($field: T::exp2(v.$field),)+ 815 | } 816 | } 817 | 818 | fn log2(v: Self) -> Self { 819 | Self { 820 | $($field: T::log2(v.$field),)+ 821 | } 822 | } 823 | 824 | fn log10(v: Self) -> Self { 825 | Self { 826 | $($field: T::log10(v.$field),)+ 827 | } 828 | } 829 | 830 | fn log(v: Self, base: T) -> Self { 831 | Self { 832 | $($field: T::log(v.$field, base),)+ 833 | } 834 | } 835 | } 836 | 837 | impl Index for $VecN { 838 | type Output = T; 839 | fn index(&self, i: usize) -> &Self::Output { 840 | match i { 841 | $($field_index => &self.$field, )+ 842 | _ => &self.x 843 | } 844 | } 845 | } 846 | 847 | impl IndexMut for $VecN { 848 | fn index_mut(&mut self, i: usize) -> &mut T { 849 | match i { 850 | $($field_index => &mut self.$field, )+ 851 | _ => &mut self.x 852 | } 853 | } 854 | } 855 | 856 | /// displays like [10.0, 12.0, 13.0] 857 | impl Display for $VecN where T: Display { 858 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 859 | let mut output = String::from("["); 860 | $( 861 | output += &self.$field.to_string(); 862 | if $field_index < $len-1 { 863 | output += &String::from(", "); 864 | } 865 | )+ 866 | output += "]"; 867 | write!(f, "{}", output) 868 | } 869 | } 870 | 871 | /// default to zero 872 | impl Default for $VecN where T: Number { 873 | fn default() -> Self { 874 | Self::zero() 875 | } 876 | } 877 | 878 | // 879 | // ops 880 | // 881 | 882 | impl Deref for $VecN where T: Number { 883 | type Target = [T]; 884 | fn deref(&self) -> &Self::Target { 885 | self.as_slice() 886 | } 887 | } 888 | 889 | impl DerefMut for $VecN where T: Number { 890 | fn deref_mut(&mut self) -> &mut [T] { 891 | self.as_mut_slice() 892 | } 893 | } 894 | 895 | impl Add for $VecN where T: Number { 896 | type Output = Self; 897 | fn add(self, other: Self) -> Self { 898 | Self { 899 | $($field: self.$field + other.$field,)+ 900 | } 901 | } 902 | } 903 | 904 | impl Add for $VecN where T: Number { 905 | type Output = Self; 906 | fn add(self, other: T) -> Self { 907 | Self { 908 | $($field: self.$field + other,)+ 909 | } 910 | } 911 | } 912 | 913 | // add refs 914 | impl Add<&Self> for $VecN where T: Number { 915 | type Output = Self; 916 | fn add(self, other: &Self) -> Self { 917 | self.add(*other) 918 | } 919 | } 920 | 921 | impl Add<$VecN> for &$VecN where T: Number { 922 | type Output = $VecN; 923 | fn add(self, other: $VecN) -> $VecN { 924 | *self + other 925 | } 926 | } 927 | 928 | impl Add for &$VecN where T: Number { 929 | type Output = $VecN; 930 | fn add(self, other: Self) -> $VecN { 931 | *self + other 932 | } 933 | } 934 | 935 | impl AddAssign for $VecN where T: Number { 936 | fn add_assign(&mut self, other: Self) { 937 | $(self.$field += other.$field;)+ 938 | } 939 | } 940 | 941 | impl AddAssign for $VecN where T: Number { 942 | fn add_assign(&mut self, other: T) { 943 | $(self.$field += other;)+ 944 | } 945 | } 946 | 947 | // add assign ref 948 | impl AddAssign<&Self> for $VecN where T: Number { 949 | fn add_assign(&mut self, other: &Self) { 950 | $(self.$field += other.$field;)+ 951 | } 952 | } 953 | 954 | impl Sub for $VecN where T: Number { 955 | type Output = Self; 956 | fn sub(self, other: Self) -> Self { 957 | Self { 958 | $($field: self.$field - other.$field,)+ 959 | } 960 | } 961 | } 962 | 963 | impl Sub for $VecN where T: Number { 964 | type Output = Self; 965 | fn sub(self, other: T) -> Self { 966 | Self { 967 | $($field: self.$field - other,)+ 968 | } 969 | } 970 | } 971 | 972 | // sub refs 973 | impl Sub<&Self> for $VecN where T: Number { 974 | type Output = Self; 975 | fn sub(self, other: &Self) -> Self { 976 | self.sub(*other) 977 | } 978 | } 979 | 980 | impl Sub<$VecN> for &$VecN where T: Number { 981 | type Output = $VecN; 982 | fn sub(self, other: $VecN) -> $VecN { 983 | *self - other 984 | } 985 | } 986 | 987 | impl Sub for &$VecN where T: Number { 988 | type Output = $VecN; 989 | fn sub(self, other: Self) -> $VecN { 990 | *self - other 991 | } 992 | } 993 | 994 | impl SubAssign for $VecN where T: Number { 995 | fn sub_assign(&mut self, other: Self) { 996 | $(self.$field -= other.$field;)+ 997 | } 998 | } 999 | 1000 | impl SubAssign for $VecN where T: Number { 1001 | fn sub_assign(&mut self, other: T) { 1002 | $(self.$field -= other;)+ 1003 | } 1004 | } 1005 | 1006 | // sub assign ref 1007 | impl SubAssign<&Self> for $VecN where T: Number { 1008 | fn sub_assign(&mut self, other: &Self) { 1009 | $(self.$field -= other.$field;)+ 1010 | } 1011 | } 1012 | 1013 | impl Mul for $VecN where T: Number { 1014 | type Output = Self; 1015 | fn mul(self, other: Self) -> Self { 1016 | Self { 1017 | $($field: self.$field * other.$field,)+ 1018 | } 1019 | } 1020 | } 1021 | 1022 | impl Mul for $VecN where T: Number { 1023 | type Output = Self; 1024 | fn mul(self, other: T) -> Self { 1025 | Self { 1026 | $($field: self.$field * other,)+ 1027 | } 1028 | } 1029 | } 1030 | 1031 | // mul refs 1032 | impl Mul<&Self> for $VecN where T: Number { 1033 | type Output = Self; 1034 | fn mul(self, other: &Self) -> Self { 1035 | self.mul(*other) 1036 | } 1037 | } 1038 | 1039 | impl Mul<$VecN> for &$VecN where T: Number { 1040 | type Output = $VecN; 1041 | fn mul(self, other: $VecN) -> $VecN { 1042 | *self * other 1043 | } 1044 | } 1045 | 1046 | impl Mul for &$VecN where T: Number { 1047 | type Output = $VecN; 1048 | fn mul(self, other: Self) -> $VecN { 1049 | *self * other 1050 | } 1051 | } 1052 | 1053 | impl MulAssign for $VecN where T: Number { 1054 | fn mul_assign(&mut self, other: Self) { 1055 | $(self.$field *= other.$field;)+ 1056 | } 1057 | } 1058 | 1059 | impl MulAssign for $VecN where T: Number { 1060 | fn mul_assign(&mut self, other: T) { 1061 | $(self.$field *= other;)+ 1062 | } 1063 | } 1064 | 1065 | // mul assign ref 1066 | impl MulAssign<&Self> for $VecN where T: Number { 1067 | fn mul_assign(&mut self, other: &Self) { 1068 | $(self.$field *= other.$field;)+ 1069 | } 1070 | } 1071 | 1072 | impl Div for $VecN where T: Number { 1073 | type Output = Self; 1074 | fn div(self, other: Self) -> Self { 1075 | Self { 1076 | $($field: self.$field / other.$field,)+ 1077 | } 1078 | } 1079 | } 1080 | 1081 | impl Div for $VecN where T: Number { 1082 | type Output = Self; 1083 | fn div(self, other: T) -> Self { 1084 | Self { 1085 | $($field: self.$field / other,)+ 1086 | } 1087 | } 1088 | } 1089 | 1090 | // div refs 1091 | impl Div<&Self> for $VecN where T: Number { 1092 | type Output = Self; 1093 | fn div(self, other: &Self) -> Self { 1094 | self.div(*other) 1095 | } 1096 | } 1097 | 1098 | impl Div<$VecN> for &$VecN where T: Number { 1099 | type Output = $VecN; 1100 | fn div(self, other: $VecN) -> $VecN { 1101 | *self / other 1102 | } 1103 | } 1104 | 1105 | impl Div for &$VecN where T: Number { 1106 | type Output = $VecN; 1107 | fn div(self, other: Self) -> $VecN { 1108 | *self / other 1109 | } 1110 | } 1111 | 1112 | impl DivAssign for $VecN where T: Number { 1113 | fn div_assign(&mut self, other: Self) { 1114 | $(self.$field /= other.$field;)+ 1115 | } 1116 | } 1117 | 1118 | impl DivAssign for $VecN where T: Number { 1119 | fn div_assign(&mut self, other: T) { 1120 | $(self.$field /= other;)+ 1121 | } 1122 | } 1123 | 1124 | // div assign ref 1125 | impl DivAssign<&Self> for $VecN where T: Number { 1126 | fn div_assign(&mut self, other: &Self) { 1127 | $(self.$field /= other.$field;)+ 1128 | } 1129 | } 1130 | 1131 | impl Rem for $VecN where T: Number { 1132 | type Output = Self; 1133 | fn rem(self, other: Self) -> Self { 1134 | Self { 1135 | $($field: self.$field % other.$field,)+ 1136 | } 1137 | } 1138 | } 1139 | 1140 | impl Rem for $VecN where T: Number { 1141 | type Output = Self; 1142 | fn rem(self, other: T) -> Self { 1143 | Self { 1144 | $($field: self.$field % other,)+ 1145 | } 1146 | } 1147 | } 1148 | 1149 | impl RemAssign for $VecN where T: Number { 1150 | fn rem_assign(&mut self, other: Self) { 1151 | $(self.$field %= other.$field;)+ 1152 | } 1153 | } 1154 | 1155 | impl RemAssign for $VecN where T: Number { 1156 | fn rem_assign(&mut self, other: T) { 1157 | $(self.$field %= other;)+ 1158 | } 1159 | } 1160 | 1161 | impl Neg for $VecN where T: SignedNumber { 1162 | type Output = Self; 1163 | fn neg(self) -> Self::Output { 1164 | Self { 1165 | $($field: -self.$field,)+ 1166 | } 1167 | } 1168 | } 1169 | 1170 | impl Eq for $VecN where T: Eq {} 1171 | impl PartialEq for $VecN where T: PartialEq { 1172 | fn eq(&self, other: &Self) -> bool { 1173 | $(self.$field == other.$field &&)+ 1174 | true 1175 | } 1176 | } 1177 | } 1178 | } 1179 | 1180 | /// macro to stamp out various typed c-style constructors. ie. let v = vec3f(0.0, 1.0, 0.0); 1181 | macro_rules! vec_ctor { 1182 | ($VecN:ident { $($field:ident),+ }, $ctor:ident, $splat:ident, $t:ident) => { 1183 | pub fn $ctor($($field: $t,)+) -> $VecN<$t> { 1184 | $VecN { 1185 | $($field,)+ 1186 | } 1187 | } 1188 | pub fn $splat(v: $t) -> $VecN<$t> { 1189 | $VecN { 1190 | $($field: v,)+ 1191 | } 1192 | } 1193 | } 1194 | } 1195 | 1196 | /// macro to stamp out all arithmetic ops for lhs scalars 1197 | macro_rules! vec_scalar_lhs { 1198 | ($VecN:ident { $($field:ident),+ }, $t:ident) => { 1199 | impl Add<$VecN<$t>> for $t { 1200 | type Output = $VecN<$t>; 1201 | fn add(self, other: $VecN<$t>) -> $VecN<$t> { 1202 | $VecN { 1203 | $($field: self + other.$field,)+ 1204 | } 1205 | } 1206 | } 1207 | 1208 | impl Sub<$VecN<$t>> for $t { 1209 | type Output = $VecN<$t>; 1210 | fn sub(self, other: $VecN<$t>) -> $VecN<$t> { 1211 | $VecN { 1212 | $($field: self - other.$field,)+ 1213 | } 1214 | } 1215 | } 1216 | 1217 | impl Mul<$VecN<$t>> for $t { 1218 | type Output = $VecN<$t>; 1219 | fn mul(self, other: $VecN<$t>) -> $VecN<$t> { 1220 | $VecN { 1221 | $($field: self * other.$field,)+ 1222 | } 1223 | } 1224 | } 1225 | 1226 | impl Div<$VecN<$t>> for $t { 1227 | type Output = $VecN<$t>; 1228 | fn div(self, other: $VecN<$t>) -> $VecN<$t> { 1229 | $VecN { 1230 | $($field: self / other.$field,)+ 1231 | } 1232 | } 1233 | } 1234 | 1235 | impl Rem<$VecN<$t>> for $t { 1236 | type Output = $VecN<$t>; 1237 | fn rem(self, other: $VecN<$t>) -> $VecN<$t> { 1238 | $VecN { 1239 | $($field: self % other.$field,)+ 1240 | } 1241 | } 1242 | } 1243 | } 1244 | } 1245 | 1246 | // 1247 | // From 1248 | // 1249 | 1250 | /// constructs vec2 from scalar T splatting to x and y 1251 | impl From for Vec2 where T: Number { 1252 | fn from(other: T) -> Vec2 { 1253 | Vec2 { 1254 | x: other, 1255 | y: other, 1256 | } 1257 | } 1258 | } 1259 | 1260 | // constructs vec2 from tuple of 2 scalars x: .0, y: .1 1261 | impl From<(T, T)> for Vec2 where T: Number { 1262 | fn from(other: (T, T)) -> Vec2 { 1263 | Vec2 { 1264 | x: other.0, 1265 | y: other.1, 1266 | } 1267 | } 1268 | } 1269 | 1270 | /// constructs vec2 from vec3 copying the x,y and truncating the z 1271 | impl From> for Vec2 where T: Number { 1272 | fn from(other: Vec3) -> Vec2 { 1273 | Vec2 { 1274 | x: other.x, 1275 | y: other.y, 1276 | } 1277 | } 1278 | } 1279 | 1280 | /// constructs vec2 from vec4 copying the x,y and truncating the z,w 1281 | impl From> for Vec2 where T: Number { 1282 | fn from(other: Vec4) -> Vec2 { 1283 | Vec2 { 1284 | x: other.x, 1285 | y: other.y, 1286 | } 1287 | } 1288 | } 1289 | 1290 | /// constructs vec3 from scalar T splatting to x,y,z 1291 | impl From for Vec3 where T: Number { 1292 | fn from(other: T) -> Vec3 { 1293 | Vec3 { 1294 | x: other, 1295 | y: other, 1296 | z: other 1297 | } 1298 | } 1299 | } 1300 | 1301 | /// constructs vec3 from vec2 copying the x,y and zeroing the z 1302 | impl From> for Vec3 where T: Number { 1303 | fn from(other: Vec2) -> Vec3 { 1304 | Vec3 { 1305 | x: other.x, 1306 | y: other.y, 1307 | z: T::zero() 1308 | } 1309 | } 1310 | } 1311 | 1312 | /// constructs vec3 from tuple of 3 scalars 1313 | impl From<(T, T, T)> for Vec3 where T: Number { 1314 | fn from(other: (T, T, T)) -> Vec3 { 1315 | Vec3 { 1316 | x: other.0, 1317 | y: other.1, 1318 | z: other.2 1319 | } 1320 | } 1321 | } 1322 | 1323 | /// construct from a tuple of vec2 into x,y and scalar into z 1324 | impl From<(Vec2, T)> for Vec3 where T: Number { 1325 | fn from(other: (Vec2, T)) -> Vec3 { 1326 | Vec3 { 1327 | x: other.0.x, 1328 | y: other.0.y, 1329 | z: other.1 1330 | } 1331 | } 1332 | } 1333 | 1334 | /// constructs vec3 from vec4 copying the x,y,z and truncating the w 1335 | impl From> for Vec3 where T: Number { 1336 | fn from(other: Vec4) -> Vec3 { 1337 | Vec3 { 1338 | x: other.x, 1339 | y: other.y, 1340 | z: other.z, 1341 | } 1342 | } 1343 | } 1344 | 1345 | /// constructs vec4 from scalar T splatting to x,y,z,w 1346 | impl From for Vec4 where T: Number { 1347 | fn from(other: T) -> Vec4 { 1348 | Vec4 { 1349 | x: other, 1350 | y: other, 1351 | z: other, 1352 | w: other 1353 | } 1354 | } 1355 | } 1356 | 1357 | /// constructs vec4 from vec2 copying the x,y and zeroing the z,w 1358 | impl From> for Vec4 where T: Number { 1359 | fn from(other: Vec2) -> Vec4 { 1360 | Vec4 { 1361 | x: other.x, 1362 | y: other.y, 1363 | z: T::zero(), 1364 | w: T::zero() 1365 | } 1366 | } 1367 | } 1368 | 1369 | /// constructs vec4 from vec2 copying the x,y,z and zeroing the w 1370 | impl From> for Vec4 where T: Number { 1371 | fn from(other: Vec3) -> Vec4 { 1372 | Vec4 { 1373 | x: other.x, 1374 | y: other.y, 1375 | z: other.z, 1376 | w: T::zero() 1377 | } 1378 | } 1379 | } 1380 | 1381 | /// construct from a tuple of vec2 into x,y 2 scalars into z and w 1382 | impl From<(Vec2, T, T)> for Vec4 where T: Number { 1383 | fn from(other: (Vec2, T, T)) -> Vec4 { 1384 | Vec4 { 1385 | x: other.0.x, 1386 | y: other.0.y, 1387 | z: other.1, 1388 | w: other.2 1389 | } 1390 | } 1391 | } 1392 | 1393 | /// construct from a tuple of vec2 into x,y and vec2 into z,w 1394 | impl From<(Vec2, Vec2)> for Vec4 where T: Number { 1395 | fn from(other: (Vec2, Vec2)) -> Vec4 { 1396 | Vec4 { 1397 | x: other.0.x, 1398 | y: other.0.y, 1399 | z: other.1.x, 1400 | w: other.1.y 1401 | } 1402 | } 1403 | } 1404 | 1405 | /// construct from a tuple of vec3 into x,y,z and a scalar into w 1406 | impl From<(Vec3, T)> for Vec4 where T: Number { 1407 | fn from(other: (Vec3, T)) -> Vec4 { 1408 | Vec4 { 1409 | x: other.0.x, 1410 | y: other.0.y, 1411 | z: other.0.z, 1412 | w: other.1 1413 | } 1414 | } 1415 | } 1416 | 1417 | /// constructs vec4 from tuple of 4 scalars 1418 | impl From<(T, T, T, T)> for Vec4 where T: Number { 1419 | fn from(other: (T, T, T, T)) -> Vec4 { 1420 | Vec4 { 1421 | x: other.0, 1422 | y: other.1, 1423 | z: other.2, 1424 | w: other.3 1425 | } 1426 | } 1427 | } 1428 | 1429 | macro_rules! vec_cast { 1430 | ($VecN:ident { $($field:ident),+ }, $t:ident, $u:ident) => { 1431 | impl From<$VecN<$u>> for $VecN<$t> { 1432 | fn from(other: $VecN<$u>) -> $VecN<$t> { 1433 | $VecN { 1434 | $($field: other.$field as $t,)+ 1435 | } 1436 | } 1437 | } 1438 | 1439 | impl From<$VecN<$t>> for $VecN<$u> { 1440 | fn from(other: $VecN<$t>) -> $VecN<$u> { 1441 | $VecN { 1442 | $($field: other.$field as $u,)+ 1443 | } 1444 | } 1445 | } 1446 | } 1447 | } 1448 | 1449 | // 1450 | // Macro Decl 1451 | // 1452 | 1453 | vec_impl!(Vec2 { x, 0, y, 1 }, 2, v2); 1454 | vec_impl!(Vec3 { x, 0, y, 1, z, 2 }, 3, v3); 1455 | vec_impl!(Vec4 { x, 0, y, 1, z, 2, w, 3 }, 4, v4); 1456 | 1457 | #[cfg(feature = "lhs_scalar_vec_ops")] 1458 | vec_scalar_lhs!(Vec2 { x, y }, f32); 1459 | vec_scalar_lhs!(Vec3 { x, y, z }, f32); 1460 | vec_scalar_lhs!(Vec4 { x, y, z, w }, f32); 1461 | vec_scalar_lhs!(Vec2 { x, y }, f64); 1462 | vec_scalar_lhs!(Vec3 { x, y, z }, f64); 1463 | vec_scalar_lhs!(Vec4 { x, y, z, w }, f64); 1464 | vec_scalar_lhs!(Vec2 { x, y }, i32); 1465 | vec_scalar_lhs!(Vec3 { x, y, z }, i32); 1466 | vec_scalar_lhs!(Vec4 { x, y, z, w }, i32); 1467 | vec_scalar_lhs!(Vec2 { x, y }, u32); 1468 | vec_scalar_lhs!(Vec3 { x, y, z }, u32); 1469 | vec_scalar_lhs!(Vec4 { x, y, z, w }, u32); 1470 | 1471 | #[cfg(feature = "short_hand_constructors")] 1472 | vec_ctor!(Vec2 { x, y }, vec2f, splat2f, f32); 1473 | vec_ctor!(Vec3 { x, y, z }, vec3f, splat3f, f32); 1474 | vec_ctor!(Vec4 { x, y, z, w }, vec4f, splat4f, f32); 1475 | vec_ctor!(Vec2 { x, y }, vec2d, splat2d, f64); 1476 | vec_ctor!(Vec3 { x, y, z }, vec3d, splat3d, f64); 1477 | vec_ctor!(Vec4 { x, y, z, w }, vec4d, splat4d, f64); 1478 | vec_ctor!(Vec2 { x, y }, vec2i, splat2i, i32); 1479 | vec_ctor!(Vec3 { x, y, z }, vec3i, splat3i, i32); 1480 | vec_ctor!(Vec4 { x, y, z, w }, vec4i, splat4i, i32); 1481 | vec_ctor!(Vec2 { x, y }, vec2u, splat2u, u32); 1482 | vec_ctor!(Vec3 { x, y, z }, vec3u, splat3u, u32); 1483 | vec_ctor!(Vec4 { x, y, z, w }, vec4u, splat4u, u32); 1484 | 1485 | #[cfg(feature = "casts")] 1486 | vec_cast!(Vec2 { x, y }, f64, i32); 1487 | vec_cast!(Vec2 { x, y }, f64, u32); 1488 | vec_cast!(Vec2 { x, y }, f32, f64); 1489 | vec_cast!(Vec2 { x, y }, f32, i32); 1490 | vec_cast!(Vec2 { x, y }, f32, u32); 1491 | vec_cast!(Vec2 { x, y }, i32, u32); 1492 | vec_cast!(Vec3 {x, y, z}, f64, i32); 1493 | vec_cast!(Vec3 {x, y, z}, f64, u32); 1494 | vec_cast!(Vec3 {x, y, z}, f32, f64); 1495 | vec_cast!(Vec3 {x, y, z}, f32, i32); 1496 | vec_cast!(Vec3 {x, y, z}, f32, u32); 1497 | vec_cast!(Vec3 {x, y, z}, i32, u32); 1498 | vec_cast!(Vec4 {x, y, z, w}, f64, i32); 1499 | vec_cast!(Vec4 {x, y, z, w}, f64, u32); 1500 | vec_cast!(Vec4 {x, y, z, w}, f32, f64); 1501 | vec_cast!(Vec4 {x, y, z, w}, f32, i32); 1502 | vec_cast!(Vec4 {x, y, z, w}, f32, u32); 1503 | vec_cast!(Vec4 {x, y, z, w}, i32, u32); --------------------------------------------------------------------------------