├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE ├── src ├── ext │ ├── common.rs │ ├── trig.rs │ ├── exp.rs │ ├── matrix │ │ ├── mod.rs │ │ └── transform.rs │ ├── mod.rs │ ├── geom.rs │ └── consts.rs ├── builtin │ ├── mod.rs │ ├── exp.rs │ ├── matrix.rs │ ├── trig.rs │ ├── geom.rs │ ├── vecrel.rs │ ├── pack.rs │ ├── integer.rs │ ├── noise.rs │ └── common.rs ├── mat │ ├── traits.rs │ ├── ctor.rs │ └── sqmat.rs ├── vec │ ├── traits.rs │ ├── swizzle.rs │ └── vec.rs ├── traits.rs ├── lib.rs ├── basenum.rs └── cast.rs └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | .DS_Store 3 | Cargo.lock 4 | Session.vim 5 | target 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: rust 3 | rust: 4 | - nightly 5 | - beta 6 | - stable 7 | env: 8 | global: 9 | # - TRAVIS_CARGO_NIGHTLY_FEATURE=dev 10 | - secure: cbKR6Shd18JPkPkglV866GORaziY0G/ncMji6Iz0XwuQjqdu8wQmydefAKJR+HLbE++vYiKiAhbdzwCrPHNmx5xl4ssJIQu3IcSkyhdUI3ja1wNFQ08XoEgonipBj1wLFO0XCVDL2G4tzbDaj62c5ZVXfoTb4AxCZT3ZPal2So4= 11 | matrix: 12 | allow_failures: 13 | - rust: nightly 14 | before_script: 15 | - | 16 | pip install 'travis-cargo<0.2' --user && 17 | export PATH=$HOME/.local/bin:$PATH 18 | script: 19 | - | 20 | travis-cargo build && 21 | travis-cargo test && 22 | travis-cargo bench && 23 | travis-cargo --only stable doc 24 | after_success: 25 | - travis-cargo --only stable doc-upload 26 | - travis-cargo coveralls --no-sudo 27 | notifications: 28 | email: 29 | on_success: never 30 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "glm" 4 | version = "0.3.0" 5 | edition = "2021" 6 | 7 | authors = [ 8 | "Che Kenan ", 9 | "Nerijus Arlauskas ", 10 | "Fredrik Norén", 11 | "Cameron Hart ", 12 | "human9 ", 13 | "Raphaël Duhen ", 14 | "Joel Nordström ", 15 | "kitcatier ", 16 | ] 17 | 18 | description = "GLSL mathematics for Rust." 19 | keywords = ["glm", "math", "opengl", "glsl"] 20 | license = "MIT" 21 | repository = "https://github.com/dche/glm-rs/" 22 | 23 | [dependencies] 24 | num-traits = { version = "0.2" } 25 | 26 | [dev-dependencies] 27 | quickcheck = "^1.0.3" 28 | 29 | [features] 30 | default = [] 31 | wrapping_ops = [] 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015, 2025 The glm-rs authors. 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/ext/common.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use num_traits::Float; 25 | 26 | use crate::basenum::BaseFloat; 27 | use crate::traits::GenFloat; 28 | 29 | /// Returns the reciprocal (inverse) of float number `x`. 30 | /// 31 | /// # Example 32 | /// 33 | /// ``` 34 | /// use glm::ext::recip; 35 | /// 36 | /// let x = 2f32; 37 | /// let y = glm::vec3(1., 2., 4.); 38 | /// assert_eq!(recip(x), 0.5); 39 | /// assert_eq!(recip(y), glm::vec3(1., 0.5, 0.25)); 40 | /// ``` 41 | #[inline(always)] 42 | pub fn recip>(x: T) -> T { 43 | x.map(Float::recip) 44 | } 45 | -------------------------------------------------------------------------------- /src/ext/trig.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use num_traits::Float; 25 | 26 | use crate::basenum::BaseFloat; 27 | use crate::traits::GenFloat; 28 | 29 | /// Simultaneously computes the sine and cosine of `x`, returns 30 | /// `(sin(x), cos(x))`. 31 | /// 32 | /// # Example 33 | /// 34 | /// ```rust 35 | /// use glm::*; 36 | /// use glm::ext::*; 37 | /// 38 | /// let v = vec2(0., half_pi()); 39 | /// let (s, c) = sin_cos(v); 40 | /// assert!(is_approx_eq(&s, &vec2(0., 1.))); 41 | /// assert!(is_approx_eq(&c, &vec2(1., 0.))); 42 | /// ``` 43 | #[inline(always)] 44 | pub fn sin_cos>(x: T) -> (T, T) { 45 | x.split(Float::sin_cos) 46 | } 47 | -------------------------------------------------------------------------------- /src/ext/exp.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use num_traits::Float; 25 | 26 | use crate::basenum::{BaseFloat, BaseNum}; 27 | use crate::traits::{GenFloat, GenNum}; 28 | 29 | /// Returns the cubic root. 30 | #[inline(always)] 31 | pub fn cbrt>(x: T) -> T { 32 | x.map(Float::cbrt) 33 | } 34 | 35 | /// `x * x`. 36 | #[inline(always)] 37 | pub fn pow2>(x: T) -> T { 38 | x * x 39 | } 40 | 41 | /// `x * x * x`. 42 | #[inline(always)] 43 | pub fn pow3>(x: T) -> T { 44 | x * x * x 45 | } 46 | 47 | /// Raise a number to an integer power. 48 | #[inline(always)] 49 | pub fn powi>(x: T, y: i32) -> T { 50 | x.map(|f| -> F { Float::powi(f, y) }) 51 | } 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GLSL Mathematics for Rust. 2 | 3 | [![Build Status](https://travis-ci.org/dche/glm-rs.png?branch=master)](https://travis-ci.org/dche/glm-rs) 4 | 5 | Another Rust mathematics library for graphics applications. 6 | 7 | Inspired by the great **[GLM](glm.g-truc.net)** library for C++, `glm-rs` 8 | implements the data types, operators and built-in functions defined in GLSL 9 | specification to help graphics programmers who are familiar with GLSL, so they 10 | do not need to learn more than one math API. 11 | 12 | Because of the not so small syntax/semantics difference between Rust and GLSL, 13 | some parts of GLSL are missing or changed, some functions are added to 14 | complete the functionalities. See the [glm-rs documentation](http://dche.github.io/glm-rs/) for full list 15 | of differences. 16 | 17 | The project is in beta status until the major version reaches to `1`. 18 | 19 | ## Thanks 20 | 21 | - [GLM](glm.g-truc.net) by G-Truc (Christophe Riccio). The implementation of 22 | noise functions are directly translated from GLM. 23 | - Creators of the [Rust](http://rust-lang.org) for the language. 24 | 25 | ## v0.3 (2025-08-17) Note 26 | 27 | This version is a quick fix to let the crate work with new versions of Rust, 28 | with following PRs & issues resolved. 29 | 30 | - Support Rust edition 2021 (#26, #30). 31 | - Manually merged PR #29. 32 | - `quickcheck` is a dev-dependency now (#25). 33 | - Marked pack/unpack functions `unsafe` (#27). 34 | - Constructor functions (e.g., `vec3(..)`, `mat4x3(...)`) are `const` (#31). 35 | 36 | ### Breaking Change 37 | 38 | - `GenNum` dropped `Rand` trait, which was removed in new versions of `rand` crate. 39 | 40 | Creating scalar and vector structs randomly with default distribution and range 41 | has few meanings in practice. So following statement does not compile anymore, 42 | 43 | ```rust 44 | let _ = Vec3::rand(); 45 | ``` 46 | 47 | ### Future Plan 48 | 49 | - [ ] `no_std` support. 50 | - [ ] SIMD support. 51 | - [ ] Quaternion. 52 | - [ ] Re-design the generic scalar/vector types using the new Rust language features. 53 | 54 | ## License 55 | 56 | The MIT License (MIT) 57 | -------------------------------------------------------------------------------- /src/ext/matrix/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use crate::basenum::BaseFloat; 25 | use crate::mat::traits::GenSquareMat; 26 | use crate::vec::traits::GenFloatVec; 27 | 28 | pub use self::transform::*; 29 | 30 | mod transform; 31 | 32 | /// Returns the trace of a square matrix `m`. 33 | /// 34 | /// # Example 35 | /// 36 | /// ``` 37 | /// use glm::mat2; 38 | /// use glm::ext::trace; 39 | /// 40 | /// let m2 = mat2(1., 3., 2., 4.); 41 | /// assert_eq!(trace(&m2), 5.); 42 | /// ``` 43 | #[inline] 44 | pub fn trace, M: GenSquareMat>(m: &M) -> F { 45 | let s = C::dim(); 46 | let mut tr = F::zero(); 47 | for i in 0..s { 48 | tr = tr + m[i][i]; 49 | } 50 | tr 51 | } 52 | 53 | /// Returns `true` if the square matrix `m` is invertible, i.e., its determinant 54 | /// does not close or equal to `0`. 55 | /// 56 | /// # Example 57 | /// 58 | /// ``` 59 | /// use glm::mat2; 60 | /// use glm::ext::is_invertible; 61 | /// 62 | /// let m1 = mat2(1., 2., 3., 6.); 63 | /// assert!(!is_invertible(&m1)); 64 | /// let m2 = mat2(1., 2., 3., 4.); 65 | /// assert!(is_invertible(&m2)); 66 | /// ``` 67 | #[inline] 68 | pub fn is_invertible, M: GenSquareMat>(m: &M) -> bool { 69 | let y = F::zero(); 70 | !m.determinant().is_approx_eq(&y) 71 | } 72 | -------------------------------------------------------------------------------- /src/ext/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | //! Functions that extend the functionalities of GLSL data types. 25 | //! 26 | //! # Note 27 | //! 28 | //! - Unlike built-in functions, extension functions are not re-exported to 29 | //! the root module of `glm`. You have to `use glm::ext`. 30 | //! - Also unlike the built-in functions, the naming of extension functions 31 | //! follows the Rust convention, instead of the GLSL's. That is, snake case 32 | //! is used. 33 | //! - The parameters of matrix related functions are passed by reference. 34 | 35 | pub use self::trig::*; 36 | pub use self::exp::*; 37 | pub use self::common::*; 38 | pub use self::geom::*; 39 | pub use self::matrix::*; 40 | pub use self::consts::{ 41 | Consts, 42 | epsilon, 43 | pi, 44 | tau, 45 | root_pi, 46 | half_pi, 47 | one_third_pi, 48 | quarter_pi, 49 | one_over_pi, 50 | one_over_tau, 51 | two_over_pi, 52 | four_over_pi, 53 | two_over_root_pi, 54 | one_over_root_two, 55 | root_half_pi, 56 | root_tau, 57 | root_ln_four, 58 | e, 59 | euler, 60 | root_two, 61 | root_three, 62 | root_five, 63 | ln_two, 64 | ln_ten, 65 | ln_ln_two, 66 | one_third, 67 | two_thirds, 68 | golden_ratio 69 | }; 70 | 71 | mod trig; 72 | mod exp; 73 | mod common; 74 | mod geom; 75 | mod matrix; 76 | pub mod consts; 77 | -------------------------------------------------------------------------------- /src/builtin/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | //! 25 | //! Built-in funcions defined in GLSL specification chapter 8. 26 | //! 27 | //! 28 | 29 | pub use self::trig::{ 30 | radians, degrees, 31 | sin, cos, tan, asin, acos, atan2, atan, 32 | sinh, cosh, tanh, asinh, acosh, atanh, 33 | }; 34 | 35 | pub use self::exp::{ 36 | pow, exp, log, exp2, log2, sqrt, inversesqrt 37 | }; 38 | 39 | pub use self::common::{ 40 | abs, sign, 41 | floor, trunc, round, roundEven, ceil, fract, fmod, mod_s, modf, 42 | min, min_s, max, max_s, clamp, clamp_s, 43 | mix, mix_s, mix_bool, step, step_s, smoothstep, smoothstep_s, 44 | isnan, isinf, 45 | floatBitsToInt, floatBitsToUint, intBitsToFloat, uintBitsToFloat, 46 | fma, 47 | frexp, ldexp, 48 | }; 49 | 50 | pub use self::pack::{ 51 | packUnorm2x16, packUnorm4x8, packSnorm2x16, packSnorm4x8, 52 | unpackUnorm2x16, unpackUnorm4x8, unpackSnorm2x16, unpackSnorm4x8, 53 | packDouble2x32, unpackDouble2x32, 54 | }; 55 | 56 | pub use self::geom::{ 57 | dot, length, distance, normalize, faceforward, reflect, refract, cross, 58 | }; 59 | 60 | pub use self::matrix::{ 61 | matrixCompMult, outerProduct, transpose, determinant, inverse, 62 | }; 63 | 64 | pub use self::vecrel::{ 65 | lessThan, lessThanEqual, greaterThan, greaterThanEqual, equal, notEqual, 66 | all, any, not, 67 | }; 68 | 69 | pub use self::integer::{ 70 | uaddCarry, usubBorrow, umulExtended, imulExtended, 71 | bitfieldExtract, bitfieldInsert, bitfieldReverse, bitCount, 72 | findLSB, findMSB, 73 | }; 74 | 75 | pub use self::noise::{ 76 | noise1, noise2, noise3, noise4, 77 | }; 78 | 79 | mod trig; 80 | mod exp; 81 | mod common; 82 | mod pack; 83 | mod geom; 84 | mod matrix; 85 | mod vecrel; 86 | mod integer; 87 | mod noise; 88 | -------------------------------------------------------------------------------- /src/mat/traits.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use core::ops::{Add, Div, Index, IndexMut, Mul, Neg, Rem, Sub}; 25 | 26 | use num_traits::{One, Zero}; 27 | 28 | use crate::basenum::{ApproxEq, BaseFloat}; 29 | use crate::vec::traits::GenFloatVec; 30 | 31 | /// Generic Matrix type. 32 | pub trait GenMat>: 33 | Sized 34 | + Zero 35 | + Add 36 | + Sub 37 | + Div 38 | + Rem 39 | + Neg 40 | + Mul 41 | + Index 42 | + IndexMut 43 | + ApproxEq 44 | { 45 | /// Type of row vectors. 46 | type R: GenFloatVec; 47 | 48 | /// Type of transpose matrix. 49 | type Transpose: GenMat; 50 | 51 | /// Returns the transpose matrix. 52 | /// 53 | /// # Example 54 | /// 55 | /// ``` 56 | /// use glm::GenMat; // bing the method into scope. 57 | /// 58 | /// let m = glm::mat3x2(1., 2., 3., 4., 5., 6.); 59 | /// let tm = glm::mat2x3(1., 3., 5., 2., 4., 6.); 60 | /// assert_eq!(tm, m.transpose()); 61 | /// ``` 62 | fn transpose(&self) -> Self::Transpose; 63 | 64 | /// Component-wise multiplication. 65 | /// 66 | /// # Example 67 | /// 68 | /// ``` 69 | /// use glm::GenMat; // bing the method into scope. 70 | /// 71 | /// let m1 = glm::mat2(1., 2., 3., 4.); 72 | /// let m2 = glm::mat2(0., 0., -7., 0.5); 73 | /// assert_eq!(m1.mul_c(&m2), glm::mat2(0., 0., -21., 2.)); 74 | /// ``` 75 | fn mul_c(&self, rhs: &Self) -> Self; 76 | } 77 | 78 | /// Generic type of square matrix. 79 | pub trait GenSquareMat>: 80 | GenMat + One 81 | { 82 | /// Returns the determinant of a square matrix. 83 | /// 84 | /// # Example 85 | /// 86 | /// ``` 87 | /// use glm::GenSquareMat; 88 | /// 89 | /// let mat = glm::mat2(1., 3., 2., 4.); 90 | /// assert_eq!(mat.determinant(), -2.); 91 | /// ``` 92 | fn determinant(&self) -> T; 93 | 94 | /// Returns the inverse matrix of a square matrix, or `None` if the 95 | /// matrix is not invertible. 96 | fn inverse(&self) -> Option; 97 | } 98 | -------------------------------------------------------------------------------- /src/vec/traits.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use core::ops::{Index, IndexMut}; 25 | 26 | use crate::basenum::{BaseFloat, BaseNum, Primitive}; 27 | use crate::traits::{GenBType, GenFloat, GenNum}; 28 | 29 | /// Generic vector type. 30 | pub trait GenVec: 31 | Copy + Index + IndexMut 32 | { 33 | /// Returns the dimension of the vector. 34 | /// 35 | /// # Example 36 | /// 37 | /// ``` 38 | /// use glm::GenVec; // bring the method into scope. 39 | /// assert_eq!(glm::IVec4::dim(), 4); 40 | /// ``` 41 | fn dim() -> usize; 42 | 43 | // XXX: swap(i, j) 44 | } 45 | 46 | /// Trait of all vector types that are GenNum. 47 | pub trait GenNumVec: GenNum + GenVec { 48 | /// Returns the sum of all components. 49 | // 50 | /// # Example 51 | /// 52 | /// ``` 53 | /// use glm::GenNumVec; // bring the method into scope. 54 | /// let v = glm::vec3(1., 2., 3.); 55 | /// assert_eq!(v.sum(), 6.0); 56 | /// ``` 57 | fn sum(&self) -> T; 58 | 59 | /// Multiplies all components. 60 | /// 61 | /// # Example 62 | /// 63 | /// ``` 64 | /// use glm::GenNumVec; // bring the method into scope. 65 | /// let v = glm::vec3(2., 3., 4.); 66 | /// assert_eq!(v.product(), 24.); 67 | /// ``` 68 | fn product(&self) -> T; 69 | 70 | /// Returns the minimal value of all components. 71 | /// 72 | /// # Example 73 | /// 74 | /// ``` 75 | /// use glm::GenNumVec; // bring the method into scope. 76 | /// let v = glm::vec3(1.0, 2.0, 3.0); 77 | /// assert_eq!(v.min(), 1.0); 78 | /// ``` 79 | fn min(&self) -> T; 80 | 81 | /// Returns the maximal value of all components. 82 | /// 83 | /// # Example 84 | /// 85 | /// ``` 86 | /// use glm::GenNumVec; // bring the method into scope. 87 | /// 88 | /// let v = glm::vec3(1.0, 2.0, 3.0); 89 | /// assert_eq!(v.max(), 3.0); 90 | /// ``` 91 | fn max(&self) -> T; 92 | } 93 | 94 | /// Generic type of vectors of float number. 95 | pub trait GenFloatVec: GenNumVec + GenFloat {} 96 | 97 | /// Generic boolean vector type. 98 | pub trait GenBVec: GenVec + GenBType { 99 | /// Returns `true` if there is any component of the receiver is `true`. 100 | /// 101 | /// # Example 102 | /// 103 | /// ``` 104 | /// use glm::{ GenBVec, bvec2 }; 105 | /// 106 | /// assert!(bvec2(true, false).any()); 107 | /// assert_eq!(bvec2(false, false).all(), false); 108 | /// ``` 109 | fn any(&self) -> bool; 110 | 111 | /// Returns `true` if all components of the receiver are `true`. 112 | /// 113 | /// # Example 114 | /// 115 | /// ``` 116 | /// use glm::{ GenBVec, bvec2 }; 117 | /// 118 | /// assert_eq!(bvec2(true, false).all(), false); 119 | /// assert_eq!(bvec2(true, true).all(), true); 120 | /// ``` 121 | fn all(&self) -> bool; 122 | 123 | /// Returns the component-wise logical complement of the receiver. 124 | /// 125 | /// # Example 126 | /// 127 | /// ``` 128 | /// use glm::{ GenBVec, bvec2 }; 129 | /// 130 | /// assert_eq!(bvec2(true, false).not(), bvec2(false, true)); 131 | /// ``` 132 | fn not(&self) -> Self; 133 | } 134 | -------------------------------------------------------------------------------- /src/ext/geom.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use crate::basenum::BaseFloat; 25 | use crate::builtin as bif; 26 | use crate::traits::GenFloat; 27 | use crate::vec::traits::GenFloatVec; 28 | 29 | /// Returns the squre of the length of vector `x`. 30 | /// 31 | /// # Example 32 | /// 33 | /// ```rust 34 | /// use glm::*; 35 | /// use glm::ext::*; 36 | /// 37 | /// assert_eq!(sqlength(vec2(1., 2.)), 5.); 38 | /// ``` 39 | #[inline(always)] 40 | pub fn sqlength>(x: T) -> F { 41 | bif::dot(x, x) 42 | } 43 | 44 | /// Returns the reciprocal (inverse) of the length of vector `x`. 45 | /// 46 | /// # Example 47 | /// 48 | /// ```rust 49 | /// use glm::*; 50 | /// use glm::ext::*; 51 | /// 52 | /// let v = vec2(3., 4.); 53 | /// assert_eq!(recip_length(v), 0.2); 54 | /// ``` 55 | #[inline(always)] 56 | pub fn recip_length, T: GenFloatVec>(x: T) -> F { 57 | bif::inversesqrt(sqlength(x)) 58 | } 59 | 60 | /// Normalizes vector `x` of specific length `len`. 61 | /// 62 | /// # Example 63 | /// 64 | /// ``` 65 | /// use glm::length; 66 | /// use glm::ext::normalize_to; 67 | /// 68 | /// let v = glm::vec2(3., 4.); 69 | /// assert_eq!(length(normalize_to(v, 2.)), 2.); 70 | /// ``` 71 | #[inline(always)] 72 | pub fn normalize_to, T: GenFloatVec>(x: T, len: F) -> T { 73 | bif::normalize(x) * len 74 | } 75 | 76 | /// Projects `x` on `y`. 77 | /// 78 | /// # Example 79 | /// 80 | /// ``` 81 | /// use glm::vec2; 82 | /// use glm::ext::projection; 83 | /// 84 | /// assert_eq!(projection(vec2(1., 0.), vec2(1., 1.)), vec2(0.5, 0.5)); 85 | /// ``` 86 | #[inline] 87 | pub fn projection>(x: T, y: T) -> T { 88 | let ling = F::zero(); 89 | let sqlen = sqlength(y); 90 | if sqlen.is_approx_eq(&ling) { 91 | T::zero() 92 | } else { 93 | y * bif::dot(x, y) * sqlen.recip() 94 | } 95 | } 96 | 97 | /// Returns `true` if vector `x` is perpendicular to `y`, i.e., angle between 98 | /// `x` and `y` is π/2. 99 | /// 100 | /// # Example 101 | /// 102 | /// ```rust 103 | /// use glm::ext::is_perpendicular; 104 | /// 105 | /// let x = glm::vec2(1., 0.); 106 | /// let y = glm::vec2(0., 1.); 107 | /// assert!(is_perpendicular(x, y)); 108 | /// ``` 109 | #[inline(always)] 110 | pub fn is_perpendicular>(x: T, y: T) -> bool { 111 | bif::dot(x, y).is_approx_eq(&F::zero()) 112 | } 113 | 114 | /// Returns angle between vectors `x` and `y`. 115 | /// 116 | /// The return value is in radian unit and in the interval [0, π]. 117 | /// 118 | /// # Note 119 | /// 120 | /// - `x` and `y` need be normalized to get meaningful result. 121 | /// - If either `x` or `y` is zero, the angle is undefined, and `0` is returned. 122 | /// 123 | /// # Example 124 | /// 125 | /// ``` 126 | /// use glm::*; 127 | /// use glm::ext::*; 128 | /// 129 | /// let vx = vec2(1., 0.); 130 | /// let vy = vec2(0., 1.); 131 | /// assert!(is_approx_eq(&angle(vx, vy), &half_pi())); 132 | /// assert!(is_approx_eq(&angle(vy, vx), &half_pi())); 133 | /// ``` 134 | #[inline] 135 | pub fn angle, T: GenFloatVec>(x: T, y: T) -> F { 136 | let ling = F::zero(); 137 | let sqmag = bif::dot(x, x) * bif::dot(y, y); 138 | if sqmag.is_approx_eq(&ling) { 139 | ling 140 | } else { 141 | (bif::dot(x, y) * bif::inversesqrt(sqmag)).acos() 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/builtin/exp.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // The GLSL Specification, ch 8.2, Exponential Functions. 24 | 25 | use num_traits::Float; 26 | 27 | use crate::basenum::BaseFloat; 28 | use crate::traits::GenFloat; 29 | 30 | /// Returns `x` raised to the `y` power, i.e., *xy*. 31 | /// 32 | /// Results are undefined if `x < 0`. 33 | /// 34 | /// Results are undefined if `x = 0` and `y ≤ 0`. 35 | /// 36 | /// # Example 37 | /// 38 | /// ``` 39 | /// use glm::{ pow, vec3 }; 40 | /// 41 | /// assert_eq!(pow(2.0, 3.0), 8.0); 42 | /// let v1 = vec3(1.0, 2.0, 3.0); 43 | /// let v2 = vec3(1.0, 4.0, 27.0); 44 | /// assert_eq!(pow(v1, v1), v2); 45 | /// ``` 46 | #[inline(always)] 47 | pub fn pow>(x: T, y: T) -> T { 48 | x.zip(y, Float::powf) 49 | } 50 | 51 | /// Returns the natural exponentiation of `x`. i.e., *ex*. 52 | /// 53 | /// # Example 54 | /// 55 | /// ``` 56 | /// use glm::{ exp, ApproxEq }; 57 | /// use glm::ext::e; 58 | /// 59 | /// let e1: f32 = e(); 60 | /// let e2 = e1 * e1; 61 | /// assert!(exp(2.).is_close_to(&e2, 0.000001)); 62 | /// ``` 63 | #[inline(always)] 64 | pub fn exp>(x: T) -> T { 65 | x.map(Float::exp) 66 | } 67 | 68 | /// Returns the natural logarithm of `x`. i.e., the value `y` which satisfies 69 | /// *x = ey*. 70 | /// 71 | /// # Example 72 | /// 73 | /// ``` 74 | /// use glm::{ log, ApproxEq }; 75 | /// use glm::ext::e; 76 | /// 77 | /// let e1: f64 = e(); 78 | /// let e2 = e1 * e1; 79 | /// assert!(log(e2).is_approx_eq(&2.)); 80 | /// ``` 81 | #[inline(always)] 82 | pub fn log>(x: T) -> T { 83 | x.map(Float::ln) 84 | } 85 | 86 | /// Returns `2` raised to the power of `x`. i.e., *2x*. 87 | /// 88 | /// # Example 89 | /// 90 | /// ``` 91 | /// use glm::{ exp2, dvec2 }; 92 | /// 93 | /// assert_eq!(exp2(10_f32), 1024.); 94 | /// assert_eq!(exp2(dvec2(-1., 5.)), dvec2(0.5, 32.)); 95 | /// ``` 96 | #[inline(always)] 97 | pub fn exp2>(x: T) -> T { 98 | x.map(Float::exp2) 99 | } 100 | 101 | /// Returns the base `2` logarithm of `x`. i.e., the value `y` which satisfies 102 | /// *x = 2y*. 103 | /// 104 | /// Results are undefined if `x < 0`. 105 | /// 106 | /// # Example 107 | /// 108 | /// ``` 109 | /// use glm::{ log2, vec2 }; 110 | /// assert_eq!(log2(vec2(64., 256.)), vec2(6., 8.)); 111 | /// ``` 112 | #[inline(always)] 113 | pub fn log2>(x: T) -> T { 114 | x.map(Float::log2) 115 | } 116 | 117 | /// Returns the square root of `x`. i.e., the value `sqrt(x)`. 118 | /// 119 | /// Results are undefined if `x < 0`. 120 | /// 121 | /// # Example 122 | /// 123 | /// ``` 124 | /// use glm::{ sqrt, vec2 }; 125 | /// assert_eq!(sqrt(vec2(64., 1.)), vec2(8., 1.)); 126 | /// ``` 127 | #[inline(always)] 128 | pub fn sqrt>(x: T) -> T { 129 | x.map(Float::sqrt) 130 | } 131 | 132 | /// Returns the inverse of the square root of `x`. i.e., the value `1/sqrt(x)`. 133 | /// 134 | /// Results are undefined if `x ≤ 0`. 135 | /// 136 | /// # Example 137 | /// 138 | /// ``` 139 | /// use glm::{ inversesqrt, vec2 }; 140 | /// assert_eq!(inversesqrt(4_f32), 0.5); 141 | /// assert_eq!(inversesqrt(vec2(64., 1.)), vec2(0.125, 1.)); 142 | /// ``` 143 | #[inline(always)] 144 | pub fn inversesqrt>(x: T) -> T { 145 | x.map(|f| -> F { f.sqrt().recip() }) 146 | } 147 | -------------------------------------------------------------------------------- /src/builtin/matrix.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | // The GLSL Specification, ch 8.6, Matrix Functions. 25 | 26 | use crate::basenum::BaseFloat; 27 | use crate::mat::traits::{GenMat, GenSquareMat}; 28 | use crate::vec::traits::GenFloatVec; 29 | 30 | /// Multiply matrix `x` by matrix `y` component-wise, i.e., `result[i][j]` is 31 | /// the scalar product of `x[i][j]` and `y[i][j]`. 32 | /// 33 | /// # Note 34 | /// 35 | /// To get linear algebraic matrix multiplication, use the multiply operator 36 | /// `*`. 37 | /// 38 | /// # Example 39 | /// 40 | /// ``` 41 | /// use glm::{ matrixCompMult, mat3x2 }; 42 | /// 43 | /// let m1 = mat3x2(1., 4., 2., 5., 3., 6.); 44 | /// let m2 = mat3x2(2., 3., 2., 3., 2., 3.); 45 | /// let me = mat3x2(2., 12., 4., 15., 6., 18.); 46 | /// assert_eq!(matrixCompMult(&m1, &m2), me); 47 | /// ``` 48 | #[inline(always)] 49 | #[allow(non_snake_case)] 50 | pub fn matrixCompMult, M: GenMat>(x: &M, y: &M) -> M { 51 | x.mul_c(y) 52 | } 53 | 54 | /// Treats the first parameter `c` as a column vector (matrix with one column) 55 | /// and the second parameter `r` as a row vector (matrix with one row) 56 | /// and does a linear algebraic matrix multiply `c * r`, 57 | /// yielding a matrix whose number of rows is the number of components in `c` 58 | /// and whose number of columns is the number of components in `r`. 59 | /// 60 | /// # Example 61 | /// 62 | /// ``` 63 | /// # use glm::*; 64 | /// let v2 = vec2(1., 2.); 65 | /// let v3 = vec3(4., 0., -1.); 66 | /// let e = mat3x2(4., 8., 0., 0., -1., -2.); 67 | /// let op: Mat3x2 = outerProduct(v2, v3); 68 | /// assert_eq!(op, e); 69 | /// ``` 70 | #[inline] 71 | #[allow(non_snake_case)] 72 | pub fn outerProduct< 73 | T: BaseFloat, 74 | C: GenFloatVec, 75 | R: GenFloatVec, 76 | /* 77 | * NOTE: 78 | * I can't believe Rust allows this! But Rust is wrong at the first place. 79 | * Associated types (e.g., `R` and `Transpose` of `GenMat` here) are not type 80 | * parameters, and should not be mandatorily required when specifying a type, 81 | * and if `Transpose` is ommitted (as we did before), that does not mean 82 | * `GenMat` is not implemented for `Tanspose` of `M` (E0277). How could that 83 | * be possible? 84 | */ 85 | N: GenMat, 86 | M: GenMat, 87 | >( 88 | c: C, 89 | r: R, 90 | ) -> M { 91 | let mut z = M::zero(); 92 | let dim = R::dim(); 93 | for i in 0..dim { 94 | z[i] = c * r[i]; 95 | } 96 | z 97 | } 98 | 99 | /// Returns a matrix that is the transpose of `m`. 100 | /// 101 | /// The input matrix `m` is not modified. 102 | #[inline(always)] 103 | pub fn transpose, M: GenMat>(m: &M) -> M::Transpose { 104 | m.transpose() 105 | } 106 | 107 | /// Returns the determinant of `m`. 108 | #[inline(always)] 109 | pub fn determinant, M: GenSquareMat>(m: &M) -> T { 110 | m.determinant() 111 | } 112 | 113 | /// Returns a matrix that is the inverse of `m`. 114 | /// 115 | /// The input matrix `m` is not modified. 116 | /// 117 | /// # Panic 118 | /// 119 | /// It is a panic if `m` is singular or poorly-conditioned (nearly singular). 120 | #[inline] 121 | pub fn inverse, M: GenSquareMat>(m: &M) -> M { 122 | let inv = m.inverse(); 123 | match inv { 124 | Some(im) => im, 125 | _ => panic!("inverse a matrix that is not invertible."), 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/vec/swizzle.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use basenum::Primitive; 25 | use super::vec::{ Vector2, Vector3, Vector4 }; 26 | 27 | macro_rules! def_swizzle2 { 28 | ( 29 | {$($f1: ident, $field1: ident),+}, 30 | {$($f2: ident, {$($field2: ident),+}),+} 31 | ) => { 32 | pub trait Swizzle2 { 33 | fn x(&self) -> T; 34 | fn y(&self) -> T; 35 | $( 36 | #[inline(always)] 37 | fn $f1(&self) -> T { self.$field1() } 38 | )+ 39 | $( 40 | #[inline(always)] 41 | fn $f2(&self) -> Vector2 { 42 | Vector2::new($(self.$field2()),+) 43 | } 44 | )+ 45 | } 46 | } 47 | } 48 | 49 | macro_rules! gen_swizzle2 { 50 | ( 51 | {$($fx: ident),+}, 52 | {$($fy: ident),+}, 53 | { 54 | $({$($f2x: ident),+}, {$($f2y: ident),+}),+ 55 | } 56 | ) => { 57 | def_swizzle2! { 58 | { $($fx, x),+, $($fy, y),+ }, 59 | { 60 | $( 61 | $( 62 | concat_idents!($f2x, $f2y), { $f2x, $f2y } 63 | ),+ 64 | )+ 65 | } 66 | } 67 | } 68 | } 69 | 70 | gen_swizzle2! { 71 | { r, u }, 72 | { g, v }, 73 | { 74 | { x, y }, { x, y }, 75 | { r, g }, { r, g }, 76 | { u, v }, { u, v } 77 | } 78 | } 79 | 80 | macro_rules! def_swizzle3 { 81 | () => { 82 | pub trait Swizzle3: Swizzle2 { 83 | fn z(&self) -> T; 84 | } 85 | } 86 | } 87 | 88 | macro_rules! def_swizzle4 { 89 | () => { 90 | pub trait Swizzle4: Swizzle3 { 91 | fn w(&self) -> T; 92 | } 93 | } 94 | } 95 | 96 | def_swizzle3! {} 97 | def_swizzle4! {} 98 | 99 | macro_rules! impl_swizzle2 { 100 | ($($v: ident),+) => { 101 | $( 102 | impl Swizzle2 for $v { 103 | #[inline(always)] 104 | fn x(&self) -> T { self.x } 105 | #[inline(always)] 106 | fn y(&self) -> T { self.y } 107 | } 108 | )+ 109 | } 110 | } 111 | 112 | macro_rules! impl_swizzle3 { 113 | ($($v: ident),+) => { 114 | $( 115 | impl Swizzle3 for $v { 116 | #[inline(always)] 117 | fn z(&self) -> T { self.z } 118 | } 119 | )+ 120 | } 121 | } 122 | 123 | impl_swizzle2! { Vector2, Vector3, Vector4 } 124 | impl_swizzle3! { Vector3, Vector4 } 125 | 126 | impl Swizzle4 for Vector4 { 127 | #[inline(always)] 128 | fn w(&self) -> T { self.w } 129 | } 130 | 131 | #[cfg(test)] 132 | mod test { 133 | 134 | use vec::vec::*; 135 | use super::*; 136 | 137 | #[test] 138 | fn test_swizzle2() { 139 | let v = ivec4(1, 2, 3, 4); 140 | assert_eq!(v.xy(), ivec2(1, 2)); 141 | assert_eq!(v.ww(), ivec2(4, 4)); 142 | assert_eq!(v.zy(), ivec2(3, 2)); 143 | assert_eq!(v.gb(), ivec2(2, 3)); 144 | assert_eq!(v.ts(), ivec2(4, 3)); 145 | assert_eq!(v.vv(), ivec2(2, 2)); 146 | assert_eq!(v.bb(), v.ss()); 147 | } 148 | 149 | #[test] 150 | fn test_swizzle3() { 151 | let v = vec3(0., 1., 2.); 152 | 153 | } 154 | 155 | #[test] 156 | fn test_swizzle4() { 157 | let v = uvec4(0, 7, 5, 2); 158 | 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/traits.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use core::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Rem, Shl, Shr, Sub}; 25 | 26 | use num_traits::{Float, One, Zero}; 27 | 28 | use crate::basenum::{ApproxEq, BaseFloat, BaseInt, BaseNum, SignedNum}; 29 | 30 | // TODO: use associated types to reduce redundant type parameters. 31 | 32 | /// Generic numeric type. 33 | pub trait GenNum: 34 | Copy 35 | + Sized 36 | + Clone 37 | + One 38 | + Zero 39 | + Div 40 | + Rem 41 | + Add 42 | + Mul 43 | { 44 | /// Constructs from a scalar number. 45 | fn from_s(x: E) -> Self; 46 | 47 | fn map(self, f: F) -> Self 48 | where 49 | F: Fn(E) -> E; 50 | 51 | fn zip(self, y: Self, f: F) -> Self 52 | where 53 | F: Fn(E, E) -> E; 54 | 55 | fn split(self, f: F) -> (Self, Self) 56 | where 57 | F: Fn(E) -> (E, E); 58 | 59 | fn map2(self, y: Self, f: F) -> (Self, Self) 60 | where 61 | F: Fn(E, E) -> (E, E); 62 | } 63 | 64 | macro_rules! impl_GenNum_for_scalar( 65 | ($t: ty) => { 66 | impl GenNum<$t> for $t { 67 | #[inline(always)] 68 | fn from_s(x: $t) -> Self { 69 | x 70 | } 71 | #[inline(always)] 72 | fn map $t>(self, f: F) -> $t { 73 | f(self) 74 | } 75 | #[inline(always)] 76 | fn zip $t>(self, y: $t, f: F) -> $t { 77 | f(self, y) 78 | } 79 | #[inline(always)] 80 | fn split ($t, $t)>(self, f: F) -> ($t, $t) { 81 | f(self) 82 | } 83 | #[inline(always)] 84 | fn map2 ($t, $t)>(self, y: $t, f: F) -> ($t, $t) { 85 | f(self, y) 86 | } 87 | } 88 | } 89 | ); 90 | 91 | /// Generic interger type. 92 | pub trait GenInt: 93 | GenNum 94 | + Eq 95 | + Not 96 | + BitAnd 97 | + BitOr 98 | + BitXor 99 | + Shl 100 | + Shr 101 | { 102 | } 103 | 104 | /// Generic signed integer type. 105 | /// 106 | /// # Note 107 | /// 108 | /// Only 32-bit integer is used in GLSL. 109 | pub trait GenIType: GenInt + SignedNum + Sub {} 110 | 111 | impl_GenNum_for_scalar! { i32 } 112 | impl GenInt for i32 {} 113 | impl GenIType for i32 {} 114 | 115 | /// Generic unsigned integer type. 116 | /// 117 | /// # Note 118 | /// 119 | /// Only 32-bit unsigned integer is used in GLSL. 120 | pub trait GenUType: GenInt {} 121 | 122 | impl_GenNum_for_scalar! { u32 } 123 | impl GenInt for u32 {} 124 | impl GenUType for u32 {} 125 | 126 | /// Generic float number type. 127 | pub trait GenFloat: 128 | GenNum + ApproxEq + SignedNum + Sub 129 | { 130 | /// Computes and returns `a * b + c`. 131 | fn fma(&self, b: &Self, c: &Self) -> Self; 132 | } 133 | 134 | pub trait GenType: GenFloat {} 135 | pub trait GenDType: GenFloat {} 136 | 137 | macro_rules! impl_GenFloat_for_scalar( 138 | ($t: ty, $gt: path) => { 139 | impl_GenNum_for_scalar! { $t } 140 | impl GenFloat<$t> for $t { 141 | fn fma(&self, b: &$t, c: &$t) -> $t { 142 | Float::mul_add(*self, *b, *c) 143 | } 144 | } 145 | impl $gt for $t {} 146 | } 147 | ); 148 | 149 | impl_GenFloat_for_scalar! { f32, GenType } 150 | impl_GenFloat_for_scalar! { f64, GenDType } 151 | 152 | /// Generic boolean type. 153 | pub trait GenBType: Eq {} 154 | 155 | impl GenBType for bool {} 156 | -------------------------------------------------------------------------------- /src/builtin/trig.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | // The GLSL Specification, ch 8.1, Angle and Trigonometry Functions. 25 | 26 | use num_traits::Float; 27 | 28 | use crate::basenum::BaseFloat; 29 | use crate::traits::GenFloat; 30 | 31 | /// Converts `degrees` to radians, i.e., `π/180 * degrees`. 32 | #[inline(always)] 33 | pub fn radians>(degrees: T) -> T { 34 | degrees.map(BaseFloat::to_radians) 35 | } 36 | 37 | /// Converts `radians` to degrees, i.e., `180/π * radians`. 38 | #[inline(always)] 39 | pub fn degrees>(radians: T) -> T { 40 | radians.map(BaseFloat::to_degrees) 41 | } 42 | 43 | /// The standard trigonometric sine function. 44 | #[inline(always)] 45 | pub fn sin>(angle: T) -> T { 46 | angle.map(Float::sin) 47 | } 48 | 49 | /// The standard trigonometric cosine function. 50 | #[inline(always)] 51 | pub fn cos>(angle: T) -> T { 52 | angle.map(Float::cos) 53 | } 54 | 55 | /// The standard trigonometric tangent. 56 | #[inline(always)] 57 | pub fn tan>(angle: T) -> T { 58 | angle.map(Float::tan) 59 | } 60 | 61 | /// Returns an angle whose sine is `x`. 62 | /// 63 | /// The range of values returned by this function is `[-π/2, π/2]`. 64 | /// 65 | /// Results are undefined if `|x| > 1`. 66 | #[inline(always)] 67 | pub fn asin>(x: T) -> T { 68 | x.map(Float::asin) 69 | } 70 | 71 | /// Returns an angle whose cosine is `x`. 72 | /// 73 | /// The range of values returned by this function is `[0, π]`. 74 | /// 75 | /// Results are undefined if `∣x∣ > 1`. 76 | #[inline(always)] 77 | pub fn acos>(x: T) -> T { 78 | x.map(Float::acos) 79 | } 80 | 81 | /// Returns an angle whose tangent is `y / x`. 82 | /// 83 | /// The signs of `x` and `y` are used to determine what quadrant the angle is 84 | /// in. 85 | /// 86 | /// The range of values returned by this function is `[−π, π]`. 87 | /// 88 | /// Results are undefined if `x` and `y` are both `0`. 89 | /// 90 | /// # Note 91 | /// 92 | /// `atan2` is not a GLSL function name. 93 | #[inline(always)] 94 | pub fn atan2>(y: T, x: T) -> T { 95 | x.zip(y, Float::atan2) 96 | } 97 | 98 | /// Returns an angle whose tangent is `y_over_x`. 99 | /// 100 | /// The range of values returned by this function is `[-π/2, π/2]`. 101 | #[inline(always)] 102 | pub fn atan>(y_over_x: T) -> T { 103 | y_over_x.map(Float::atan) 104 | } 105 | 106 | /// Returns the hyperbolic sine function (ex - e-x) / 2. 107 | #[inline(always)] 108 | pub fn sinh>(x: T) -> T { 109 | x.map(Float::sinh) 110 | } 111 | 112 | /// Returns the hyperbolic cosine function (ex + e-x) / 2. 113 | #[inline(always)] 114 | pub fn cosh>(x: T) -> T { 115 | x.map(Float::cosh) 116 | } 117 | 118 | /// Returns the hyperbolic tangent function `sinh(x)/cosh(x)`. 119 | #[inline(always)] 120 | pub fn tanh>(x: T) -> T { 121 | x.map(Float::tanh) 122 | } 123 | 124 | /// Arc hyperbolic sine; returns the inverse of **sinh**. 125 | #[inline(always)] 126 | pub fn asinh>(x: T) -> T { 127 | x.map(Float::asinh) 128 | } 129 | 130 | /// Arc hyperbolic cosine; returns the non-negative inverse of **cosh**. 131 | /// 132 | /// Results are undefined if `x < 1`. 133 | #[inline(always)] 134 | pub fn acosh>(x: T) -> T { 135 | x.map(Float::acosh) 136 | } 137 | 138 | /// Arc hyperbolic tangent; returns the inverse of **tanh**. 139 | /// 140 | /// Results are undefined if `∣x∣ ≥ 1`. 141 | #[inline(always)] 142 | pub fn atanh>(x: T) -> T { 143 | x.map(Float::atanh) 144 | } 145 | -------------------------------------------------------------------------------- /src/builtin/geom.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | // The GLSL Specification, ch 8.5, Geometric Functions. 25 | // 26 | // NOTE: 27 | // - `ftransform` is not implemented. 28 | 29 | use crate::basenum::BaseFloat; 30 | use crate::traits::GenFloat; 31 | use crate::vec::traits::GenFloatVec; 32 | use crate::vec::vec::Vector3; 33 | 34 | use super::exp::inversesqrt; 35 | 36 | /// Returns the dot product of `x` and `y`, i.e., 37 | /// `x[0] * y[0] + x[1] * y[1] + ...`. 38 | /// 39 | /// # Example 40 | /// 41 | /// ``` 42 | /// use glm::{ dot, vec2 }; 43 | /// 44 | /// let v1 = vec2(1., 2.); 45 | /// let v2 = vec2(3., 4.); 46 | /// assert_eq!(dot(v1, v2), 11.); 47 | /// ``` 48 | #[inline(always)] 49 | pub fn dot>(x: T, y: T) -> S { 50 | (x * y).sum() 51 | } 52 | 53 | /// Returns the length of vector `x`, i.e., `sqrt(x[0]^2 + x[1]^2 + ...)`. 54 | /// 55 | /// # Example 56 | /// 57 | /// ``` 58 | /// assert_eq!(glm::length(glm::vec2(3., 4.)), 5.); 59 | /// ``` 60 | #[inline(always)] 61 | pub fn length>(x: T) -> S { 62 | dot(x, x).sqrt() 63 | } 64 | 65 | /// Returns a vector in the same direction as `x` but with a length of `1`. 66 | /// 67 | /// # Example 68 | /// 69 | /// ``` 70 | /// use glm::{ normalize, dvec2, ApproxEq }; 71 | /// 72 | /// assert!(normalize(dvec2(3., 4.)).is_approx_eq(&dvec2(0.6, 0.8))); 73 | /// ``` 74 | #[inline(always)] 75 | pub fn normalize, T: GenFloatVec>(x: T) -> T { 76 | x * inversesqrt(dot(x, x)) 77 | } 78 | 79 | /// Returns the distance between `p0` and `p1`, i.e., `length(p0 – p1)`. 80 | /// 81 | /// # Example 82 | /// 83 | /// ``` 84 | /// use glm::{ distance, vec2 }; 85 | /// 86 | /// let v1 = vec2(1., 2.); 87 | /// let v2 = vec2(4., 6.); 88 | /// assert_eq!(distance(v1, v2), 5.); 89 | /// ``` 90 | #[inline(always)] 91 | pub fn distance>(p0: T, p1: T) -> S { 92 | length(p0 - p1) 93 | } 94 | 95 | /// If `dot(Nref, I) < 0` return *N*, otherwise return *-N*. 96 | #[inline] 97 | #[allow(non_snake_case)] 98 | pub fn faceforward>(N: T, I: T, Nref: T) -> T { 99 | let ling = S::zero(); 100 | if dot(Nref, I) < ling { 101 | N 102 | } else { 103 | -N 104 | } 105 | } 106 | 107 | /// For the incident vector *I* and surface orientation *N*, 108 | /// returns the reflection direction: `I - 2 ∗ dot(N, I) ∗ N`. 109 | /// 110 | /// *N* must already be normalized in order to achieve the desired result. 111 | #[inline] 112 | #[allow(non_snake_case)] 113 | pub fn reflect>(I: T, N: T) -> T { 114 | let d = dot(N, I); 115 | I - N * (d + d) 116 | } 117 | 118 | /// For the incident vector *I* and surface normal *N*, and the ratio of 119 | /// indices of refraction `eta`, return the refraction vector. 120 | /// 121 | /// The result is computed by, 122 | /// ```ignore 123 | /// k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) 124 | /// if (k < 0.0) 125 | /// return genType(0.0) // or genDType(0.0) 126 | /// else 127 | /// return eta * I - (eta * dot(N, I) + sqrt(k)) * N 128 | /// ``` 129 | /// 130 | /// The input parameters for the incident vector *I* and the surface normal *N* 131 | /// must already be normalized to get the desired results. 132 | #[inline] 133 | #[allow(non_snake_case)] 134 | pub fn refract>(I: T, N: T, eta: S) -> T { 135 | let dot_ni = dot(I, N); 136 | let yi = S::one(); 137 | let ling = S::zero(); 138 | 139 | let k = yi - eta * eta * (yi - dot_ni) * dot_ni; 140 | if k < ling { 141 | T::zero() 142 | } else { 143 | I * eta - N * (eta * dot_ni + k.sqrt()) 144 | } 145 | } 146 | 147 | /// Returns the cross product of `x` and `y`. 148 | /// 149 | /// # Example 150 | /// 151 | /// ``` 152 | /// use glm::vec3; 153 | /// 154 | /// let x = vec3(1.0, 0.0, 0.0); 155 | /// let y = vec3(0.0, 1.0, 0.0); 156 | /// let z = vec3(0.0, 0.0, 1.0); 157 | /// assert_eq!(glm::cross(x, y), z); 158 | /// ``` 159 | #[inline] 160 | pub fn cross(x: Vector3, y: Vector3) -> Vector3 { 161 | Vector3::new( 162 | x.y * y.z - y.y * x.z, 163 | x.z * y.x - y.z * x.x, 164 | x.x * y.y - y.x * x.y, 165 | ) 166 | } 167 | -------------------------------------------------------------------------------- /src/builtin/vecrel.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | // The GLSL Specification, ch 8.7, Vector Relational Functions 25 | 26 | use core::cmp::{PartialEq, PartialOrd}; 27 | 28 | use crate::basenum::Primitive; 29 | use crate::vec::traits::{GenBVec, GenVec}; 30 | use crate::vec::vec::{Vector2, Vector3, Vector4}; 31 | 32 | pub trait VecRel: GenVec { 33 | fn zip_bool(&self, rhs: &Self, oper: fn(&T, &T) -> bool) -> B; 34 | } 35 | 36 | macro_rules! impl_vecrel_for( 37 | ($t: ident, $($field: ident), +) => { 38 | impl VecRel> for $t { 39 | #[inline(always)] 40 | fn zip_bool(&self, rhs: &$t, oper: fn(&T, &T) -> bool) -> $t { 41 | $t::new($(oper(&(self.$field), &(rhs.$field))), +) 42 | } 43 | } 44 | } 45 | ); 46 | 47 | impl_vecrel_for! { Vector2, x, y } 48 | impl_vecrel_for! { Vector3, x, y, z } 49 | impl_vecrel_for! { Vector4, x, y, z, w } 50 | 51 | /// Returns the component-wise compare of `x < y`. 52 | /// 53 | /// # Example 54 | /// 55 | /// ``` 56 | /// use glm::*; 57 | /// 58 | /// let a = ivec4(1, 2, 3, 4); 59 | /// let b = ivec4(2, 3, 4, 5); 60 | /// assert_eq!(lessThan(b, a), bvec4(false, false, false, false)); 61 | /// assert!(all(lessThan(a, b))); 62 | /// ``` 63 | #[inline(always)] 64 | #[allow(non_snake_case)] 65 | pub fn lessThan>(x: V, y: V) -> B { 66 | x.zip_bool(&y, PartialOrd::lt) 67 | } 68 | 69 | /// Returns the component-wise compare of `x ≤ y`. 70 | /// 71 | /// # Example 72 | /// 73 | /// ``` 74 | /// use glm::*; 75 | /// 76 | /// let a = ivec4(1, 2, 3, 4); 77 | /// let b = ivec4(2, 2, 3, 3); 78 | /// assert_eq!(lessThanEqual(a, b), bvec4(true, true, true, false)); 79 | /// assert_eq!(lessThanEqual(a, b), not(greaterThan(a, b))); 80 | /// ``` 81 | #[inline(always)] 82 | #[allow(non_snake_case)] 83 | pub fn lessThanEqual>(x: V, y: V) -> B { 84 | x.zip_bool(&y, PartialOrd::le) 85 | } 86 | 87 | /// Returns the component-wise compare of `x > y`. 88 | /// 89 | /// # Example 90 | /// 91 | /// ``` 92 | /// use glm::*; 93 | /// 94 | /// let a = ivec4(1, 2, 3, 4); 95 | /// let b = ivec4(2, 2, 3, 3); 96 | /// assert_eq!(greaterThan(a, b), bvec4(false, false, false, true)); 97 | /// assert_eq!(greaterThan(a, b), lessThan(b, a)); 98 | /// ``` 99 | #[inline(always)] 100 | #[allow(non_snake_case)] 101 | pub fn greaterThan>(x: V, y: V) -> B { 102 | x.zip_bool(&y, PartialOrd::gt) 103 | } 104 | 105 | /// Returns the component-wise compare of `x ≥ y`. 106 | /// 107 | /// # Example 108 | /// 109 | /// ``` 110 | /// use glm::*; 111 | /// 112 | /// let a = ivec4(1, 2, 3, 4); 113 | /// let b = ivec4(2, 2, 3, 3); 114 | /// assert_eq!(greaterThanEqual(a, b), bvec4(false, true, true, true)); 115 | /// assert_eq!(greaterThanEqual(a, b), lessThanEqual(b, a)); 116 | /// assert_eq!(greaterThanEqual(a, b), not(lessThan(a, b))); 117 | /// ``` 118 | #[inline(always)] 119 | #[allow(non_snake_case)] 120 | pub fn greaterThanEqual>(x: V, y: V) -> B { 121 | x.zip_bool(&y, PartialOrd::ge) 122 | } 123 | 124 | /// Returns the component-wise compare of `x == y`. 125 | /// 126 | /// # Example 127 | /// 128 | /// ``` 129 | /// use glm::*; 130 | /// 131 | /// let a = ivec4(1, 2, 3, 4); 132 | /// let b = ivec4(2, 2, 3, 3); 133 | /// assert_eq!(equal(a, b), bvec4(false, true, true, false)); 134 | /// assert_eq!(equal(a, b), equal(b, a)); 135 | /// ``` 136 | #[inline(always)] 137 | pub fn equal>(x: V, y: V) -> B { 138 | x.zip_bool(&y, PartialEq::eq) 139 | } 140 | 141 | /// Returns the component-wise compare of `x ≠ y`. 142 | /// 143 | /// # Example 144 | /// 145 | /// ``` 146 | /// use glm::*; 147 | /// 148 | /// let a = ivec4(1, 2, 3, 4); 149 | /// let b = ivec4(2, 2, 3, 3); 150 | /// assert_eq!(notEqual(a, b), bvec4(true, false, false, true)); 151 | /// assert_eq!(notEqual(a, b), not(equal(b, a))); 152 | /// ``` 153 | #[inline(always)] 154 | #[allow(non_snake_case)] 155 | pub fn notEqual>(x: V, y: V) -> B { 156 | x.zip_bool(&y, PartialEq::ne) 157 | } 158 | 159 | /// Returns `true` if any component of `x` is **true**. 160 | #[inline(always)] 161 | pub fn any(bvec: T) -> bool { 162 | bvec.any() 163 | } 164 | 165 | /// Returns `true` only if all components of `x` are **true**. 166 | #[inline(always)] 167 | pub fn all(bvec: T) -> bool { 168 | bvec.all() 169 | } 170 | 171 | /// Returns the component-wise logical complement of `x`. 172 | #[inline(always)] 173 | pub fn not(bvec: T) -> T { 174 | bvec.not() 175 | } 176 | -------------------------------------------------------------------------------- /src/ext/matrix/transform.rs: -------------------------------------------------------------------------------- 1 | use num_traits::{One, Zero}; 2 | 3 | use crate::basenum::BaseFloat; 4 | use crate::builtin::{cross, dot, normalize}; 5 | use crate::mat::mat::{Matrix3, Matrix4}; 6 | use crate::traits::GenFloat; 7 | use crate::vec::vec::{Vector3, Vector4}; 8 | 9 | /// Builds a translation 4 * 4 matrix created from a vector of 3 components. 10 | /// 11 | /// Uses input matrix `m` and translation vector coordinates `v`. 12 | /// 13 | /// # Example 14 | /// 15 | /// ```rust 16 | /// # fn main() { 17 | /// use glm::*; 18 | /// use glm::ext::*; 19 | /// 20 | /// let matrix = translate(&num_traits::one(), vec3(1., 2., 3.)); 21 | /// assert_eq!(matrix[3], vec4(1., 2., 3., 1.)); 22 | /// # } 23 | /// ``` 24 | #[inline] 25 | pub fn translate(m: &Matrix4, v: Vector3) -> Matrix4 26 | where 27 | T: BaseFloat, 28 | { 29 | Matrix4::new( 30 | m.c0, 31 | m.c1, 32 | m.c2, 33 | m.c0 * v.x + m.c1 * v.y + m.c2 * v.z + m.c3, 34 | ) 35 | } 36 | 37 | /// Creates a matrix for a symetric perspective-view frustum based on the default handedness. 38 | /// 39 | /// `fov_y` is the field of view angle in the y direction in radians. 40 | /// The `aspect` ratio determines the field of view in the x direction. 41 | /// `near_z` is the distance from the viewer to the near clipping plane (always positive) and 42 | /// `far_z` is the distance from the viewer to the far clipping plane (always positive). 43 | #[inline] 44 | pub fn perspective(fov_y: T, aspect: T, z_near: T, z_far: T) -> Matrix4 45 | where 46 | T: BaseFloat, 47 | { 48 | // TODO: make this a compile option 49 | perspective_rh(fov_y, aspect, z_near, z_far) 50 | } 51 | 52 | /// Creates a matrix for a right handed, symetric perspective-view frustum. 53 | /// 54 | /// `fov_y` is the field of view angle in the y direction in radians. 55 | /// The `aspect` ratio determines the field of view in the x direction. 56 | /// `near_z` is the distance from the viewer to the near clipping plane (always positive) and 57 | /// `far_z` is the distance from the viewer to the far clipping plane (always positive). 58 | #[inline] 59 | pub fn perspective_rh(fov_y: T, aspect: T, z_near: T, z_far: T) -> Matrix4 60 | where 61 | T: BaseFloat, 62 | { 63 | let zero = num_traits::zero::(); 64 | let one = num_traits::one::(); 65 | let two = one + one; 66 | let q = one / (fov_y / two).tan(); 67 | let a = q / aspect; 68 | let b = (z_near + z_far) / (z_near - z_far); 69 | let c = (two * z_near * z_far) / (z_near - z_far); 70 | 71 | Matrix4::new( 72 | Vector4::new(a, zero, zero, zero), 73 | Vector4::new(zero, q, zero, zero), 74 | Vector4::new(zero, zero, b, zero - one), 75 | Vector4::new(zero, zero, c, zero), 76 | ) 77 | } 78 | 79 | /// Builds a rotation 4 * 4 matrix created from an axis vector and an angle. 80 | /// 81 | /// `m` as the input matrix multiplied by this rotation matrix. 82 | /// `angle` is the rotation angle expressed in radians. 83 | /// Rotation `axis` is recommended to be normalized. 84 | #[inline] 85 | pub fn rotate(m: &Matrix4, angle: T, v: Vector3) -> Matrix4 86 | where 87 | T: BaseFloat + GenFloat, 88 | { 89 | let zero = num_traits::zero::(); 90 | let one = num_traits::one::(); 91 | 92 | let a = angle; 93 | let (s, c) = a.sin_cos(); 94 | let axis = normalize(v); 95 | let temp = axis * (one - c); 96 | 97 | let rotate = Matrix3::new( 98 | Vector3::new( 99 | c + temp.x * axis.x, 100 | temp.x * axis.y + s * axis.z, 101 | temp.x * axis.z - s * axis.y, 102 | ), 103 | Vector3::new( 104 | temp.y * axis.x - s * axis.z, 105 | c + temp.y * axis.y, 106 | temp.y * axis.z + s * axis.x, 107 | ), 108 | Vector3::new( 109 | temp.z * axis.x + s * axis.y, 110 | temp.z * axis.y - s * axis.x, 111 | c + temp.z * axis.z, 112 | ), 113 | ); 114 | 115 | Matrix4::new( 116 | m.c0 * rotate.c0.x + m.c1 * rotate.c0.y + m.c2 * rotate.c0.z, 117 | m.c0 * rotate.c1.x + m.c1 * rotate.c1.y + m.c2 * rotate.c1.z, 118 | m.c0 * rotate.c2.x + m.c1 * rotate.c2.y + m.c2 * rotate.c2.z, 119 | m.c3, 120 | ) 121 | } 122 | 123 | /// Builds a scale 4 * 4 matrix created from 3 scalars. 124 | /// 125 | /// `m` is the input matrix multiplied by this scale matrix. 126 | /// `v` is the ratio of scaling for each axis. 127 | #[inline] 128 | pub fn scale(m: &Matrix4, v: Vector3) -> Matrix4 129 | where 130 | T: BaseFloat + GenFloat, 131 | { 132 | Matrix4::new(m.c0 * v.x, m.c1 * v.y, m.c2 * v.z, m.c3) 133 | } 134 | 135 | /// Build a look at view matrix based on the default handedness. 136 | /// 137 | /// View matrix is based on the `eye` position of the camera, `center` position where the camera is 138 | /// looking at and a normalized `up` vector, how the camera is oriented. Typically (0, 0, 1) 139 | #[inline] 140 | pub fn look_at(eye: Vector3, center: Vector3, up: Vector3) -> Matrix4 141 | where 142 | T: BaseFloat + GenFloat, 143 | { 144 | // TODO: make handedness configurable 145 | look_at_rh::(eye, center, up) 146 | } 147 | 148 | /// Build a right handed look at view matrix. 149 | /// 150 | /// View matrix is based on the `eye` position of the camera, `center` position where the camera is 151 | /// looking at and a normalized `up` vector, how the camera is oriented. Typically (0, 0, 1) 152 | #[inline] 153 | pub fn look_at_rh(eye: Vector3, center: Vector3, up: Vector3) -> Matrix4 154 | where 155 | T: BaseFloat + GenFloat, 156 | { 157 | let zero = ::zero(); 158 | let one = ::one(); 159 | let f = normalize(center - eye); 160 | let s = normalize(cross(f, up)); 161 | let u = cross(s, f); 162 | Matrix4::new( 163 | Vector4::new(s.x, u.x, -f.x, zero), 164 | Vector4::new(s.y, u.y, -f.y, zero), 165 | Vector4::new(s.z, u.z, -f.z, zero), 166 | Vector4::new(-dot(s, eye), -dot(u, eye), dot(f, eye), one), 167 | ) 168 | } 169 | 170 | #[cfg(test)] 171 | mod test { 172 | 173 | use crate::ext::{perspective, translate, Consts}; 174 | use crate::vec::vec::{vec3, vec4}; 175 | 176 | #[test] 177 | fn test_translate() { 178 | let v = vec3(1.0, 3.0, 2.0); 179 | let m = num_traits::one(); 180 | let t = translate(&m, v); 181 | assert_eq!(t[0], vec4(1., 0., 0., 0.)); 182 | assert_eq!(t[1], vec4(0., 1., 0., 0.)); 183 | assert_eq!(t[2], vec4(0., 0., 1., 0.)); 184 | assert_eq!(t[3], v.extend(1.)); 185 | } 186 | 187 | #[test] 188 | fn test_perspective() { 189 | let p = perspective(f32::pi() * 2.0 * 45.0 / 360.0, 1920.0 / 1080.0, 0.1, 100.0); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #![allow(unused_variables)] 25 | 26 | //! GLSL mathematics for Rust programming language. 27 | //! 28 | //! *glm-rs* is yet another Rust math library for graphics applications. 29 | //! Inspired by the great [GLM](glm.g-truc.net) library for C++, the goal is to 30 | //! provide a familiar math API to programmers who know GLSL as well. 31 | //! 32 | //! ## Differences to GLSL specification 33 | //! 34 | //! Like *GLM*, following GLSL conventions is a strict policy of *glm-rs* too. 35 | //! *glm* crate implements all GLSL data types, operators and 36 | //! built-in functions. However, Rust is not a C-like language, and the 37 | //! syntax/semantics distances from Rust to GLSL is way longer than from C++ to 38 | //! GLSL. 39 | //! This is the major reason of following feature and syntax differences to GLSL 40 | //! specification, 41 | //! 42 | //! - Precision qualifiers is not supported, 43 | //! - Half float type is not available, yet, 44 | //! - There is no vector swizzle operators. For example, you can't do this, 45 | //! 46 | //! ~~~ignore 47 | //! # use glm::*; 48 | //! let mut my_vec2 = my_vec4.wz; 49 | //! // and, 50 | //! my_vec2.yx = my_vec4.xx; 51 | //! ~~~ 52 | //! Part of swizzle operators can be done but must be in a very tedious way 53 | //! at the moment. 54 | //! The plan is to implemente accessing swizzle operators *after* Rust macro 55 | //! supports concatenating identifiers. 56 | //! - Because Rust does not support function name overloading, loads of 57 | //! convenient constructor functions can't be implemented. For example, 58 | //! you can't do this, 59 | //! 60 | //! ~~~ignore 61 | //! let v2 = vec2(1., 2.); 62 | //! // compile error: this function takes 3 parameters but 2 parameters were supplied [E0061] 63 | //! let v3 = vec3(v2, 3.); 64 | //! ~~~ 65 | //! This will be fixed in future version by introducing functions like 66 | //! ```no_run fn vec21(x: Vec2, y: f32) -> Vec3```, in which function names 67 | //! indicate the forms of result vectors. 68 | //! - Also because of lacking of function name overloading, following built-in 69 | //! functions are added, 70 | //! 71 | //! `atan2`, `mod_s`, `max_s`, `min_s`, `clamp_s`, `mix_s`, `mix_bool`, `step_s`, 72 | //! and `smoothstep_s`. 73 | //! 74 | //! The suffix `_s` stands for *scalar*, which means this is a variant of 75 | //! original function that some parameters are specific to be scalar, 76 | //! instead a generic type. 77 | //! 78 | //! See documentation of these functions for detail. 79 | //! - Most explicit conversion functions, like `vec2`, `dmat4x3` etc., do not 80 | //! work, for the same reason as above. 81 | //! This is rather inconvenient, and the plan is introducing functions like 82 | //! `to_vec2`, `to_dmat4x3` in future version. 83 | //! - No implicit conversion. 84 | //! - Explicit type conversion function `bool` is renamed to `boolean`. 85 | //! - Many explicit type conversion functions for vector types are introduced. 86 | //! In GLSL spec, these fucntions have the same name as vector type 87 | //! constructors, which is not allowed in Rust. The naming rule is to get a 88 | //! vector type conversion fucntion, adds a `to_` before the constructor 89 | //! function. For example, 90 | //! 91 | //! ~~~ 92 | //! # use glm::*; 93 | //! let v = to_vec2(1_f32); 94 | //! assert_eq!(v, vec2(1., 1.)); 95 | //! ~~~ 96 | //! - Lots of convertion functions are still missing (e.g., from matrices to 97 | //! vectors). These functions are syntax sugar actually, and will be fixed 98 | //! along with the constructor issue in future version. 99 | //! - GLSL uses out parameter for returning multiple results of functions. In 100 | //! Rust, we can do this by returning a tuple. Following functions' 101 | //! signatures are changed because of this, 102 | //! 103 | //! - `modf`, 104 | //! - `frexp`, 105 | //! - `uaddCarry`, 106 | //! - `usubBorrow`, 107 | //! - `umulExtended`, 108 | //! - `imulExtended` 109 | //! 110 | //! The rule of changing is the out parameter is the second member of the 111 | //! return tuple. 112 | //! - Function parameters of matrix related functions (e.g., `inverse`, 113 | //! `cross`) are passed by reference, instead of by value as in the GLSL spec. 114 | //! For example, 115 | //! 116 | //! ~~~ 117 | //! # use glm::*; 118 | //! let m = mat2(1., 2., 3., 4.); 119 | //! // instead of `inverse(m)`, 120 | //! let inv = inverse(&m); 121 | //! ~~~ 122 | //! - Built-in function `mod` is renamed to `fmod`, because **mod** is a Rust 123 | //! keyword. 124 | //! 125 | 126 | pub use builtin::*; 127 | 128 | pub use basenum::{ 129 | is_approx_eq, is_close_to, ApproxEq, BaseFloat, BaseInt, BaseNum, Primitive, SignedNum, 130 | }; 131 | 132 | pub use traits::{GenFloat, GenInt, GenNum}; 133 | 134 | pub use vec::traits::{GenBVec, GenFloatVec, GenNumVec, GenVec}; 135 | 136 | pub use vec::vec::{ 137 | bvec2, bvec3, bvec4, dvec2, dvec3, dvec4, ivec2, ivec3, ivec4, uvec2, uvec3, uvec4, vec2, vec3, 138 | vec4, BVec2, BVec3, BVec4, DVec2, DVec3, DVec4, IVec2, IVec3, IVec4, UVec2, UVec3, UVec4, Vec2, 139 | Vec3, Vec4, Vector2, Vector3, Vector4, 140 | }; 141 | 142 | // pub use vec::swizzle::{ 143 | // Swizzle2, Swizzle3, Swizzle4, 144 | // }; 145 | 146 | pub use mat::traits::{GenMat, GenSquareMat}; 147 | 148 | pub use mat::mat::{ 149 | DMat2, DMat2x3, DMat2x4, DMat3, DMat3x2, DMat3x4, DMat4, DMat4x2, DMat4x3, Mat2, Mat2x3, 150 | Mat2x4, Mat3, Mat3x2, Mat3x4, Mat4, Mat4x2, Mat4x3, Matrix2, Matrix2x3, Matrix2x4, Matrix3, 151 | Matrix3x2, Matrix3x4, Matrix4, Matrix4x2, Matrix4x3, 152 | }; 153 | 154 | pub use mat::ctor::{ 155 | dmat2, dmat2x3, dmat2x4, dmat3, dmat3x2, dmat3x4, dmat4, dmat4x2, dmat4x3, mat2, mat2x3, 156 | mat2x4, mat3, mat3x2, mat3x4, mat4, mat4x2, mat4x3, 157 | }; 158 | 159 | pub use cast::{ 160 | boolean, double, float, int, to_bvec2, to_bvec3, to_bvec4, to_dvec2, to_dvec3, to_dvec4, 161 | to_ivec2, to_ivec3, to_ivec4, to_uvec2, to_uvec3, to_uvec4, to_vec2, to_vec3, to_vec4, uint, 162 | PrimCast, 163 | }; 164 | 165 | #[macro_use] 166 | mod basenum; 167 | mod traits; 168 | mod vec { 169 | pub mod traits; 170 | pub mod vec; 171 | } 172 | mod mat { 173 | pub mod ctor; 174 | pub mod mat; 175 | pub mod sqmat; 176 | pub mod traits; 177 | } 178 | mod cast; 179 | 180 | pub mod builtin; 181 | pub mod ext; 182 | -------------------------------------------------------------------------------- /src/mat/ctor.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use super::mat::*; 25 | 26 | use crate::vec::vec::{dvec2, dvec3, dvec4, vec2, vec3, vec4}; 27 | 28 | #[inline] 29 | #[rustfmt::skip] 30 | pub const fn mat2( 31 | m11: f32, m21: f32, 32 | m12: f32, m22: f32, 33 | ) -> Mat2 { 34 | Matrix2 { 35 | c0: vec2(m11, m21), 36 | c1: vec2(m12, m22), 37 | } 38 | } 39 | 40 | #[inline] 41 | #[rustfmt::skip] 42 | pub const fn mat3x2( 43 | m11: f32, m21: f32, 44 | m12: f32, m22: f32, 45 | m13: f32, m23: f32, 46 | ) -> Mat3x2 { 47 | Matrix3x2 { 48 | c0: vec2(m11, m21), 49 | c1: vec2(m12, m22), 50 | c2: vec2(m13, m23), 51 | } 52 | } 53 | 54 | #[inline] 55 | #[rustfmt::skip] 56 | pub const fn mat4x2( 57 | m11: f32, m21: f32, 58 | m12: f32, m22: f32, 59 | m13: f32, m23: f32, 60 | m14: f32, m24: f32, 61 | ) -> Mat4x2 { 62 | Matrix4x2 { 63 | c0: vec2(m11, m21), 64 | c1: vec2(m12, m22), 65 | c2: vec2(m13, m23), 66 | c3: vec2(m14, m24), 67 | } 68 | } 69 | 70 | #[inline] 71 | #[rustfmt::skip] 72 | pub const fn mat3( 73 | m11: f32, m21: f32, m31: f32, 74 | m12: f32, m22: f32, m32: f32, 75 | m13: f32, m23: f32, m33: f32, 76 | ) -> Mat3 { 77 | Matrix3 { 78 | c0: vec3(m11, m21, m31), 79 | c1: vec3(m12, m22, m32), 80 | c2: vec3(m13, m23, m33), 81 | } 82 | } 83 | 84 | #[inline] 85 | #[rustfmt::skip] 86 | pub const fn mat2x3( 87 | m11: f32, m21: f32, m31: f32, 88 | m12: f32, m22: f32, m32: f32, 89 | ) -> Mat2x3 { 90 | Matrix2x3 { 91 | c0: vec3(m11, m21, m31), 92 | c1: vec3(m12, m22, m32), 93 | } 94 | } 95 | 96 | #[inline] 97 | #[rustfmt::skip] 98 | pub const fn mat4x3( 99 | m11: f32, m21: f32, m31: f32, 100 | m12: f32, m22: f32, m32: f32, 101 | m13: f32, m23: f32, m33: f32, 102 | m14: f32, m24: f32, m34: f32, 103 | ) -> Mat4x3 { 104 | Matrix4x3 { 105 | c0: vec3(m11, m21, m31), 106 | c1: vec3(m12, m22, m32), 107 | c2: vec3(m13, m23, m33), 108 | c3: vec3(m14, m24, m34), 109 | } 110 | } 111 | 112 | #[inline] 113 | #[rustfmt::skip] 114 | pub const fn mat4( 115 | m11: f32, m21: f32, m31: f32, m41: f32, 116 | m12: f32, m22: f32, m32: f32, m42: f32, 117 | m13: f32, m23: f32, m33: f32, m43: f32, 118 | m14: f32, m24: f32, m34: f32, m44: f32, 119 | ) -> Mat4 { 120 | Matrix4 { 121 | c0: vec4(m11, m21, m31, m41), 122 | c1: vec4(m12, m22, m32, m42), 123 | c2: vec4(m13, m23, m33, m43), 124 | c3: vec4(m14, m24, m34, m44), 125 | } 126 | } 127 | 128 | #[inline] 129 | #[rustfmt::skip] 130 | pub const fn mat2x4( 131 | m11: f32, m21: f32, m31: f32, m41: f32, 132 | m12: f32, m22: f32, m32: f32, m42: f32, 133 | ) -> Mat2x4 { 134 | Matrix2x4 { 135 | c0: vec4(m11, m21, m31, m41), 136 | c1: vec4(m12, m22, m32, m42), 137 | } 138 | } 139 | 140 | #[inline] 141 | #[rustfmt::skip] 142 | pub const fn mat3x4( 143 | m11: f32, m21: f32, m31: f32, m41: f32, 144 | m12: f32, m22: f32, m32: f32, m42: f32, 145 | m13: f32, m23: f32, m33: f32, m43: f32, 146 | ) -> Mat3x4 { 147 | Matrix3x4 { 148 | c0: vec4(m11, m21, m31, m41), 149 | c1: vec4(m12, m22, m32, m42), 150 | c2: vec4(m13, m23, m33, m43), 151 | } 152 | } 153 | 154 | #[inline] 155 | #[rustfmt::skip] 156 | pub const fn dmat2( 157 | m11: f64, m21: f64, 158 | m12: f64, m22: f64, 159 | ) -> DMat2 { 160 | Matrix2 { 161 | c0: dvec2(m11, m21), 162 | c1: dvec2(m12, m22), 163 | } 164 | } 165 | 166 | #[inline] 167 | #[rustfmt::skip] 168 | pub const fn dmat3x2( 169 | m11: f64, m21: f64, 170 | m12: f64, m22: f64, 171 | m13: f64, m23: f64, 172 | ) -> DMat3x2 { 173 | Matrix3x2 { 174 | c0: dvec2(m11, m21), 175 | c1: dvec2(m12, m22), 176 | c2: dvec2(m13, m23), 177 | } 178 | } 179 | 180 | #[inline] 181 | #[rustfmt::skip] 182 | pub const fn dmat4x2( 183 | m11: f64, m21: f64, 184 | m12: f64, m22: f64, 185 | m13: f64, m23: f64, 186 | m14: f64, m24: f64, 187 | ) -> DMat4x2 { 188 | Matrix4x2 { 189 | c0: dvec2(m11, m21), 190 | c1: dvec2(m12, m22), 191 | c2: dvec2(m13, m23), 192 | c3: dvec2(m14, m24), 193 | } 194 | } 195 | 196 | #[inline] 197 | #[rustfmt::skip] 198 | pub const fn dmat3( 199 | m11: f64, m21: f64, m31: f64, 200 | m12: f64, m22: f64, m32: f64, 201 | m13: f64, m23: f64, m33: f64, 202 | ) -> DMat3 { 203 | Matrix3 { 204 | c0: dvec3(m11, m21, m31), 205 | c1: dvec3(m12, m22, m32), 206 | c2: dvec3(m13, m23, m33), 207 | } 208 | } 209 | 210 | #[inline] 211 | #[rustfmt::skip] 212 | pub const fn dmat2x3( 213 | m11: f64, m21: f64, m31: f64, 214 | m12: f64, m22: f64, m32: f64, 215 | ) -> DMat2x3 { 216 | Matrix2x3 { 217 | c0: dvec3(m11, m21, m31), 218 | c1: dvec3(m12, m22, m32), 219 | } 220 | } 221 | 222 | #[inline] 223 | #[rustfmt::skip] 224 | pub const fn dmat4x3( 225 | m11: f64, m21: f64, m31: f64, 226 | m12: f64, m22: f64, m32: f64, 227 | m13: f64, m23: f64, m33: f64, 228 | m14: f64, m24: f64, m34: f64, 229 | ) -> DMat4x3 { 230 | Matrix4x3 { 231 | c0: dvec3(m11, m21, m31), 232 | c1: dvec3(m12, m22, m32), 233 | c2: dvec3(m13, m23, m33), 234 | c3: dvec3(m14, m24, m34), 235 | } 236 | } 237 | 238 | #[inline] 239 | #[rustfmt::skip] 240 | pub const fn dmat4( 241 | m11: f64, m21: f64, m31: f64, m41: f64, 242 | m12: f64, m22: f64, m32: f64, m42: f64, 243 | m13: f64, m23: f64, m33: f64, m43: f64, 244 | m14: f64, m24: f64, m34: f64, m44: f64, 245 | ) -> DMat4 { 246 | Matrix4 { 247 | c0: dvec4(m11, m21, m31, m41), 248 | c1: dvec4(m12, m22, m32, m42), 249 | c2: dvec4(m13, m23, m33, m43), 250 | c3: dvec4(m14, m24, m34, m44), 251 | } 252 | } 253 | 254 | #[inline] 255 | #[rustfmt::skip] 256 | pub const fn dmat2x4( 257 | m11: f64, m21: f64, m31: f64, m41: f64, 258 | m12: f64, m22: f64, m32: f64, m42: f64, 259 | ) -> DMat2x4 { 260 | Matrix2x4 { 261 | c0: dvec4(m11, m21, m31, m41), 262 | c1: dvec4(m12, m22, m32, m42), 263 | } 264 | } 265 | 266 | #[inline] 267 | #[rustfmt::skip] 268 | pub const fn dmat3x4( 269 | m11: f64, m21: f64, m31: f64, m41: f64, 270 | m12: f64, m22: f64, m32: f64, m42: f64, 271 | m13: f64, m23: f64, m33: f64, m43: f64, 272 | ) -> DMat3x4 { 273 | Matrix3x4 { 274 | c0: dvec4(m11, m21, m31, m41), 275 | c1: dvec4(m12, m22, m32, m42), 276 | c2: dvec4(m13, m23, m33, m43), 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /src/basenum.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use core::cmp; 25 | use core::ops::{Div, Neg, Rem, Sub}; 26 | use core::{f32, f64}; 27 | 28 | use num_traits::{Float, One, PrimInt, Signed, Zero}; 29 | 30 | /// Marker trait for primitive types. 31 | /// 32 | /// # Note 33 | /// 34 | /// In `glm`, not all Rust primitive number types are used. Only those types 35 | /// that used in GLSL, i.e., `f32`, `f64`, `i32`, `u32` and `bool`, implement 36 | /// this trait. 37 | pub trait Primitive: Send + Copy + Sized + Clone + PartialOrd + PartialEq {} 38 | 39 | impl Primitive for bool {} 40 | 41 | /// Trait for primitive number type. 42 | pub trait BaseNum: 43 | Primitive + Zero + One + Div + Rem 44 | { 45 | /// Returns the smaller one of two numbers. 46 | /// 47 | /// # Example 48 | /// 49 | /// ``` 50 | /// use glm::BaseNum; 51 | /// assert_eq!(BaseNum::min(1i32, 2i32), 1i32); 52 | /// ``` 53 | fn min(self, other: Self) -> Self; 54 | 55 | /// Returns the larger one of two numbers. 56 | /// 57 | /// # Example 58 | /// 59 | /// ``` 60 | /// use glm::BaseNum; 61 | /// assert_eq!(BaseNum::max(1i32, 2i32), 2i32); 62 | /// ``` 63 | fn max(self, other: Self) -> Self; 64 | } 65 | 66 | /// Trait for numerical types that have negative values. 67 | pub trait SignedNum: Sized + Neg + Sub { 68 | /// Returns the absolute value of the receiver. 69 | fn abs(&self) -> Self; 70 | 71 | /// Returns the sign number of the receiver. 72 | /// 73 | /// # Example 74 | /// 75 | /// ``` 76 | /// use glm::{ SignedNum, dvec3 }; 77 | /// assert_eq!(dvec3(2.718, 0., -0.).sign(), dvec3(1., 0., 0.)); 78 | /// ``` 79 | fn sign(&self) -> Self; 80 | } 81 | 82 | /// Marker trait for primitive integer number type. 83 | pub trait BaseInt: PrimInt + BaseNum {} 84 | 85 | /// Trait for comparing types that are derived from float numbers. 86 | /// 87 | /// # Note 88 | /// 89 | /// Comparing float numbers is tricky. This trait is mainly for convenience. 90 | /// See [this article](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/) 91 | /// for the details of comparing float numbers. 92 | pub trait ApproxEq { 93 | type BaseType: BaseFloat; 94 | 95 | /// Returns `true` if the difference between `x` and `y` is less than 96 | /// `max_diff`. 97 | /// 98 | /// # Note 99 | /// 100 | /// The meanings of "difference" and "less than" are up to the 101 | /// implementations. 102 | /// 103 | /// # Example 104 | /// 105 | /// use glm::*; 106 | /// 107 | /// let v1 = vec2(1000., 2000.); 108 | /// let v2 = vec2(1010., 1080.); 109 | /// assert!(v1.is_close_to(&v2, 50.)); 110 | /// assert!(!v1.is_close_to(&v2, 10.)); 111 | fn is_close_to(&self, rhs: &Self, max_diff: Self::BaseType) -> bool; 112 | 113 | /// Returns `true` if the difference between `x` and `y` is less than 114 | /// [machine epsilon](http://en.wikipedia.org/wiki/Machine_epsilon). 115 | /// 116 | /// # Example 117 | /// 118 | /// ``` 119 | /// use glm::*; 120 | /// 121 | /// let f = 0.1_f32; 122 | /// let mut sum = 0f32; 123 | /// for i in 0..10 { 124 | /// sum += f; 125 | /// } 126 | /// assert_eq!(1.0_f32 == sum, false); 127 | /// assert_eq!(1f32.is_approx_eq(&sum), true); 128 | /// ``` 129 | fn is_approx_eq(&self, rhs: &Self) -> bool { 130 | self.is_close_to(rhs, Self::BaseType::epsilon()) 131 | } 132 | } 133 | 134 | /// Returns the result of `x.is_close_to(y, max_diff)`. 135 | #[inline(always)] 136 | pub fn is_close_to(x: &T, y: &T, max_diff: T::BaseType) -> bool { 137 | x.is_close_to(y, max_diff) 138 | } 139 | 140 | /// Returns the result of `x.is_approx_eq(y)`. 141 | #[inline(always)] 142 | pub fn is_approx_eq(x: &T, y: &T) -> bool { 143 | x.is_approx_eq(y) 144 | } 145 | 146 | #[macro_export] 147 | macro_rules! assert_approx_eq( 148 | ($left: expr, $right: expr) => ({ 149 | let lhs = &($left); 150 | let rhs = &($right); 151 | if !is_approx_eq(lhs, rhs) { 152 | panic!( 153 | "assertion failed: left ≈ right` (left: `{:?}`, right: `{:?}`)", 154 | *lhs, *rhs, 155 | ) 156 | } 157 | }) 158 | ); 159 | 160 | #[macro_export] 161 | macro_rules! assert_close_to( 162 | ($left: expr, $right: expr, $max_diff: expr) => ({ 163 | let lhs = &($left); 164 | let rhs = &($right); 165 | let diff = $max_diff; 166 | if !is_close_to(lhs, rhs, diff) { 167 | panic!( 168 | "assertion failed: left ≈ right` (left: `{:?}`, right: `{:?}`, tolerance: `{:?}`)", 169 | *lhs, *rhs, diff 170 | ) 171 | } 172 | }) 173 | ); 174 | 175 | /// Trait for primitive float number type. 176 | pub trait BaseFloat: Float + BaseNum + SignedNum + ApproxEq { 177 | fn to_degrees(self) -> Self; 178 | fn to_radians(self) -> Self; 179 | fn frexp(self) -> (Self, isize); 180 | fn ldexp(self, exp: isize) -> Self; 181 | } 182 | 183 | impl SignedNum for i32 { 184 | #[inline(always)] 185 | fn abs(&self) -> i32 { 186 | Signed::abs(self) 187 | } 188 | #[inline(always)] 189 | fn sign(&self) -> i32 { 190 | self.signum() 191 | } 192 | } 193 | 194 | macro_rules! impl_int( 195 | ($($t: ty), +) => { 196 | $( 197 | impl Primitive for $t {} 198 | impl BaseNum for $t { 199 | #[inline(always)] 200 | fn min(self, other: $t) -> $t { 201 | cmp::min(self, other) 202 | } 203 | #[inline(always)] 204 | fn max(self, other: $t) -> $t { 205 | cmp::max(self, other) 206 | } 207 | } 208 | impl BaseInt for $t {} 209 | )+ 210 | } 211 | ); 212 | impl_int! { i32, u32 } 213 | 214 | macro_rules! impl_flt( 215 | ($t: ident) => { 216 | impl Primitive for $t {} 217 | impl SignedNum for $t { 218 | #[inline(always)] 219 | fn abs(&self) -> $t { 220 | Float::abs(*self) 221 | } 222 | #[inline(always)] 223 | fn sign(&self) -> $t { 224 | let l = $t::zero(); 225 | if self.is_zero() { 226 | l 227 | } else { 228 | self.signum() 229 | } 230 | } 231 | } 232 | impl ApproxEq for $t { 233 | type BaseType = $t; 234 | #[inline(always)] 235 | fn is_close_to(&self, rhs: &$t, max_diff: $t) -> bool { 236 | (self - *rhs).abs() <= max_diff 237 | } 238 | } 239 | impl BaseNum for $t { 240 | #[inline(always)] 241 | fn min(self, other: $t) -> $t { 242 | self.min(other) 243 | } 244 | #[inline(always)] 245 | fn max(self, other: $t) -> $t { 246 | self.max(other) 247 | } 248 | } 249 | impl BaseFloat for $t { 250 | #[inline(always)] 251 | fn to_degrees(self) -> $t { 252 | self * (180. / $t::consts::PI) 253 | } 254 | #[inline(always)] 255 | fn to_radians(self) -> $t { 256 | self * ($t::consts::PI / 180.) 257 | } 258 | #[inline(always)] 259 | fn frexp(self) -> ($t, isize) { 260 | // CHECK: use impl in `libstd` after it's stable. 261 | if self.is_zero() || self.is_infinite() || self.is_nan() { 262 | (self, 0) 263 | } else { 264 | let lg = self.abs().log2(); 265 | let x = (lg.fract() - 1.).exp2(); 266 | let exp = lg.floor() + 1.; 267 | (self.signum() * x, exp as isize) 268 | } 269 | } 270 | #[inline(always)] 271 | fn ldexp(self, exp: isize) -> $t { 272 | // CHECK: use impl in `libstd` after it's stable. 273 | let f = exp as $t; 274 | self * f.exp2() 275 | } 276 | } 277 | } 278 | ); 279 | 280 | impl_flt! { f32 } 281 | impl_flt! { f64 } 282 | -------------------------------------------------------------------------------- /src/builtin/pack.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | // The GLSL Specification, ch 8.4, Floating-Point Pack and Unpack Functions. 25 | 26 | use core::mem; 27 | 28 | use crate::vec::vec::*; 29 | 30 | use super::common::{clamp_s, round}; 31 | 32 | /// First, converts each component of the normalized floating-point value `v` 33 | /// into 16-bit integer values. Then, the results are packed into the 34 | /// returned 32-bit unsigned integer. 35 | /// 36 | /// The conversion for component `c` of `v` to fixed point is done as follows: 37 | /// ```round(clamp(c, 0, 1) * 65535.0)``` 38 | /// 39 | /// The first component of the vector will be written to the least significant 40 | /// bits of the output; the last component will be written to the most 41 | /// significant bits. 42 | /// 43 | /// # Example 44 | /// 45 | /// ``` 46 | /// 47 | /// ``` 48 | #[inline] 49 | #[allow(non_snake_case)] 50 | pub unsafe fn packUnorm2x16(v: Vec2) -> u32 { 51 | let us = round(clamp_s(v, 0., 1.) * 65535.); 52 | let pack: [u16; 2] = [us.y as u16, us.x as u16]; 53 | let r: &u32 = unsafe { mem::transmute(&pack) }; 54 | *r 55 | } 56 | 57 | /// First, unpacks a single 32-bit unsigned integer `p` into a pair of 16-bit 58 | /// unsigned integers. Then, each component is converted to a normalized 59 | /// floating-point value to generate the returned two-component vector. 60 | /// 61 | /// The conversion for unpacked fixed-point value `f` to floating point is done 62 | /// as follows: `f / 65535.0`. 63 | /// 64 | /// The first component of the returned vector will be extracted from the least 65 | /// significant bits of the input; the last component will be extracted from 66 | /// the most significant bits. 67 | /// 68 | /// # Example 69 | /// 70 | /// ``` 71 | /// 72 | /// ``` 73 | #[inline] 74 | #[allow(non_snake_case)] 75 | pub unsafe fn unpackUnorm2x16(p: u32) -> Vec2 { 76 | let unpack: &[u16; 2] = unsafe { mem::transmute(&p) }; 77 | let v = vec2(unpack[1] as f32, unpack[0] as f32); 78 | // v / 65535. 79 | v * 1.5259021896696421759365224689097e-5 80 | } 81 | 82 | /// First, converts each component of the normalized floating-point value `v` 83 | /// into 8-bit integer values. Then, the results are packed into the 84 | /// returned 32-bit unsigned integer. 85 | /// 86 | /// The conversion for component `c` of `v` to fixed point is done as follows: 87 | /// ```round(clamp(c, 0, 1) * 255.0)``` 88 | /// 89 | /// The first component of the vector will be written to the least significant 90 | /// bits of the output; the last component will be written to the most 91 | /// significant bits. 92 | /// 93 | /// # Example 94 | /// 95 | /// ``` 96 | /// 97 | /// ``` 98 | #[inline] 99 | #[allow(non_snake_case)] 100 | pub unsafe fn packUnorm4x8(v: Vec4) -> u32 { 101 | let us = round(clamp_s(v, 0., 1.) * 255.); 102 | let pack: [u8; 4] = [us.w as u8, us.z as u8, us.y as u8, us.x as u8]; 103 | let r: &u32 = unsafe { mem::transmute(&pack) }; 104 | *r 105 | } 106 | 107 | /// First, unpacks a single 32-bit unsigned integer `p` into four 8-bit unsigned 108 | /// integers. Then, each component is converted to a normalized floating-point 109 | /// value to generate the returned four-component vector. 110 | /// 111 | /// The conversion for unpacked fixed-point value `f` to floating point is done 112 | /// as follows: `f / 255.0`. 113 | /// 114 | /// The first component of the returned vector will be extracted from the least 115 | /// significant bits of the input; the last component will be extracted from 116 | /// the most significant bits. 117 | /// 118 | /// # Example 119 | /// 120 | /// ``` 121 | /// 122 | /// ``` 123 | #[inline] 124 | #[allow(non_snake_case)] 125 | pub unsafe fn unpackUnorm4x8(p: u32) -> Vec4 { 126 | let unpack: &[u8; 4] = unsafe { mem::transmute(&p) }; 127 | let v = vec4( 128 | unpack[3] as f32, 129 | unpack[2] as f32, 130 | unpack[1] as f32, 131 | unpack[0] as f32, 132 | ); 133 | // v / 255. 134 | v * 0.0039215686274509803921568627451 135 | } 136 | 137 | /// First, converts each component of the normalized floating-point value `v` 138 | /// into 16-bit integer values. Then, the results are packed into the 139 | /// returned 32-bit unsigned integer. 140 | /// 141 | /// The conversion for component `c` of `v` to fixed point is done as follows: 142 | /// ```round(clamp(c, -1, 1) * 32767.0)``` 143 | /// 144 | /// The first component of the vector will be written to the least significant 145 | /// bits of the output; the last component will be written to the most 146 | /// significant bits. 147 | /// 148 | /// # Example 149 | /// 150 | /// ``` 151 | /// 152 | /// ``` 153 | #[inline] 154 | #[allow(non_snake_case)] 155 | pub unsafe fn packSnorm2x16(v: Vec2) -> u32 { 156 | let is = round(clamp_s(v, -1., 1.) * 32767.); 157 | let pack: [i16; 2] = [is.y as i16, is.x as i16]; 158 | let r: &u32 = unsafe { mem::transmute(&pack) }; 159 | *r 160 | } 161 | 162 | /// First, unpacks a single 32-bit unsigned integer `p` into two 16-bit signed 163 | /// integers. Then, each component is converted to a normalized floating-point 164 | /// value to generate the returned two-component vector. 165 | /// 166 | /// The conversion for unpacked fixed-point value `f` to floating point is 167 | /// done as follows: `clamp(f / 32767.0, -1, +1)` 168 | /// 169 | /// The first component of the returned vector will be extracted from the 170 | /// least significant bits of the input; the last component will be extracted 171 | /// from the most significant bits. 172 | /// 173 | /// # Example 174 | /// 175 | /// ``` 176 | /// 177 | /// ``` 178 | #[inline] 179 | #[allow(non_snake_case)] 180 | pub unsafe fn unpackSnorm2x16(p: u32) -> Vec2 { 181 | let unpack: &[i16; 2] = unsafe { mem::transmute(&p) }; 182 | let v = vec2(unpack[1] as f32, unpack[0] as f32); 183 | // v / 32767. 184 | clamp_s(v * 3.0518509475997192297128208258309e-5, -1., 1.) 185 | } 186 | 187 | /// First, converts each component of the normalized floating-point value `v` 188 | /// into 8-bit integer values. Then, the results are packed into the 189 | /// returned 32-bit unsigned integer. 190 | /// 191 | /// The conversion for component `c` of `v` to fixed point is done as follows: 192 | /// ```round(clamp(c, -1, 1) * 127.0)``` 193 | /// 194 | /// The first component of the vector will be written to the least significant 195 | /// bits of the output; the last component will be written to the most 196 | /// significant bits. 197 | /// 198 | /// # Example 199 | /// 200 | /// ``` 201 | /// 202 | /// ``` 203 | #[inline] 204 | #[allow(non_snake_case)] 205 | pub unsafe fn packSnorm4x8(v: Vec4) -> u32 { 206 | let is = round(clamp_s(v, -1., 1.) * 127.); 207 | let pack: [i8; 4] = [is.w as i8, is.z as i8, is.y as i8, is.x as i8]; 208 | let r: &u32 = unsafe { mem::transmute(&pack) }; 209 | *r 210 | } 211 | 212 | /// First, unpacks a single 32-bit unsigned integer `p` into four 8-bit signed 213 | /// integers. Then, each component is converted to a normalized floating-point 214 | /// value to generate the returned four-component vector. 215 | /// 216 | /// The conversion for unpacked fixed-point value `f` to floating point is 217 | /// done as follows: `clamp(f / 127.0, -1, +1)` 218 | /// 219 | /// The first component of the returned vector will be extracted from the 220 | /// least significant bits of the input; the last component will be extracted 221 | /// from the most significant bits. 222 | /// 223 | /// # Example 224 | /// 225 | /// ``` 226 | /// 227 | /// ``` 228 | #[inline] 229 | #[allow(non_snake_case)] 230 | pub unsafe fn unpackSnorm4x8(p: u32) -> Vec4 { 231 | let unpack: &[i8; 4] = unsafe { mem::transmute(&p) }; 232 | let v = vec4( 233 | unpack[3] as f32, 234 | unpack[2] as f32, 235 | unpack[1] as f32, 236 | unpack[0] as f32, 237 | ); 238 | // v / 127. 239 | clamp_s(v * 0.0078740157480315, -1., 1.) 240 | } 241 | 242 | /// Returns a double-precision value obtained by packing the components of `v` 243 | /// into a 64-bit value. 244 | /// 245 | /// If an IEEE 754 Iinf or **NaN** is created, it will not signal, and the 246 | /// resulting floating point value is unspecified. Otherwise, the bit-level 247 | /// representation of `v` is preserved. The first vector component specifies 248 | /// the 32 least significant bits; the second component specifies the 32 most 249 | /// significant bits. 250 | /// 251 | /// # Example 252 | /// 253 | /// ``` 254 | /// 255 | /// ``` 256 | #[allow(non_snake_case)] 257 | #[inline(always)] 258 | pub unsafe fn packDouble2x32(v: UVec2) -> f64 { 259 | let f: &f64 = unsafe { mem::transmute(&v) }; 260 | *f 261 | } 262 | 263 | /// Returns a two-component unsigned integer vector representation of `v`. 264 | /// The bit-level representation of `v` is preserved. 265 | /// 266 | /// The first component of the vector contains the 32 least significant bits 267 | /// of the double; the second component consists the 32 most significant bits. 268 | /// 269 | /// # Example 270 | /// 271 | /// ``` 272 | /// 273 | /// ``` 274 | #[allow(non_snake_case)] 275 | #[inline(always)] 276 | pub unsafe fn unpackDouble2x32(v: f64) -> UVec2 { 277 | let uv: &UVec2 = unsafe { mem::transmute(&v) }; 278 | *uv 279 | } 280 | -------------------------------------------------------------------------------- /src/mat/sqmat.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use num_traits::One; 25 | 26 | use crate::basenum::BaseFloat; 27 | use crate::vec::vec::{Vector2, Vector3, Vector4}; 28 | 29 | use super::mat::*; 30 | use super::traits::{GenMat, GenSquareMat}; 31 | 32 | impl One for Matrix2 { 33 | #[inline] 34 | fn one() -> Matrix2 { 35 | let y = T::one(); 36 | let l = T::zero(); 37 | Matrix2::new(Vector2::new(y, l), Vector2::new(l, y)) 38 | } 39 | } 40 | 41 | impl GenSquareMat> for Matrix2 { 42 | #[inline(always)] 43 | fn determinant(&self) -> T { 44 | self[0][0] * self[1][1] - self[0][1] * self[1][0] 45 | } 46 | #[inline] 47 | fn inverse(&self) -> Option> { 48 | let det = self.determinant(); 49 | let ling = T::zero(); 50 | if det.is_approx_eq(&ling) { 51 | None 52 | } else { 53 | let inv_det = det.recip(); 54 | let m = Matrix2::new( 55 | Vector2::new(self[1][1] * inv_det, -self[0][1] * inv_det), 56 | Vector2::new(-self[1][0] * inv_det, self[0][0] * inv_det), 57 | ); 58 | Some(m) 59 | } 60 | } 61 | } 62 | 63 | impl One for Matrix3 { 64 | #[inline] 65 | fn one() -> Matrix3 { 66 | let y = T::one(); 67 | let l = T::zero(); 68 | Matrix3::new( 69 | Vector3::new(y, l, l), 70 | Vector3::new(l, y, l), 71 | Vector3::new(l, l, y), 72 | ) 73 | } 74 | } 75 | 76 | impl GenSquareMat> for Matrix3 { 77 | #[inline] 78 | fn determinant(&self) -> T { 79 | self[0][0] * (self[1][1] * self[2][2] - self[2][1] * self[1][2]) 80 | - self[1][0] * (self[0][1] * self[2][2] - self[2][1] * self[0][2]) 81 | + self[2][0] * (self[0][1] * self[1][2] - self[1][1] * self[0][2]) 82 | } 83 | #[inline] 84 | fn inverse(&self) -> Option> { 85 | let det = self.determinant(); 86 | let ling = T::zero(); 87 | if det.is_approx_eq(&ling) { 88 | None 89 | } else { 90 | let inv_det = det.recip(); 91 | let r11 = self[1][1] * self[2][2] - self[2][1] * self[1][2]; 92 | let r12 = self[2][0] * self[1][2] - self[1][0] * self[2][2]; 93 | let r13 = self[1][0] * self[2][1] - self[2][0] * self[1][1]; 94 | let r21 = self[2][1] * self[0][2] - self[0][1] * self[2][2]; 95 | let r22 = self[0][0] * self[2][2] - self[2][0] * self[0][2]; 96 | let r23 = self[2][0] * self[0][1] - self[0][0] * self[2][1]; 97 | let r31 = self[0][1] * self[1][2] - self[1][1] * self[0][2]; 98 | let r32 = self[1][0] * self[0][2] - self[0][0] * self[1][2]; 99 | let r33 = self[0][0] * self[1][1] - self[1][0] * self[0][1]; 100 | let m = Matrix3::new( 101 | Vector3::new(r11 * inv_det, r21 * inv_det, r31 * inv_det), 102 | Vector3::new(r12 * inv_det, r22 * inv_det, r32 * inv_det), 103 | Vector3::new(r13 * inv_det, r23 * inv_det, r33 * inv_det), 104 | ); 105 | Some(m) 106 | } 107 | } 108 | } 109 | 110 | impl One for Matrix4 { 111 | #[inline] 112 | fn one() -> Matrix4 { 113 | let y = T::one(); 114 | let l = T::zero(); 115 | Matrix4::new( 116 | Vector4::new(y, l, l, l), 117 | Vector4::new(l, y, l, l), 118 | Vector4::new(l, l, y, l), 119 | Vector4::new(l, l, l, y), 120 | ) 121 | } 122 | } 123 | 124 | impl GenSquareMat> for Matrix4 { 125 | #[inline] 126 | #[rustfmt::skip] 127 | fn determinant(&self) -> T { 128 | self[0][0] * ( 129 | self[1][1] * self[2][2] * self[3][3] + 130 | self[2][1] * self[3][2] * self[1][3] + 131 | self[3][1] * self[1][2] * self[2][3] - 132 | self[3][1] * self[2][2] * self[1][3] - 133 | self[1][1] * self[3][2] * self[2][3] - 134 | self[2][1] * self[1][2] * self[3][3] 135 | ) - 136 | self[1][0] * ( 137 | self[0][1] * self[2][2] * self[3][3] + 138 | self[2][1] * self[3][2] * self[0][3] + 139 | self[3][1] * self[0][2] * self[2][3] - 140 | self[3][1] * self[2][2] * self[0][3] - 141 | self[0][1] * self[3][2] * self[2][3] - 142 | self[2][1] * self[0][2] * self[3][3] 143 | ) + 144 | self[2][0] * ( 145 | self[0][1] * self[1][2] * self[3][3] + 146 | self[1][1] * self[3][2] * self[0][3] + 147 | self[3][1] * self[0][2] * self[1][3] - 148 | self[3][1] * self[1][2] * self[0][3] - 149 | self[0][1] * self[3][2] * self[1][3] - 150 | self[1][1] * self[0][2] * self[3][3] 151 | ) - 152 | self[3][0] * ( 153 | self[0][1] * self[1][2] * self[2][3] + 154 | self[1][1] * self[2][2] * self[0][3] + 155 | self[2][1] * self[0][2] * self[1][3] - 156 | self[2][1] * self[1][2] * self[0][3] - 157 | self[0][1] * self[2][2] * self[1][3] - 158 | self[1][1] * self[0][2] * self[2][3] 159 | ) 160 | } 161 | #[inline] 162 | fn inverse(&self) -> Option> { 163 | let det = self.determinant(); 164 | let ling = T::zero(); 165 | if det.is_approx_eq(&ling) { 166 | None 167 | } else { 168 | let inv_det = det.recip(); 169 | let tr = self.transpose(); 170 | let cf = |i, j| -> T { 171 | let mat = match i { 172 | 0 => Matrix3::new(tr.c1.truncate(j), tr.c2.truncate(j), tr.c3.truncate(j)), 173 | 1 => Matrix3::new(tr.c0.truncate(j), tr.c2.truncate(j), tr.c3.truncate(j)), 174 | 2 => Matrix3::new(tr.c0.truncate(j), tr.c1.truncate(j), tr.c3.truncate(j)), 175 | 3 => Matrix3::new(tr.c0.truncate(j), tr.c1.truncate(j), tr.c2.truncate(j)), 176 | _ => unreachable!(), 177 | }; 178 | let d = mat.determinant() * inv_det; 179 | if (i + j) & 1 == 1 { 180 | -d 181 | } else { 182 | d 183 | } 184 | }; 185 | let m = Matrix4::new( 186 | Vector4::new(cf(0, 0), cf(0, 1), cf(0, 2), cf(0, 3)), 187 | Vector4::new(cf(1, 0), cf(1, 1), cf(1, 2), cf(1, 3)), 188 | Vector4::new(cf(2, 0), cf(2, 1), cf(2, 2), cf(2, 3)), 189 | Vector4::new(cf(3, 0), cf(3, 1), cf(3, 2), cf(3, 3)), 190 | ); 191 | Some(m) 192 | } 193 | } 194 | } 195 | 196 | #[cfg(test)] 197 | mod test { 198 | use num_traits::{One, Zero}; 199 | 200 | use crate::*; 201 | 202 | #[test] 203 | fn test_determinant() { 204 | let m2 = mat2(4., 5., 6., 7.); 205 | assert_eq!(m2.determinant(), -2.); 206 | assert_eq!(Mat3::one().determinant(), 1.); 207 | let m4 = mat4( 208 | 1., 0., 4., 0., 2., 1., 2., 1., 3., 2., 3., 1., 4., 3., 0., 0., 209 | ); 210 | assert_eq!(m4.determinant(), -7.); 211 | assert_eq!((m4 * m4).determinant(), 49.); 212 | assert_eq!(Mat4::one().determinant(), 1.); 213 | } 214 | 215 | #[test] 216 | fn test_inverse_mat2() { 217 | let yi = Mat2::one(); 218 | assert!(yi.inverse().is_some()); 219 | assert!(DMat2::zero().inverse().is_none()); 220 | let mat = mat2(1., 3., 2., 4.); 221 | let inv = mat.inverse().unwrap(); 222 | assert_close_to!(mat * inv, yi, 0.000001); 223 | assert_close_to!(inv * mat, yi, 0.000001); 224 | let m2 = mat2(1., 2., 2., 4.); 225 | assert!(m2.inverse().is_none()); 226 | } 227 | 228 | #[test] 229 | fn test_inverse_mat3() { 230 | let yi = Mat3::one(); 231 | assert!(yi.inverse().is_some()); 232 | assert_eq!(yi.inverse().unwrap(), yi); 233 | assert!(DMat3::zero().inverse().is_none()); 234 | let mat = mat3(5., 7., 11., -6., 9., 2., 1., 13., 0.); 235 | let inv = mat.inverse().unwrap(); 236 | assert_close_to!(mat * inv, yi, 0.000001); 237 | assert_close_to!(inv * mat, yi, 0.000001); 238 | } 239 | 240 | #[test] 241 | #[rustfmt::skip] 242 | fn test_inverse_mat4() { 243 | let mat = mat4( 244 | 1., 0., 4., 0., 245 | 2., 1., 2., 1., 246 | 3., 2., 3., 1., 247 | 4., 3., 0., 0., 248 | ); 249 | let invm = mat4( 250 | 3./7., 12./7., -12./7., 4./7., 251 | -4./7., -16./7., 16./7., -3./7., 252 | 1./7., -3./7., 3./7., -1./7., 253 | -4./7., 5./7., 2./7., -3./7., 254 | ); 255 | assert_approx_eq!(mat.inverse().unwrap(), invm); 256 | assert_close_to!(mat.inverse().unwrap().inverse().unwrap(), mat, 0.000001); 257 | assert!(Mat4::one().inverse().is_some()); 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /src/ext/consts.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use crate::basenum::BaseFloat; 25 | use crate::traits::GenFloat; 26 | use crate::vec::traits::GenFloatVec; 27 | 28 | pub trait Consts: GenFloat { 29 | fn pi() -> Self; 30 | fn tau() -> Self; 31 | fn root_pi() -> Self; 32 | fn half_pi() -> Self; 33 | fn one_third_pi() -> Self; 34 | fn quarter_pi() -> Self; 35 | fn one_over_pi() -> Self; 36 | fn one_over_tau() -> Self; 37 | fn two_over_pi() -> Self; 38 | fn four_over_pi() -> Self; 39 | fn two_over_root_pi() -> Self; 40 | fn one_over_root_two() -> Self; 41 | fn root_half_pi() -> Self; 42 | fn root_tau() -> Self; 43 | fn root_ln_four() -> Self; 44 | fn e() -> Self; 45 | fn euler() -> Self; 46 | fn root_two() -> Self; 47 | fn root_three() -> Self; 48 | fn root_five() -> Self; 49 | fn ln_two() -> Self; 50 | fn ln_ten() -> Self; 51 | fn ln_ln_two() -> Self; 52 | fn one_third() -> Self; 53 | fn two_thirds() -> Self; 54 | fn golden_ratio() -> Self; 55 | } 56 | 57 | macro_rules! impl_Consts_for { 58 | ($($bt: ident),+) => { 59 | $( 60 | impl Consts<$bt> for T where T: GenFloat<$bt> { 61 | #[inline(always)] 62 | fn pi() -> T { 63 | T::from_s(3.14159265358979323846264338327950288) 64 | } 65 | #[inline(always)] 66 | fn tau() -> T { 67 | T::from_s(6.28318530717958647692528676655900576) 68 | } 69 | #[inline(always)] 70 | fn root_pi() -> T { 71 | T::from_s(1.772453850905516027) 72 | } 73 | #[inline(always)] 74 | fn half_pi() -> T { 75 | T::from_s(1.57079632679489661923132169163975144) 76 | } 77 | #[inline(always)] 78 | fn one_third_pi() -> T { 79 | T::from_s(1.04719755119659774615421446109316763) 80 | } 81 | #[inline(always)] 82 | fn quarter_pi() -> T { 83 | T::from_s(0.785398163397448309615660845819875721) 84 | } 85 | #[inline(always)] 86 | fn one_over_pi() -> T { 87 | T::from_s(0.318309886183790671537767526745028724) 88 | } 89 | #[inline(always)] 90 | fn one_over_tau() -> T { 91 | T::from_s(0.159154943091895335768883763372514362) 92 | } 93 | #[inline(always)] 94 | fn two_over_pi() -> T { 95 | T::from_s(0.636619772367581343075535053490057448) 96 | } 97 | #[inline(always)] 98 | fn four_over_pi() -> T { 99 | T::from_s(1.273239544735162686151070106980114898) 100 | } 101 | #[inline(always)] 102 | fn two_over_root_pi() -> T { 103 | T::from_s(1.12837916709551257389615890312154517) 104 | } 105 | #[inline(always)] 106 | fn one_over_root_two() -> T { 107 | T::from_s(0.707106781186547524400844362104849039) 108 | } 109 | #[inline(always)] 110 | fn root_half_pi() -> T { 111 | T::from_s(1.253314137315500251) 112 | } 113 | #[inline(always)] 114 | fn root_tau() -> T { 115 | T::from_s(2.506628274631000502) 116 | } 117 | #[inline(always)] 118 | fn root_ln_four() -> T { 119 | T::from_s(1.17741002251547469) 120 | } 121 | #[inline(always)] 122 | fn e() -> T { 123 | T::from_s(2.71828182845904523536028747135266250) 124 | } 125 | #[inline(always)] 126 | fn euler() -> T { 127 | T::from_s(0.577215664901532860606) 128 | } 129 | #[inline(always)] 130 | fn root_two() -> T { 131 | T::from_s(1.41421356237309504880168872420969808) 132 | } 133 | #[inline(always)] 134 | fn root_three() -> T { 135 | T::from_s(1.73205080756887729352744634150587236) 136 | } 137 | #[inline(always)] 138 | fn root_five() -> T { 139 | T::from_s(2.23606797749978969640917366873127623) 140 | } 141 | #[inline(always)] 142 | fn ln_two() -> T { 143 | T::from_s(0.693147180559945309417232121458176568) 144 | } 145 | #[inline(always)] 146 | fn ln_ten() -> T { 147 | T::from_s(2.30258509299404568401799145468436421) 148 | } 149 | #[inline(always)] 150 | fn ln_ln_two() -> T { 151 | T::from_s(-0.3665129205816643) 152 | } 153 | #[inline(always)] 154 | fn one_third() -> T { 155 | T::from_s(0.3333333333333333333333333333333333333333) 156 | } 157 | #[inline(always)] 158 | fn two_thirds() -> T { 159 | T::from_s(0.666666666666666666666666666666666666667) 160 | } 161 | fn golden_ratio() -> T { 162 | T::from_s(1.61803398874989484820458683436563811) 163 | } 164 | } 165 | )+ 166 | } 167 | } 168 | 169 | impl_Consts_for! { f32, f64 } 170 | 171 | // NOTE: can't define these functions without the indirection (trait `Consts`), 172 | // because Rust does not support implicit conversion. 173 | 174 | /// Returns the epsilon constant for floating point types. 175 | #[inline(always)] 176 | pub fn epsilon>() -> T { 177 | T::from_s(F::epsilon()) 178 | } 179 | 180 | /// Returns the Archimedes' constant π. 181 | /// 182 | /// # Example 183 | /// 184 | /// ```rust 185 | /// use glm::*; 186 | /// use glm::ext::*; 187 | /// 188 | /// assert_eq!(DVec4::pi(), dvec4(pi(), pi(), pi(), pi())); 189 | #[inline(always)] 190 | pub fn pi>() -> T { 191 | Consts::pi() 192 | } 193 | 194 | /// Returns π * 2. 195 | #[inline(always)] 196 | pub fn tau>() -> T { 197 | Consts::tau() 198 | } 199 | 200 | /// Returns square root of π. 201 | #[inline(always)] 202 | pub fn root_pi>() -> T { 203 | Consts::root_pi() 204 | } 205 | 206 | /// Returns π / 2. 207 | #[inline(always)] 208 | pub fn half_pi>() -> T { 209 | Consts::half_pi() 210 | } 211 | 212 | /// Returns π / 3. 213 | #[inline(always)] 214 | pub fn one_third_pi>() -> T { 215 | Consts::one_third_pi() 216 | } 217 | 218 | /// Returns π / 4. 219 | #[inline(always)] 220 | pub fn quarter_pi>() -> T { 221 | Consts::quarter_pi() 222 | } 223 | 224 | /// Returns 1 / π. 225 | #[inline(always)] 226 | pub fn one_over_pi>() -> T { 227 | Consts::one_over_pi() 228 | } 229 | 230 | /// Returns 1 / tau. 231 | #[inline(always)] 232 | pub fn one_over_tau>() -> T { 233 | Consts::one_over_tau() 234 | } 235 | 236 | /// Returns 2 / π. 237 | #[inline(always)] 238 | pub fn two_over_pi>() -> T { 239 | Consts::two_over_pi() 240 | } 241 | 242 | /// Returns 4 / π. 243 | #[inline(always)] 244 | pub fn four_over_pi>() -> T { 245 | Consts::four_over_pi() 246 | } 247 | 248 | /// Returns 2 / sqrt(π). 249 | #[inline(always)] 250 | pub fn two_over_root_pi>() -> T { 251 | Consts::two_over_root_pi() 252 | } 253 | 254 | /// Returns 1 / sqrt(2). 255 | #[inline(always)] 256 | pub fn one_over_root_two>() -> T { 257 | Consts::one_over_root_two() 258 | } 259 | 260 | /// Returns sqrt(π / 2). 261 | #[inline(always)] 262 | pub fn root_half_pi>() -> T { 263 | Consts::root_half_pi() 264 | } 265 | 266 | /// Returns sqrt(tau). 267 | #[inline(always)] 268 | pub fn root_tau>() -> T { 269 | Consts::root_tau() 270 | } 271 | 272 | /// Returns sqrt(ln(4)). 273 | #[inline(always)] 274 | pub fn root_ln_four>() -> T { 275 | Consts::root_ln_four() 276 | } 277 | 278 | /// Returns e constant. 279 | #[inline(always)] 280 | pub fn e>() -> T { 281 | Consts::e() 282 | } 283 | 284 | /// Returns Euler's constant. 285 | #[inline(always)] 286 | pub fn euler>() -> T { 287 | Consts::euler() 288 | } 289 | 290 | /// Returns sqrt(2). 291 | #[inline(always)] 292 | pub fn root_two>() -> T { 293 | Consts::root_two() 294 | } 295 | 296 | /// Returns sqrt(3). 297 | #[inline(always)] 298 | pub fn root_three>() -> T { 299 | Consts::root_three() 300 | } 301 | 302 | /// Returns sqrt(5). 303 | #[inline(always)] 304 | pub fn root_five>() -> T { 305 | Consts::root_five() 306 | } 307 | 308 | /// Returns ln(2). 309 | #[inline(always)] 310 | pub fn ln_two>() -> T { 311 | Consts::ln_two() 312 | } 313 | 314 | /// Returns ln(10). 315 | #[inline(always)] 316 | pub fn ln_ten>() -> T { 317 | Consts::ln_ten() 318 | } 319 | 320 | /// Returns ln(ln(2)). 321 | #[inline(always)] 322 | pub fn ln_ln_two>() -> T { 323 | Consts::ln_ln_two() 324 | } 325 | 326 | /// Returns 1 / 3. 327 | #[inline(always)] 328 | pub fn one_third>() -> T { 329 | Consts::one_third() 330 | } 331 | 332 | /// Returns 2 / 3. 333 | #[inline(always)] 334 | pub fn two_thirds>() -> T { 335 | Consts::two_thirds() 336 | } 337 | 338 | /// Returns the golden ratio constant. 339 | pub fn golden_ratio>() -> T { 340 | Consts::golden_ratio() 341 | } 342 | -------------------------------------------------------------------------------- /src/builtin/integer.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | // The GLSL Specification, ch 8.8, Integer Functions. 25 | 26 | use core::mem; 27 | 28 | use crate::basenum::BaseInt; 29 | use crate::traits::{GenIType, GenInt, GenNum, GenUType}; 30 | use crate::vec::vec::{IVec2, IVec3, IVec4, UVec2, UVec3, UVec4}; 31 | 32 | // used by `findLSB` and `findMSB`. 33 | pub trait IntIntRel: GenInt { 34 | fn map_int i32>(&self, f: F) -> T; 35 | } 36 | 37 | macro_rules! impl_IntIntRel_for_int { 38 | ($($t: ident),+) => { 39 | $( 40 | impl IntIntRel for $t { 41 | #[inline(always)] 42 | fn map_int i32>(&self, f: F) -> $t { 43 | self.map(f) 44 | } 45 | } 46 | )+ 47 | } 48 | } 49 | 50 | impl_IntIntRel_for_int! { i32, IVec2, IVec3, IVec4 } 51 | 52 | impl IntIntRel for u32 { 53 | #[inline(always)] 54 | fn map_int i32>(&self, f: F) -> i32 { 55 | f(*self) 56 | } 57 | } 58 | 59 | macro_rules! impl_IntIntRel_for_uint { 60 | ($({ $ut: ident, $it: ident, $($field: ident),+ }),+) => { 61 | $( 62 | impl IntIntRel for $ut { 63 | #[inline(always)] 64 | fn map_int i32>(&self, f: F) -> $it { 65 | $it { $($field: f(self.$field)),+ } 66 | } 67 | } 68 | )+ 69 | } 70 | } 71 | 72 | impl_IntIntRel_for_uint! { 73 | { UVec2, IVec2, x, y }, 74 | { UVec3, IVec3, x, y, z }, 75 | { UVec4, IVec4, x, y, z, w } 76 | } 77 | 78 | /// Adds 32-bit unsigned integer `x` and `y`, returning the sum modulus 79 | /// *232* and the carry bit. 80 | /// 81 | /// Carry is set to `0` if the sum was less than *232*, or to `1` 82 | /// otherwise. 83 | /// 84 | /// # Note 85 | /// 86 | /// In GLSL, the carry bit is returned via the output parameter `carry`. 87 | /// 88 | /// # Example 89 | /// 90 | /// ``` 91 | /// use glm::{ uvec2, uaddCarry }; 92 | /// 93 | /// let v = uvec2(0xFFFFFFFE, 0); 94 | /// assert_eq!(uaddCarry(v, uvec2(3, 3)), (uvec2(1, 3), uvec2(1, 0))) 95 | /// ``` 96 | #[inline] 97 | #[allow(non_snake_case)] 98 | pub fn uaddCarry(x: T, y: T) -> (T, T) { 99 | x.map2(y, |i, j| -> (u32, u32) { 100 | match i.checked_add(j) { 101 | Some(s) => (s, 0), 102 | None => (i - (0xFFFFFFFF - j + 1), 1), 103 | } 104 | }) 105 | } 106 | 107 | /// Subtracts the 32-bit unsigned integer `y` from `x`, returning the 108 | /// difference and the borrow bit. 109 | /// 110 | /// Returns the difference if it is non-negative, or *232* plus the 111 | /// difference otherwise. 112 | /// 113 | /// The borrow bit is set to `0` if` x ≥ y`, or to `1` otherwise. 114 | /// 115 | /// # Example 116 | /// 117 | /// ``` 118 | /// use glm::{ usubBorrow, uvec2 }; 119 | /// 120 | /// let uv1 = uvec2(16, 17); 121 | /// let uv2 = uvec2(17, 16); 122 | /// assert_eq!(usubBorrow(uv1, uv2), (uvec2(0xFFFFFFFE, 1), uvec2(1, 0))); 123 | /// ``` 124 | #[inline] 125 | #[allow(non_snake_case)] 126 | pub fn usubBorrow(x: T, y: T) -> (T, T) { 127 | x.map2(y, |i, j| -> (u32, u32) { 128 | if i >= j { 129 | (i - j, 0) 130 | } else { 131 | (0xFFFFFFFF - j + i, 1) 132 | } 133 | }) 134 | } 135 | 136 | /// Multiplies 32-bit unsigned integers `x` and `y`, producing a 64-bit 137 | /// result. 138 | /// 139 | /// The 32 least-significant bits are returned in `lsb`. 140 | /// 141 | /// The 32 most-significant bits are returned in `msb`. 142 | #[allow(non_snake_case)] 143 | pub fn umulExtended(x: T, y: T) -> (T, T) { 144 | x.map2(y, |i, j| -> (u32, u32) { 145 | let ei = i as u64; 146 | let ej = j as u64; 147 | let p = ei * ej; 148 | ((p >> 32) as u32, p as u32) 149 | }) 150 | } 151 | 152 | /// Multiplies 32-bit integers `x` and `y`, producing a 64-bit result. 153 | /// 154 | /// The 32 least-significant bits are returned in `lsb`. 155 | /// 156 | /// The 32 most-significant bits are returned in `msb`. 157 | #[allow(non_snake_case)] 158 | pub fn imulExtended(x: T, y: T) -> (T, T) { 159 | x.map2(y, |i, j| -> (i32, i32) { 160 | let ei = i as i64; 161 | let ej = j as i64; 162 | let p = ei * ej; 163 | ((p >> 32) as i32, p as i32) 164 | }) 165 | } 166 | 167 | /// Extracts bits `[offset, offset + bits - 1]` from `value`, returning them in 168 | /// the least significant bits of the result. 169 | /// 170 | /// For unsigned data types, the most significant bits of the result will 171 | /// be set to zero. For signed data types, the most significant bits will 172 | /// be set to the value of bit offset + base – 1. 173 | /// 174 | /// If `bits` is zero, the result will be zero. The result will be undefined 175 | /// if `offset` or `bits` is negative, or if the sum of `offset` and `bits` is 176 | /// greater than the number of bits used to store the operand. 177 | /// 178 | /// # Example 179 | /// 180 | /// ``` 181 | /// use glm::bitfieldExtract; 182 | /// 183 | /// assert_eq!(bitfieldExtract(0xF000FFFF_u32, 32, 12), 0); 184 | /// assert_eq!(bitfieldExtract(0b11100011_u32, 1, 6), 0b110001); 185 | /// ``` 186 | #[allow(non_snake_case)] 187 | pub fn bitfieldExtract>(value: T, offset: usize, bits: usize) -> T { 188 | let ling = T::zero(); 189 | if value.is_zero() || bits == 0 || offset + bits > 32 { 190 | ling 191 | } else { 192 | let mask = I::from((1_u32 << bits) - 1).unwrap(); 193 | value.map(|i| -> I { (i >> offset) & mask }) 194 | } 195 | } 196 | 197 | /// Returns the insertion the `bits` least-significant bits of `insert` into 198 | /// `base`. 199 | /// 200 | /// The result will have bits `[offset, offset + bits - 1]` taken from 201 | /// bits `[0, bits – 1]` of `insert`, and all other bits taken directly from 202 | /// the corresponding bits of `base`. If `bits` is zero, the result will 203 | /// simply be `base`. 204 | /// 205 | /// The result will be undefined if `offset` or `bits` is negative, 206 | /// or if the sum of `offset` and `bits` is greater than the number of bits 207 | /// used to store the operand. 208 | /// 209 | /// # Example 210 | /// 211 | /// ``` 212 | /// use glm::bitfieldInsert; 213 | /// 214 | /// assert_eq!(bitfieldInsert(1_u32, 0xFF00FF00, 8, 20), 0xF00FF01); 215 | /// ``` 216 | #[allow(non_snake_case)] 217 | pub fn bitfieldInsert>( 218 | base: T, 219 | insert: T, 220 | offset: usize, 221 | bits: usize, 222 | ) -> T { 223 | if bits == 0 { 224 | base 225 | } else { 226 | let mask = I::from(((1_u32 << bits) - 1) << offset).unwrap(); 227 | base.zip(insert, |i, j| -> I { (i & !mask) | (j & mask) }) 228 | } 229 | } 230 | 231 | /// Returns the reversal of the bits of `value`. 232 | /// 233 | /// The bit numbered n of the result will be taken from bit `(bits - 1) - n` 234 | /// of `value`, where *bits* is the total number of bits used to represent 235 | /// `value`. 236 | /// 237 | /// # Example 238 | /// 239 | /// ``` 240 | /// use glm::bitfieldReverse; 241 | /// 242 | /// assert_eq!(bitfieldReverse(0xF30000F3_u32), 0xCF0000CF); 243 | /// ``` 244 | #[allow(non_snake_case)] 245 | pub fn bitfieldReverse>(value: T) -> T { 246 | #[inline(always)] 247 | fn reverse_step(x: u32, mask: u32, shift: usize) -> u32 { 248 | ((x & mask) << shift) | ((x & !mask) >> shift) 249 | } 250 | value.map(|i| -> I { 251 | // reinterpret_cast 252 | let u: &u32 = unsafe { mem::transmute(&i) }; 253 | let mut x = *u; 254 | x = reverse_step(x, 0x55555555, 1); 255 | x = reverse_step(x, 0x33333333, 2); 256 | x = reverse_step(x, 0x0F0F0F0F, 4); 257 | x = reverse_step(x, 0x00FF00FF, 8); 258 | x = reverse_step(x, 0x0000FFFF, 16); 259 | let r: &I = unsafe { mem::transmute(&x) }; 260 | *r 261 | }) 262 | } 263 | 264 | /// Returns the number of bits set to 1 in the binary representation of 265 | /// `value`. 266 | /// 267 | /// # Example 268 | /// 269 | /// ``` 270 | /// use glm::{ bitCount, ivec2 }; 271 | /// 272 | /// let v = ivec2(0b01010101, 0); 273 | /// assert_eq!(bitCount(v), ivec2(4, 0)); 274 | /// ``` 275 | #[allow(non_snake_case)] 276 | pub fn bitCount>(value: T) -> T { 277 | value.map(|i| -> I { 278 | let c = I::from(i.count_ones()).unwrap(); 279 | c 280 | }) 281 | } 282 | 283 | /// Returns the bit number of the least significant bit set to 1 in the binary 284 | /// representation of `value`. 285 | /// 286 | /// If `value` is zero, `-1` will be returned. 287 | /// 288 | /// # Example 289 | /// 290 | /// ``` 291 | /// use glm::{ findLSB, ivec2, uvec2 }; 292 | /// 293 | /// assert_eq!(findLSB(0u32), -1); 294 | /// let v = uvec2(0b0101000, 0x80000000); 295 | /// assert_eq!(findLSB(v), ivec2(3, 31)); 296 | /// ``` 297 | #[allow(non_snake_case)] 298 | pub fn findLSB>(value: T) -> I { 299 | value.map_int(|i| -> i32 { 300 | if i.is_zero() { 301 | -1 302 | } else { 303 | i.trailing_zeros() as i32 304 | } 305 | }) 306 | } 307 | 308 | /// Returns the bit number of the most significant bit in the binary 309 | /// representation of `value`. 310 | /// 311 | /// For positive integers, the result will be the bit number of the 312 | /// most significant bit set to `1`. 313 | /// 314 | /// For negative integers, the result will be the bit number of the most 315 | /// significant bit set to `0`. For a value of zero or negative one, `-1` will 316 | /// be returned. 317 | /// 318 | /// # Example 319 | /// 320 | /// ``` 321 | /// use glm::{ findMSB, ivec3 }; 322 | /// 323 | /// assert_eq!(findMSB(0_i32), -1); 324 | /// assert_eq!(findMSB(ivec3(-1, -2, 0x7FFFFFFF)), ivec3(-1, 0, 30)); 325 | /// ``` 326 | #[allow(non_snake_case)] 327 | pub fn findMSB>(value: T) -> I { 328 | value.map_int(|i| -> i32 { 329 | let ling = B::zero(); 330 | if i.is_zero() { 331 | -1 332 | } else if i < ling { 333 | 31 - ((!i).leading_zeros() as i32) 334 | } else { 335 | 31 - (i.leading_zeros() as i32) 336 | } 337 | }) 338 | } 339 | -------------------------------------------------------------------------------- /src/cast.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use core::default::Default; 25 | 26 | use num_traits::{ToPrimitive, Zero}; 27 | 28 | use crate::basenum::Primitive; 29 | use crate::vec::traits::GenVec; 30 | use crate::vec::vec::*; 31 | 32 | /// This trait is like the `std::num::ToPrimitive`, but function `to_bool()` 33 | /// is added. 34 | pub trait ToPrim: Primitive { 35 | fn to_i32(&self) -> Option; 36 | 37 | fn to_u32(&self) -> Option; 38 | 39 | fn to_f32(&self) -> Option; 40 | 41 | fn to_f64(&self) -> Option; 42 | 43 | fn to_bool(&self) -> Option; 44 | } 45 | 46 | macro_rules! impl_ToPrim_for { 47 | ($($t: ident),+) => { 48 | $( 49 | impl ToPrim for $t { 50 | #[inline] 51 | fn to_i32(&self) -> Option { 52 | ToPrimitive::to_i32(self) 53 | } 54 | #[inline] 55 | fn to_u32(&self) -> Option { 56 | ToPrimitive::to_u32(self) 57 | } 58 | #[inline] 59 | fn to_f32(&self) -> Option { 60 | ToPrimitive::to_f32(self) 61 | } 62 | #[inline] 63 | fn to_f64(&self) -> Option { 64 | ToPrimitive::to_f64(self) 65 | } 66 | #[inline] 67 | fn to_bool(&self) -> Option { 68 | let b = if self.is_zero() { false } else { true }; 69 | Some(b) 70 | } 71 | } 72 | )+ 73 | }; 74 | } 75 | 76 | impl_ToPrim_for! { i32, u32, f32, f64 } 77 | 78 | impl ToPrim for bool { 79 | #[inline] 80 | fn to_i32(&self) -> Option { 81 | let i = if *self { 1 } else { 0 }; 82 | Some(i) 83 | } 84 | #[inline] 85 | fn to_u32(&self) -> Option { 86 | let i = if *self { 1 } else { 0 }; 87 | Some(i) 88 | } 89 | #[inline] 90 | fn to_f32(&self) -> Option { 91 | let i = if *self { 1. } else { 0. }; 92 | Some(i) 93 | } 94 | #[inline] 95 | fn to_f64(&self) -> Option { 96 | let i = if *self { 1. } else { 0. }; 97 | Some(i) 98 | } 99 | #[inline] 100 | fn to_bool(&self) -> Option { 101 | Some(*self) 102 | } 103 | } 104 | 105 | /// This trait provides parameterized function `from`. 106 | pub trait PrimCast: ToPrim { 107 | /// Converts from a value with primitive type `p`. 108 | fn from(p: F) -> Option; 109 | } 110 | 111 | macro_rules! impl_PrimCast_for { 112 | ($({ $t: ident, $cf: ident }),+) => { 113 | $( 114 | impl PrimCast for $t { 115 | #[inline] 116 | fn from(p: F) -> Option<$t> { 117 | p.$cf() 118 | } 119 | } 120 | )+ 121 | } 122 | } 123 | 124 | impl_PrimCast_for! { 125 | { i32, to_i32 }, 126 | { u32, to_u32 }, 127 | { f32, to_f32 }, 128 | { f64, to_f64 }, 129 | { bool, to_bool } 130 | } 131 | 132 | /// This trait unifies all scalar and vector types, so we can convert between 133 | /// any two of them. 134 | // TODO: move GenPrimitive to `traits.rs`? 135 | // and move functions defined in `GenNum` (map, zip, etc.) here? 136 | pub trait GenPrimitive { 137 | type BaseType: PrimCast; 138 | } 139 | 140 | macro_rules! impl_GenPrimitive_for_scalar { 141 | ($($t: ident),+) => { 142 | $( 143 | impl GenPrimitive for $t { 144 | type BaseType = $t; 145 | } 146 | )+ 147 | } 148 | } 149 | 150 | impl_GenPrimitive_for_scalar! { i32, u32, f32, f64, bool } 151 | 152 | macro_rules! impl_GenPrimitive_for_vector { 153 | ($($t: ident),+) => { 154 | $( 155 | impl GenPrimitive for $t { 156 | type BaseType = T; 157 | } 158 | )+ 159 | } 160 | } 161 | 162 | impl_GenPrimitive_for_vector! { 163 | Vector2, Vector3, Vector4 164 | } 165 | 166 | /// Traits for converting any scalar/vector value to a scalar. 167 | pub trait ToScalar: GenPrimitive { 168 | /// Casts _self_ to a value of type `T`. 169 | /// 170 | /// According to the GLSL spec, if _self_ is a vector, casts the first 171 | /// component only. 172 | /// 173 | /// # Example 174 | /// 175 | /// ```rust 176 | /// use glm::*; 177 | /// 178 | /// assert_eq!(int(bvec2(true, false)), 1); 179 | /// assert_eq!(int(3.14_f32), 3); 180 | /// ``` 181 | fn to(self) -> Option; 182 | } 183 | 184 | macro_rules! impl_ToScalar_for_scalar { 185 | ($($t: ident),+) => { 186 | $( 187 | impl ToScalar<$t, T> for $t { 188 | #[inline(always)] 189 | fn to(self) -> Option { 190 | T::from(self) 191 | } 192 | } 193 | )+ 194 | } 195 | } 196 | 197 | impl_ToScalar_for_scalar! { i32, u32, f32, f64, bool } 198 | 199 | macro_rules! impl_ToScalar_for_vector { 200 | ($($t: ident),+) => { 201 | $( 202 | impl ToScalar for $t { 203 | #[inline(always)] 204 | fn to(self) -> Option { 205 | T::from(self[0]) 206 | } 207 | } 208 | )+ 209 | } 210 | } 211 | 212 | impl_ToScalar_for_vector! { Vector2, Vector3, Vector4 } 213 | 214 | macro_rules! def_cast_scalar_fun { 215 | ($({ $nm: ident, $t: ty }),+) => { 216 | $( 217 | pub fn $nm>(from: F) -> $t { 218 | from.to().unwrap() 219 | } 220 | )+ 221 | } 222 | } 223 | 224 | def_cast_scalar_fun! { 225 | { int, i32 }, 226 | { uint, u32 }, 227 | { float, f32 }, 228 | { double, f64 }, 229 | { boolean, bool } 230 | } 231 | 232 | /// Traits for converting any scalar/vector values to a vector. 233 | pub trait ToVector + GenVec>: 234 | GenPrimitive 235 | { 236 | /// Convertes _self_ to a value of Vector type. 237 | /// 238 | /// # Example 239 | /// 240 | /// ```rust 241 | /// use glm::*; 242 | /// 243 | /// assert_eq!(to_bvec2(0_i32), bvec2(false, false)); 244 | /// assert_eq!(to_dvec4(bvec4(true, true, false, true)), dvec4(1., 1., 0., 1.)); 245 | /// ``` 246 | fn to(self) -> Option; 247 | } 248 | 249 | macro_rules! impl_ToVector_for_scalar { 250 | ($t: ident, $v: ident, $($field: ident),+) => { 251 | impl ToVector<$t, T, $v> for $t { 252 | #[inline] 253 | fn to(self) -> Option<$v> { 254 | PrimCast::from(self).map(|t| -> $v { 255 | $v { $($field: t),+ } 256 | }) 257 | } 258 | } 259 | } 260 | } 261 | 262 | macro_rules! impl_ToVectors_for_scalar { 263 | ($($t: ident),+) => { 264 | $( 265 | impl_ToVector_for_scalar! { $t, Vector2, x, y } 266 | impl_ToVector_for_scalar! { $t, Vector3, x, y, z } 267 | impl_ToVector_for_scalar! { $t, Vector4, x, y, z, w } 268 | )+ 269 | } 270 | } 271 | 272 | impl_ToVectors_for_scalar! { i32, u32, f32, f64, bool } 273 | 274 | // TODO: to support convertion between vectors with different dimensions. 275 | // by introducing something like `DimCast`. 276 | 277 | macro_rules! impl_ToVector_for_vector { 278 | ($({ $v: ident, $($field: ident),+ }),+) => { 279 | $( 280 | impl ToVector> for $v { 281 | #[inline] 282 | fn to(self) -> Option<$v> { 283 | let os = [$(T::from(self.$field)),+]; 284 | if os.iter().any(|&o| -> bool { o.is_none() }) { 285 | None 286 | } else { 287 | // all Primitives implement `Default`. 288 | let mut zero: $v = $v { $($field: Default::default()),+ }; 289 | os.iter().fold(0, |i, &o| -> usize { 290 | zero[i] = o.unwrap(); 291 | i + 1 292 | }); 293 | Some(zero) 294 | } 295 | } 296 | } 297 | )+ 298 | } 299 | } 300 | 301 | impl_ToVector_for_vector! { 302 | { Vector2, x, y }, 303 | { Vector3, x, y, z }, 304 | { Vector4, x, y, z, w } 305 | } 306 | 307 | macro_rules! def_cast_vector_fun { 308 | ($({ $nm: ident, $s: ty, $v: ty }),+) => { 309 | $( 310 | #[inline] 311 | pub fn $nm>(gp: F) -> $v { 312 | gp.to().unwrap() 313 | } 314 | )+ 315 | } 316 | } 317 | 318 | def_cast_vector_fun! { 319 | { to_ivec2, i32, IVec2 }, 320 | { to_ivec3, i32, IVec3 }, 321 | { to_ivec4, i32, IVec4 }, 322 | { to_uvec2, u32, UVec2 }, 323 | { to_uvec3, u32, UVec3 }, 324 | { to_uvec4, u32, UVec4 }, 325 | { to_vec2, f32, Vec2 }, 326 | { to_vec3, f32, Vec3 }, 327 | { to_vec4, f32, Vec4 }, 328 | { to_dvec2, f64, DVec2 }, 329 | { to_dvec3, f64, DVec3 }, 330 | { to_dvec4, f64, DVec4 }, 331 | { to_bvec2, bool, BVec2 }, 332 | { to_bvec3, bool, BVec3 }, 333 | { to_bvec4, bool, BVec4 } 334 | } 335 | 336 | // TODO: support casting matrices to vectors. Just returns the first column. 337 | 338 | #[cfg(test)] 339 | mod test { 340 | 341 | use super::*; 342 | 343 | #[test] 344 | fn test_int() { 345 | assert_eq!(int(1_f32), 1_i32); 346 | assert_eq!(int(true), 1_i32); 347 | assert_eq!(int(false), 0_i32); 348 | } 349 | 350 | #[test] 351 | fn test_boolean() { 352 | assert_eq!(boolean(uvec2(0, 1)), false); 353 | assert_eq!(boolean(vec3(1., -1., 0.)), true); 354 | } 355 | 356 | #[test] 357 | fn test_float() { 358 | assert_eq!(float(bvec2(true, false)), 1.); 359 | assert_eq!(float(123_u32), 123.); 360 | assert_eq!(float(0_f64), 0.); 361 | } 362 | 363 | #[test] 364 | fn test_to_vec() { 365 | assert_eq!(to_vec2(bvec2(true, false)), vec2(1., 0.)); 366 | assert_eq!(to_bvec3(ivec3(0, 1, -1)), bvec3(false, true, true)); 367 | } 368 | } 369 | -------------------------------------------------------------------------------- /src/builtin/noise.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | // The GLSL Specification, ch 8.11, Noise Functions. 25 | 26 | ////////////////////////////////////////////////////////////////////////////// 27 | // Translated directly from g-truc (Christophe Riccio)'s original implementation. 28 | ////////////////////////////////////////////////////////////////////////////// 29 | // OpenGL Mathematics (glm.g-truc.net) 30 | // 31 | // Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) 32 | // 33 | // MIT License 34 | ////////////////////////////////////////////////////////////////////////////// 35 | 36 | #![allow(non_snake_case)] 37 | 38 | use num_traits::{One, Zero}; 39 | 40 | use crate::cast::to_vec4; 41 | use crate::traits::GenType; 42 | use crate::vec::vec::{vec2, vec3, vec4, Vec2, Vec3, Vec4}; 43 | 44 | use super::common::*; 45 | use super::geom::dot; 46 | use super::vecrel::lessThan; 47 | 48 | #[allow(non_snake_case)] 49 | pub fn grad4(j: f32, ip: Vec4) -> Vec4 { 50 | let mut pXYZ = floor(fract(vec3(j, j, j) * ip.truncate(3)) * 7.) * ip[2] - 1.; 51 | let pW = 1.5 - dot(abs(pXYZ), Vec3::one()); 52 | let s = to_vec4(lessThan(vec4(pXYZ.x, pXYZ.y, pXYZ.z, pW), Vec4::zero())); 53 | pXYZ = pXYZ + (s.truncate(3) * 2. - 1.) * s.w; 54 | vec4(pXYZ.x, pXYZ.y, pXYZ.z, pW) 55 | } 56 | 57 | #[inline(always)] 58 | pub fn mod289(x: T) -> T { 59 | x - floor(x * (1. / 289.)) * 289. 60 | } 61 | 62 | #[inline(always)] 63 | pub fn permute(x: T) -> T { 64 | mod289((x * 34. + 1.) * x) 65 | } 66 | 67 | #[inline(always)] 68 | pub fn taylor_inv_sqrt(x: T) -> T { 69 | -x * 0.85373472095314 + 1.79284291400159 70 | } 71 | 72 | pub trait NoiseImpl { 73 | fn noise1(self) -> f32; 74 | } 75 | 76 | impl NoiseImpl for f32 { 77 | #[inline] 78 | fn noise1(self) -> f32 { 79 | vec2(self, 0.).noise1() 80 | } 81 | } 82 | 83 | impl NoiseImpl for Vec2 { 84 | fn noise1(self) -> f32 { 85 | let yi = Vec2::one(); 86 | let C = vec4( 87 | 0.211324865405187, // (3.0 - sqrt(3.0)) / 6.0 88 | 0.366025403784439, // 0.5 * (sqrt(3.0) - 1.0) 89 | -0.577350269189626, // -1.0 + 2.0 * C.x 90 | 0.024390243902439, // 1.0 / 41.0 91 | ); 92 | // first corner 93 | let mut i = floor(self + dot(self, yi * C.y)); 94 | let x0 = self - i + dot(i, yi * C.x); 95 | // Other corners 96 | //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0 97 | //i1.y = 1.0 - i1.x; 98 | let i1 = if x0.x > x0.y { 99 | vec2(1., 0.) 100 | } else { 101 | vec2(0., 1.) 102 | }; 103 | 104 | // x0 = x0 - 0.0 + 0.0 * C.xx ; 105 | // x1 = x0 - i1 + 1.0 * C.xx ; 106 | // x2 = x0 - 1.0 + 2.0 * C.xx ; 107 | let mut x12 = vec4(x0.x, x0.y, x0.x, x0.y) + vec4(C.x, C.x, C.z, C.z); 108 | x12 = vec4(x12.x - i1.x, x12.y - i1.y, x12.z, x12.w); 109 | 110 | // Permutations 111 | i = mod_s(i, 289.); // Avoid truncation effects in permutation 112 | let p = permute(permute(vec3(0., i1.y, 1.) + i.y) + vec3(0., i1.x, 1.) + i.x); 113 | 114 | let mut m = max_s( 115 | -vec3( 116 | dot(x0, x0), 117 | dot(vec2(x12.x, x12.y), vec2(x12.x, x12.y)), 118 | dot(vec2(x12.z, x12.w), vec2(x12.z, x12.w)), 119 | ) + 0.5, 120 | 0., 121 | ); 122 | m = m * m; 123 | m = m * m; 124 | 125 | // Gradients: 41 points uniformly over a line, mapped onto a diamond. 126 | // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) 127 | 128 | let x = fract(p * C.w) * 2. - 1.; 129 | let h = abs(x) - 0.5; 130 | let ox = floor(x + 0.5); 131 | let a0 = x - ox; 132 | 133 | // Normalise gradients implicitly by scaling m 134 | // Inlined for speed: m *= taylorInvSqrt( a0*a0 + h*h ); 135 | m = m * ((a0 * a0 + h * h) * -0.85373472095314 + 1.79284291400159); 136 | 137 | // Compute final noise value at P 138 | let g = vec3( 139 | a0.x * x0.x + h.x * x0.y, 140 | //g.yz = a0.yz * x12.xz + h.yz * x12.yw; 141 | a0.y * x12.x + h.y * x12.y, 142 | a0.z * x12.z + h.z * x12.w, 143 | ); 144 | dot(m, g) * 130. 145 | } 146 | } 147 | 148 | impl NoiseImpl for Vec3 { 149 | fn noise1(self) -> f32 { 150 | let yi = Vec3::one(); 151 | let C = vec2(1. / 6., 1. / 3.); 152 | let D = vec4(0., 0.5, 1., 2.); 153 | 154 | // First corner 155 | let mut i = floor(self + dot(self, yi * C.y)); 156 | let x0 = self - i + dot(i, yi * C.x); 157 | 158 | // Other corners 159 | let g = step(vec3(x0.y, x0.z, x0.x), x0); 160 | let l = yi - g; 161 | let i1 = min(g, vec3(l.z, l.x, l.y)); 162 | let i2 = max(g, vec3(l.z, l.x, l.y)); 163 | 164 | // x0 = x0 - 0.0 + 0.0 * C.xxx; 165 | // x1 = x0 - i1 + 1.0 * C.xxx; 166 | // x2 = x0 - i2 + 2.0 * C.xxx; 167 | // x3 = x0 - 1.0 + 3.0 * C.xxx; 168 | let x1 = x0 - i1 + C.x; 169 | let x2 = x0 - i2 + C.y; // 2.0*C.x = 1/3 = C.y 170 | let x3 = x0 - D.y; // -1.0+3.0*C.x = -0.5 = -D.y 171 | 172 | // Permutations 173 | i = mod289(i); 174 | let p: Vec4 = permute( 175 | permute(permute(vec4(0., i1.z, i2.z, 1.) + i.z) + vec4(0., i1.y, i2.y, 1.) + i.y) 176 | + vec4(0., i1.x, i2.x, 1.) 177 | + i.x, 178 | ); 179 | 180 | // Gradients: 7x7 points over a square, mapped onto an octahedron. 181 | // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) 182 | let n_ = 0.142857142857_f32; // 1.0 / 7.0; 183 | let ns = vec3(D.w, D.y, D.z) * n_ - vec3(D.x, D.z, D.x); 184 | 185 | let j = p - floor(p * ns.z * ns.z) * 49.; // mod(p,7*7) 186 | 187 | let x_ = floor(j * ns.z); 188 | let y_ = floor(j - x_ * 7.); // mod(j, N) 189 | 190 | let x = x_ * ns.x + ns.y; 191 | let y = y_ * ns.x + ns.y; 192 | let h = Vec4::one() - abs(x) - abs(y); 193 | 194 | let b0 = vec4(x.x, x.y, y.x, y.y); 195 | let b1 = vec4(x.z, x.w, y.z, y.w); 196 | 197 | // vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; 198 | // vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; 199 | let s0 = floor(b0) * 2. + 1.; 200 | let s1 = floor(b1) * 2. + 1.; 201 | let sh = -step(h, Vec4::zero()); 202 | 203 | let a0 = vec4(b0.x, b0.z, b0.y, b0.w) 204 | + vec4(s0.x, s0.z, s0.y, s0.w) * vec4(sh.x, sh.x, sh.y, sh.y); 205 | let a1 = vec4(b1.x, b1.z, b1.y, b1.w) 206 | + vec4(s1.x, s1.z, s1.y, s1.w) * vec4(sh.z, sh.z, sh.w, sh.w); 207 | 208 | let mut p0 = vec3(a0.x, a0.y, h.x); 209 | let mut p1 = vec3(a0.z, a0.w, h.y); 210 | let mut p2 = vec3(a1.x, a1.y, h.z); 211 | let mut p3 = vec3(a1.z, a1.w, h.w); 212 | 213 | // Normalise gradients 214 | let norm = taylor_inv_sqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); 215 | p0 = p0 * norm.x; 216 | p1 = p1 * norm.y; 217 | p2 = p2 * norm.z; 218 | p3 = p3 * norm.w; 219 | 220 | // Mix final noise value 221 | let mut m = max_s( 222 | -vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)) + 0.6, 223 | 0., 224 | ); 225 | m = m * m; 226 | 42. * dot( 227 | m * m, 228 | vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)), 229 | ) 230 | } 231 | } 232 | 233 | impl NoiseImpl for Vec4 { 234 | fn noise1(self) -> f32 { 235 | let yi = Vec4::one(); 236 | let C = vec4( 237 | 0.138196601125011, // (5 - sqrt(5))/20 G4 238 | 0.276393202250021, // 2 * G4 239 | 0.414589803375032, // 3 * G4 240 | -0.447213595499958, // -1 + 4 * G4 241 | ); 242 | // (sqrt(5) - 1)/4 = F4, used once below 243 | let F4: f32 = 0.309016994374947451; 244 | 245 | // First corner 246 | let mut i = floor(self + dot(self, yi * F4)); 247 | let x0 = self - i + dot(i, yi * C.x); 248 | 249 | // Other corners 250 | 251 | // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) 252 | let isX = step(vec3(x0.y, x0.z, x0.w), vec3(x0.x, x0.x, x0.x)); 253 | let isYZ = step(vec3(x0.z, x0.w, x0.w), vec3(x0.y, x0.y, x0.z)); 254 | 255 | // i0.x = dot(isX, vec3(1.0)); 256 | // i0.x = isX.x + isX.y + isX.z; 257 | // i0.yzw = static_cast(1) - isX; 258 | let mut i0 = vec4(isX.x + isX.y + isX.z, 1. - isX.x, 1. - isX.y, 1. - isX.z); 259 | // i0.y += dot(isYZ.xy, vec2(1.0)); 260 | i0.y += isYZ.x + isYZ.y; 261 | //i0.zw += 1.0 - tvec2(isYZ.x, isYZ.y); 262 | i0.z += 1. - isYZ.x; 263 | i0.w += 1. - isYZ.y; 264 | i0.z += isYZ.z; 265 | i0.w += 1. - isYZ.z; 266 | 267 | // i0 now contains the unique values 0,1,2,3 in each channel 268 | let i3 = clamp_s(i0, 0., 1.); 269 | let i2 = clamp_s(i0 - 1., 0., 1.); 270 | let i1 = clamp_s(i0 - 2., 0., 1.); 271 | 272 | // x0 = x0 - 0.0 + 0.0 * C.xxxx 273 | // x1 = x0 - i1 + 0.0 * C.xxxx 274 | // x2 = x0 - i2 + 0.0 * C.xxxx 275 | // x3 = x0 - i3 + 0.0 * C.xxxx 276 | // x4 = x0 - 1.0 + 4.0 * C.xxxx 277 | let x1 = x0 - i1 + C.x; 278 | let x2 = x0 - i2 + C.y; 279 | let x3 = x0 - i3 + C.z; 280 | let x4 = x0 + C.w; 281 | 282 | // Permutations 283 | i = mod_s(i, 289.); 284 | let j0 = permute(permute(permute(permute(i.w) + i.z) + i.y) + i.x); 285 | let j1 = permute( 286 | permute( 287 | permute( 288 | permute(vec4(i1.w, i2.w, i3.w, 1.) + i.w) + vec4(i1.z, i2.z, i3.z, 1.) + i.z, 289 | ) + vec4(i1.y, i2.y, i3.y, 1.) 290 | + i.y, 291 | ) + vec4(i1.x, i2.x, i3.x, 1.) 292 | + i.x, 293 | ); 294 | 295 | // Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope 296 | // 7*7*6 = 294, which is close to the ring size 17*17 = 289. 297 | let ip = vec4(1. / 294., 1. / 49., 1. / 7., 0.); 298 | 299 | let mut p0 = grad4(j0, ip); 300 | let mut p1 = grad4(j1.x, ip); 301 | let mut p2 = grad4(j1.y, ip); 302 | let mut p3 = grad4(j1.z, ip); 303 | let mut p4 = grad4(j1.w, ip); 304 | 305 | // Normalise gradients 306 | let norm = taylor_inv_sqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); 307 | p0 = p0 * norm.x; 308 | p1 = p1 * norm.y; 309 | p2 = p2 * norm.z; 310 | p3 = p3 * norm.w; 311 | p4 = p4 * taylor_inv_sqrt(dot(p4, p4)); 312 | 313 | // Mix contributions from the five corners 314 | let mut m0 = max_s( 315 | vec3(0.6, 0.6, 0.6) - vec3(dot(x0, x0), dot(x1, x1), dot(x2, x2)), 316 | 0., 317 | ); 318 | let mut m1 = max_s(vec2(0.6, 0.6) - vec2(dot(x3, x3), dot(x4, x4)), 0.); 319 | m0 = m0 * m0; 320 | m1 = m1 * m1; 321 | 322 | dot(m0 * m0, vec3(dot(p0, x0), dot(p1, x1), dot(p2, x2))) 323 | + dot(m1 * m1, vec2(dot(p3, x3), dot(p4, x4))) * 49. 324 | } 325 | } 326 | 327 | /// Returns a 1D noise value based on the input value `x`. 328 | #[inline] 329 | pub fn noise1(x: T) -> f32 { 330 | x.noise1() 331 | } 332 | 333 | /// Returns a 2D noise value based on the input value `x`. 334 | #[inline] 335 | pub fn noise2(x: T) -> Vec2 { 336 | vec2(x.noise1(), (-x).noise1()) 337 | } 338 | 339 | /// Returns a 3D noise value based on the input value `x`. 340 | #[inline] 341 | pub fn noise3(x: T) -> Vec3 { 342 | let yi = T::one(); 343 | vec3((x - yi).noise1(), x.noise1(), (x + yi).noise1()) 344 | } 345 | 346 | /// Returns a 4D noise value based on the input value `x`. 347 | #[inline] 348 | pub fn noise4(x: T) -> Vec4 { 349 | let yi = T::one(); 350 | vec4( 351 | (x - yi).noise1(), 352 | x.noise1(), 353 | (x + yi).noise1(), 354 | (x + yi + yi).noise1(), 355 | ) 356 | } 357 | 358 | #[cfg(test)] 359 | mod test {} 360 | -------------------------------------------------------------------------------- /src/vec/vec.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | use core::cmp::Eq; 25 | use core::mem; 26 | use core::ops::{ 27 | Add, AddAssign, BitAnd, BitOr, BitXor, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, 28 | Not, Rem, Shl, Shr, Sub, SubAssign, 29 | }; 30 | 31 | use num_traits::{Float, One, Zero}; 32 | #[cfg(feature = "wrapping_ops")] 33 | use num_traits::{WrappingAdd, WrappingMul, WrappingSub}; 34 | #[cfg(test)] 35 | use quickcheck::{Arbitrary, Gen}; 36 | 37 | use crate::basenum::*; 38 | use crate::traits::*; 39 | 40 | use super::traits::{GenBVec, GenFloatVec, GenNumVec, GenVec}; 41 | 42 | // copied from `cgmath-rs/src/vector.rs`. 43 | macro_rules! fold( 44 | ($m: ident, { $x: expr, $y: expr }) => { 45 | $x.$m($y) 46 | }; 47 | ($m: ident, { $x: expr, $y: expr, $z: expr }) => { 48 | $x.$m($y).$m($z) 49 | }; 50 | ($m: ident, { $x: expr, $y: expr, $z: expr, $w: expr }) => { 51 | $x.$m($y).$m($z).$m($w) 52 | }; 53 | ); 54 | 55 | macro_rules! def_genvec( 56 | ( 57 | $t: ident, // name of the type to be defined, 58 | $n: expr, // dimension (2, 3, or 4), 59 | $($field: ident),+ // list of field names (e.g., "x, y, z"). 60 | ) => { 61 | #[repr(C)] 62 | #[derive(Copy, Clone, PartialEq, Debug)] 63 | pub struct $t { 64 | $(pub $field: T),+ 65 | } 66 | 67 | impl $t { 68 | #[inline(always)] 69 | pub fn new($($field: T),+) -> $t { 70 | $t { $($field: $field),+ } 71 | } 72 | #[inline(always)] 73 | pub fn from_array(ary: &[T; $n]) -> &$t { 74 | let r: &$t = unsafe { mem::transmute(ary) }; 75 | r 76 | } 77 | #[inline(always)] 78 | pub fn from_array_mut(ary: &mut [T; $n]) -> &mut $t { 79 | let r: &mut $t = unsafe { mem::transmute(ary) }; 80 | r 81 | } 82 | #[inline(always)] 83 | pub fn as_array(&self) -> &[T; $n] { 84 | let ary: &[T; $n] = unsafe { mem::transmute(self) }; 85 | ary 86 | } 87 | #[inline(always)] 88 | pub fn as_array_mut(&mut self) -> &mut [T; $n] { 89 | let ary: &mut [T; $n] = unsafe { mem::transmute(self) }; 90 | ary 91 | } 92 | } 93 | impl GenVec for $t { 94 | #[inline(always)] 95 | fn dim() -> usize { $n } 96 | } 97 | impl Index for $t { 98 | type Output = T; 99 | #[inline(always)] 100 | fn index<'a>(&'a self, i: usize) -> &'a T { 101 | self.as_array().index(i) 102 | } 103 | } 104 | impl IndexMut for $t { 105 | #[inline(always)] 106 | fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut T { 107 | self.as_array_mut().index_mut(i) 108 | } 109 | } 110 | #[cfg(test)] 111 | impl Arbitrary for $t { 112 | fn arbitrary(g: &mut Gen) -> $t { 113 | $t {$($field: ::arbitrary(g)),+} 114 | } 115 | } 116 | impl Eq for $t {} 117 | impl GenBType for $t {} 118 | impl GenBVec for $t { 119 | #[inline(always)] 120 | fn all(&self) -> bool { 121 | $(self.$field) && + 122 | } 123 | #[inline(always)] 124 | fn any(&self) -> bool { 125 | $(self.$field) || + 126 | } 127 | #[inline(always)] 128 | fn not(&self) -> $t { 129 | $t::new($(!self.$field),+) 130 | } 131 | } 132 | impl Add<$t> for $t { 133 | type Output = $t; 134 | #[inline(always)] 135 | fn add(self, rhs: $t) -> $t { 136 | $t::new($(self.$field + rhs.$field),+) 137 | } 138 | } 139 | impl Add for $t { 140 | type Output = $t; 141 | #[inline(always)] 142 | fn add(self, rhs: T) -> $t { 143 | $t::new($(self.$field + rhs),+) 144 | } 145 | } 146 | #[cfg(feature="wrapping_ops")] 147 | impl AddAssign<$t> for $t { 148 | fn add_assign(&mut self, rhs: $t) { 149 | $( self.$field = self.$field + rhs.$field; )+ 150 | } 151 | } 152 | #[cfg(feature="wrapping_ops")] 153 | impl AddAssign for $t { 154 | fn add_assign(&mut self, rhs: f32) { 155 | $( self.$field = self.$field + rhs; )+ 156 | } 157 | } 158 | #[cfg(feature="wrapping_ops")] 159 | impl AddAssign<$t> for $t { 160 | fn add_assign(&mut self, rhs: $t) { 161 | $( self.$field = self.$field + rhs.$field; )+ 162 | } 163 | } 164 | #[cfg(feature="wrapping_ops")] 165 | impl AddAssign for $t { 166 | fn add_assign(&mut self, rhs: f64) { 167 | $( self.$field = self.$field + rhs; )+ 168 | } 169 | } 170 | #[cfg(feature="wrapping_ops")] 171 | impl> AddAssign<$t> for $t { 172 | fn add_assign(&mut self, rhs: $t) { 173 | $( self.$field = self.$field.wrapping_add(&rhs.$field); )+ 174 | } 175 | } 176 | #[cfg(feature="wrapping_ops")] 177 | impl> AddAssign for $t { 178 | fn add_assign(&mut self, rhs: T) { 179 | $( self.$field = self.$field.wrapping_add(&rhs); )+ 180 | } 181 | } 182 | #[cfg(not(feature="wrapping_ops"))] 183 | impl AddAssign<$t> for $t { 184 | #[inline(always)] 185 | fn add_assign(&mut self, rhs: $t) { 186 | $( self.$field = self.$field + rhs.$field; )+ 187 | } 188 | } 189 | #[cfg(not(feature="wrapping_ops"))] 190 | impl AddAssign for $t { 191 | #[inline(always)] 192 | fn add_assign(&mut self, rhs: T) { 193 | $( self.$field = self.$field + rhs; )+ 194 | } 195 | } 196 | impl Mul<$t> for $t { 197 | type Output = $t; 198 | #[inline(always)] 199 | fn mul(self, rhs: $t) -> $t { 200 | $t::new($(self.$field * rhs.$field),+) 201 | } 202 | } 203 | impl Mul for $t { 204 | type Output = $t; 205 | #[inline(always)] 206 | fn mul(self, rhs: T) -> $t { 207 | $t::new($(self.$field * rhs),+) 208 | } 209 | } 210 | #[cfg(feature="wrapping_ops")] 211 | impl MulAssign<$t> for $t { 212 | fn mul_assign(&mut self, rhs: $t) { 213 | $( self.$field = self.$field * rhs.$field; )+ 214 | } 215 | } 216 | #[cfg(feature="wrapping_ops")] 217 | impl MulAssign for $t { 218 | fn mul_assign(&mut self, rhs: f32) { 219 | $( self.$field = self.$field * rhs; )+ 220 | } 221 | } 222 | #[cfg(feature="wrapping_ops")] 223 | impl MulAssign<$t> for $t { 224 | fn mul_assign(&mut self, rhs: $t) { 225 | $( self.$field = self.$field * rhs.$field; )+ 226 | } 227 | } 228 | #[cfg(feature="wrapping_ops")] 229 | impl MulAssign for $t { 230 | fn mul_assign(&mut self, rhs: f64) { 231 | $( self.$field = self.$field * rhs; )+ 232 | } 233 | } 234 | #[cfg(feature="wrapping_ops")] 235 | impl> MulAssign<$t> for $t { 236 | fn mul_assign(&mut self, rhs: $t) { 237 | $( self.$field = self.$field.wrapping_mul(&rhs.$field); )+ 238 | } 239 | } 240 | #[cfg(feature="wrapping_ops")] 241 | impl> MulAssign for $t { 242 | fn mul_assign(&mut self, rhs: T) { 243 | $( self.$field = self.$field.wrapping_mul(&rhs); )+ 244 | } 245 | } 246 | #[cfg(not(feature="wrapping_ops"))] 247 | impl MulAssign<$t> for $t { 248 | #[inline(always)] 249 | fn mul_assign(&mut self, rhs: $t) { 250 | $( self.$field = self.$field * rhs.$field; )+ 251 | } 252 | } 253 | #[cfg(not(feature="wrapping_ops"))] 254 | impl MulAssign for $t { 255 | #[inline(always)] 256 | fn mul_assign(&mut self, rhs: T) { 257 | $( self.$field = self.$field * rhs; )+ 258 | } 259 | } 260 | impl Div<$t> for $t { 261 | type Output = $t; 262 | #[inline(always)] 263 | fn div(self, rhs: $t) -> $t { 264 | $t::new($(self.$field / rhs.$field),+) 265 | } 266 | } 267 | impl Div for $t { 268 | type Output = $t; 269 | #[inline(always)] 270 | fn div(self, rhs: T) -> $t { 271 | $t::new($(self.$field / rhs),+) 272 | } 273 | } 274 | impl DivAssign<$t> for $t { 275 | #[inline(always)] 276 | fn div_assign(&mut self, rhs: $t) { 277 | $( self.$field = self.$field / rhs.$field; )+ 278 | } 279 | } 280 | impl DivAssign for $t { 281 | #[inline(always)] 282 | fn div_assign(&mut self, rhs: T) { 283 | $( self.$field = self.$field / rhs; )+ 284 | } 285 | } 286 | impl Rem<$t> for $t { 287 | type Output = $t; 288 | #[inline(always)] 289 | fn rem(self, rhs: $t) -> $t { 290 | $t::new($(self.$field % rhs.$field),+) 291 | } 292 | } 293 | impl Rem for $t { 294 | type Output = $t; 295 | #[inline(always)] 296 | fn rem(self, rhs: T) -> $t { 297 | $t::new($(self.$field % rhs),+) 298 | } 299 | } 300 | impl One for $t { 301 | #[inline(always)] 302 | fn one() -> $t { 303 | let y = T::one(); 304 | $t { $($field: y),+ } 305 | } 306 | } 307 | impl Zero for $t { 308 | #[inline(always)] 309 | fn zero() -> $t { 310 | let l = T::zero(); 311 | $t { $($field: l),+ } 312 | } 313 | #[inline] 314 | fn is_zero(&self) -> bool { 315 | let l = T::zero(); 316 | $(self.$field == l) && + 317 | } 318 | } 319 | impl GenNum for $t { 320 | #[inline(always)] 321 | fn from_s(x: T) -> Self { 322 | $t { $($field: x),+ } 323 | } 324 | #[inline(always)] 325 | fn map T>(self, f: F) -> $t { 326 | $t::new($(f(self.$field)),+) 327 | } 328 | #[inline(always)] 329 | fn zip T>(self, y: $t, f: F) -> $t { 330 | $t::new($(f(self.$field, y.$field)),+) 331 | } 332 | #[inline] 333 | fn split (T, T)>(self, f: F) -> ($t, $t) { 334 | let ling = $t::::zero(); 335 | let mut a = ling; 336 | let mut b = ling; 337 | let dim = $t::::dim(); 338 | for i in 0..dim { 339 | let (c, d) = f(self[i]); 340 | a[i] = c; 341 | b[i] = d; 342 | } 343 | (a, b) 344 | } 345 | #[inline] 346 | fn map2 (T, T)>(self, y: Self, f: F) -> (Self, Self) { 347 | let ling = Self::zero(); 348 | let mut a = ling; 349 | let mut b = ling; 350 | let dim = Self::dim(); 351 | for i in 0..dim { 352 | let (c, d) = f(self[i], y[i]); 353 | a[i] = c; 354 | b[i] = d; 355 | } 356 | (a, b) 357 | } 358 | } 359 | impl GenNumVec for $t { 360 | #[inline(always)] 361 | fn sum(&self) -> T { 362 | fold!(add, { $(self.$field),+ }) 363 | } 364 | #[inline(always)] 365 | fn product(&self) -> T { 366 | fold!(mul, { $(self.$field),+ }) 367 | } 368 | #[inline(always)] 369 | fn min(&self) -> T { 370 | fold!(min, { $(self.$field),+ }) 371 | } 372 | #[inline(always)] 373 | fn max(&self) -> T { 374 | fold!(max, { $(self.$field),+ }) 375 | } 376 | } 377 | impl Neg for $t { 378 | type Output = $t; 379 | #[inline] 380 | fn neg(self) -> $t { 381 | $t::new($(-(self.$field)),+) 382 | } 383 | } 384 | impl Sub<$t> for $t { 385 | type Output = $t; 386 | #[inline(always)] 387 | fn sub(self, rhs: $t) -> $t { 388 | $t::new($(self.$field - rhs.$field),+) 389 | } 390 | } 391 | impl Sub for $t { 392 | type Output = $t; 393 | #[inline(always)] 394 | fn sub(self, rhs: T) -> $t { 395 | $t::new($(self.$field - rhs),+) 396 | } 397 | } 398 | #[cfg(feature="wrapping_ops")] 399 | impl SubAssign<$t> for $t { 400 | fn sub_assign(&mut self, rhs: $t) { 401 | $( self.$field = self.$field - rhs.$field; )+ 402 | } 403 | } 404 | #[cfg(feature="wrapping_ops")] 405 | impl SubAssign for $t { 406 | fn sub_assign(&mut self, rhs: f32) { 407 | $( self.$field = self.$field - rhs; )+ 408 | } 409 | } 410 | #[cfg(feature="wrapping_ops")] 411 | impl SubAssign<$t> for $t { 412 | fn sub_assign(&mut self, rhs: $t) { 413 | $( self.$field = self.$field - rhs.$field; )+ 414 | } 415 | } 416 | #[cfg(feature="wrapping_ops")] 417 | impl SubAssign for $t { 418 | fn sub_assign(&mut self, rhs: f64) { 419 | $( self.$field = self.$field - rhs; )+ 420 | } 421 | } 422 | #[cfg(feature="wrapping_ops")] 423 | impl> SubAssign<$t> for $t { 424 | fn sub_assign(&mut self, rhs: $t) { 425 | $( self.$field = self.$field.wrapping_sub(&rhs.$field); )+ 426 | } 427 | } 428 | #[cfg(feature="wrapping_ops")] 429 | impl> SubAssign for $t { 430 | fn sub_assign(&mut self, rhs: T) { 431 | $( self.$field = self.$field.wrapping_sub(&rhs); )+ 432 | } 433 | } 434 | #[cfg(not(feature="wrapping_ops"))] 435 | impl SubAssign<$t> for $t { 436 | #[inline(always)] 437 | fn sub_assign(&mut self, rhs: $t) { 438 | $( self.$field = self.$field - rhs.$field; )+ 439 | } 440 | } 441 | #[cfg(not(feature="wrapping_ops"))] 442 | impl SubAssign for $t { 443 | #[inline(always)] 444 | fn sub_assign(&mut self, rhs: T) { 445 | $( self.$field = self.$field * rhs; )+ 446 | } 447 | } 448 | impl SignedNum for $t { 449 | #[inline] 450 | fn abs(&self) -> $t { 451 | $t::new($(self.$field.abs()),+) 452 | } 453 | #[inline] 454 | fn sign(&self) -> $t { 455 | $t::new($(self.$field.sign()),+) 456 | } 457 | } 458 | impl Eq for $t {} 459 | impl Not for $t { 460 | type Output = Self; 461 | #[inline] 462 | fn not(self) -> Self { 463 | $t::new($(!self.$field),+) 464 | } 465 | } 466 | impl BitAnd for $t { 467 | type Output = Self; 468 | #[inline] 469 | fn bitand(self, rhs: T) -> Self { 470 | $t::new($(self.$field & rhs),+) 471 | } 472 | } 473 | impl BitAnd<$t> for $t { 474 | type Output = Self; 475 | #[inline] 476 | fn bitand(self, rhs: Self) -> Self { 477 | $t::new($(self.$field & rhs.$field),+) 478 | } 479 | } 480 | impl BitOr for $t { 481 | type Output = Self; 482 | #[inline] 483 | fn bitor(self, rhs: T) -> Self { 484 | $t::new($(self.$field | rhs),+) 485 | } 486 | } 487 | impl BitOr<$t> for $t { 488 | type Output = Self; 489 | #[inline] 490 | fn bitor(self, rhs: Self) -> Self { 491 | $t::new($(self.$field | rhs.$field),+) 492 | } 493 | } 494 | impl BitXor for $t { 495 | type Output = Self; 496 | #[inline] 497 | fn bitxor(self, rhs: T) -> Self { 498 | $t::new($(self.$field ^ rhs),+) 499 | } 500 | } 501 | impl BitXor<$t> for $t { 502 | type Output = Self; 503 | #[inline] 504 | fn bitxor(self, rhs: Self) -> Self { 505 | $t::new($(self.$field ^ rhs.$field),+) 506 | } 507 | } 508 | impl Shl for $t { 509 | type Output = Self; 510 | #[inline] 511 | fn shl(self, rhs: usize) -> Self { 512 | $t::new($(self.$field << rhs),+) 513 | } 514 | } 515 | impl Shr for $t { 516 | type Output = Self; 517 | #[inline] 518 | fn shr(self, rhs: usize) -> Self { 519 | $t::new($(self.$field >> rhs),+) 520 | } 521 | } 522 | impl GenInt for $t {} 523 | impl GenIType for $t {} 524 | impl GenUType for $t {} 525 | impl ApproxEq for $t { 526 | type BaseType = T; 527 | #[inline] 528 | fn is_close_to(&self, rhs: &$t, max_diff: T) -> bool { 529 | $(self.$field.is_close_to(&rhs.$field, max_diff)) && + 530 | } 531 | } 532 | impl GenFloat for $t { 533 | fn fma(&self, b: &$t, c: &$t) -> $t { 534 | $t::new($(Float::mul_add(self.$field, b.$field, c.$field)),+) 535 | } 536 | } 537 | impl GenFloatVec for $t {} 538 | impl GenType for $t {} 539 | impl GenDType for $t {} 540 | } 541 | ); 542 | 543 | def_genvec! { Vector2, 2, x, y } 544 | def_genvec! { Vector3, 3, x, y, z } 545 | def_genvec! { Vector4, 4, x, y, z, w } 546 | 547 | impl Vector2 { 548 | /// Extends _self_ to a `Vector3` by appending `z`. 549 | /// 550 | /// # Example 551 | /// 552 | /// ```rust 553 | /// use glm::*; 554 | /// 555 | /// let v2 = vec2(1., 2.); 556 | /// let v3 = vec3(1., 2., 3.); 557 | /// assert_eq!(v2.extend(3.), v3); 558 | /// ``` 559 | #[inline] 560 | pub fn extend(&self, z: T) -> Vector3 { 561 | Vector3 { 562 | x: self.x, 563 | y: self.y, 564 | z, 565 | } 566 | } 567 | } 568 | 569 | impl Vector3 { 570 | /// Extends _self_ to a `Vector4` by appending `w`. 571 | /// 572 | /// # Example 573 | /// 574 | /// ```rust 575 | /// use glm::*; 576 | /// 577 | /// let v3 = vec3(1., 2., 3.); 578 | /// let v4 = vec4(1., 2., 3., 4.); 579 | /// assert_eq!(v3.extend(4.), v4); 580 | /// ``` 581 | #[inline] 582 | pub fn extend(&self, w: T) -> Vector4 { 583 | Vector4 { 584 | x: self.x, 585 | y: self.y, 586 | z: self.z, 587 | w: w, 588 | } 589 | } 590 | 591 | /// Truncates _self_ to a `Vector2` by remove the `i`th element. 592 | /// 593 | /// Parameter `i` is `0` based index. 594 | /// 595 | /// # Panic 596 | /// 597 | /// It is a panic if i is larger than `2`. 598 | /// 599 | /// # Example 600 | /// 601 | /// ```rust 602 | /// use glm::*; 603 | /// 604 | /// let v3 = vec3(1., 2., 3.); 605 | /// let v2 = vec2(1., 3.); 606 | /// assert_eq!(v3.truncate(1), v2); 607 | /// ``` 608 | #[inline] 609 | pub fn truncate(&self, i: usize) -> Vector2 { 610 | match i { 611 | 0 => Vector2::new(self.y, self.z), 612 | 1 => Vector2::new(self.x, self.z), 613 | 2 => Vector2::new(self.x, self.y), 614 | _ => panic!("parameter i is out of range [{:?} > 2].", i), 615 | } 616 | } 617 | } 618 | 619 | impl Vector3 { 620 | pub fn combine(a: &Self, b: &Self, a_scale: T, b_scale: T) -> Self { 621 | *a * a_scale + *b * b_scale 622 | } 623 | 624 | pub fn scale(v: &Self, desired_length: T) -> Self { 625 | *v * desired_length / crate::length(*v) 626 | } 627 | } 628 | 629 | impl Vector4 { 630 | /// Truncates _self_ to a `Vector3` by remove the `i`th element. 631 | /// 632 | /// Parameter `i` is `0` based index. 633 | /// 634 | /// # Panic 635 | /// 636 | /// It is a panic if i is larger than `3`. 637 | #[inline] 638 | pub fn truncate(&self, i: usize) -> Vector3 { 639 | match i { 640 | 0 => Vector3::new(self.y, self.z, self.w), 641 | 1 => Vector3::new(self.x, self.z, self.w), 642 | 2 => Vector3::new(self.x, self.y, self.w), 643 | 3 => Vector3::new(self.x, self.y, self.z), 644 | _ => panic!("parameter i is out of range [{:?} > 3].", i), 645 | } 646 | } 647 | } 648 | 649 | macro_rules! def_alias( 650 | ( 651 | $({ 652 | $a: ident, // type alias (e.g., Vec2 for Vector2), 653 | $t: ident, // type to be aliased, 654 | $et: ty, // element type, 655 | $ctor: ident, // constructor name (e.g., vec3), 656 | $($field: ident),+ // fields, 657 | }),+ 658 | ) => { 659 | $( 660 | pub type $a = $t<$et>; 661 | #[inline(always)] 662 | pub const fn $ctor($($field: $et),+) -> $t<$et> { 663 | $t { $($field: $field),+ } 664 | } 665 | )+ 666 | } 667 | ); 668 | 669 | def_alias! { 670 | { BVec2, Vector2, bool, bvec2, x, y }, 671 | { BVec3, Vector3, bool, bvec3, x, y, z }, 672 | { BVec4, Vector4, bool, bvec4, x, y, z, w }, 673 | 674 | { Vec2, Vector2, f32, vec2, x, y }, 675 | { Vec3, Vector3, f32, vec3, x, y, z }, 676 | { Vec4, Vector4, f32, vec4, x, y, z, w }, 677 | 678 | { DVec2, Vector2, f64, dvec2, x, y }, 679 | { DVec3, Vector3, f64, dvec3, x, y, z }, 680 | { DVec4, Vector4, f64, dvec4, x, y, z, w }, 681 | 682 | { IVec2, Vector2, i32, ivec2, x, y }, 683 | { IVec3, Vector3, i32, ivec3, x, y, z }, 684 | { IVec4, Vector4, i32, ivec4, x, y, z, w }, 685 | 686 | { UVec2, Vector2, u32, uvec2, x, y }, 687 | { UVec3, Vector3, u32, uvec3, x, y, z }, 688 | { UVec4, Vector4, u32, uvec4, x, y, z, w } 689 | } 690 | 691 | #[cfg(test)] 692 | mod test { 693 | use super::*; 694 | use quickcheck::*; 695 | 696 | #[test] 697 | fn test_as_array() { 698 | fn prop(v3: IVec3) -> bool { 699 | let ary: &[i32; 3] = v3.as_array(); 700 | ary[0] == v3.x && ary[1] == v3.y && ary[2] == v3.z 701 | } 702 | quickcheck(prop as fn(IVec3) -> bool); 703 | } 704 | 705 | #[test] 706 | fn test_as_array_mut() { 707 | fn prop(v2: DVec2) -> TestResult { 708 | let DVec2 { x, y } = v2; 709 | let mut v = v2; 710 | let ary: &mut [f64; 2] = v.as_array_mut(); 711 | if ary.iter().any(|f| !f.is_normal()) { 712 | return TestResult::discard(); 713 | } 714 | ary[0] = x + 1.; 715 | ary[1] = y * 2.; 716 | TestResult::from_bool((x + 1.) == v.x && (y * 2.) == v.y) 717 | } 718 | quickcheck(prop as fn(DVec2) -> TestResult) 719 | } 720 | 721 | #[test] 722 | fn test_index() { 723 | fn prop(v3: IVec3) -> bool { 724 | v3[0] == v3.x && v3[1] == v3.y && v3[2] == v3.z 725 | } 726 | quickcheck(prop as fn(IVec3) -> bool); 727 | } 728 | 729 | #[test] 730 | fn test_index_mut() { 731 | fn prop(iv: Vec3) -> TestResult { 732 | let mut miv = iv; 733 | if miv.as_array().iter().any(|f| !f.is_normal()) { 734 | return TestResult::discard(); 735 | } 736 | miv[0] = iv.x + 1.0; 737 | miv[1] = iv.y + 1.0; 738 | miv[2] = iv.z + 1.0; 739 | TestResult::from_bool(miv == iv + num_traits::one::()) 740 | } 741 | quickcheck(prop as fn(Vec3) -> TestResult); 742 | } 743 | } 744 | -------------------------------------------------------------------------------- /src/builtin/common.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015, 2025 The glm-rs authors. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | // The GLSL Specification, ch 8.3, Common Functions. 25 | 26 | use core::mem; 27 | use core::ops::Rem; 28 | 29 | use num_traits::{Float, Zero}; 30 | 31 | use crate::basenum::*; 32 | use crate::traits::*; 33 | use crate::vec::traits::{GenFloatVec, GenNumVec, GenVec}; 34 | use crate::vec::vec::{Vector2, Vector3, Vector4}; 35 | 36 | pub trait FloatIntRel>: GenFloat { 37 | // float -> int 38 | fn map_int I>(&self, fun: F) -> GI; 39 | // (float) -> (float, int) 40 | fn split_int (E, I)>(&self, fun: F) -> (Self, GI); 41 | } 42 | 43 | pub trait IntFloatRel>: GenInt { 44 | // int -> float 45 | fn map_flt E>(&self, fun: F) -> GF; 46 | // (int, float) -> float 47 | fn zip_flt E>(&self, f: &GF, fun: F) -> GF; 48 | } 49 | 50 | pub trait NumBoolRel: GenNum { 51 | // num -> bool 52 | fn map_bool bool>(&self, fun: F) -> B; 53 | // (num, bool) -> num 54 | fn zip_bool N>(&self, b: &B, fun: F) -> Self; 55 | } 56 | 57 | macro_rules! impl_scalar_FloatIntRel { 58 | ($($t: ident),+) => { 59 | $( 60 | impl> FloatIntRel<$t, I, I> for $t { 61 | #[inline(always)] 62 | fn map_int I>(&self, fun: F) -> I { 63 | fun(*self) 64 | } 65 | #[inline(always)] 66 | fn split_int ($t, I)>(&self, fun: F) -> ($t, I) { 67 | fun(*self) 68 | } 69 | } 70 | )+ 71 | } 72 | } 73 | 74 | impl_scalar_FloatIntRel! { f32, f64 } 75 | 76 | macro_rules! impl_vec_FloatIntRel { 77 | ($({ $t: ident, $($field: ident),+ }),+) => { 78 | $( 79 | impl FloatIntRel> for $t { 80 | #[inline] 81 | fn map_int I>(&self, fun: F) -> $t { 82 | $t::new($(fun(self.$field)),+) 83 | } 84 | #[inline] 85 | fn split_int (E, I)>(&self, fun: F) -> ($t, $t) { 86 | let mut f = $t::::zero(); 87 | let mut i = $t::::zero(); 88 | let dim = $t::::dim(); 89 | for j in 0..dim { 90 | let (a, b) = fun(self[j]); 91 | f[j] = a; 92 | i[j] = b; 93 | } 94 | (f, i) 95 | } 96 | } 97 | )+ 98 | } 99 | } 100 | 101 | impl_vec_FloatIntRel! { 102 | { Vector2, x, y }, 103 | { Vector3, x, y, z }, 104 | { Vector4, x, y, z, w } 105 | } 106 | 107 | macro_rules! impl_scalar_IntFloatRel { 108 | ($($t: ident),+) => { 109 | $( 110 | impl> IntFloatRel<$t, E, E> for $t { 111 | #[inline] 112 | fn map_flt E>(&self, fun: F) -> E { 113 | fun(*self) 114 | } 115 | #[inline] 116 | fn zip_flt E>(&self, f: &E, fun: F) -> E { 117 | fun(*self, *f) 118 | } 119 | } 120 | )+ 121 | } 122 | } 123 | 124 | impl_scalar_IntFloatRel! { i32, u32 } 125 | 126 | macro_rules! impl_vec_IntFloatRel { 127 | ($({ $t: ident, $($field: ident),+ }),+) => { 128 | $( 129 | impl IntFloatRel> for $t { 130 | #[inline] 131 | fn map_flt E>(&self, fun: F) -> $t { 132 | $t::new($(fun(self.$field)),+) 133 | } 134 | #[inline] 135 | fn zip_flt E>(&self, f: &$t, fun: F) -> $t { 136 | $t::new($(fun(self.$field, f.$field)),+) 137 | } 138 | } 139 | )+ 140 | } 141 | } 142 | 143 | impl_vec_IntFloatRel! { 144 | { Vector2, x, y }, 145 | { Vector3, x, y, z }, 146 | { Vector4, x, y, z, w } 147 | } 148 | 149 | macro_rules! impl_scalar_NumBoolRel { 150 | ($($t: ident),+) => { 151 | $( 152 | impl NumBoolRel<$t, bool> for $t { 153 | #[inline] 154 | fn map_bool bool>(&self, fun: F) -> bool { 155 | fun(*self) 156 | } 157 | #[inline] 158 | fn zip_bool $t>(&self, b: &bool, fun: F) -> $t { 159 | fun(*self, *b) 160 | } 161 | } 162 | )+ 163 | } 164 | } 165 | 166 | impl_scalar_NumBoolRel! { i32, u32, f32, f64 } 167 | 168 | macro_rules! impl_vec_NumBoolRel { 169 | ($({ $t: ident, $($field: ident),+ }),+) => { 170 | $( 171 | impl NumBoolRel> for $t { 172 | #[inline] 173 | fn map_bool bool>(&self, fun: F) -> $t { 174 | $t::new($(fun(self.$field)),+) 175 | } 176 | #[inline] 177 | fn zip_bool N>(&self, b: &$t, fun: F) -> $t { 178 | $t::new($(fun(self.$field, b.$field)),+) 179 | } 180 | } 181 | )+ 182 | } 183 | } 184 | 185 | impl_vec_NumBoolRel! { 186 | { Vector2, x, y }, 187 | { Vector3, x, y, z }, 188 | { Vector4, x, y, z, w } 189 | } 190 | 191 | /// Returns `x` if `x ≥ 0`, otherwise it returns `–x`. 192 | /// 193 | /// # Example 194 | /// 195 | /// ``` 196 | /// use glm::{ abs, dvec4, SignedNum }; 197 | /// 198 | /// assert_eq!(abs(-1_f32), 1.); 199 | /// let v4 = dvec4(0., 100., -2., -3.); 200 | /// assert_eq!(abs(v4), v4.abs()); 201 | /// assert_eq!(abs(v4), dvec4(0., 100., 2., 3.)); 202 | /// ``` 203 | #[inline(always)] 204 | pub fn abs>(x: T) -> T { 205 | x.map(|s: S| SignedNum::abs(&s)) 206 | } 207 | 208 | /// Returns `1.0` if `x > 0`, `0.0` if `x = 0`, or `–1.0` if `x < 0`. 209 | /// 210 | /// # Example 211 | /// 212 | /// ``` 213 | /// use glm::{ sign, vec3 }; 214 | /// 215 | /// assert_eq!(sign(-0_f32), 0.); 216 | /// assert_eq!(sign(vec3(-100., 2., 0.)), vec3(-1., 1., 0.)); 217 | /// ``` 218 | #[inline(always)] 219 | pub fn sign>(x: T) -> T { 220 | x.map(|s: S| SignedNum::sign(&s)) 221 | } 222 | 223 | /// Returns a value equal to the nearest integer that is less than or 224 | /// equal to `x`. 225 | /// 226 | /// # Example 227 | /// 228 | /// ``` 229 | /// assert_eq!(glm::floor(-3.14_f32), -4.); 230 | /// assert_eq!(glm::floor(glm::vec3(-1.7, 4., 4.9)), glm::vec3(-2., 4., 4.)); 231 | /// ``` 232 | #[inline(always)] 233 | pub fn floor>(x: T) -> T { 234 | x.map(Float::floor) 235 | } 236 | 237 | /// Returns a value equal to the nearest integer to `x` whose absolute value 238 | /// is not larger than the absolute value of `x`. 239 | /// 240 | /// # Example 241 | /// 242 | /// ``` 243 | /// assert_eq!(glm::trunc(-3.14_f32), -3.); 244 | /// assert_eq!(glm::trunc(glm::vec3(-1.7, 4., 4.9)), glm::vec3(-1., 4., 4.)); 245 | /// ``` 246 | #[inline(always)] 247 | pub fn trunc>(x: T) -> T { 248 | x.map(Float::trunc) 249 | } 250 | 251 | /// Returns a value equal to the nearest integer to `x`. 252 | /// 253 | /// The fraction `0.5` will round in a direction chosen by the implementation, 254 | /// presumably the direction that is fastest. This includes the possibility 255 | /// that `round(x)` returns the same value as `roundEven(x)` for all values of 256 | /// `x`. 257 | /// 258 | /// # Example 259 | /// 260 | /// ``` 261 | /// use glm::{ round, vec3 }; 262 | /// 263 | /// assert_eq!(round(-3.14_f32), -3.); 264 | /// assert_eq!(round(vec3(-1.7, 4., 4.9)), vec3(-2., 4., 5.)); 265 | /// ``` 266 | #[inline(always)] 267 | pub fn round>(x: T) -> T { 268 | x.map(Float::round) 269 | } 270 | 271 | /// Returns a value equal to the nearest integer to `x`. 272 | /// 273 | /// A fractional part of `0.5` will round toward the nearest even integer. 274 | /// (Both `3.5` and `4.5` for x will return `4.0`.) 275 | /// 276 | /// # Example 277 | /// 278 | /// ``` 279 | /// use glm::{ roundEven, vec4 }; 280 | /// 281 | /// assert_eq!(roundEven(2.5_f32), 2.); 282 | /// assert_eq!(roundEven(1.5_f32), 2.); 283 | /// assert_eq!(roundEven(vec4(3.14, -3.14, -1.5, -2.5)), vec4(3., -3., -2., -2.)); 284 | /// ``` 285 | #[inline(always)] 286 | #[allow(non_snake_case)] 287 | pub fn roundEven>(x: T) -> T { 288 | x.map(|f| -> F { 289 | let ling = F::zero(); 290 | let yi = F::one(); 291 | let er = yi + yi; 292 | 293 | let int = f.trunc(); 294 | if f.fract().abs() != F::from(0.5).unwrap() { 295 | f.round() 296 | } else if int % er == ling { 297 | int 298 | } else if int < ling { 299 | int - yi 300 | } else { 301 | int + yi 302 | } 303 | }) 304 | } 305 | 306 | /// Returns a value equal to the nearest integer that is greater than or 307 | /// equal to `x`. 308 | /// 309 | /// # Example 310 | /// 311 | /// ``` 312 | /// use glm::{ ceil, dvec3 }; 313 | /// 314 | /// assert_eq!(ceil(-3.14_f32), -3.); 315 | /// assert_eq!(ceil(3.14_f32), 4.); 316 | /// assert_eq!(ceil(dvec3(-1.8, 1., 1.8)), dvec3(-1., 1., 2.)); 317 | /// ``` 318 | #[inline(always)] 319 | pub fn ceil>(x: T) -> T { 320 | x.map(Float::ceil) 321 | } 322 | 323 | /// Returns `x – floor(x)`. 324 | /// 325 | /// # Example 326 | /// 327 | /// ``` 328 | /// use glm::{ fract, vec2 }; 329 | /// 330 | /// assert_eq!(fract(3.25_f32), 0.25); 331 | /// assert_eq!(fract(vec2(-1.5, 1.)), vec2(-0.5, 0.)); 332 | /// ``` 333 | #[inline(always)] 334 | pub fn fract>(x: T) -> T { 335 | x.map(Float::fract) 336 | } 337 | 338 | /// Modulus. Returns `x – y ∗ floor(x/y)`. 339 | /// 340 | /// # Note 341 | /// 342 | /// Original function name `mod` is renamed to `fmod` because **mod** is 343 | /// a keyword in Rust. 344 | /// 345 | /// # Example 346 | /// 347 | /// ``` 348 | /// assert_eq!(glm::fmod(3.5_f32, 3.), 0.5); 349 | /// ``` 350 | #[inline(always)] 351 | pub fn fmod>(x: T, y: T) -> T { 352 | x.zip(y, Rem::rem) 353 | } 354 | 355 | /// Modulus with a scalar number. 356 | /// 357 | /// # Note 358 | /// 359 | /// `mod_s` is not a GLSL function name. It is a variant of original `mod` 360 | /// function and is introduced because Rust does not support function name 361 | /// overloading. 362 | /// 363 | /// # Example 364 | /// 365 | /// ``` 366 | /// use glm::{ mod_s, dvec3 }; 367 | /// 368 | /// let v = dvec3(-1.5, 1.5, 10.5); 369 | /// assert_eq!(mod_s(v, 2.), dvec3(-1.5, 1.5, 0.5)); 370 | /// ``` 371 | #[inline(always)] 372 | pub fn mod_s>(x: T, y: F) -> T { 373 | x.map(|f| -> F { f.rem(y) }) 374 | } 375 | 376 | /// Returns the fractional and integer parts of `x`. 377 | /// 378 | /// Both parts will have the same sign as `x`. 379 | /// 380 | /// # Note 381 | /// 382 | /// In GLSL, the integer part is returned via a output parameter `i`. 383 | /// In Rust we can return both parts using a tuple *(interger part, fractional part)*. 384 | /// 385 | /// # Example 386 | /// 387 | /// ``` 388 | /// use glm::{ modf, vec3 }; 389 | /// 390 | /// assert_eq!(modf(1.5_f32), (1., 0.5)); 391 | /// assert_eq!(modf(vec3(0., -1.25, 3.75)), (vec3(0., -1., 3.), vec3(0., -0.25, 0.75))); 392 | /// ``` 393 | #[inline(always)] 394 | pub fn modf>(x: T) -> (T, T) { 395 | (trunc(x), fract(x)) 396 | } 397 | 398 | /// Returns `y` if `y < x`, otherwise it returns `x`. 399 | /// 400 | /// # Example 401 | /// 402 | /// ``` 403 | /// let v1 = glm::vec2(1., 4.); 404 | /// let v2 = glm::vec2(2., 3.); 405 | /// assert_eq!(glm::min(v1, v2), glm::vec2(1., 3.)); 406 | /// ``` 407 | #[inline(always)] 408 | pub fn min>(x: T, y: T) -> T { 409 | x.zip(y, BaseNum::min) 410 | } 411 | 412 | /// A variant of function `min` that uses a scalar value as comparator. 413 | /// 414 | /// # Note 415 | /// 416 | /// `mod_s` is not a GLSL function name. 417 | /// 418 | /// # Example 419 | /// 420 | /// ``` 421 | /// let v = glm::vec2(1., 3.); 422 | /// let y = 2_f32; 423 | /// assert_eq!(glm::min_s(v, y), glm::vec2(1., 2.)); 424 | /// ``` 425 | #[inline(always)] 426 | pub fn min_s>(x: T, y: S) -> T { 427 | x.map(|c| -> S { BaseNum::min(c, y) }) 428 | } 429 | 430 | /// Returns `y` if `x < y`, otherwise it returns `x`. 431 | /// 432 | /// # Example 433 | /// 434 | /// ``` 435 | /// let v1 = glm::vec2(1., 4.); 436 | /// let v2 = glm::vec2(2., 3.); 437 | /// assert_eq!(glm::max(v1, v2), glm::vec2(2., 4.)); 438 | /// ``` 439 | #[inline(always)] 440 | pub fn max>(x: T, y: T) -> T { 441 | x.zip(y, BaseNum::max) 442 | } 443 | 444 | /// A variant of `max` that always uses a scalar value as the comparator. 445 | /// 446 | /// # Note 447 | /// 448 | /// `max_s` is not a GLSL function name. It is introduced because Rust does 449 | /// not support function name overloading. 450 | /// 451 | /// # Example 452 | /// 453 | /// ``` 454 | /// let v = glm::vec2(1., 3.); 455 | /// let y = 2_f32; 456 | /// assert_eq!(glm::max_s(v, y), glm::vec2(2., 3.)); 457 | /// ``` 458 | #[inline(always)] 459 | pub fn max_s>(x: T, y: S) -> T { 460 | x.map(|s| -> S { BaseNum::max(s, y) }) 461 | } 462 | 463 | /// Returns `min (max (x, min_val), max_val)`. 464 | /// 465 | /// # Example 466 | /// 467 | /// ``` 468 | /// use glm::{ clamp, vec3 }; 469 | /// 470 | /// assert_eq!(clamp(3.14_f32, 0., 1.), 1.); 471 | /// let v = vec3(-1., 0., 100.); 472 | /// let min = vec3(0., 0., 0.); 473 | /// let max = vec3(1., 1., 1.); 474 | /// assert_eq!(clamp(v, min, max), vec3(0., 0., 1.)); 475 | /// ``` 476 | #[inline(always)] 477 | pub fn clamp>(x: T, min_val: T, max_val: T) -> T { 478 | min(max(x, min_val), max_val) 479 | } 480 | 481 | /// A variant of function `clamp` that uses scalar values as thresholds. 482 | /// 483 | /// # Note 484 | /// 485 | /// `clamp_s` is not a GLSL function name. 486 | /// 487 | /// # Example 488 | /// 489 | /// ``` 490 | /// use glm::{ clamp_s, dvec2 }; 491 | /// 492 | /// let dv2 = dvec2(-1., 3.14); 493 | /// assert_eq!(clamp_s(dv2, 0., 1.), dvec2(0., 1.)); 494 | /// ``` 495 | #[inline(always)] 496 | pub fn clamp_s>(x: T, min_val: S, max_val: S) -> T { 497 | min_s(max_s(x, min_val), max_val) 498 | } 499 | 500 | /// Returns the linear blend of `x` and `y`, i.e., `x⋅(1−a)+y⋅a`. 501 | /// 502 | /// # Example 503 | /// 504 | /// ``` 505 | /// use glm::{ mix, vec2 }; 506 | /// 507 | /// assert_eq!(mix(0_f32, 1_f32, 0.5), 0.5); 508 | /// let x = vec2(1., 2.); 509 | /// let y = vec2(3., 4.); 510 | /// let a = vec2(0.5, 2.); 511 | /// let r = vec2(2., 6.); 512 | /// assert_eq!(mix(x, y, a), r); 513 | /// ``` 514 | #[inline(always)] 515 | pub fn mix>(x: T, y: T, a: T) -> T { 516 | let yi = T::one(); 517 | x * (yi - a) + y * a 518 | } 519 | 520 | /// A variant of function `mix` that parameter `a` is a scalar. 521 | /// 522 | /// # Note 523 | /// 524 | /// `mix_s` is not a GLSL function name. It is introduced because Rust does 525 | /// not support function name overloading. 526 | /// 527 | /// # Example 528 | /// 529 | /// ``` 530 | /// use glm::{ mix_s, dvec3 }; 531 | /// 532 | /// let x = dvec3(10., 20., 30.); 533 | /// let y = dvec3(100., 200., 300.); 534 | /// assert_eq!(mix_s(x, y, 0.5), dvec3(55., 110., 165.)); 535 | /// ``` 536 | #[inline(always)] 537 | pub fn mix_s>(x: T, y: T, a: F) -> T { 538 | let yi = F::one(); 539 | x * (yi - a) + y * a 540 | } 541 | 542 | /// Selects which vector each returned component comes from. 543 | /// 544 | /// For a component of `a` that is `false`, the corresponding component of `x` 545 | /// is returned. For a component of `a` that is `true`, the corresponding 546 | /// component of `y` is returned. Components of `x` and `y` that are not 547 | /// selected are allowed to be invalid floating point values and will have no 548 | /// effect on the results. 549 | /// 550 | /// # Note 551 | /// 552 | /// 1. `mix_bool` is not a GLSL function name. It is a variant of `mix` 553 | /// function and is introduced becasue Rust does not support function name 554 | /// overloading. 555 | /// 1. This function works for scalar types too. 556 | /// 557 | /// # Example 558 | /// 559 | /// ``` 560 | /// use glm::{ bvec4, dvec4, mix_bool }; 561 | /// 562 | /// let a = bvec4(true, false, false, true); 563 | /// let x = dvec4(1., 1., 1., 1.); 564 | /// let y = dvec4(2., 2., 2., 2.); 565 | /// assert_eq!(mix_bool(x, y, a), dvec4(2., 1., 1., 2.)); 566 | /// // works for scalars too. 567 | /// assert_eq!(mix_bool(1_f32, 2., false), 1.); 568 | /// ``` 569 | #[inline(always)] 570 | pub fn mix_bool>(x: T, y: T, a: B) -> T { 571 | let ling = F::zero(); 572 | x.zip_bool(&a, |f, b| -> F { 573 | if b { 574 | ling 575 | } else { 576 | f 577 | } 578 | }) + y.zip_bool(&a, |f, b| -> F { 579 | if b { 580 | f 581 | } else { 582 | ling 583 | } 584 | }) 585 | } 586 | 587 | /// Returns `0.0` if `x` < `edge`, otherwise it returns `1.0`. 588 | /// 589 | /// # Example 590 | /// 591 | /// ``` 592 | /// use glm::{ step, dvec2 }; 593 | /// assert_eq!(step(1f32, 1.), 1.); 594 | /// assert_eq!(step(dvec2(1., 2.), dvec2(2., 1.)), dvec2(1., 0.)); 595 | /// ``` 596 | #[inline(always)] 597 | pub fn step>(edge: T, x: T) -> T { 598 | x.zip(edge, |f, e| -> F { 599 | if f < e { 600 | F::zero() 601 | } else { 602 | F::one() 603 | } 604 | }) 605 | } 606 | 607 | /// A variant of `step` function that use scalar as the edge. 608 | /// 609 | /// # Note 610 | /// 611 | /// `step_s` is not a GLSL function name. 612 | /// 613 | /// # Example 614 | /// 615 | /// ``` 616 | /// use glm::{ step_s, vec3 }; 617 | /// 618 | /// assert_eq!(step_s(0_f32, vec3(-1., 0., 1.)), vec3(0., 1., 1.)); 619 | /// ``` 620 | #[inline(always)] 621 | pub fn step_s>(edge: F, x: T) -> T { 622 | x.map(|f| -> F { 623 | if f < edge { 624 | F::zero() 625 | } else { 626 | F::one() 627 | } 628 | }) 629 | } 630 | 631 | /// Returns `0.0` if `x ≤ edge0` and `1.0` if `x ≥ edge1` and performs 632 | /// smooth Hermite interpolation between 0 and 1 when `edge0 < x < edge1`. 633 | /// 634 | /// This is useful in cases where you would want a threshold function with 635 | /// a smooth transition. 636 | /// 637 | /// Results are undefined if `edge0 ≥ edge1`. 638 | /// 639 | /// # Example 640 | /// 641 | /// ``` 642 | /// use glm::{ smoothstep, dvec2 }; 643 | /// 644 | /// assert_eq!(smoothstep(0f32, 1., -1.), 0.); 645 | /// let e0 = dvec2(0., -100.); 646 | /// let e1 = dvec2(1., 100.); 647 | /// let v = dvec2(1., 50.); 648 | /// assert_eq!(smoothstep(e0, e1, v), dvec2(1., 0.84375)); 649 | /// ``` 650 | #[inline] 651 | pub fn smoothstep>(edge0: T, edge1: T, x: T) -> T { 652 | let ling = T::zero(); 653 | let yi = T::one(); 654 | let er = yi + yi; 655 | let san = er + yi; 656 | 657 | let t = clamp((x - edge0) / (edge1 - edge0), ling, yi); 658 | t * t * (t * -er + san) 659 | } 660 | 661 | /// A variant of `smoothstep` function that use scalar as edges. 662 | /// 663 | /// # Note 664 | /// 665 | /// `smoothstep_s` is not a GLSL function name. 666 | #[inline] 667 | pub fn smoothstep_s, T: GenFloatVec>(edge0: F, edge1: F, x: T) -> T { 668 | let ling = F::zero(); 669 | let yi = F::one(); 670 | let er = yi + yi; 671 | let san = er + yi; 672 | 673 | x.map(|f| -> F { 674 | let t = clamp((f - edge0) / (edge1 - edge0), ling, yi); 675 | t * t * (san - er * t) 676 | }) 677 | } 678 | 679 | /// Returns `true` if `x` holds a *NaN*. Returns `false` otherwise. 680 | /// 681 | /// # Example 682 | /// 683 | /// ``` 684 | /// # fn main() { 685 | /// use glm::{ bvec3, dvec3, isnan }; 686 | /// use num_traits::Float; 687 | /// 688 | /// let nan: f64 = Float::nan(); 689 | /// assert!(isnan(nan)); 690 | /// assert_eq!(isnan(dvec3(nan, 1., -0.)), bvec3(true, false, false)); 691 | /// # } 692 | /// ``` 693 | #[inline(always)] 694 | pub fn isnan>(x: T) -> B { 695 | x.map_bool(Float::is_nan) 696 | } 697 | 698 | /// Returns true if x holds a positive infinity or negative infinity. 699 | /// Returns false otherwise. 700 | /// 701 | /// # Example 702 | /// 703 | /// ``` 704 | /// # fn main() { 705 | /// use num_traits::Float; 706 | /// 707 | /// let inf: f32 = Float::infinity(); 708 | /// assert!(glm::isinf(inf)); 709 | /// assert_eq!(glm::isinf(glm::vec2(inf, 0.)), glm::bvec2(true, false)); 710 | /// # } 711 | /// ``` 712 | #[inline(always)] 713 | pub fn isinf>(x: T) -> B { 714 | x.map_bool(Float::is_infinite) 715 | } 716 | 717 | /// Returns a signed integer value representing the encoding of 718 | /// a floating-point value. 719 | /// 720 | /// The floating-point value's bit-level representation is preserved. 721 | /// 722 | /// # Example 723 | /// 724 | /// ``` 725 | /// # fn main() { 726 | /// use glm::*; 727 | /// use num_traits::Float; 728 | /// 729 | /// let f = 1_f32; 730 | /// let i = floatBitsToInt(f); 731 | /// assert_eq!(i, 0x3F800000); 732 | /// let inf: f32 = Float::infinity(); 733 | /// let v = vec3(0.2, 0., inf); 734 | /// assert_eq!(floatBitsToInt(v), ivec3(0x3E4CCCCD, 0, 0x7f800000)); 735 | /// # } 736 | /// ``` 737 | #[inline(always)] 738 | #[allow(non_snake_case)] 739 | pub fn floatBitsToInt>(value: T) -> G { 740 | value.map_int(|f| -> i32 { 741 | let i: i32 = unsafe { mem::transmute(f) }; 742 | i 743 | }) 744 | } 745 | 746 | /// Returns a unsigned integer value representing the encoding of 747 | /// a floating-point value. 748 | /// 749 | /// The floating- point value's bit-level representation is preserved. 750 | /// 751 | /// # Example 752 | /// 753 | /// ``` 754 | /// # fn main() { 755 | /// use glm::{ floatBitsToUint, vec3, uvec3 }; 756 | /// use num_traits::Float; 757 | /// 758 | /// let f = 1_f32; 759 | /// let u = floatBitsToUint(f); 760 | /// assert_eq!(u, 0x3F800000); 761 | /// let inf: f32 = Float::infinity(); 762 | /// let v = vec3(0.2, 0., inf); 763 | /// assert_eq!(floatBitsToUint(v), uvec3(0x3E4CCCCD, 0, 0x7f800000)); 764 | /// # } 765 | /// ``` 766 | #[inline(always)] 767 | #[allow(non_snake_case)] 768 | pub fn floatBitsToUint>(value: T) -> G { 769 | value.map_int(|f| -> u32 { 770 | let u: u32 = unsafe { mem::transmute(f) }; 771 | u 772 | }) 773 | } 774 | 775 | /// Returns a floating-point value corresponding to a signed integer encoding 776 | /// of a floating-point value. 777 | /// 778 | /// # Example 779 | /// 780 | /// ``` 781 | /// # fn main() { 782 | /// use glm::{ intBitsToFloat, vec3, ivec3 }; 783 | /// use num_traits::Float; 784 | /// 785 | /// let i: i32 = 0x3F800000; 786 | /// let f = intBitsToFloat(i); 787 | /// assert_eq!(f, 1.); 788 | /// let inf: f32 = Float::infinity(); 789 | /// let vi = ivec3(0x3E4CCCCD, 0, 0x7f800000); 790 | /// let vf = vec3(0.2, 0., inf); 791 | /// assert_eq!(intBitsToFloat(vi), vf); 792 | /// # } 793 | /// ``` 794 | #[inline(always)] 795 | #[allow(non_snake_case)] 796 | pub fn intBitsToFloat>(value: T) -> G { 797 | value.map_flt(|i| -> f32 { 798 | let f: f32 = unsafe { mem::transmute(i) }; 799 | f 800 | }) 801 | } 802 | 803 | /// Returns a floating-point value corresponding to a unsigned integer encoding 804 | /// of a floating-point value. 805 | /// 806 | /// # Example 807 | /// 808 | /// ``` 809 | /// # fn main() { 810 | /// use glm::{ uintBitsToFloat, vec3, uvec3 }; 811 | /// use num_traits::Float; 812 | /// 813 | /// let i: u32 = 0x3F800000; 814 | /// let f = uintBitsToFloat(i); 815 | /// assert_eq!(f, 1.); 816 | /// let inf: f32 = Float::infinity(); 817 | /// let vu = uvec3(0x3E4CCCCD, 0, 0x7f800000); 818 | /// let vf = vec3(0.2, 0., inf); 819 | /// assert_eq!(uintBitsToFloat(vu), vf); 820 | /// # } 821 | /// ``` 822 | #[inline(always)] 823 | #[allow(non_snake_case)] 824 | pub fn uintBitsToFloat>(value: T) -> G { 825 | value.map_flt(|u| -> f32 { 826 | let f: f32 = unsafe { mem::transmute(u) }; 827 | f 828 | }) 829 | } 830 | 831 | /// Computes and returns `a * b + c`. 832 | /// 833 | /// # Example 834 | /// 835 | /// ``` 836 | /// use glm::{ fma, vec3 }; 837 | /// assert_eq!(fma(1.5_f32, 2.25, 3.125), 6.5); 838 | /// let a = vec3(-1., 2., 3.); 839 | /// let b = vec3(4., 5., 6.); 840 | /// let c = vec3(7., 8., 0.); 841 | /// assert_eq!(fma(a, b, c), vec3(3., 18., 18.)); 842 | /// ``` 843 | #[inline(always)] 844 | pub fn fma>(a: T, b: T, c: T) -> T { 845 | a.fma(&b, &c) 846 | } 847 | 848 | /// Splits `x` into a floating-point significand in the range [0.5, 1.0) and 849 | /// an integral exponent of two, such that: 850 | /// *x = significand⋅2exponent*. 851 | /// 852 | /// For a floating-point value of zero, the significant and exponent are both 853 | /// zero. 854 | /// 855 | /// For a floating-point value that is an infinity or is not a number, 856 | /// the results are undefined. 857 | /// 858 | /// # Note 859 | /// 860 | /// In GLSL, the significand is returned by the function and the exponent is 861 | /// returned in the output parameter `exp`. In Rust, we have the luxury to 862 | /// return both of them very naturally via a tuple. 863 | /// 864 | /// # Example 865 | /// 866 | /// ``` 867 | /// use glm::{ frexp, dvec3, ivec3 }; 868 | /// 869 | /// assert_eq!(frexp(0_f32), (0., 0)); 870 | /// let v3 = dvec3(1024., 1., 3.); 871 | /// let s = dvec3(0.5, 0.5, glm::exp2(glm::log2(3.) - 2.)); 872 | /// let e = ivec3(11, 1, 2); 873 | /// assert_eq!((s, e), frexp(v3)); 874 | /// ``` 875 | #[inline(always)] 876 | pub fn frexp>(x: T) -> (T, I) { 877 | x.split_int(|f| -> (F, i32) { 878 | let (s, e) = BaseFloat::frexp(f); 879 | (s, e as i32) 880 | }) 881 | } 882 | 883 | /// Builds a floating-point number from `x` and the corresponding integral 884 | /// exponent of two in `exp`, returning: 885 | /// *significand ⋅ 2exponent*. 886 | /// 887 | /// If this product is too large to be represented in the floating-point type, 888 | /// the result is undefined. 889 | /// 890 | /// # Example 891 | /// 892 | /// ``` 893 | /// use glm::{ ldexp, vec3, ivec3 }; 894 | /// 895 | /// assert_eq!(ldexp(2_f32, 2), 8.); 896 | /// let vf = vec3(1., 2., 3.); 897 | /// let vi = ivec3(-1, 1, 2); 898 | /// assert_eq!(ldexp(vf, vi), vec3(0.5, 4., 12.)); 899 | /// ``` 900 | #[inline(always)] 901 | pub fn ldexp, T: IntFloatRel>(x: G, exp: T) -> G { 902 | exp.zip_flt(&x, |i, f| -> F { BaseFloat::ldexp(f, i as isize) }) 903 | } 904 | --------------------------------------------------------------------------------