├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── basenum.rs ├── builtin ├── common.rs ├── exp.rs ├── geom.rs ├── integer.rs ├── matrix.rs ├── mod.rs ├── noise.rs ├── pack.rs ├── trig.rs └── vecrel.rs ├── cast.rs ├── ext ├── common.rs ├── consts.rs ├── exp.rs ├── geom.rs ├── matrix │ ├── mod.rs │ └── transform.rs ├── mod.rs └── trig.rs ├── lib.rs ├── mat ├── ctor.rs ├── mat.rs ├── sqmat.rs └── traits.rs ├── traits.rs └── vec ├── swizzle.rs ├── traits.rs └── vec.rs /.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.2.3" 5 | authors = [ 6 | "Che Kenan ", 7 | "Nerijus Arlauskas ", 8 | "Fredrik Norén", 9 | "Cameron Hart ", 10 | "human9 " 11 | ] 12 | 13 | description = "GLSL mathematics for Rust." 14 | keywords = ["glm", "math", "opengl", "glsl"] 15 | license = "MIT" 16 | repository = "https://github.com/dche/glm-rs/" 17 | 18 | [dependencies] 19 | rand = "^0.3.14" 20 | num = "^0.1.36" 21 | quickcheck = "^0.2.27" 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2015 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # GLSL Mathematics for Rust. 3 | 4 | [![Build Status](https://travis-ci.org/dche/glm-rs.png?branch=master)](https://travis-ci.org/dche/glm-rs) 5 | 6 | Another Rust mathematics library for graphics applications. 7 | 8 | Inspired by the great **[GLM](glm.g-truc.net)** library for C++, `glm-rs` 9 | implements the data types, operators and built-in functions defined in GLSL 10 | specification to help graphics programmers who are familiar with GLSL, so they 11 | do not need to learn more than one math API. 12 | 13 | Because of the not so small syntax/semantics difference between Rust and GLSL, 14 | some parts of GLSL are missing or changed, some functions are added to 15 | complete the functionalities. See the [glm-rs documentation](http://dche.github.io/glm-rs/) for full list 16 | of differences. 17 | 18 | The project is in beta status until the major version reaches to `1`. 19 | 20 | # Thanks 21 | 22 | - [GLM](glm.g-truc.net) by G-Truc (Christophe Riccio). The implementation of 23 | noise functions are directly translated from GLM. 24 | - Creators of the [Rust](http://rust-lang.org) for the language. 25 | 26 | # License 27 | 28 | The MIT License (MIT) 29 | -------------------------------------------------------------------------------- /src/basenum.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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 std::cmp; 25 | use std::{ f32, f64 }; 26 | use std::ops::{ Sub, Div, Rem, Neg }; 27 | use rand::Rand; 28 | use num::{ PrimInt, Float, One, 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 38 | : Send + Copy + Sized + Clone + PartialOrd + PartialEq + Rand {} 39 | 40 | impl Primitive for bool {} 41 | 42 | /// Trait for primitive number type. 43 | pub trait BaseNum 44 | : Primitive 45 | + Zero 46 | + One 47 | + Div 48 | + Rem 49 | { 50 | /// Returns the smaller one of two numbers. 51 | /// 52 | /// # Example 53 | /// 54 | /// ``` 55 | /// use glm::BaseNum; 56 | /// assert_eq!(BaseNum::min(1i32, 2i32), 1i32); 57 | /// ``` 58 | fn min(self, other: Self) -> Self; 59 | 60 | /// Returns the larger one of two numbers. 61 | /// 62 | /// # Example 63 | /// 64 | /// ``` 65 | /// use glm::BaseNum; 66 | /// assert_eq!(BaseNum::max(1i32, 2i32), 2i32); 67 | /// ``` 68 | fn max(self, other: Self) -> Self; 69 | } 70 | 71 | /// Trait for numerical types that have negative values. 72 | pub trait SignedNum 73 | : Sized 74 | + Neg 75 | + Sub 76 | { 77 | /// Returns the absolute value of the receiver. 78 | fn abs(&self) -> Self; 79 | 80 | /// Returns the sign number of the receiver. 81 | /// 82 | /// # Example 83 | /// 84 | /// ``` 85 | /// use glm::{ SignedNum, dvec3 }; 86 | /// assert_eq!(dvec3(2.718, 0., -0.).sign(), dvec3(1., 0., 0.)); 87 | /// ``` 88 | fn sign(&self) -> Self; 89 | } 90 | 91 | /// Marker trait for primitive integer number type. 92 | pub trait BaseInt: PrimInt + BaseNum {} 93 | 94 | /// Trait for comparing types that are derived from float numbers. 95 | /// 96 | /// # Note 97 | /// 98 | /// Comparing float numbers is tricky. This trait is mainly for convenience. 99 | /// See [this article](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/) 100 | /// for the details of comparing float numbers. 101 | pub trait ApproxEq { 102 | 103 | type BaseType: BaseFloat; 104 | 105 | /// Returns `true` if the difference between `x` and `y` is less than 106 | /// `max_diff`. 107 | /// 108 | /// # Note 109 | /// 110 | /// The meanings of "difference" and "less than" are up to the 111 | /// implementations. 112 | /// 113 | /// # Example 114 | /// 115 | /// use glm::*; 116 | /// 117 | /// let v1 = vec2(1000., 2000.); 118 | /// let v2 = vec2(1010., 1080.); 119 | /// assert!(v1.is_close_to(&v2, 50.)); 120 | /// assert!(!v1.is_close_to(&v2, 10.)); 121 | fn is_close_to(&self, rhs: &Self, max_diff: Self::BaseType) -> bool; 122 | 123 | /// Returns `true` if the difference between `x` and `y` is less than 124 | /// [machine epsilon](http://en.wikipedia.org/wiki/Machine_epsilon). 125 | /// 126 | /// # Example 127 | /// 128 | /// ``` 129 | /// use glm::*; 130 | /// 131 | /// let f = 0.1_f32; 132 | /// let mut sum = 0f32; 133 | /// for i in 0..10 { 134 | /// sum += f; 135 | /// } 136 | /// assert_eq!(1.0_f32 == sum, false); 137 | /// assert_eq!(1f32.is_approx_eq(&sum), true); 138 | /// ``` 139 | fn is_approx_eq(&self, rhs: &Self) -> bool { 140 | self.is_close_to(rhs, Self::BaseType::epsilon()) 141 | } 142 | } 143 | 144 | /// Returns the result of `x.is_close_to(y, max_diff)`. 145 | #[inline(always)] 146 | pub fn is_close_to(x: &T, y: &T, max_diff: T::BaseType) -> bool { 147 | x.is_close_to(y, max_diff) 148 | } 149 | 150 | /// Returns the result of `x.is_approx_eq(y)`. 151 | #[inline(always)] 152 | pub fn is_approx_eq(x: &T, y: &T) -> bool { 153 | x.is_approx_eq(y) 154 | } 155 | 156 | #[macro_export] 157 | macro_rules! assert_approx_eq( 158 | ($left: expr, $right: expr) => ({ 159 | let lhs = &($left); 160 | let rhs = &($right); 161 | if !is_approx_eq(lhs, rhs) { 162 | panic!( 163 | "assertion failed: left ≈ right` (left: `{:?}`, right: `{:?}`)", 164 | *lhs, *rhs, 165 | ) 166 | } 167 | }) 168 | ); 169 | 170 | #[macro_export] 171 | macro_rules! assert_close_to( 172 | ($left: expr, $right: expr, $max_diff: expr) => ({ 173 | let lhs = &($left); 174 | let rhs = &($right); 175 | let diff = $max_diff; 176 | if !is_close_to(lhs, rhs, diff) { 177 | panic!( 178 | "assertion failed: left ≈ right` (left: `{:?}`, right: `{:?}`, tolerance: `{:?}`)", 179 | *lhs, *rhs, diff 180 | ) 181 | } 182 | }) 183 | ); 184 | 185 | 186 | /// Trait for primitive float number type. 187 | pub trait BaseFloat: Float + BaseNum + SignedNum + ApproxEq { 188 | fn to_degrees(self) -> Self; 189 | fn to_radians(self) -> Self; 190 | fn frexp(self) -> (Self, isize); 191 | fn ldexp(self, exp: isize) -> Self; 192 | } 193 | 194 | impl SignedNum for i32 { 195 | #[inline(always)] 196 | fn abs(&self) -> i32 { 197 | Signed::abs(self) 198 | } 199 | #[inline(always)] 200 | fn sign(&self) -> i32 { 201 | self.signum() 202 | } 203 | } 204 | 205 | macro_rules! impl_int( 206 | ($($t: ty), +) => { 207 | $( 208 | impl Primitive for $t {} 209 | impl BaseNum for $t { 210 | #[inline(always)] 211 | fn min(self, other: $t) -> $t { 212 | cmp::min(self, other) 213 | } 214 | #[inline(always)] 215 | fn max(self, other: $t) -> $t { 216 | cmp::max(self, other) 217 | } 218 | } 219 | impl BaseInt for $t {} 220 | )+ 221 | } 222 | ); 223 | impl_int! { i32, u32 } 224 | 225 | macro_rules! impl_flt( 226 | ($t: ident) => { 227 | impl Primitive for $t {} 228 | impl SignedNum for $t { 229 | #[inline(always)] 230 | fn abs(&self) -> $t { 231 | Float::abs(*self) 232 | } 233 | #[inline(always)] 234 | fn sign(&self) -> $t { 235 | let l = $t::zero(); 236 | if self.is_zero() { 237 | l 238 | } else { 239 | self.signum() 240 | } 241 | } 242 | } 243 | impl ApproxEq for $t { 244 | type BaseType = $t; 245 | #[inline(always)] 246 | fn is_close_to(&self, rhs: &$t, max_diff: $t) -> bool { 247 | (self - *rhs).abs() <= max_diff 248 | } 249 | } 250 | impl BaseNum for $t { 251 | #[inline(always)] 252 | fn min(self, other: $t) -> $t { 253 | Float::min(self, other) 254 | } 255 | #[inline(always)] 256 | fn max(self, other: $t) -> $t { 257 | Float::max(self, other) 258 | } 259 | } 260 | impl BaseFloat for $t { 261 | #[inline(always)] 262 | fn to_degrees(self) -> $t { 263 | self * (180. / $t::consts::PI) 264 | } 265 | #[inline(always)] 266 | fn to_radians(self) -> $t { 267 | self * ($t::consts::PI / 180.) 268 | } 269 | #[inline(always)] 270 | fn frexp(self) -> ($t, isize) { 271 | // CHECK: use impl in `libstd` after it's stable. 272 | if self.is_zero() || self.is_infinite() || self.is_nan() { 273 | (self, 0) 274 | } else { 275 | let lg = self.abs().log2(); 276 | let x = (lg.fract() - 1.).exp2(); 277 | let exp = lg.floor() + 1.; 278 | (self.signum() * x, exp as isize) 279 | } 280 | } 281 | #[inline(always)] 282 | fn ldexp(self, exp: isize) -> $t { 283 | // CHECK: use impl in `libstd` after it's stable. 284 | let f = exp as $t; 285 | self * f.exp2() 286 | } 287 | } 288 | } 289 | ); 290 | 291 | impl_flt! { f32 } 292 | impl_flt! { f64 } 293 | -------------------------------------------------------------------------------- /src/builtin/exp.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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 basenum::BaseFloat; 26 | use traits::GenFloat; 27 | use num::Float; 28 | 29 | /// Returns `x` raised to the `y` power, i.e., *xy*. 30 | /// 31 | /// Results are undefined if `x < 0`. 32 | /// 33 | /// Results are undefined if `x = 0` and `y ≤ 0`. 34 | /// 35 | /// # Example 36 | /// 37 | /// ``` 38 | /// use glm::{ pow, vec3 }; 39 | /// 40 | /// assert_eq!(pow(2.0, 3.0), 8.0); 41 | /// let v1 = vec3(1.0, 2.0, 3.0); 42 | /// let v2 = vec3(1.0, 4.0, 27.0); 43 | /// assert_eq!(pow(v1, v1), v2); 44 | /// ``` 45 | #[inline(always)] 46 | pub fn pow>(x: T, y: T) -> T { 47 | x.zip(y, Float::powf) 48 | } 49 | 50 | /// Returns the natural exponentiation of `x`. i.e., *ex*. 51 | /// 52 | /// # Example 53 | /// 54 | /// ``` 55 | /// use glm::{ exp, ApproxEq }; 56 | /// use glm::ext::e; 57 | /// 58 | /// let e1: f32 = e(); 59 | /// let e2 = e1 * e1; 60 | /// assert!(exp(2.).is_close_to(&e2, 0.000001)); 61 | /// ``` 62 | #[inline(always)] 63 | pub fn exp>(x: T) -> T { 64 | x.map(Float::exp) 65 | } 66 | 67 | /// Returns the natural logarithm of `x`. i.e., the value `y` which satisfies 68 | /// *x = ey*. 69 | /// 70 | /// # Example 71 | /// 72 | /// ``` 73 | /// use glm::{ log, ApproxEq }; 74 | /// use glm::ext::e; 75 | /// 76 | /// let e1: f64 = e(); 77 | /// let e2 = e1 * e1; 78 | /// assert!(log(e2).is_approx_eq(&2.)); 79 | /// ``` 80 | #[inline(always)] 81 | pub fn log>(x: T) -> T { 82 | x.map(Float::ln) 83 | } 84 | 85 | /// Returns `2` raised to the power of `x`. i.e., *2x*. 86 | /// 87 | /// # Example 88 | /// 89 | /// ``` 90 | /// use glm::{ exp2, dvec2 }; 91 | /// 92 | /// assert_eq!(exp2(10_f32), 1024.); 93 | /// assert_eq!(exp2(dvec2(-1., 5.)), dvec2(0.5, 32.)); 94 | /// ``` 95 | #[inline(always)] 96 | pub fn exp2>(x: T) -> T { 97 | x.map(Float::exp2) 98 | } 99 | 100 | /// Returns the base `2` logarithm of `x`. i.e., the value `y` which satisfies 101 | /// *x = 2y*. 102 | /// 103 | /// Results are undefined if `x < 0`. 104 | /// 105 | /// # Example 106 | /// 107 | /// ``` 108 | /// use glm::{ log2, vec2 }; 109 | /// assert_eq!(log2(vec2(64., 256.)), vec2(6., 8.)); 110 | /// ``` 111 | #[inline(always)] 112 | pub fn log2>(x: T) -> T { 113 | x.map(Float::log2) 114 | } 115 | 116 | /// Returns the square root of `x`. i.e., the value `sqrt(x)`. 117 | /// 118 | /// Results are undefined if `x < 0`. 119 | /// 120 | /// # Example 121 | /// 122 | /// ``` 123 | /// use glm::{ sqrt, vec2 }; 124 | /// assert_eq!(sqrt(vec2(64., 1.)), vec2(8., 1.)); 125 | /// ``` 126 | #[inline(always)] 127 | pub fn sqrt>(x: T) -> T { 128 | x.map(Float::sqrt) 129 | } 130 | 131 | /// Returns the inverse of the square root of `x`. i.e., the value `1/sqrt(x)`. 132 | /// 133 | /// Results are undefined if `x ≤ 0`. 134 | /// 135 | /// # Example 136 | /// 137 | /// ``` 138 | /// use glm::{ inversesqrt, vec2 }; 139 | /// assert_eq!(inversesqrt(4_f32), 0.5); 140 | /// assert_eq!(inversesqrt(vec2(64., 1.)), vec2(0.125, 1.)); 141 | /// ``` 142 | #[inline(always)] 143 | pub fn inversesqrt>(x: T) -> T { 144 | x.map(|f| -> F { 145 | f.sqrt().recip() 146 | }) 147 | } 148 | -------------------------------------------------------------------------------- /src/builtin/geom.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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 basenum::BaseFloat; 30 | use traits::GenFloat; 31 | use vec::traits::GenFloatVec; 32 | use vec::vec::Vector3; 33 | use super::exp::inversesqrt; 34 | 35 | /// Returns the dot product of `x` and `y`, i.e., 36 | /// `x[0] * y[0] + x[1] * y[1] + ...`. 37 | /// 38 | /// # Example 39 | /// 40 | /// ``` 41 | /// use glm::{ dot, vec2 }; 42 | /// 43 | /// let v1 = vec2(1., 2.); 44 | /// let v2 = vec2(3., 4.); 45 | /// assert_eq!(dot(v1, v2), 11.); 46 | /// ``` 47 | #[inline(always)] 48 | pub fn dot>(x: T, y: T) -> S { 49 | (x * y).sum() 50 | } 51 | 52 | /// Returns the length of vector `x`, i.e., `sqrt(x[0]^2 + x[1]^2 + ...)`. 53 | /// 54 | /// # Example 55 | /// 56 | /// ``` 57 | /// assert_eq!(glm::length(glm::vec2(3., 4.)), 5.); 58 | /// ``` 59 | #[inline(always)] 60 | pub fn length>(x: T) -> S { 61 | dot(x, x).sqrt() 62 | } 63 | 64 | /// Returns a vector in the same direction as `x` but with a length of `1`. 65 | /// 66 | /// # Example 67 | /// 68 | /// ``` 69 | /// use glm::{ normalize, dvec2, ApproxEq }; 70 | /// 71 | /// assert!(normalize(dvec2(3., 4.)).is_approx_eq(&dvec2(0.6, 0.8))); 72 | /// ``` 73 | #[inline(always)] 74 | pub fn normalize, T: GenFloatVec>(x: T) -> T { 75 | x * inversesqrt(dot(x, x)) 76 | } 77 | 78 | /// Returns the distance between `p0` and `p1`, i.e., `length(p0 – p1)`. 79 | /// 80 | /// # Example 81 | /// 82 | /// ``` 83 | /// use glm::{ distance, vec2 }; 84 | /// 85 | /// let v1 = vec2(1., 2.); 86 | /// let v2 = vec2(4., 6.); 87 | /// assert_eq!(distance(v1, v2), 5.); 88 | /// ``` 89 | #[inline(always)] 90 | pub fn distance>(p0: T, p1: T) -> S { 91 | length(p0 - p1) 92 | } 93 | 94 | /// If `dot(Nref, I) < 0` return *N*, otherwise return *-N*. 95 | #[inline] 96 | #[allow(non_snake_case)] 97 | pub fn faceforward>(N: T, I: T, Nref: T) -> T { 98 | let ling = S::zero(); 99 | if dot(Nref, I) < ling { 100 | N 101 | } else { 102 | -N 103 | } 104 | } 105 | 106 | /// For the incident vector *I* and surface orientation *N*, 107 | /// returns the reflection direction: `I - 2 ∗ dot(N, I) ∗ N`. 108 | /// 109 | /// *N* must already be normalized in order to achieve the desired result. 110 | #[inline] 111 | #[allow(non_snake_case)] 112 | pub fn reflect>(I: T, N: T) -> T { 113 | let d = dot(N, I); 114 | I - N * (d + d) 115 | } 116 | 117 | /// For the incident vector *I* and surface normal *N*, and the ratio of 118 | /// indices of refraction `eta`, return the refraction vector. 119 | /// 120 | /// The result is computed by, 121 | /// ```ignore 122 | /// k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) 123 | /// if (k < 0.0) 124 | /// return genType(0.0) // or genDType(0.0) 125 | /// else 126 | /// return eta * I - (eta * dot(N, I) + sqrt(k)) * N 127 | /// ``` 128 | /// 129 | /// The input parameters for the incident vector *I* and the surface normal *N* 130 | /// must already be normalized to get the desired results. 131 | #[inline] 132 | #[allow(non_snake_case)] 133 | pub fn refract>(I: T, N: T, eta: S) -> T { 134 | let dot_ni = dot(I, N); 135 | let yi = S::one(); 136 | let ling = S::zero(); 137 | 138 | let k = yi - eta * eta * (yi - dot_ni) * dot_ni; 139 | if k < ling { 140 | T::zero() 141 | } else { 142 | I * eta - N * (eta * dot_ni + k.sqrt()) 143 | } 144 | } 145 | 146 | /// Returns the cross product of `x` and `y`. 147 | /// 148 | /// # Example 149 | /// 150 | /// ``` 151 | /// use glm::vec3; 152 | /// 153 | /// let x = vec3(1.0, 0.0, 0.0); 154 | /// let y = vec3(0.0, 1.0, 0.0); 155 | /// let z = vec3(0.0, 0.0, 1.0); 156 | /// assert_eq!(glm::cross(x, y), z); 157 | /// ``` 158 | #[inline] 159 | pub fn cross(x: Vector3, y: Vector3) -> Vector3 { 160 | Vector3::new( 161 | x.y * y.z - y.y * x.z, 162 | x.z * y.x - y.z * x.x, 163 | x.x * y.y - y.x * x.y 164 | ) 165 | } 166 | -------------------------------------------------------------------------------- /src/builtin/integer.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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 basenum::BaseInt; 27 | use traits::{ GenNum, GenInt, GenIType, GenUType }; 28 | use vec::vec::{ UVec2, UVec3, UVec4, IVec2, IVec3, IVec4 }; 29 | use std::mem; 30 | 31 | // used by `findLSB` and `findMSB`. 32 | pub trait IntIntRel: GenInt { 33 | fn map_int i32>(&self, f: F) -> T; 34 | } 35 | 36 | macro_rules! impl_IntIntRel_for_int { 37 | ($($t: ident),+) => { 38 | $( 39 | impl IntIntRel for $t { 40 | #[inline(always)] 41 | fn map_int i32>(&self, f: F) -> $t { 42 | self.map(f) 43 | } 44 | } 45 | )+ 46 | } 47 | } 48 | 49 | impl_IntIntRel_for_int! { i32, IVec2, IVec3, IVec4 } 50 | 51 | impl IntIntRel for u32 { 52 | #[inline(always)] 53 | fn map_int i32>(&self, f: F) -> i32 { 54 | f(*self) 55 | } 56 | } 57 | 58 | macro_rules! impl_IntIntRel_for_uint { 59 | ($({ $ut: ident, $it: ident, $($field: ident),+ }),+) => { 60 | $( 61 | impl IntIntRel for $ut { 62 | #[inline(always)] 63 | fn map_int i32>(&self, f: F) -> $it { 64 | $it { $($field: f(self.$field)),+ } 65 | } 66 | } 67 | )+ 68 | } 69 | } 70 | 71 | impl_IntIntRel_for_uint! { 72 | { UVec2, IVec2, x, y }, 73 | { UVec3, IVec3, x, y, z }, 74 | { UVec4, IVec4, x, y, z, w } 75 | } 76 | 77 | /// Adds 32-bit unsigned integer `x` and `y`, returning the sum modulus 78 | /// *232* and the carry bit. 79 | /// 80 | /// Carry is set to `0` if the sum was less than *232*, or to `1` 81 | /// otherwise. 82 | /// 83 | /// # Note 84 | /// 85 | /// In GLSL, the carry bit is returned via the output parameter `carry`. 86 | /// 87 | /// # Example 88 | /// 89 | /// ``` 90 | /// use glm::{ uvec2, uaddCarry }; 91 | /// 92 | /// let v = uvec2(0xFFFFFFFE, 0); 93 | /// assert_eq!(uaddCarry(v, uvec2(3, 3)), (uvec2(1, 3), uvec2(1, 0))) 94 | /// ``` 95 | #[inline] 96 | #[allow(non_snake_case)] 97 | pub fn uaddCarry(x: T, y: T) -> (T, T) { 98 | x.map2(y, |i, j| -> (u32, u32) { 99 | match i.checked_add(j) { 100 | Some(s) => (s, 0), 101 | None => (i - (0xFFFFFFFF - j + 1), 1), 102 | } 103 | }) 104 | } 105 | 106 | /// Subtracts the 32-bit unsigned integer `y` from `x`, returning the 107 | /// difference and the borrow bit. 108 | /// 109 | /// Returns the difference if it is non-negative, or *232* plus the 110 | /// difference otherwise. 111 | /// 112 | /// The borrow bit is set to `0` if` x ≥ y`, or to `1` otherwise. 113 | /// 114 | /// # Example 115 | /// 116 | /// ``` 117 | /// use glm::{ usubBorrow, uvec2 }; 118 | /// 119 | /// let uv1 = uvec2(16, 17); 120 | /// let uv2 = uvec2(17, 16); 121 | /// assert_eq!(usubBorrow(uv1, uv2), (uvec2(0xFFFFFFFE, 1), uvec2(1, 0))); 122 | /// ``` 123 | #[inline] 124 | #[allow(non_snake_case)] 125 | pub fn usubBorrow(x: T, y: T) -> (T, T) { 126 | x.map2(y, |i, j| -> (u32, u32) { 127 | if i >= j { 128 | (i - j, 0) 129 | } else { 130 | (0xFFFFFFFF - j + i, 1) 131 | } 132 | }) 133 | } 134 | 135 | /// Multiplies 32-bit unsigned integers `x` and `y`, producing a 64-bit 136 | /// result. 137 | /// 138 | /// The 32 least-significant bits are returned in `lsb`. 139 | /// 140 | /// The 32 most-significant bits are returned in `msb`. 141 | #[allow(non_snake_case)] 142 | pub fn umulExtended(x: T, y: T) -> (T, T) { 143 | x.map2(y, |i, j| -> (u32, u32) { 144 | let ei = i as u64; 145 | let ej = j as u64; 146 | let p = ei * ej; 147 | ((p >> 32) as u32, p as u32) 148 | }) 149 | } 150 | 151 | /// Multiplies 32-bit integers `x` and `y`, producing a 64-bit result. 152 | /// 153 | /// The 32 least-significant bits are returned in `lsb`. 154 | /// 155 | /// The 32 most-significant bits are returned in `msb`. 156 | #[allow(non_snake_case)] 157 | pub fn imulExtended(x: T, y: T) -> (T, T) { 158 | x.map2(y, |i, j| -> (i32, i32) { 159 | let ei = i as i64; 160 | let ej = j as i64; 161 | let p = ei * ej; 162 | ((p >> 32) as i32, p as i32) 163 | }) 164 | } 165 | 166 | /// Extracts bits `[offset, offset + bits - 1]` from `value`, returning them in 167 | /// the least significant bits of the result. 168 | /// 169 | /// For unsigned data types, the most significant bits of the result will 170 | /// be set to zero. For signed data types, the most significant bits will 171 | /// be set to the value of bit offset + base – 1. 172 | /// 173 | /// If `bits` is zero, the result will be zero. The result will be undefined 174 | /// if `offset` or `bits` is negative, or if the sum of `offset` and `bits` is 175 | /// greater than the number of bits used to store the operand. 176 | /// 177 | /// # Example 178 | /// 179 | /// ``` 180 | /// use glm::bitfieldExtract; 181 | /// 182 | /// assert_eq!(bitfieldExtract(0xF000FFFF, 32, 12), 0); 183 | /// assert_eq!(bitfieldExtract(0b11100011_u32, 1, 6), 0b110001); 184 | /// ``` 185 | #[allow(non_snake_case)] 186 | pub fn bitfieldExtract 187 | < 188 | I: BaseInt, 189 | T: GenInt 190 | >(value: T, offset: usize, bits: usize) -> T { 191 | let ling = T::zero(); 192 | if value.is_zero() || bits == 0 || offset + bits > 32 { 193 | ling 194 | } else { 195 | let mask = I::from((1_u32 << bits) - 1).unwrap(); 196 | value.map(|i| -> I { 197 | (i >> offset) & mask 198 | }) 199 | } 200 | } 201 | 202 | /// Returns the insertion the `bits` least-significant bits of `insert` into 203 | /// `base`. 204 | /// 205 | /// The result will have bits `[offset, offset + bits - 1]` taken from 206 | /// bits `[0, bits – 1]` of `insert`, and all other bits taken directly from 207 | /// the corresponding bits of `base`. If `bits` is zero, the result will 208 | /// simply be `base`. 209 | /// 210 | /// The result will be undefined if `offset` or `bits` is negative, 211 | /// or if the sum of `offset` and `bits` is greater than the number of bits 212 | /// used to store the operand. 213 | /// 214 | /// # Example 215 | /// 216 | /// ``` 217 | /// use glm::bitfieldInsert; 218 | /// 219 | /// assert_eq!(bitfieldInsert(1_i32, 0xFF00FF00, 8, 20), 0xF00FF01); 220 | /// ``` 221 | #[allow(non_snake_case)] 222 | pub fn bitfieldInsert 223 | < 224 | I: BaseInt, 225 | T: GenInt 226 | >(base: T, insert: T, offset: usize, bits: usize) -> T { 227 | if bits == 0 { 228 | base 229 | } else { 230 | let mask = I::from(((1_u32 << bits) - 1) << offset).unwrap(); 231 | base.zip(insert, |i, j| -> I { 232 | (i & !mask) | (j & mask) 233 | }) 234 | } 235 | } 236 | 237 | /// Returns the reversal of the bits of `value`. 238 | /// 239 | /// The bit numbered n of the result will be taken from bit `(bits - 1) - n` 240 | /// of `value`, where *bits* is the total number of bits used to represent 241 | /// `value`. 242 | /// 243 | /// # Example 244 | /// 245 | /// ``` 246 | /// use glm::bitfieldReverse; 247 | /// 248 | /// assert_eq!(bitfieldReverse(0xF30000F3), 0xCF0000CF); 249 | /// ``` 250 | #[allow(non_snake_case)] 251 | pub fn bitfieldReverse>(value: T) -> T { 252 | #[inline(always)] 253 | fn reverse_step(x: u32, mask: u32, shift: usize) -> u32 { 254 | ((x & mask) << shift) | ((x & !mask) >> shift) 255 | } 256 | value.map(|i| -> I { 257 | // reinterpret_cast 258 | let u: &u32 = unsafe { mem::transmute(&i) }; 259 | let mut x = *u; 260 | x = reverse_step(x, 0x55555555, 1); 261 | x = reverse_step(x, 0x33333333, 2); 262 | x = reverse_step(x, 0x0F0F0F0F, 4); 263 | x = reverse_step(x, 0x00FF00FF, 8); 264 | x = reverse_step(x, 0x0000FFFF, 16); 265 | let r: &I = unsafe { mem::transmute(&x) }; 266 | *r 267 | }) 268 | } 269 | 270 | /// Returns the number of bits set to 1 in the binary representation of 271 | /// `value`. 272 | /// 273 | /// # Example 274 | /// 275 | /// ``` 276 | /// use glm::{ bitCount, ivec2 }; 277 | /// 278 | /// let v = ivec2(0b01010101, 0); 279 | /// assert_eq!(bitCount(v), ivec2(4, 0)); 280 | /// ``` 281 | #[allow(non_snake_case)] 282 | pub fn bitCount>(value: T) -> T { 283 | value.map(|i| -> I { 284 | let c = I::from(i.count_ones()).unwrap(); 285 | c 286 | }) 287 | } 288 | 289 | /// Returns the bit number of the least significant bit set to 1 in the binary 290 | /// representation of `value`. 291 | /// 292 | /// If `value` is zero, `-1` will be returned. 293 | /// 294 | /// # Example 295 | /// 296 | /// ``` 297 | /// use glm::{ findLSB, ivec2, uvec2 }; 298 | /// 299 | /// assert_eq!(findLSB(0u32), -1); 300 | /// let v = uvec2(0b0101000, 0x80000000); 301 | /// assert_eq!(findLSB(v), ivec2(3, 31)); 302 | /// ``` 303 | #[allow(non_snake_case)] 304 | pub fn findLSB< 305 | B: BaseInt, 306 | I: GenIType, 307 | T: IntIntRel 308 | >(value: T) -> I { 309 | value.map_int(|i| -> i32 { 310 | if i.is_zero() { 311 | -1 312 | } else { 313 | i.trailing_zeros() as i32 314 | } 315 | }) 316 | } 317 | 318 | /// Returns the bit number of the most significant bit in the binary 319 | /// representation of `value`. 320 | /// 321 | /// For positive integers, the result will be the bit number of the 322 | /// most significant bit set to `1`. 323 | /// 324 | /// For negative integers, the result will be the bit number of the most 325 | /// significant bit set to `0`. For a value of zero or negative one, `-1` will 326 | /// be returned. 327 | /// 328 | /// # Example 329 | /// 330 | /// ``` 331 | /// use glm::{ findMSB, ivec3 }; 332 | /// 333 | /// assert_eq!(findMSB(0_i32), -1); 334 | /// assert_eq!(findMSB(ivec3(-1, -2, 0x7FFFFFFF)), ivec3(-1, 0, 30)); 335 | /// ``` 336 | #[allow(non_snake_case)] 337 | pub fn findMSB< 338 | B: BaseInt, 339 | I: GenIType, 340 | T: IntIntRel 341 | >(value: T) -> I { 342 | value.map_int(|i| -> i32 { 343 | let ling = B::zero(); 344 | if i.is_zero() { 345 | -1 346 | } else if i < ling { 347 | 31 - ((!i).leading_zeros() as i32) 348 | } else { 349 | 31 - (i.leading_zeros() as i32) 350 | } 351 | }) 352 | } 353 | -------------------------------------------------------------------------------- /src/builtin/matrix.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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 basenum::BaseFloat; 27 | use mat::traits::{ GenMat, GenSquareMat }; 28 | use 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< 51 | T: BaseFloat, 52 | C: GenFloatVec, 53 | M: GenMat 54 | >(x: &M, y: &M) -> M { 55 | x.mul_c(y) 56 | } 57 | 58 | /// Treats the first parameter `c` as a column vector (matrix with one column) 59 | /// and the second parameter `r` as a row vector (matrix with one row) 60 | /// and does a linear algebraic matrix multiply `c * r`, 61 | /// yielding a matrix whose number of rows is the number of components in `c` 62 | /// and whose number of columns is the number of components in `r`. 63 | /// 64 | /// # Example 65 | /// 66 | /// ``` 67 | /// # use glm::*; 68 | /// let v2 = vec2(1., 2.); 69 | /// let v3 = vec3(4., 0., -1.); 70 | /// let e = mat3x2(4., 8., 0., 0., -1., -2.); 71 | /// let op: Mat3x2 = outerProduct(v2, v3); 72 | /// assert_eq!(op, e); 73 | /// ``` 74 | #[inline] 75 | #[allow(non_snake_case)] 76 | pub fn outerProduct< 77 | T: BaseFloat, 78 | C: GenFloatVec, 79 | R: GenFloatVec, 80 | /* 81 | * NOTE: 82 | * I can't believe Rust allows this! But Rust is wrong at the first place. 83 | * Associated types (e.g., `R` and `Transpose` of `GenMat` here) are not type 84 | * parameters, and should not be mandatorily required when specifying a type, 85 | * and if `Transpose` is ommitted (as we did before), that does not mean 86 | * `GenMat` is not implemented for `Tanspose` of `M` (E0277). How could that 87 | * be possible? 88 | */ 89 | N: GenMat, 90 | M: GenMat 91 | >(c: C, r: R) -> M { 92 | let mut z = M::zero(); 93 | let dim = R::dim(); 94 | for i in 0..dim { 95 | z[i] = c * r[i]; 96 | }; 97 | z 98 | } 99 | 100 | /// Returns a matrix that is the transpose of `m`. 101 | /// 102 | /// The input matrix `m` is not modified. 103 | #[inline(always)] 104 | pub fn transpose< 105 | T: BaseFloat, 106 | C: GenFloatVec, 107 | M: GenMat 108 | >(m: &M) -> M::Transpose { 109 | m.transpose() 110 | } 111 | 112 | /// Returns the determinant of `m`. 113 | #[inline(always)] 114 | pub fn determinant< 115 | T: BaseFloat, 116 | C: GenFloatVec, 117 | M: GenSquareMat 118 | >(m: &M) -> T { 119 | m.determinant() 120 | } 121 | 122 | /// Returns a matrix that is the inverse of `m`. 123 | /// 124 | /// The input matrix `m` is not modified. 125 | /// 126 | /// # Panic 127 | /// 128 | /// It is a panic if `m` is singular or poorly-conditioned (nearly singular). 129 | #[inline] 130 | pub fn inverse< 131 | T: BaseFloat, 132 | C: GenFloatVec, 133 | M: GenSquareMat 134 | >(m: &M) -> M { 135 | let inv = m.inverse(); 136 | match inv { 137 | Some(im) => im, 138 | _ => panic!("inverse a matrix that is not invertible.") 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/builtin/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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/builtin/noise.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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 traits::GenType; 39 | use cast::to_vec4; 40 | use vec::vec::{ Vec2, Vec3, Vec4, vec2, vec3, vec4 }; 41 | use super::common::*; 42 | use super::geom::dot; 43 | use super::vecrel::lessThan; 44 | use num::{ One, Zero }; 45 | 46 | #[allow(non_snake_case)] 47 | pub fn grad4(j: f32, ip: Vec4) -> Vec4 { 48 | let mut pXYZ = floor(fract(vec3(j, j, j) * ip.truncate(3)) * 7.) * ip[2] - 1.; 49 | let pW = 1.5 - dot(abs(pXYZ), Vec3::one()); 50 | let s = to_vec4(lessThan(vec4(pXYZ.x, pXYZ.y, pXYZ.z, pW), Vec4::zero())); 51 | pXYZ = pXYZ + (s.truncate(3) * 2. - 1.) * s.w; 52 | vec4(pXYZ.x, pXYZ.y, pXYZ.z, pW) 53 | } 54 | 55 | #[inline(always)] 56 | pub fn mod289(x: T) -> T { 57 | x - floor(x * (1. / 289.)) * 289. 58 | } 59 | 60 | #[inline(always)] 61 | pub fn permute(x: T) -> T { 62 | mod289((x * 34. + 1.) * x) 63 | } 64 | 65 | #[inline(always)] 66 | pub fn taylor_inv_sqrt(x: T) -> T { 67 | -x * 0.85373472095314 + 1.79284291400159 68 | } 69 | 70 | pub trait NoiseImpl { 71 | fn noise1(self) -> f32; 72 | } 73 | 74 | impl NoiseImpl for f32 { 75 | #[inline] 76 | fn noise1(self) -> f32 { 77 | vec2(self, 0.).noise1() 78 | } 79 | } 80 | 81 | impl NoiseImpl for Vec2 { 82 | fn noise1(self) -> f32 { 83 | let yi = Vec2::one(); 84 | let C = vec4( 85 | 0.211324865405187, // (3.0 - sqrt(3.0)) / 6.0 86 | 0.366025403784439, // 0.5 * (sqrt(3.0) - 1.0) 87 | -0.577350269189626, // -1.0 + 2.0 * C.x 88 | 0.024390243902439 // 1.0 / 41.0 89 | ); 90 | // first corner 91 | let mut i = floor(self + dot(self, yi * C.y)); 92 | let x0 = self - i + dot(i, yi * C.x); 93 | // Other corners 94 | //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0 95 | //i1.y = 1.0 - i1.x; 96 | let i1 = if x0.x > x0.y { vec2(1., 0.) } else { vec2(0., 1.) }; 97 | 98 | // x0 = x0 - 0.0 + 0.0 * C.xx ; 99 | // x1 = x0 - i1 + 1.0 * C.xx ; 100 | // x2 = x0 - 1.0 + 2.0 * C.xx ; 101 | let mut x12 = vec4(x0.x, x0.y, x0.x, x0.y) + vec4(C.x, C.x, C.z, C.z); 102 | x12 = vec4(x12.x - i1.x, x12.y - i1.y, x12.z, x12.w); 103 | 104 | // Permutations 105 | i = mod_s(i, 289.); // Avoid truncation effects in permutation 106 | let p = permute(permute( 107 | vec3(0., i1.y, 1.) + i.y) + 108 | vec3(0., i1.x, 1.) + i.x); 109 | 110 | let mut m = max_s( 111 | -vec3( 112 | dot(x0, x0), 113 | dot(vec2(x12.x, x12.y), vec2(x12.x, x12.y)), 114 | dot(vec2(x12.z, x12.w), vec2(x12.z, x12.w)) 115 | ) + 0.5, 116 | 0. 117 | ); 118 | m = m * m; 119 | m = m * m; 120 | 121 | // Gradients: 41 points uniformly over a line, mapped onto a diamond. 122 | // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) 123 | 124 | let x = fract(p * C.w) * 2. - 1.; 125 | let h = abs(x) - 0.5; 126 | let ox = floor(x + 0.5); 127 | let a0 = x - ox; 128 | 129 | // Normalise gradients implicitly by scaling m 130 | // Inlined for speed: m *= taylorInvSqrt( a0*a0 + h*h ); 131 | m = m * ((a0 * a0 + h * h) * -0.85373472095314 + 1.79284291400159); 132 | 133 | // Compute final noise value at P 134 | let g = vec3( 135 | a0.x * x0.x + h.x * x0.y, 136 | //g.yz = a0.yz * x12.xz + h.yz * x12.yw; 137 | a0.y * x12.x + h.y * x12.y, 138 | a0.z * x12.z + h.z * x12.w 139 | ); 140 | dot(m, g) * 130. 141 | } 142 | } 143 | 144 | impl NoiseImpl for Vec3 { 145 | fn noise1(self) -> f32 { 146 | let yi = Vec3::one(); 147 | let C = vec2(1./6., 1./3.); 148 | let D = vec4(0., 0.5, 1., 2.); 149 | 150 | // First corner 151 | let mut i = floor(self + dot(self, yi * C.y)); 152 | let x0 = self - i + dot(i, yi * C.x); 153 | 154 | // Other corners 155 | let g = step(vec3(x0.y, x0.z, x0.x), x0); 156 | let l = yi - g; 157 | let i1 = min(g, vec3(l.z, l.x, l.y)); 158 | let i2 = max(g, vec3(l.z, l.x, l.y)); 159 | 160 | // x0 = x0 - 0.0 + 0.0 * C.xxx; 161 | // x1 = x0 - i1 + 1.0 * C.xxx; 162 | // x2 = x0 - i2 + 2.0 * C.xxx; 163 | // x3 = x0 - 1.0 + 3.0 * C.xxx; 164 | let x1 = x0 - i1 + C.x; 165 | let x2 = x0 - i2 + C.y; // 2.0*C.x = 1/3 = C.y 166 | let x3 = x0 - D.y; // -1.0+3.0*C.x = -0.5 = -D.y 167 | 168 | // Permutations 169 | i = mod289(i); 170 | let p: Vec4 = permute(permute(permute( 171 | vec4(0., i1.z, i2.z, 1.) + i.z) + 172 | vec4(0., i1.y, i2.y, 1.) + i.y) + 173 | vec4(0., i1.x, i2.x, 1.) + i.x); 174 | 175 | // Gradients: 7x7 points over a square, mapped onto an octahedron. 176 | // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) 177 | let n_ = 0.142857142857_f32; // 1.0 / 7.0; 178 | let ns = vec3(D.w, D.y, D.z) * n_ - vec3(D.x, D.z, D.x); 179 | 180 | let j = p - floor(p * ns.z * ns.z) * 49.; // mod(p,7*7) 181 | 182 | let x_ = floor(j * ns.z); 183 | let y_ = floor(j - x_ * 7.); // mod(j, N) 184 | 185 | let x = x_ * ns.x + ns.y; 186 | let y = y_ * ns.x + ns.y; 187 | let h = Vec4::one() - abs(x) - abs(y); 188 | 189 | let b0 = vec4(x.x, x.y, y.x, y.y); 190 | let b1 = vec4(x.z, x.w, y.z, y.w); 191 | 192 | // vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; 193 | // vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; 194 | let s0 = floor(b0) * 2. + 1.; 195 | let s1 = floor(b1) * 2. + 1.; 196 | let sh = -step(h, Vec4::zero()); 197 | 198 | let a0 = vec4(b0.x, b0.z, b0.y, b0.w) + vec4(s0.x, s0.z, s0.y, s0.w) * vec4(sh.x, sh.x, sh.y, sh.y); 199 | let a1 = vec4(b1.x, b1.z, b1.y, b1.w) + vec4(s1.x, s1.z, s1.y, s1.w) * vec4(sh.z, sh.z, sh.w, sh.w); 200 | 201 | let mut p0 = vec3(a0.x, a0.y, h.x); 202 | let mut p1 = vec3(a0.z, a0.w, h.y); 203 | let mut p2 = vec3(a1.x, a1.y, h.z); 204 | let mut p3 = vec3(a1.z, a1.w, h.w); 205 | 206 | // Normalise gradients 207 | let norm = taylor_inv_sqrt(vec4( 208 | dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3) 209 | )); 210 | p0 = p0 * norm.x; 211 | p1 = p1 * norm.y; 212 | p2 = p2 * norm.z; 213 | p3 = p3 * norm.w; 214 | 215 | // Mix final noise value 216 | let mut m = max_s(-vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)) + 0.6, 0.); 217 | m = m * m; 218 | 42. * dot(m * m, vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3))) 219 | } 220 | } 221 | 222 | impl NoiseImpl for Vec4 { 223 | fn noise1(self) -> f32 { 224 | let yi = Vec4::one(); 225 | let C = vec4( 226 | 0.138196601125011, // (5 - sqrt(5))/20 G4 227 | 0.276393202250021, // 2 * G4 228 | 0.414589803375032, // 3 * G4 229 | -0.447213595499958 // -1 + 4 * G4 230 | ); 231 | // (sqrt(5) - 1)/4 = F4, used once below 232 | let F4: f32 = 0.309016994374947451; 233 | 234 | // First corner 235 | let mut i = floor(self + dot(self, yi * F4)); 236 | let x0 = self - i + dot(i, yi * C.x); 237 | 238 | // Other corners 239 | 240 | // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) 241 | let isX = step(vec3(x0.y, x0.z, x0.w), vec3(x0.x, x0.x, x0.x)); 242 | let isYZ = step(vec3(x0.z, x0.w, x0.w), vec3(x0.y, x0.y, x0.z)); 243 | 244 | // i0.x = dot(isX, vec3(1.0)); 245 | // i0.x = isX.x + isX.y + isX.z; 246 | // i0.yzw = static_cast(1) - isX; 247 | let mut i0 = vec4(isX.x + isX.y + isX.z, 1. - isX.x, 1. - isX.y, 1. - isX.z); 248 | // i0.y += dot(isYZ.xy, vec2(1.0)); 249 | i0.y += isYZ.x + isYZ.y; 250 | //i0.zw += 1.0 - tvec2(isYZ.x, isYZ.y); 251 | i0.z += 1. - isYZ.x; 252 | i0.w += 1. - isYZ.y; 253 | i0.z += isYZ.z; 254 | i0.w += 1. - isYZ.z; 255 | 256 | // i0 now contains the unique values 0,1,2,3 in each channel 257 | let i3 = clamp_s(i0, 0., 1.); 258 | let i2 = clamp_s(i0 - 1., 0., 1.); 259 | let i1 = clamp_s(i0 - 2., 0., 1.); 260 | 261 | // x0 = x0 - 0.0 + 0.0 * C.xxxx 262 | // x1 = x0 - i1 + 0.0 * C.xxxx 263 | // x2 = x0 - i2 + 0.0 * C.xxxx 264 | // x3 = x0 - i3 + 0.0 * C.xxxx 265 | // x4 = x0 - 1.0 + 4.0 * C.xxxx 266 | let x1 = x0 - i1 + C.x; 267 | let x2 = x0 - i2 + C.y; 268 | let x3 = x0 - i3 + C.z; 269 | let x4 = x0 + C.w; 270 | 271 | // Permutations 272 | i = mod_s(i, 289.); 273 | let j0 = permute(permute(permute(permute(i.w) + i.z) + i.y) + i.x); 274 | let j1 = permute(permute(permute(permute( 275 | vec4(i1.w, i2.w, i3.w, 1.) + i.w) + 276 | vec4(i1.z, i2.z, i3.z, 1.) + i.z) + 277 | vec4(i1.y, i2.y, i3.y, 1.) + i.y) + 278 | vec4(i1.x, i2.x, i3.x, 1.) + i.x); 279 | 280 | // Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope 281 | // 7*7*6 = 294, which is close to the ring size 17*17 = 289. 282 | let ip = vec4(1./294., 1./49., 1./7., 0.); 283 | 284 | let mut p0 = grad4(j0, ip); 285 | let mut p1 = grad4(j1.x, ip); 286 | let mut p2 = grad4(j1.y, ip); 287 | let mut p3 = grad4(j1.z, ip); 288 | let mut p4 = grad4(j1.w, ip); 289 | 290 | // Normalise gradients 291 | let norm = 292 | taylor_inv_sqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); 293 | p0 = p0 * norm.x; 294 | p1 = p1 * norm.y; 295 | p2 = p2 * norm.z; 296 | p3 = p3 * norm.w; 297 | p4 = p4 * taylor_inv_sqrt(dot(p4, p4)); 298 | 299 | // Mix contributions from the five corners 300 | let mut m0 = max_s(vec3(0.6, 0.6, 0.6) - vec3(dot(x0, x0), dot(x1, x1), dot(x2, x2)), 0.); 301 | let mut m1 = max_s(vec2(0.6, 0.6) - vec2(dot(x3, x3), dot(x4, x4)), 0.); 302 | m0 = m0 * m0; 303 | m1 = m1 * m1; 304 | 305 | dot(m0 * m0, vec3(dot(p0, x0), dot(p1, x1), dot(p2, x2))) + 306 | dot(m1 * m1, vec2(dot(p3, x3), dot (p4, x4))) * 49. 307 | } 308 | } 309 | 310 | /// Returns a 1D noise value based on the input value `x`. 311 | #[inline] 312 | pub fn noise1(x: T) -> f32 { 313 | x.noise1() 314 | } 315 | 316 | /// Returns a 2D noise value based on the input value `x`. 317 | #[inline] 318 | pub fn noise2(x: T) -> Vec2 { 319 | vec2(x.noise1(), (-x).noise1()) 320 | } 321 | 322 | /// Returns a 3D noise value based on the input value `x`. 323 | #[inline] 324 | pub fn noise3(x: T) -> Vec3 { 325 | let yi = T::one(); 326 | vec3((x - yi).noise1(), x.noise1(), (x + yi).noise1()) 327 | } 328 | 329 | /// Returns a 4D noise value based on the input value `x`. 330 | #[inline] 331 | pub fn noise4(x: T) -> Vec4 { 332 | let yi = T::one(); 333 | vec4( 334 | (x - yi).noise1(), 335 | x.noise1(), 336 | (x + yi).noise1(), 337 | (x + yi + yi).noise1() 338 | ) 339 | } 340 | 341 | #[cfg(test)] 342 | mod test { 343 | 344 | } 345 | -------------------------------------------------------------------------------- /src/builtin/pack.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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 vec::vec::*; 27 | use super::common::{ clamp_s, round }; 28 | use std::mem; 29 | 30 | /// First, converts each component of the normalized floating-point value `v` 31 | /// into 16-bit integer values. Then, the results are packed into the 32 | /// returned 32-bit unsigned integer. 33 | /// 34 | /// The conversion for component `c` of `v` to fixed point is done as follows: 35 | /// ```round(clamp(c, 0, 1) * 65535.0)``` 36 | /// 37 | /// The first component of the vector will be written to the least significant 38 | /// bits of the output; the last component will be written to the most 39 | /// significant bits. 40 | /// 41 | /// # Example 42 | /// 43 | /// ``` 44 | /// 45 | /// ``` 46 | #[inline] 47 | #[allow(non_snake_case)] 48 | pub fn packUnorm2x16(v: Vec2) -> u32 { 49 | let us = round(clamp_s(v, 0., 1.) * 65535.); 50 | let pack: [u16; 2] = [us.y as u16, us.x as u16]; 51 | let r: &u32 = unsafe { mem::transmute(&pack) }; 52 | *r 53 | } 54 | 55 | /// First, unpacks a single 32-bit unsigned integer `p` into a pair of 16-bit 56 | /// unsigned integers. Then, each component is converted to a normalized 57 | /// floating-point value to generate the returned two-component vector. 58 | /// 59 | /// The conversion for unpacked fixed-point value `f` to floating point is done 60 | /// as follows: `f / 65535.0`. 61 | /// 62 | /// The first component of the returned vector will be extracted from the least 63 | /// significant bits of the input; the last component will be extracted from 64 | /// the most significant bits. 65 | /// 66 | /// # Example 67 | /// 68 | /// ``` 69 | /// 70 | /// ``` 71 | #[inline] 72 | #[allow(non_snake_case)] 73 | pub fn unpackUnorm2x16(p: u32) -> Vec2 { 74 | let unpack: &[u16; 2] = unsafe { mem::transmute(&p) }; 75 | let v = vec2(unpack[1] as f32, unpack[0] as f32); 76 | // v / 65535. 77 | v * 1.5259021896696421759365224689097e-5 78 | } 79 | 80 | /// First, converts each component of the normalized floating-point value `v` 81 | /// into 8-bit integer values. Then, the results are packed into the 82 | /// returned 32-bit unsigned integer. 83 | /// 84 | /// The conversion for component `c` of `v` to fixed point is done as follows: 85 | /// ```round(clamp(c, 0, 1) * 255.0)``` 86 | /// 87 | /// The first component of the vector will be written to the least significant 88 | /// bits of the output; the last component will be written to the most 89 | /// significant bits. 90 | /// 91 | /// # Example 92 | /// 93 | /// ``` 94 | /// 95 | /// ``` 96 | #[inline] 97 | #[allow(non_snake_case)] 98 | pub fn packUnorm4x8(v: Vec4) -> u32 { 99 | let us = round(clamp_s(v, 0., 1.) * 255.); 100 | let pack: [u8; 4] = [us.w as u8, us.z as u8, us.y as u8, us.x as u8]; 101 | let r: &u32 = unsafe { mem::transmute(&pack) }; 102 | *r 103 | } 104 | 105 | /// First, unpacks a single 32-bit unsigned integer `p` into four 8-bit unsigned 106 | /// integers. Then, each component is converted to a normalized floating-point 107 | /// value to generate the returned four-component vector. 108 | /// 109 | /// The conversion for unpacked fixed-point value `f` to floating point is done 110 | /// as follows: `f / 255.0`. 111 | /// 112 | /// The first component of the returned vector will be extracted from the least 113 | /// significant bits of the input; the last component will be extracted from 114 | /// the most significant bits. 115 | /// 116 | /// # Example 117 | /// 118 | /// ``` 119 | /// 120 | /// ``` 121 | #[inline] 122 | #[allow(non_snake_case)] 123 | pub fn unpackUnorm4x8(p: u32) -> Vec4 { 124 | let unpack: &[u8; 4] = unsafe { mem::transmute(&p) }; 125 | let v = 126 | vec4( 127 | unpack[3] as f32, 128 | unpack[2] as f32, 129 | unpack[1] as f32, 130 | unpack[0] as f32 131 | ); 132 | // v / 255. 133 | v * 0.0039215686274509803921568627451 134 | } 135 | 136 | /// First, converts each component of the normalized floating-point value `v` 137 | /// into 16-bit integer values. Then, the results are packed into the 138 | /// returned 32-bit unsigned integer. 139 | /// 140 | /// The conversion for component `c` of `v` to fixed point is done as follows: 141 | /// ```round(clamp(c, -1, 1) * 32767.0)``` 142 | /// 143 | /// The first component of the vector will be written to the least significant 144 | /// bits of the output; the last component will be written to the most 145 | /// significant bits. 146 | /// 147 | /// # Example 148 | /// 149 | /// ``` 150 | /// 151 | /// ``` 152 | #[inline] 153 | #[allow(non_snake_case)] 154 | pub fn packSnorm2x16(v: Vec2) -> u32 { 155 | let is = round(clamp_s(v, -1., 1.) * 32767.); 156 | let pack: [i16; 2] = [is.y as i16, is.x as i16]; 157 | let r: &u32 = unsafe { mem::transmute(&pack) }; 158 | *r 159 | } 160 | 161 | /// First, unpacks a single 32-bit unsigned integer `p` into two 16-bit signed 162 | /// integers. Then, each component is converted to a normalized floating-point 163 | /// value to generate the returned two-component vector. 164 | /// 165 | /// The conversion for unpacked fixed-point value `f` to floating point is 166 | /// done as follows: `clamp(f / 32767.0, -1, +1)` 167 | /// 168 | /// The first component of the returned vector will be extracted from the 169 | /// least significant bits of the input; the last component will be extracted 170 | /// from the most significant bits. 171 | /// 172 | /// # Example 173 | /// 174 | /// ``` 175 | /// 176 | /// ``` 177 | #[inline] 178 | #[allow(non_snake_case)] 179 | pub fn unpackSnorm2x16(p: u32) -> Vec2 { 180 | let unpack: &[i16; 2] = unsafe { mem::transmute(&p) }; 181 | let v = vec2(unpack[1] as f32, unpack[0] as f32); 182 | // v / 32767. 183 | clamp_s(v * 3.0518509475997192297128208258309e-5, -1., 1.) 184 | } 185 | 186 | /// First, converts each component of the normalized floating-point value `v` 187 | /// into 8-bit integer values. Then, the results are packed into the 188 | /// returned 32-bit unsigned integer. 189 | /// 190 | /// The conversion for component `c` of `v` to fixed point is done as follows: 191 | /// ```round(clamp(c, -1, 1) * 127.0)``` 192 | /// 193 | /// The first component of the vector will be written to the least significant 194 | /// bits of the output; the last component will be written to the most 195 | /// significant bits. 196 | /// 197 | /// # Example 198 | /// 199 | /// ``` 200 | /// 201 | /// ``` 202 | #[inline] 203 | #[allow(non_snake_case)] 204 | pub fn packSnorm4x8(v: Vec4) -> u32 { 205 | let is = round(clamp_s(v, -1., 1.) * 127.); 206 | let pack: [i8; 4] = [is.w as i8, is.z as i8, is.y as i8, is.x as i8]; 207 | let r: &u32 = unsafe { mem::transmute(&pack) }; 208 | *r 209 | } 210 | 211 | /// First, unpacks a single 32-bit unsigned integer `p` into four 8-bit signed 212 | /// integers. Then, each component is converted to a normalized floating-point 213 | /// value to generate the returned four-component vector. 214 | /// 215 | /// The conversion for unpacked fixed-point value `f` to floating point is 216 | /// done as follows: `clamp(f / 127.0, -1, +1)` 217 | /// 218 | /// The first component of the returned vector will be extracted from the 219 | /// least significant bits of the input; the last component will be extracted 220 | /// from the most significant bits. 221 | /// 222 | /// # Example 223 | /// 224 | /// ``` 225 | /// 226 | /// ``` 227 | #[inline] 228 | #[allow(non_snake_case)] 229 | pub fn unpackSnorm4x8(p: u32) -> Vec4 { 230 | let unpack: &[i8; 4] = unsafe { mem::transmute(&p) }; 231 | let v = 232 | 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 | 243 | /// Returns a double-precision value obtained by packing the components of `v` 244 | /// into a 64-bit value. 245 | /// 246 | /// If an IEEE 754 Iinf or **NaN** is created, it will not signal, and the 247 | /// resulting floating point value is unspecified. Otherwise, the bit-level 248 | /// representation of `v` is preserved. The first vector component specifies 249 | /// the 32 least significant bits; the second component specifies the 32 most 250 | /// significant bits. 251 | /// 252 | /// # Example 253 | /// 254 | /// ``` 255 | /// 256 | /// ``` 257 | #[allow(non_snake_case)] 258 | #[inline(always)] 259 | pub fn packDouble2x32(v: UVec2) -> f64 { 260 | let f: &f64 = unsafe { mem::transmute(&v) }; 261 | *f 262 | } 263 | 264 | /// Returns a two-component unsigned integer vector representation of `v`. 265 | /// The bit-level representation of `v` is preserved. 266 | /// 267 | /// The first component of the vector contains the 32 least significant bits 268 | /// of the double; the second component consists the 32 most significant bits. 269 | /// 270 | /// # Example 271 | /// 272 | /// ``` 273 | /// 274 | /// ``` 275 | #[allow(non_snake_case)] 276 | #[inline(always)] 277 | pub fn unpackDouble2x32(v: f64) -> UVec2 { 278 | let uv: &UVec2 = unsafe { mem::transmute(&v) }; 279 | *uv 280 | } 281 | -------------------------------------------------------------------------------- /src/builtin/trig.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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 basenum::BaseFloat; 27 | use traits::GenFloat; 28 | use num::Float; 29 | 30 | /// Converts `degrees` to radians, i.e., `π/180 * degrees`. 31 | #[inline(always)] 32 | pub fn radians>(degrees: T) -> T { 33 | degrees.map(BaseFloat::to_radians) 34 | } 35 | 36 | /// Converts `radians` to degrees, i.e., `180/π * radians`. 37 | #[inline(always)] 38 | pub fn degrees>(radians: T) -> T { 39 | radians.map(BaseFloat::to_degrees) 40 | } 41 | 42 | /// The standard trigonometric sine function. 43 | #[inline(always)] 44 | pub fn sin>(angle: T) -> T { 45 | angle.map(Float::sin) 46 | } 47 | 48 | /// The standard trigonometric cosine function. 49 | #[inline(always)] 50 | pub fn cos>(angle: T) -> T { 51 | angle.map(Float::cos) 52 | } 53 | 54 | /// The standard trigonometric tangent. 55 | #[inline(always)] 56 | pub fn tan>(angle: T) -> T { 57 | angle.map(Float::tan) 58 | } 59 | 60 | /// Returns an angle whose sine is `x`. 61 | /// 62 | /// The range of values returned by this function is `[-π/2, π/2]`. 63 | /// 64 | /// Results are undefined if `|x| > 1`. 65 | #[inline(always)] 66 | pub fn asin>(x: T) -> T { 67 | x.map(Float::asin) 68 | } 69 | 70 | /// Returns an angle whose cosine is `x`. 71 | /// 72 | /// The range of values returned by this function is `[0, π]`. 73 | /// 74 | /// Results are undefined if `∣x∣ > 1`. 75 | #[inline(always)] 76 | pub fn acos>(x: T) -> T { 77 | x.map(Float::acos) 78 | } 79 | 80 | /// Returns an angle whose tangent is `y / x`. 81 | /// 82 | /// The signs of `x` and `y` are used to determine what quadrant the angle is 83 | /// in. 84 | /// 85 | /// The range of values returned by this function is `[−π, π]`. 86 | /// 87 | /// Results are undefined if `x` and `y` are both `0`. 88 | /// 89 | /// # Note 90 | /// 91 | /// `atan2` is not a GLSL function name. 92 | #[inline(always)] 93 | pub fn atan2>(y: T, x: T) -> T { 94 | x.zip(y, Float::atan2) 95 | } 96 | 97 | /// Returns an angle whose tangent is `y_over_x`. 98 | /// 99 | /// The range of values returned by this function is `[-π/2, π/2]`. 100 | #[inline(always)] 101 | pub fn atan>(y_over_x: T) -> T { 102 | y_over_x.map(Float::atan) 103 | } 104 | 105 | /// Returns the hyperbolic sine function (ex - e-x) / 2. 106 | #[inline(always)] 107 | pub fn sinh>(x: T) -> T { 108 | x.map(Float::sinh) 109 | } 110 | 111 | /// Returns the hyperbolic cosine function (ex + e-x) / 2. 112 | #[inline(always)] 113 | pub fn cosh>(x: T) -> T { 114 | x.map(Float::cosh) 115 | } 116 | 117 | /// Returns the hyperbolic tangent function `sinh(x)/cosh(x)`. 118 | #[inline(always)] 119 | pub fn tanh>(x: T) -> T { 120 | x.map(Float::tanh) 121 | } 122 | 123 | /// Arc hyperbolic sine; returns the inverse of **sinh**. 124 | #[inline(always)] 125 | pub fn asinh>(x: T) -> T { 126 | x.map(Float::asinh) 127 | } 128 | 129 | /// Arc hyperbolic cosine; returns the non-negative inverse of **cosh**. 130 | /// 131 | /// Results are undefined if `x < 1`. 132 | #[inline(always)] 133 | pub fn acosh>(x: T) -> T { 134 | x.map(Float::acosh) 135 | } 136 | 137 | /// Arc hyperbolic tangent; returns the inverse of **tanh**. 138 | /// 139 | /// Results are undefined if `∣x∣ ≥ 1`. 140 | #[inline(always)] 141 | pub fn atanh>(x: T) -> T { 142 | x.map(Float::atanh) 143 | } 144 | -------------------------------------------------------------------------------- /src/builtin/vecrel.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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 basenum::Primitive; 27 | use vec::traits::{ GenVec, GenBVec }; 28 | use vec::vec::{ Vector2, Vector3, Vector4 }; 29 | use std::cmp::{ PartialEq, PartialOrd }; 30 | 31 | pub trait VecRel: GenVec { 32 | fn zip_bool(&self, rhs: &Self, fn(&T, &T) -> bool) -> B; 33 | } 34 | 35 | macro_rules! impl_vecrel_for( 36 | ($t: ident, $($field: ident), +) => { 37 | impl VecRel> for $t { 38 | #[inline(always)] 39 | fn zip_bool(&self, rhs: &$t, oper: fn(&T, &T) -> bool) -> $t { 40 | $t::new($(oper(&(self.$field), &(rhs.$field))), +) 41 | } 42 | } 43 | } 44 | ); 45 | 46 | impl_vecrel_for! { Vector2, x, y } 47 | impl_vecrel_for! { Vector3, x, y, z } 48 | impl_vecrel_for! { Vector4, x, y, z, w } 49 | 50 | /// Returns the component-wise compare of `x < y`. 51 | /// 52 | /// # Example 53 | /// 54 | /// ``` 55 | /// use glm::*; 56 | /// 57 | /// let a = ivec4(1, 2, 3, 4); 58 | /// let b = ivec4(2, 3, 4, 5); 59 | /// assert_eq!(lessThan(b, a), bvec4(false, false, false, false)); 60 | /// assert!(all(lessThan(a, b))); 61 | /// ``` 62 | #[inline(always)] 63 | #[allow(non_snake_case)] 64 | pub fn lessThan>(x: V, y: V) -> B { 65 | x.zip_bool(&y, PartialOrd::lt) 66 | } 67 | 68 | /// Returns the component-wise compare of `x ≤ y`. 69 | /// 70 | /// # Example 71 | /// 72 | /// ``` 73 | /// use glm::*; 74 | /// 75 | /// let a = ivec4(1, 2, 3, 4); 76 | /// let b = ivec4(2, 2, 3, 3); 77 | /// assert_eq!(lessThanEqual(a, b), bvec4(true, true, true, false)); 78 | /// assert_eq!(lessThanEqual(a, b), not(greaterThan(a, b))); 79 | /// ``` 80 | #[inline(always)] 81 | #[allow(non_snake_case)] 82 | pub fn lessThanEqual 83 | < 84 | T: Primitive, B: GenBVec, V: VecRel 85 | >(x: V, y: V) -> B { 86 | x.zip_bool(&y, PartialOrd::le) 87 | } 88 | 89 | /// Returns the component-wise compare of `x > y`. 90 | /// 91 | /// # Example 92 | /// 93 | /// ``` 94 | /// use glm::*; 95 | /// 96 | /// let a = ivec4(1, 2, 3, 4); 97 | /// let b = ivec4(2, 2, 3, 3); 98 | /// assert_eq!(greaterThan(a, b), bvec4(false, false, false, true)); 99 | /// assert_eq!(greaterThan(a, b), lessThan(b, a)); 100 | /// ``` 101 | #[inline(always)] 102 | #[allow(non_snake_case)] 103 | pub fn greaterThan 104 | < 105 | T: Primitive, B: GenBVec, V: VecRel 106 | >(x: V, y: V) -> B { 107 | x.zip_bool(&y, PartialOrd::gt) 108 | } 109 | 110 | /// Returns the component-wise compare of `x ≥ y`. 111 | /// 112 | /// # Example 113 | /// 114 | /// ``` 115 | /// use glm::*; 116 | /// 117 | /// let a = ivec4(1, 2, 3, 4); 118 | /// let b = ivec4(2, 2, 3, 3); 119 | /// assert_eq!(greaterThanEqual(a, b), bvec4(false, true, true, true)); 120 | /// assert_eq!(greaterThanEqual(a, b), lessThanEqual(b, a)); 121 | /// assert_eq!(greaterThanEqual(a, b), not(lessThan(a, b))); 122 | /// ``` 123 | #[inline(always)] 124 | #[allow(non_snake_case)] 125 | pub fn greaterThanEqual 126 | < 127 | T: Primitive, B: GenBVec, V: VecRel 128 | >(x: V, y: V) -> B { 129 | x.zip_bool(&y, PartialOrd::ge) 130 | } 131 | 132 | /// Returns the component-wise compare of `x == y`. 133 | /// 134 | /// # Example 135 | /// 136 | /// ``` 137 | /// use glm::*; 138 | /// 139 | /// let a = ivec4(1, 2, 3, 4); 140 | /// let b = ivec4(2, 2, 3, 3); 141 | /// assert_eq!(equal(a, b), bvec4(false, true, true, false)); 142 | /// assert_eq!(equal(a, b), equal(b, a)); 143 | /// ``` 144 | #[inline(always)] 145 | pub fn equal>(x: V, y: V) -> B { 146 | x.zip_bool(&y, PartialEq::eq) 147 | } 148 | 149 | /// Returns the component-wise compare of `x ≠ y`. 150 | /// 151 | /// # Example 152 | /// 153 | /// ``` 154 | /// use glm::*; 155 | /// 156 | /// let a = ivec4(1, 2, 3, 4); 157 | /// let b = ivec4(2, 2, 3, 3); 158 | /// assert_eq!(notEqual(a, b), bvec4(true, false, false, true)); 159 | /// assert_eq!(notEqual(a, b), not(equal(b, a))); 160 | /// ``` 161 | #[inline(always)] 162 | #[allow(non_snake_case)] 163 | pub fn notEqual>(x: V, y: V) -> B { 164 | x.zip_bool(&y, PartialEq::ne) 165 | } 166 | 167 | /// Returns `true` if any component of `x` is **true**. 168 | #[inline(always)] 169 | pub fn any(bvec: T) -> bool { 170 | bvec.any() 171 | } 172 | 173 | /// Returns `true` only if all components of `x` are **true**. 174 | #[inline(always)] 175 | pub fn all(bvec: T) -> bool { 176 | bvec.all() 177 | } 178 | 179 | /// Returns the component-wise logical complement of `x`. 180 | #[inline(always)] 181 | pub fn not(bvec: T) -> T { 182 | bvec.not() 183 | } 184 | -------------------------------------------------------------------------------- /src/cast.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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 vec::traits::GenVec; 26 | use vec::vec::*; 27 | use std::default::Default; 28 | use num::{ ToPrimitive, Zero }; 29 | 30 | /// This trait is like the `std::num::ToPrimitive`, but function `to_bool()` 31 | /// is added. 32 | pub trait ToPrim: Primitive { 33 | 34 | fn to_i32(&self) -> Option; 35 | 36 | fn to_u32(&self) -> Option; 37 | 38 | fn to_f32(&self) -> Option; 39 | 40 | fn to_f64(&self) -> Option; 41 | 42 | fn to_bool(&self) -> Option; 43 | } 44 | 45 | macro_rules! impl_ToPrim_for { 46 | ($($t: ident),+) => { 47 | $( 48 | impl ToPrim for $t { 49 | #[inline] 50 | fn to_i32(&self) -> Option { 51 | ToPrimitive::to_i32(self) 52 | } 53 | #[inline] 54 | fn to_u32(&self) -> Option { 55 | ToPrimitive::to_u32(self) 56 | } 57 | #[inline] 58 | fn to_f32(&self) -> Option { 59 | ToPrimitive::to_f32(self) 60 | } 61 | #[inline] 62 | fn to_f64(&self) -> Option { 63 | ToPrimitive::to_f64(self) 64 | } 65 | #[inline] 66 | fn to_bool(&self) -> Option { 67 | let b = if self.is_zero() { false } else { true }; 68 | Some(b) 69 | } 70 | } 71 | )+ 72 | }; 73 | } 74 | 75 | impl_ToPrim_for! { i32, u32, f32, f64 } 76 | 77 | impl ToPrim for bool { 78 | #[inline] 79 | fn to_i32(&self) -> Option { 80 | let i = if *self { 1 } else { 0 }; 81 | Some(i) 82 | } 83 | #[inline] 84 | fn to_u32(&self) -> Option { 85 | let i = if *self { 1 } else { 0 }; 86 | Some(i) 87 | } 88 | #[inline] 89 | fn to_f32(&self) -> Option { 90 | let i = if *self { 1. } else { 0. }; 91 | Some(i) 92 | } 93 | #[inline] 94 | fn to_f64(&self) -> Option { 95 | let i = if *self { 1. } else { 0. }; 96 | Some(i) 97 | } 98 | #[inline] 99 | fn to_bool(&self) -> Option { 100 | Some(*self) 101 | } 102 | } 103 | 104 | /// This trait provides parameterized function `from`. 105 | pub trait PrimCast: ToPrim { 106 | 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 234 | < 235 | F: PrimCast, 236 | T: PrimCast, 237 | GT: GenPrimitive + GenVec 238 | >: GenPrimitive { 239 | 240 | /// Convertes _self_ to a value of Vector type. 241 | /// 242 | /// # Example 243 | /// 244 | /// ```rust 245 | /// use glm::*; 246 | /// 247 | /// assert_eq!(to_bvec2(0_i32), bvec2(false, false)); 248 | /// assert_eq!(to_dvec4(bvec4(true, true, false, true)), dvec4(1., 1., 0., 1.)); 249 | /// ``` 250 | fn to(self) -> Option; 251 | } 252 | 253 | macro_rules! impl_ToVector_for_scalar { 254 | ($t: ident, $v: ident, $($field: ident),+) => { 255 | impl ToVector<$t, T, $v> for $t { 256 | #[inline] 257 | fn to(self) -> Option<$v> { 258 | PrimCast::from(self).map(|t| -> $v { 259 | $v { $($field: t),+ } 260 | }) 261 | } 262 | } 263 | } 264 | } 265 | 266 | macro_rules! impl_ToVectors_for_scalar { 267 | ($($t: ident),+) => { 268 | $( 269 | impl_ToVector_for_scalar! { $t, Vector2, x, y } 270 | impl_ToVector_for_scalar! { $t, Vector3, x, y, z } 271 | impl_ToVector_for_scalar! { $t, Vector4, x, y, z, w } 272 | )+ 273 | } 274 | } 275 | 276 | impl_ToVectors_for_scalar! { i32, u32, f32, f64, bool } 277 | 278 | // TODO: to support convertion between vectors with different dimensions. 279 | // by introducing something like `DimCast`. 280 | 281 | macro_rules! impl_ToVector_for_vector { 282 | ($({ $v: ident, $($field: ident),+ }),+) => { 283 | $( 284 | impl ToVector> for $v { 285 | #[inline] 286 | fn to(self) -> Option<$v> { 287 | let os = [$(T::from(self.$field)),+]; 288 | if os.iter().any(|&o| -> bool { o.is_none() }) { 289 | None 290 | } else { 291 | // all Primitives implement `Default`. 292 | let mut zero: $v = $v { $($field: Default::default()),+ }; 293 | os.iter().fold(0, |i, &o| -> usize { 294 | zero[i] = o.unwrap(); 295 | i + 1 296 | }); 297 | Some(zero) 298 | } 299 | } 300 | } 301 | )+ 302 | } 303 | } 304 | 305 | impl_ToVector_for_vector! { 306 | { Vector2, x, y }, 307 | { Vector3, x, y, z }, 308 | { Vector4, x, y, z, w } 309 | } 310 | 311 | macro_rules! def_cast_vector_fun { 312 | ($({ $nm: ident, $s: ty, $v: ty }),+) => { 313 | $( 314 | #[inline] 315 | pub fn $nm>(gp: F) -> $v { 316 | gp.to().unwrap() 317 | } 318 | )+ 319 | } 320 | } 321 | 322 | def_cast_vector_fun! { 323 | { to_ivec2, i32, IVec2 }, 324 | { to_ivec3, i32, IVec3 }, 325 | { to_ivec4, i32, IVec4 }, 326 | { to_uvec2, u32, UVec2 }, 327 | { to_uvec3, u32, UVec3 }, 328 | { to_uvec4, u32, UVec4 }, 329 | { to_vec2, f32, Vec2 }, 330 | { to_vec3, f32, Vec3 }, 331 | { to_vec4, f32, Vec4 }, 332 | { to_dvec2, f64, DVec2 }, 333 | { to_dvec3, f64, DVec3 }, 334 | { to_dvec4, f64, DVec4 }, 335 | { to_bvec2, bool, BVec2 }, 336 | { to_bvec3, bool, BVec3 }, 337 | { to_bvec4, bool, BVec4 } 338 | } 339 | 340 | // TODO: support casting matrices to vectors. Just returns the first column. 341 | 342 | #[cfg(test)] 343 | mod test { 344 | 345 | use vec::vec::*; 346 | use super::*; 347 | 348 | #[test] 349 | fn test_int() { 350 | assert_eq!(int(1_f32), 1_i32); 351 | assert_eq!(int(true), 1_i32); 352 | assert_eq!(int(false), 0_i32); 353 | } 354 | 355 | #[test] 356 | fn test_boolean() { 357 | assert_eq!(boolean(uvec2(0, 1)), false); 358 | assert_eq!(boolean(vec3(1., -1., 0.)), true); 359 | } 360 | 361 | #[test] 362 | fn test_float() { 363 | assert_eq!(float(bvec2(true, false)), 1.); 364 | assert_eq!(float(123_u32), 123.); 365 | assert_eq!(float(0_f64), 0.); 366 | } 367 | 368 | #[test] 369 | fn test_to_vec() { 370 | assert_eq!(to_vec2(bvec2(true, false)), vec2(1., 0.)); 371 | assert_eq!(to_bvec3(ivec3(0, 1, -1)), bvec3(false, true, true)); 372 | } 373 | } 374 | -------------------------------------------------------------------------------- /src/ext/common.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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::BaseFloat; 25 | use traits::GenFloat; 26 | use num::Float; 27 | 28 | /// Returns the reciprocal (inverse) of float number `x`. 29 | /// 30 | /// # Example 31 | /// 32 | /// ``` 33 | /// use glm::ext::recip; 34 | /// 35 | /// let x = 2f32; 36 | /// let y = glm::vec3(1., 2., 4.); 37 | /// assert_eq!(recip(x), 0.5); 38 | /// assert_eq!(recip(y), glm::vec3(1., 0.5, 0.25)); 39 | /// ``` 40 | #[inline(always)] 41 | pub fn recip>(x: T) -> T { 42 | x.map(Float::recip) 43 | } 44 | -------------------------------------------------------------------------------- /src/ext/consts.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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::BaseFloat; 25 | use traits::GenFloat; 26 | use 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/ext/exp.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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::{ BaseNum, BaseFloat }; 25 | use traits::{ GenNum, GenFloat }; 26 | use num::Float; 27 | 28 | /// Returns the cubic root. 29 | #[inline(always)] 30 | pub fn cbrt>(x: T) -> T { 31 | x.map(Float::cbrt) 32 | } 33 | 34 | /// `x * x`. 35 | #[inline(always)] 36 | pub fn pow2>(x: T) -> T { 37 | x * x 38 | } 39 | 40 | /// `x * x * x`. 41 | #[inline(always)] 42 | pub fn pow3>(x: T) -> T { 43 | x * x * x 44 | } 45 | 46 | /// Raise a number to an integer power. 47 | #[inline(always)] 48 | pub fn powi>(x: T, y: i32) -> T { 49 | x.map(|f| -> F { 50 | Float::powi(f, y) 51 | }) 52 | } 53 | -------------------------------------------------------------------------------- /src/ext/geom.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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::BaseFloat; 25 | use traits::GenFloat; 26 | use vec::traits::GenFloatVec; 27 | use builtin as bif; 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/ext/matrix/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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::BaseFloat; 25 | use vec::traits::GenFloatVec; 26 | use mat::traits::GenSquareMat; 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 69 | < 70 | F: BaseFloat, C: GenFloatVec, M: GenSquareMat 71 | >(m: &M) -> bool { 72 | let y = F::zero(); 73 | !m.determinant().is_approx_eq(&y) 74 | } 75 | -------------------------------------------------------------------------------- /src/ext/matrix/transform.rs: -------------------------------------------------------------------------------- 1 | use basenum::BaseFloat; 2 | use builtin::{ cross, dot, normalize }; 3 | use traits::GenFloat; 4 | use num; 5 | use mat::mat::{ Matrix3, Matrix4 }; 6 | use vec::vec::{ Vector3, Vector4 }; 7 | 8 | /// Builds a translation 4 * 4 matrix created from a vector of 3 components. 9 | /// 10 | /// Uses input matrix `m` and translation vector coordinates `v`. 11 | /// 12 | /// # Example 13 | /// 14 | /// ```rust 15 | /// # extern crate num; 16 | /// # extern crate glm; 17 | /// # fn main() { 18 | /// use glm::*; 19 | /// use glm::ext::*; 20 | /// 21 | /// let matrix = translate(&num::one(), vec3(1., 2., 3.)); 22 | /// assert_eq!(matrix[3], vec4(1., 2., 3., 1.)); 23 | /// # } 24 | /// ``` 25 | #[inline] 26 | pub fn translate( 27 | m: &Matrix4, 28 | v: Vector3 29 | ) -> Matrix4 30 | where 31 | T : BaseFloat 32 | { 33 | Matrix4::new( 34 | m.c0, m.c1, m.c2, 35 | m.c0 * v.x + m.c1 * v.y + m.c2 * v.z + m.c3) 36 | } 37 | 38 | /// Creates a matrix for a symetric perspective-view frustum based on the default handedness. 39 | /// 40 | /// `fov_y` is the field of view angle in the y direction in radians. 41 | /// The `aspect` ratio determines the field of view in the x direction. 42 | /// `near_z` is the distance from the viewer to the near clipping plane (always positive) and 43 | /// `far_z` is the distance from the viewer to the far clipping plane (always positive). 44 | #[inline] 45 | pub fn perspective( 46 | fov_y: T, 47 | aspect: T, 48 | z_near: T, 49 | z_far: T 50 | ) -> Matrix4 51 | where 52 | T : BaseFloat 53 | { 54 | // TODO: make this a compile option 55 | perspective_rh(fov_y, aspect, z_near, z_far) 56 | } 57 | 58 | /// Creates a matrix for a right handed, symetric perspective-view frustum. 59 | /// 60 | /// `fov_y` is the field of view angle in the y direction in radians. 61 | /// The `aspect` ratio determines the field of view in the x direction. 62 | /// `near_z` is the distance from the viewer to the near clipping plane (always positive) and 63 | /// `far_z` is the distance from the viewer to the far clipping plane (always positive). 64 | #[inline] 65 | pub fn perspective_rh( 66 | fov_y: T, 67 | aspect: T, 68 | z_near: T, 69 | z_far: T 70 | ) -> Matrix4 71 | where 72 | T : BaseFloat 73 | { 74 | let zero = num::zero::(); 75 | let one = num::one::(); 76 | let two = one + one; 77 | let q = one / (fov_y / two).tan(); 78 | let a = q / aspect; 79 | let b = (z_near + z_far) / (z_near - z_far); 80 | let c = (two * z_near * z_far) / (z_near - z_far); 81 | 82 | Matrix4::new( 83 | Vector4::new( a, zero, zero, zero), 84 | Vector4::new(zero, q, zero, zero), 85 | Vector4::new(zero, zero, b, zero - one), 86 | Vector4::new(zero, zero, c, zero) 87 | ) 88 | } 89 | 90 | /// Builds a rotation 4 * 4 matrix created from an axis vector and an angle. 91 | /// 92 | /// `m` as the input matrix multiplied by this rotation matrix. 93 | /// `angle` is the rotation angle expressed in radians. 94 | /// Rotation `axis` is recommended to be normalized. 95 | #[inline] 96 | pub fn rotate( 97 | m: &Matrix4, 98 | angle: T, 99 | v: Vector3 100 | ) -> Matrix4 101 | where 102 | T : BaseFloat + GenFloat 103 | { 104 | let zero = num::zero::(); 105 | let one = num::one::(); 106 | 107 | let a = angle; 108 | let (s, c) = a.sin_cos(); 109 | let axis = normalize(v); 110 | let temp = axis * (one - c); 111 | 112 | let rotate = Matrix3::new( 113 | Vector3::new( 114 | c + temp.x * axis.x, 115 | temp.x * axis.y + s * axis.z, 116 | temp.x * axis.z - s * axis.y), 117 | Vector3::new( 118 | temp.y * axis.x - s * axis.z, 119 | c + temp.y * axis.y, 120 | temp.y * axis.z + s * axis.x), 121 | Vector3::new( 122 | temp.z * axis.x + s * axis.y, 123 | temp.z * axis.y - s * axis.x, 124 | c + temp.z * axis.z) 125 | ); 126 | 127 | Matrix4::new( 128 | m.c0 * rotate.c0.x + m.c1 * rotate.c0.y + m.c2 * rotate.c0.z, 129 | m.c0 * rotate.c1.x + m.c1 * rotate.c1.y + m.c2 * rotate.c1.z, 130 | m.c0 * rotate.c2.x + m.c1 * rotate.c2.y + m.c2 * rotate.c2.z, 131 | m.c3 132 | ) 133 | } 134 | 135 | /// Builds a scale 4 * 4 matrix created from 3 scalars. 136 | /// 137 | /// `m` is the input matrix multiplied by this scale matrix. 138 | /// `v` is the ratio of scaling for each axis. 139 | #[inline] 140 | pub fn scale( 141 | m: &Matrix4, 142 | v: Vector3 143 | ) -> Matrix4 144 | where 145 | T : BaseFloat + GenFloat 146 | { 147 | Matrix4::new( 148 | m.c0 * v.x, 149 | m.c1 * v.y, 150 | m.c2 * v.z, 151 | m.c3) 152 | } 153 | 154 | /// Build a look at view matrix based on the default handedness. 155 | /// 156 | /// View matrix is based on the `eye` position of the camera, `center` position where the camera is 157 | /// looking at and a normalized `up` vector, how the camera is oriented. Typically (0, 0, 1) 158 | #[inline] 159 | pub fn look_at( 160 | eye: Vector3, 161 | center: Vector3, 162 | up: Vector3 163 | ) -> Matrix4 164 | where 165 | T : BaseFloat + GenFloat 166 | { 167 | // TODO: make handedness configurable 168 | look_at_rh::(eye, center, up) 169 | } 170 | 171 | /// Build a right handed look at view matrix. 172 | /// 173 | /// View matrix is based on the `eye` position of the camera, `center` position where the camera is 174 | /// looking at and a normalized `up` vector, how the camera is oriented. Typically (0, 0, 1) 175 | #[inline] 176 | pub fn look_at_rh( 177 | eye: Vector3, 178 | center: Vector3, 179 | up: Vector3 180 | ) -> Matrix4 181 | where 182 | T : BaseFloat + GenFloat 183 | { 184 | let zero = num::zero::(); 185 | let one = num::one::(); 186 | let f = normalize(center - eye); 187 | let s = normalize(cross(f, up)); 188 | let u = cross(s, f); 189 | Matrix4::new( 190 | Vector4::new(s.x, u.x,-f.x, zero), 191 | Vector4::new(s.y, u.y,-f.y, zero), 192 | Vector4::new(s.z, u.z,-f.z, zero), 193 | Vector4::new(-dot(s, eye), -dot(u, eye), dot(f, eye), one) 194 | ) 195 | } 196 | 197 | #[cfg(test)] 198 | mod test { 199 | use num; 200 | use std::f32; 201 | use vec::vec::{ vec3, vec4 }; 202 | use ext::{ perspective, translate }; 203 | 204 | #[test] 205 | fn test_translate() { 206 | let v = vec3(1.0, 3.0, 2.0); 207 | let m = num::one(); 208 | let t = translate(&m, v); 209 | assert_eq!(t[0], vec4(1., 0., 0., 0.)); 210 | assert_eq!(t[1], vec4(0., 1., 0., 0.)); 211 | assert_eq!(t[2], vec4(0., 0., 1., 0.)); 212 | assert_eq!(t[3], v.extend(1.)); 213 | } 214 | 215 | #[test] 216 | fn test_perspective() { 217 | let p = perspective(f32::consts::PI * 2.0 * 45.0 / 360.0, 1920.0 / 1080.0, 0.1, 100.0); 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /src/ext/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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/ext/trig.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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::BaseFloat; 25 | use traits::GenFloat; 26 | use num::Float; 27 | 28 | /// Simultaneously computes the sine and cosine of `x`, returns 29 | /// `(sin(x), cos(x))`. 30 | /// 31 | /// # Example 32 | /// 33 | /// ```rust 34 | /// use glm::*; 35 | /// use glm::ext::*; 36 | /// 37 | /// let v = vec2(0., half_pi()); 38 | /// let (s, c) = sin_cos(v); 39 | /// assert!(is_approx_eq(&s, &vec2(0., 1.))); 40 | /// assert!(is_approx_eq(&c, &vec2(1., 0.))); 41 | /// ``` 42 | #[inline(always)] 43 | pub fn sin_cos>(x: T) -> (T, T) { 44 | x.split(Float::sin_cos) 45 | } 46 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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 | extern crate rand; 127 | extern crate num; 128 | extern crate quickcheck; 129 | 130 | pub use builtin::*; 131 | 132 | pub use basenum::{ 133 | Primitive, BaseNum, BaseInt, BaseFloat, SignedNum, 134 | ApproxEq, is_approx_eq, is_close_to 135 | }; 136 | 137 | pub use traits::{ 138 | GenNum, GenInt, GenFloat 139 | }; 140 | 141 | pub use vec::traits::{ 142 | GenVec, GenNumVec, GenFloatVec, GenBVec, 143 | }; 144 | 145 | pub use vec::vec::{ 146 | Vector2, Vector3, Vector4, 147 | BVec2, BVec3, BVec4, bvec2, bvec3, bvec4, 148 | IVec2, IVec3, IVec4, ivec2, ivec3, ivec4, 149 | UVec2, UVec3, UVec4, uvec2, uvec3, uvec4, 150 | Vec2, Vec3, Vec4, vec2, vec3, vec4, 151 | DVec2, DVec3, DVec4, dvec2, dvec3, dvec4, 152 | }; 153 | 154 | // pub use vec::swizzle::{ 155 | // Swizzle2, Swizzle3, Swizzle4, 156 | // }; 157 | 158 | pub use mat::traits::{ GenMat, GenSquareMat }; 159 | 160 | pub use mat::mat::{ 161 | Matrix2, Matrix3, Matrix4, 162 | Matrix3x2, Matrix4x2, Matrix2x3, Matrix4x3, Matrix2x4, Matrix3x4, 163 | Mat2, Mat3, Mat4, 164 | Mat3x2, Mat2x3, Mat4x2, Mat2x4, Mat4x3, Mat3x4, 165 | DMat2, DMat3, DMat4, 166 | DMat3x2, DMat2x3, DMat4x2, DMat2x4, DMat4x3, DMat3x4, 167 | }; 168 | 169 | pub use mat::ctor::{ 170 | mat2, mat3, mat4, 171 | mat3x2, mat2x3, mat4x2, mat2x4, mat4x3, mat3x4, 172 | dmat2, dmat3, dmat4, 173 | dmat3x2, dmat2x3, dmat4x2, dmat2x4, dmat4x3, dmat3x4, 174 | }; 175 | 176 | pub use cast::{ 177 | PrimCast, 178 | int, uint, float, double, boolean, 179 | to_ivec2, to_ivec3, to_ivec4, 180 | to_uvec2, to_uvec3, to_uvec4, 181 | to_vec2, to_vec3, to_vec4, 182 | to_dvec2, to_dvec3, to_dvec4, 183 | to_bvec2, to_bvec3, to_bvec4 184 | }; 185 | 186 | #[macro_use] 187 | mod basenum; 188 | mod traits; 189 | mod vec { 190 | pub mod traits; 191 | pub mod vec; 192 | } 193 | mod mat { 194 | pub mod traits; 195 | pub mod mat; 196 | pub mod ctor; 197 | pub mod sqmat; 198 | } 199 | mod cast; 200 | 201 | pub mod builtin; 202 | pub mod ext; 203 | -------------------------------------------------------------------------------- /src/mat/ctor.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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 | use vec::vec::{ vec2, vec3, vec4, dvec2, dvec3, dvec4 }; 26 | 27 | #[inline] 28 | pub fn mat2( 29 | m11: f32, m21: f32, 30 | m12: f32, m22: f32 31 | ) -> Mat2 { 32 | Matrix2 { 33 | c0: vec2(m11, m21), 34 | c1: vec2(m12, m22) 35 | } 36 | } 37 | 38 | #[inline] 39 | pub fn mat3x2( 40 | m11: f32, m21: f32, 41 | m12: f32, m22: f32, 42 | m13: f32, m23: f32 43 | ) -> Mat3x2 { 44 | Matrix3x2 { 45 | c0: vec2(m11, m21), 46 | c1: vec2(m12, m22), 47 | c2: vec2(m13, m23) 48 | } 49 | } 50 | 51 | #[inline] 52 | pub fn mat4x2( 53 | m11: f32, m21: f32, 54 | m12: f32, m22: f32, 55 | m13: f32, m23: f32, 56 | m14: f32, m24: f32 57 | ) -> Mat4x2 { 58 | Matrix4x2 { 59 | c0: vec2(m11, m21), 60 | c1: vec2(m12, m22), 61 | c2: vec2(m13, m23), 62 | c3: vec2(m14, m24) 63 | } 64 | } 65 | 66 | #[inline] 67 | pub fn mat3( 68 | m11: f32, m21: f32, m31: f32, 69 | m12: f32, m22: f32, m32: f32, 70 | m13: f32, m23: f32, m33: f32 71 | ) -> Mat3 { 72 | Matrix3 { 73 | c0: vec3(m11, m21, m31), 74 | c1: vec3(m12, m22, m32), 75 | c2: vec3(m13, m23, m33) 76 | } 77 | } 78 | 79 | #[inline] 80 | pub fn mat2x3( 81 | m11: f32, m21: f32, m31: f32, 82 | m12: f32, m22: f32, m32: f32 83 | ) -> Mat2x3 { 84 | Matrix2x3 { 85 | c0: vec3(m11, m21, m31), 86 | c1: vec3(m12, m22, m32) 87 | } 88 | } 89 | 90 | #[inline] 91 | pub fn mat4x3( 92 | m11: f32, m21: f32, m31: f32, 93 | m12: f32, m22: f32, m32: f32, 94 | m13: f32, m23: f32, m33: f32, 95 | m14: f32, m24: f32, m34: f32 96 | ) -> Mat4x3 { 97 | Matrix4x3 { 98 | c0: vec3(m11, m21, m31), 99 | c1: vec3(m12, m22, m32), 100 | c2: vec3(m13, m23, m33), 101 | c3: vec3(m14, m24, m34) 102 | } 103 | } 104 | 105 | #[inline] 106 | pub fn mat4( 107 | m11: f32, m21: f32, m31: f32, m41: f32, 108 | m12: f32, m22: f32, m32: f32, m42: f32, 109 | m13: f32, m23: f32, m33: f32, m43: f32, 110 | m14: f32, m24: f32, m34: f32, m44: f32 111 | ) -> Mat4 { 112 | Matrix4 { 113 | c0: vec4(m11, m21, m31, m41), 114 | c1: vec4(m12, m22, m32, m42), 115 | c2: vec4(m13, m23, m33, m43), 116 | c3: vec4(m14, m24, m34, m44) 117 | } 118 | } 119 | 120 | #[inline] 121 | pub fn mat2x4( 122 | m11: f32, m21: f32, m31: f32, m41: f32, 123 | m12: f32, m22: f32, m32: f32, m42: f32, 124 | ) -> Mat2x4 { 125 | Matrix2x4 { 126 | c0: vec4(m11, m21, m31, m41), 127 | c1: vec4(m12, m22, m32, m42) 128 | } 129 | } 130 | 131 | #[inline] 132 | pub fn mat3x4( 133 | m11: f32, m21: f32, m31: f32, m41: f32, 134 | m12: f32, m22: f32, m32: f32, m42: f32, 135 | m13: f32, m23: f32, m33: f32, m43: f32 136 | ) -> Mat3x4 { 137 | Matrix3x4 { 138 | c0: vec4(m11, m21, m31, m41), 139 | c1: vec4(m12, m22, m32, m42), 140 | c2: vec4(m13, m23, m33, m43) 141 | } 142 | } 143 | 144 | #[inline] 145 | pub fn dmat2( 146 | m11: f64, m21: f64, 147 | m12: f64, m22: f64 148 | ) -> DMat2 { 149 | Matrix2 { 150 | c0: dvec2(m11, m21), 151 | c1: dvec2(m12, m22) 152 | } 153 | } 154 | 155 | #[inline] 156 | pub fn dmat3x2( 157 | m11: f64, m21: f64, 158 | m12: f64, m22: f64, 159 | m13: f64, m23: f64 160 | ) -> DMat3x2 { 161 | Matrix3x2 { 162 | c0: dvec2(m11, m21), 163 | c1: dvec2(m12, m22), 164 | c2: dvec2(m13, m23) 165 | } 166 | } 167 | 168 | #[inline] 169 | pub fn dmat4x2( 170 | m11: f64, m21: f64, 171 | m12: f64, m22: f64, 172 | m13: f64, m23: f64, 173 | m14: f64, m24: f64 174 | ) -> DMat4x2 { 175 | Matrix4x2 { 176 | c0: dvec2(m11, m21), 177 | c1: dvec2(m12, m22), 178 | c2: dvec2(m13, m23), 179 | c3: dvec2(m14, m24) 180 | } 181 | } 182 | 183 | #[inline] 184 | pub fn dmat3( 185 | m11: f64, m21: f64, m31: f64, 186 | m12: f64, m22: f64, m32: f64, 187 | m13: f64, m23: f64, m33: f64 188 | ) -> DMat3 { 189 | Matrix3 { 190 | c0: dvec3(m11, m21, m31), 191 | c1: dvec3(m12, m22, m32), 192 | c2: dvec3(m13, m23, m33) 193 | } 194 | } 195 | 196 | #[inline] 197 | pub fn dmat2x3( 198 | m11: f64, m21: f64, m31: f64, 199 | m12: f64, m22: f64, m32: f64 200 | ) -> DMat2x3 { 201 | Matrix2x3 { 202 | c0: dvec3(m11, m21, m31), 203 | c1: dvec3(m12, m22, m32) 204 | } 205 | } 206 | 207 | #[inline] 208 | pub fn dmat4x3( 209 | m11: f64, m21: f64, m31: f64, 210 | m12: f64, m22: f64, m32: f64, 211 | m13: f64, m23: f64, m33: f64, 212 | m14: f64, m24: f64, m34: f64 213 | ) -> DMat4x3 { 214 | Matrix4x3 { 215 | c0: dvec3(m11, m21, m31), 216 | c1: dvec3(m12, m22, m32), 217 | c2: dvec3(m13, m23, m33), 218 | c3: dvec3(m14, m24, m34) 219 | } 220 | } 221 | 222 | #[inline] 223 | pub fn dmat4( 224 | m11: f64, m21: f64, m31: f64, m41: f64, 225 | m12: f64, m22: f64, m32: f64, m42: f64, 226 | m13: f64, m23: f64, m33: f64, m43: f64, 227 | m14: f64, m24: f64, m34: f64, m44: f64 228 | ) -> DMat4 { 229 | Matrix4 { 230 | c0: dvec4(m11, m21, m31, m41), 231 | c1: dvec4(m12, m22, m32, m42), 232 | c2: dvec4(m13, m23, m33, m43), 233 | c3: dvec4(m14, m24, m34, m44) 234 | } 235 | } 236 | 237 | #[inline] 238 | pub fn dmat2x4( 239 | m11: f64, m21: f64, m31: f64, m41: f64, 240 | m12: f64, m22: f64, m32: f64, m42: f64, 241 | ) -> DMat2x4 { 242 | Matrix2x4 { 243 | c0: dvec4(m11, m21, m31, m41), 244 | c1: dvec4(m12, m22, m32, m42) 245 | } 246 | } 247 | 248 | #[inline] 249 | pub fn dmat3x4( 250 | m11: f64, m21: f64, m31: f64, m41: f64, 251 | m12: f64, m22: f64, m32: f64, m42: f64, 252 | m13: f64, m23: f64, m33: f64, m43: f64 253 | ) -> DMat3x4 { 254 | Matrix3x4 { 255 | c0: dvec4(m11, m21, m31, m41), 256 | c1: dvec4(m12, m22, m32, m42), 257 | c2: dvec4(m13, m23, m33, m43) 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /src/mat/mat.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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::{ BaseFloat, ApproxEq }; 25 | use vec::vec::{ Vector2, Vector3, Vector4 }; 26 | use super::traits::GenMat; 27 | use std::mem; 28 | use std::ops::{ Add, Mul, Sub, Neg, Div, Rem, Index, IndexMut }; 29 | use rand::{ Rand, Rng }; 30 | use num::Zero; 31 | #[cfg(test)] 32 | use quickcheck::{ Arbitrary, Gen }; 33 | 34 | macro_rules! mul_v_unrolled { 35 | ($m: ident, $v: ident, Vector2, Vector2) => { 36 | Vector2::new( 37 | $m[0].x * $v.x + $m[1].x * $v.y, 38 | $m[0].y * $v.x + $m[1].y * $v.y 39 | ) 40 | }; 41 | ($m: ident, $v: ident, Vector2, Vector3) => { 42 | Vector2::new( 43 | $m[0].x * $v.x + $m[1].x * $v.y + $m[2].x * $v.z, 44 | $m[0].y * $v.x + $m[1].y * $v.y + $m[2].y * $v.z 45 | ) 46 | }; 47 | ($m: ident, $v: ident, Vector2, Vector4) => { 48 | Vector2::new( 49 | $m[0].x * $v.x + $m[1].x * $v.y + $m[2].x * $v.z + $m[3].x * $v.w, 50 | $m[0].y * $v.x + $m[1].y * $v.y + $m[2].y * $v.z + $m[3].y * $v.w 51 | ) 52 | }; 53 | ($m: ident, $v: ident, Vector3, Vector2) => { 54 | Vector3::new( 55 | $m[0].x * $v.x + $m[1].x * $v.y, 56 | $m[0].y * $v.x + $m[1].y * $v.y, 57 | $m[0].z * $v.x + $m[1].z * $v.y 58 | ) 59 | }; 60 | ($m: ident, $v: ident, Vector3, Vector3) => { 61 | Vector3::new( 62 | $m[0].x * $v.x + $m[1].x * $v.y + $m[2].x * $v.z, 63 | $m[0].y * $v.x + $m[1].y * $v.y + $m[2].y * $v.z, 64 | $m[0].z * $v.x + $m[1].z * $v.y + $m[2].z * $v.z 65 | ) 66 | }; 67 | ($m: ident, $v: ident, Vector3, Vector4) => { 68 | Vector3::new( 69 | $m[0].x * $v.x + $m[1].x * $v.y + $m[2].x * $v.z + $m[3].x * $v.w, 70 | $m[0].y * $v.x + $m[1].y * $v.y + $m[2].y * $v.z + $m[3].y * $v.w, 71 | $m[0].z * $v.x + $m[1].z * $v.y + $m[2].z * $v.z + $m[3].z * $v.w 72 | ) 73 | }; 74 | ($m: ident, $v: ident, Vector4, Vector2) => { 75 | Vector4::new( 76 | $m[0].x * $v.x + $m[1].x * $v.y, 77 | $m[0].y * $v.x + $m[1].y * $v.y, 78 | $m[0].z * $v.x + $m[1].z * $v.y, 79 | $m[0].w * $v.x + $m[1].w * $v.y 80 | ) 81 | }; 82 | ($m: ident, $v: ident, Vector4, Vector3) => { 83 | Vector4::new( 84 | $m[0].x * $v.x + $m[1].x * $v.y + $m[2].x * $v.z, 85 | $m[0].y * $v.x + $m[1].y * $v.y + $m[2].y * $v.z, 86 | $m[0].z * $v.x + $m[1].z * $v.y + $m[2].z * $v.z, 87 | $m[0].w * $v.x + $m[1].w * $v.y + $m[2].w * $v.z 88 | ) 89 | }; 90 | ($m: ident, $v: ident, Vector4, Vector4) => { 91 | Vector4::new( 92 | $m[0].x * $v.x + $m[1].x * $v.y + $m[2].x * $v.z + $m[3].x * $v.w, 93 | $m[0].y * $v.x + $m[1].y * $v.y + $m[2].y * $v.z + $m[3].y * $v.w, 94 | $m[0].z * $v.x + $m[1].z * $v.y + $m[2].z * $v.z + $m[3].z * $v.w, 95 | $m[0].w * $v.x + $m[1].w * $v.y + $m[2].w * $v.z + $m[3].w * $v.w 96 | ) 97 | }; 98 | } 99 | 100 | macro_rules! mul_m_unrolled { 101 | ($lm: ident, $rm: ident, Matrix2) => { 102 | Matrix2::new( 103 | $lm.mul_v(&$rm.c0), 104 | $lm.mul_v(&$rm.c1) 105 | ) 106 | }; 107 | ($lm: ident, $rm: ident, Matrix3) => { 108 | Matrix3::new( 109 | $lm.mul_v(&$rm.c0), 110 | $lm.mul_v(&$rm.c1), 111 | $lm.mul_v(&$rm.c2) 112 | ) 113 | }; 114 | ($lm: ident, $rm: ident, Matrix4) => { 115 | Matrix4::new( 116 | $lm.mul_v(&$rm.c0), 117 | $lm.mul_v(&$rm.c1), 118 | $lm.mul_v(&$rm.c2), 119 | $lm.mul_v(&$rm.c3) 120 | ) 121 | }; 122 | } 123 | 124 | macro_rules! transpose_unrolled { 125 | ($m: ident, Vector2, Vector2) => { 126 | Matrix2::new( 127 | Vector2::new($m[0][0], $m[1][0]), 128 | Vector2::new($m[0][1], $m[1][1]) 129 | ) 130 | }; 131 | ($m: ident, Vector2, Vector3) => { 132 | Matrix2x3::new( 133 | Vector3::new($m[0][0], $m[1][0], $m[2][0]), 134 | Vector3::new($m[0][1], $m[1][1], $m[2][1]) 135 | ) 136 | }; 137 | ($m: ident, Vector2, Vector4) => { 138 | Matrix2x4::new( 139 | Vector4::new($m[0][0], $m[1][0], $m[2][0], $m[3][0]), 140 | Vector4::new($m[0][1], $m[1][1], $m[2][1], $m[3][1]) 141 | ) 142 | }; 143 | ($m: ident, Vector3, Vector2) => { 144 | Matrix3x2::new( 145 | Vector2::new($m[0][0], $m[1][0]), 146 | Vector2::new($m[0][1], $m[1][1]), 147 | Vector2::new($m[0][2], $m[1][2]) 148 | ) 149 | }; 150 | ($m: ident, Vector3, Vector3) => { 151 | Matrix3::new( 152 | Vector3::new($m[0][0], $m[1][0], $m[2][0]), 153 | Vector3::new($m[0][1], $m[1][1], $m[2][1]), 154 | Vector3::new($m[0][2], $m[1][2], $m[2][2]) 155 | ) 156 | }; 157 | ($m: ident, Vector3, Vector4) => { 158 | Matrix3x4::new( 159 | Vector4::new($m[0][0], $m[1][0], $m[2][0], $m[3][0]), 160 | Vector4::new($m[0][1], $m[1][1], $m[2][1], $m[3][1]), 161 | Vector4::new($m[0][2], $m[1][2], $m[2][2], $m[3][2]) 162 | ) 163 | }; 164 | ($m: ident, Vector4, Vector2) => { 165 | Matrix4x2::new( 166 | Vector2::new($m[0][0], $m[1][0]), 167 | Vector2::new($m[0][1], $m[1][1]), 168 | Vector2::new($m[0][2], $m[1][2]), 169 | Vector2::new($m[0][3], $m[1][3]) 170 | ) 171 | }; 172 | ($m: ident, Vector4, Vector3) => { 173 | Matrix4x3::new( 174 | Vector3::new($m[0][0], $m[1][0], $m[2][0]), 175 | Vector3::new($m[0][1], $m[1][1], $m[2][1]), 176 | Vector3::new($m[0][2], $m[1][2], $m[2][2]), 177 | Vector3::new($m[0][3], $m[1][3], $m[2][3]) 178 | ) 179 | }; 180 | ($m: ident, Vector4, Vector4) => { 181 | Matrix4::new( 182 | Vector4::new($m[0][0], $m[1][0], $m[2][0], $m[3][0]), 183 | Vector4::new($m[0][1], $m[1][1], $m[2][1], $m[3][1]), 184 | Vector4::new($m[0][2], $m[1][2], $m[2][2], $m[3][2]), 185 | Vector4::new($m[0][3], $m[1][3], $m[2][3], $m[3][3]) 186 | ) 187 | }; 188 | } 189 | 190 | macro_rules! def_matrix { 191 | ($({ 192 | $t: ident, // type to be defined, 193 | $ct: ident, // type of column vector, 194 | $($field: ident), + // name of columen vectors. 195 | }), +) => { 196 | $( 197 | #[repr(C)] 198 | #[derive(Copy, Clone, PartialEq, Debug)] 199 | pub struct $t { 200 | $(pub $field: $ct), + 201 | } 202 | )+ 203 | } 204 | } 205 | 206 | def_matrix! { 207 | { Matrix2, Vector2, c0, c1 }, 208 | { Matrix3x2, Vector2, c0, c1, c2 }, 209 | { Matrix4x2, Vector2, c0, c1, c2, c3 }, 210 | 211 | { Matrix2x3, Vector3, c0, c1 }, 212 | { Matrix3, Vector3, c0, c1, c2 }, 213 | { Matrix4x3, Vector3, c0, c1, c2, c3 }, 214 | 215 | { Matrix2x4, Vector4, c0, c1 }, 216 | { Matrix3x4, Vector4, c0, c1, c2 }, 217 | { Matrix4, Vector4, c0, c1, c2, c3 } 218 | } 219 | 220 | macro_rules! impl_matrix { 221 | ($({ 222 | $t: ident, // type to impl (e.g., Matrix3), 223 | $ct: ident, // type of column vector (e.g., Vec2), 224 | $rt: ident, // type of row vector, 225 | $tr: ident, // type of transpose matrix, 226 | $om: ident, // the product of multiplying transpose matrix, 227 | $cn: expr, // number of columns, i.e., the dimension of $rt, 228 | $($field: ident), + // fields for repeating reference columns, 229 | }), +) => { 230 | $( 231 | impl $t { 232 | #[inline(always)] 233 | pub fn new($($field: $ct), +) -> $t { 234 | $t { $($field: $field), + } 235 | } 236 | #[inline(always)] 237 | pub fn from_array(ary: &[$ct; $cn]) -> &$t { 238 | let m: &Self = unsafe { mem::transmute(ary) }; 239 | m 240 | } 241 | #[inline(always)] 242 | pub fn from_array_mut(ary: &mut [$ct; $cn]) -> &mut $t { 243 | let m: &mut Self = unsafe { mem::transmute(ary) }; 244 | m 245 | } 246 | #[inline(always)] 247 | pub fn as_array(&self) -> &[$ct; $cn] { 248 | let ary: &[$ct; $cn] = unsafe { mem::transmute(self) }; 249 | ary 250 | } 251 | #[inline(always)] 252 | pub fn as_array_mut(&mut self) -> &mut [$ct; $cn] { 253 | let ary: &mut[$ct; $cn] = unsafe { mem::transmute(self) }; 254 | ary 255 | } 256 | #[inline(always)] 257 | pub fn add_s(&self, rhs: T) -> $t { 258 | $t::new($(self.$field + rhs), +) 259 | } 260 | #[inline(always)] 261 | pub fn add_m(&self, rhs: &$t) -> $t { 262 | $t::new($(self.$field + rhs.$field), +) 263 | } 264 | #[inline(always)] 265 | pub fn sub_s(&self, rhs: T) -> $t { 266 | $t::new($(self.$field - rhs), +) 267 | } 268 | #[inline(always)] 269 | pub fn sub_m(&self, rhs: &$t) -> $t { 270 | $t::new($(self.$field - rhs.$field), +) 271 | } 272 | #[inline(always)] 273 | pub fn div_m(&self, rhs: &$t) -> $t { 274 | $t::new($(self.$field / rhs.$field), +) 275 | } 276 | #[inline(always)] 277 | pub fn div_s(&self, rhs: T) -> $t { 278 | $t::new($(self.$field / rhs), +) 279 | } 280 | #[inline(always)] 281 | pub fn rem_m(&self, rhs: &$t) -> $t { 282 | $t::new($(self.$field % rhs.$field), +) 283 | } 284 | #[inline(always)] 285 | pub fn rem_s(&self, rhs: T) -> $t { 286 | $t::new($(self.$field % rhs), +) 287 | } 288 | #[inline(always)] 289 | pub fn mul_s(&self, rhs: T) -> $t { 290 | $t::new($(self.$field * rhs), +) 291 | } 292 | #[inline(always)] 293 | pub fn mul_v(&self, rhs: &$rt) -> $ct { 294 | mul_v_unrolled! { self, rhs, $ct, $rt } 295 | } 296 | #[inline(always)] 297 | pub fn mul_m(&self, rhs: &$tr) -> $om { 298 | mul_m_unrolled! { self, rhs, $om } 299 | } 300 | #[inline(always)] 301 | pub fn neg_m(&self) -> $t { 302 | $t::new($(self.$field.neg()), +) 303 | } 304 | } 305 | impl Index for $t { 306 | type Output = $ct; 307 | #[inline(always)] 308 | fn index<'a>(&'a self, i: usize) -> &'a $ct { 309 | self.as_array().index(i) 310 | } 311 | } 312 | impl IndexMut for $t { 313 | #[inline(always)] 314 | fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut $ct { 315 | self.as_array_mut().index_mut(i) 316 | } 317 | } 318 | impl Rand for $t { 319 | #[inline] 320 | fn rand(rng: &mut R) -> $t { 321 | $t {$($field: rng.gen()),+} 322 | } 323 | } 324 | #[cfg(test)] 325 | impl Arbitrary for $t 326 | where T::FromStrRadixErr: 'static { 327 | #[inline] 328 | fn arbitrary(g: &mut G) -> $t { 329 | $t { $($field: $ct::::arbitrary(g)),+ } 330 | } 331 | } 332 | impl Add for $t { 333 | type Output = $t; 334 | #[inline(always)] 335 | fn add(self, rhs: T) -> $t { 336 | self.add_s(rhs) 337 | } 338 | } 339 | impl ApproxEq for $t { 340 | type BaseType = T; 341 | #[inline] 342 | fn is_close_to(&self, rhs: &$t, max_diff: T) -> bool { 343 | $(self.$field.is_close_to(&rhs.$field, max_diff)) && + 344 | } 345 | } 346 | impl Add<$t> for $t { 347 | type Output = $t; 348 | #[inline(always)] 349 | fn add(self, rhs: $t) -> $t { 350 | self.add_m(&rhs) 351 | } 352 | } 353 | impl Sub for $t { 354 | type Output = $t; 355 | #[inline(always)] 356 | fn sub(self, rhs: T) -> $t { 357 | self.sub_s(rhs) 358 | } 359 | } 360 | impl Sub<$t> for $t { 361 | type Output = $t; 362 | #[inline(always)] 363 | fn sub(self, rhs: $t) -> $t { 364 | self.sub_m(&rhs) 365 | } 366 | } 367 | impl Div for $t { 368 | type Output = $t; 369 | #[inline(always)] 370 | fn div(self, rhs: T) -> $t { 371 | self.div_s(rhs) 372 | } 373 | } 374 | impl Div<$t> for $t { 375 | type Output = $t; 376 | #[inline(always)] 377 | fn div(self, rhs: $t) -> $t { 378 | self.div_m(&rhs) 379 | } 380 | } 381 | impl Rem for $t { 382 | type Output = $t; 383 | #[inline(always)] 384 | fn rem(self, rhs: T) -> $t { 385 | self.rem_s(rhs) 386 | } 387 | } 388 | impl Rem<$t> for $t { 389 | type Output = $t; 390 | #[inline(always)] 391 | fn rem(self, rhs: $t) -> $t { 392 | self.rem_m(&rhs) 393 | } 394 | } 395 | impl Neg for $t { 396 | type Output = $t; 397 | #[inline(always)] 398 | fn neg(self) -> $t { 399 | self.neg_m() 400 | } 401 | } 402 | impl Mul for $t { 403 | type Output = $t; 404 | #[inline(always)] 405 | fn mul(self, rhs: T) -> $t { 406 | self.mul_s(rhs) 407 | } 408 | } 409 | impl Mul<$rt> for $t { 410 | type Output = $ct; 411 | #[inline(always)] 412 | fn mul(self, rhs: $rt) -> $ct { 413 | self.mul_v(&rhs) 414 | } 415 | } 416 | impl Mul<$tr> for $t { 417 | type Output = $om; 418 | #[inline(always)] 419 | fn mul(self, rhs: $tr) -> $om { 420 | self.mul_m(&rhs) 421 | } 422 | } 423 | impl Zero for $t { 424 | #[inline(always)] 425 | fn zero() -> $t { 426 | $t { $($field: $ct::::zero()), + } 427 | } 428 | #[inline(always)] 429 | fn is_zero(&self) -> bool { 430 | $(self.$field.is_zero()) && + 431 | } 432 | } 433 | impl GenMat> for $t { 434 | type R = $rt; 435 | type Transpose = $tr; 436 | #[inline] 437 | fn transpose(&self) -> $tr { 438 | transpose_unrolled!(self, $ct, $rt) 439 | } 440 | #[inline(always)] 441 | fn mul_c(&self, rhs: &$t) -> $t { 442 | $t::new($(self.$field * rhs.$field), +) 443 | } 444 | } 445 | )+ 446 | } 447 | } 448 | 449 | impl_matrix! { 450 | { Matrix2, Vector2, Vector2, Matrix2, Matrix2, 2, c0, c1 }, 451 | { Matrix3x2, Vector2, Vector3, Matrix2x3, Matrix2, 3, c0, c1, c2 }, 452 | { Matrix4x2, Vector2, Vector4, Matrix2x4, Matrix2, 4, c0, c1, c2, c3 }, 453 | 454 | { Matrix2x3, Vector3, Vector2, Matrix3x2, Matrix3, 2, c0, c1 }, 455 | { Matrix3, Vector3, Vector3, Matrix3, Matrix3, 3, c0, c1, c2 }, 456 | { Matrix4x3, Vector3, Vector4, Matrix3x4, Matrix3, 4, c0, c1, c2, c3 }, 457 | 458 | { Matrix2x4, Vector4, Vector2, Matrix4x2, Matrix4, 2, c0, c1 }, 459 | { Matrix3x4, Vector4, Vector3, Matrix4x3, Matrix4, 3, c0, c1, c2 }, 460 | { Matrix4, Vector4, Vector4, Matrix4, Matrix4, 4, c0, c1, c2, c3 } 461 | } 462 | 463 | macro_rules! impl_mul( 464 | ($({ 465 | $t: ident, $rhs: ident, $output: ident, $($field: ident), + 466 | }), +) => { 467 | $( 468 | impl Mul<$rhs> for $t { 469 | type Output = $output; 470 | #[inline(always)] 471 | fn mul(self, rhs: $rhs) -> $output { 472 | $output::new( 473 | $(self.mul_v(&rhs.$field)), + 474 | ) 475 | } 476 | } 477 | )+ 478 | }; 479 | ); 480 | 481 | impl_mul! { 482 | { Matrix2x3, Matrix2, Matrix2x3, c0, c1 }, 483 | { Matrix2x4, Matrix2, Matrix2x4, c0, c1 }, 484 | 485 | { Matrix2, Matrix3x2, Matrix3x2, c0, c1, c2 }, 486 | { Matrix2x4, Matrix3x2, Matrix3x4, c0, c1, c2 }, 487 | 488 | { Matrix2, Matrix4x2, Matrix4x2, c0, c1, c2, c3 }, 489 | { Matrix2x3, Matrix4x2, Matrix4x3, c0, c1, c2, c3 }, 490 | 491 | { Matrix3, Matrix2x3, Matrix2x3, c0, c1 }, 492 | { Matrix3x4, Matrix2x3, Matrix2x4, c0, c1 }, 493 | 494 | { Matrix3x2, Matrix3, Matrix3x2, c0, c1, c2 }, 495 | { Matrix3x4, Matrix3, Matrix3x4, c0, c1, c2 }, 496 | 497 | { Matrix3x2, Matrix4x3, Matrix4x2, c0, c1, c2, c3 }, 498 | { Matrix3, Matrix4x3, Matrix4x3, c0, c1, c2, c3 }, 499 | 500 | { Matrix4x3, Matrix2x4, Matrix2x3, c0, c1 }, 501 | { Matrix4, Matrix2x4, Matrix2x4, c0, c1 }, 502 | 503 | { Matrix4x2, Matrix3x4, Matrix3x2, c0, c1, c2 }, 504 | { Matrix4, Matrix3x4, Matrix3x4, c0, c1, c2 }, 505 | 506 | { Matrix4x2, Matrix4, Matrix4x2, c0, c1, c2, c3 }, 507 | { Matrix4x3, Matrix4, Matrix4x3, c0, c1, c2, c3 } 508 | } 509 | 510 | macro_rules! def_alias( 511 | ( 512 | $({ 513 | $a: ident, // type alias (e.g., Mat2 for Matrix2), 514 | $t: ident, // type to be aliased, 515 | $et: ty // element type, 516 | }), + 517 | ) => { 518 | $( 519 | pub type $a = $t<$et>; 520 | )+ 521 | } 522 | ); 523 | 524 | def_alias! { 525 | { Mat2, Matrix2, f32 }, 526 | { Mat3x2, Matrix3x2, f32 }, 527 | { Mat4x2, Matrix4x2, f32 }, 528 | 529 | { Mat2x3, Matrix2x3, f32 }, 530 | { Mat3, Matrix3, f32 }, 531 | { Mat4x3, Matrix4x3, f32 }, 532 | 533 | { Mat2x4, Matrix2x4, f32 }, 534 | { Mat3x4, Matrix3x4, f32 }, 535 | { Mat4, Matrix4, f32 }, 536 | 537 | { DMat2, Matrix2, f64 }, 538 | { DMat3x2, Matrix3x2, f64 }, 539 | { DMat4x2, Matrix4x2, f64 }, 540 | 541 | { DMat2x3, Matrix2x3, f64 }, 542 | { DMat3, Matrix3, f64 }, 543 | { DMat4x3, Matrix4x3, f64 }, 544 | 545 | { DMat2x4, Matrix2x4, f64 }, 546 | { DMat3x4, Matrix3x4, f64 }, 547 | { DMat4, Matrix4, f64 } 548 | } 549 | 550 | impl Matrix2 { 551 | /// Extends _self_ to a `Matrix3x2` by appending the column vector `z`. 552 | /// 553 | /// # Example 554 | /// 555 | /// ```rust 556 | /// use glm::*; 557 | /// 558 | /// let m2 = mat2(1., 2., 3., 4.); 559 | /// let m3x2 = mat3x2(1., 2., 3., 4., 0., 0.); 560 | /// assert_eq!(m2.extend(vec2(0., 0.)), m3x2); 561 | /// ``` 562 | #[inline] 563 | pub fn extend(&self, z: Vector2) -> Matrix3x2 { 564 | Matrix3x2::new(self[0], self[1], z) 565 | } 566 | } 567 | 568 | impl Matrix3 { 569 | /// Extends _self_ to a `Matrix4x3` by appending the column vector `w`. 570 | #[inline] 571 | pub fn extend(&self, w: Vector3) -> Matrix4x3 { 572 | Matrix4x3::new(self[0], self[1], self[2], w) 573 | } 574 | } 575 | 576 | #[cfg(test)] 577 | mod test { 578 | 579 | use mat::ctor::*; 580 | use vec::vec::*; 581 | 582 | #[test] 583 | fn test_index() { 584 | let m = mat4x3(1., 2., 3., 2., 4., 6., 3., 6., 9., 4., 8., 12.); 585 | assert_eq!(m[3], vec3(4., 8., 12.)); 586 | assert_eq!(m[1], m.c1); 587 | assert_eq!(m[2][0], 3.); 588 | assert_eq!(m[0][1], 2.) 589 | } 590 | 591 | #[test] 592 | #[should_panic] 593 | fn test_index_bound_check() { 594 | let m2 = mat2(1., 2., 3., 4.); 595 | m2[2]; 596 | } 597 | 598 | #[test] 599 | fn test_mul_v() { 600 | let m = mat3x2(1., 2., 3., 4., 5., 6.); 601 | let v = vec3(-2., 0., 2.); 602 | let p = vec2(8., 8.); 603 | assert_eq!(m * v, p); 604 | } 605 | } 606 | -------------------------------------------------------------------------------- /src/mat/sqmat.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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::BaseFloat; 25 | use vec::vec::{ Vector2, Vector3, Vector4 }; 26 | use super::traits::{ GenMat, GenSquareMat }; 27 | use super::mat::*; 28 | use num::One; 29 | 30 | impl One for Matrix2 { 31 | #[inline] 32 | fn one() -> Matrix2 { 33 | let y = T::one(); 34 | let l = T::zero(); 35 | Matrix2::new( 36 | Vector2::new(y, l), 37 | Vector2::new(l, y) 38 | ) 39 | } 40 | } 41 | 42 | impl GenSquareMat> for Matrix2 { 43 | #[inline(always)] 44 | fn determinant(&self) -> T { 45 | self[0][0] * self[1][1] - self[0][1] * self[1][0] 46 | } 47 | #[inline] 48 | fn inverse(&self) -> Option> { 49 | let det = self.determinant(); 50 | let ling = T::zero(); 51 | if det.is_approx_eq(&ling) { 52 | None 53 | } else { 54 | let inv_det = det.recip(); 55 | let m = Matrix2::new( 56 | Vector2::new(self[1][1] * inv_det, -self[0][1] * inv_det), 57 | Vector2::new(-self[1][0] * inv_det, self[0][0] * inv_det) 58 | ); 59 | Some(m) 60 | } 61 | } 62 | } 63 | 64 | impl One for Matrix3 { 65 | #[inline] 66 | fn one() -> Matrix3 { 67 | let y = T::one(); 68 | let l = T::zero(); 69 | Matrix3::new( 70 | Vector3::new(y, l, l), 71 | Vector3::new(l, y, l), 72 | Vector3::new(l, l, y) 73 | ) 74 | } 75 | } 76 | 77 | impl GenSquareMat> for Matrix3 { 78 | #[inline] 79 | fn determinant(&self) -> T { 80 | self[0][0] * (self[1][1] * self[2][2] - self[2][1] * self[1][2]) - 81 | self[1][0] * (self[0][1] * self[2][2] - self[2][1] * self[0][2]) + 82 | self[2][0] * (self[0][1] * self[1][2] - self[1][1] * self[0][2]) 83 | } 84 | #[inline] 85 | fn inverse(&self) -> Option> { 86 | let det = self.determinant(); 87 | let ling = T::zero(); 88 | if det.is_approx_eq(&ling) { 89 | None 90 | } else { 91 | let inv_det = det.recip(); 92 | let r11 = self[1][1] * self[2][2] - self[2][1] * self[1][2]; 93 | let r12 = self[2][0] * self[1][2] - self[1][0] * self[2][2]; 94 | let r13 = self[1][0] * self[2][1] - self[2][0] * self[1][1]; 95 | let r21 = self[2][1] * self[0][2] - self[0][1] * self[2][2]; 96 | let r22 = self[0][0] * self[2][2] - self[2][0] * self[0][2]; 97 | let r23 = self[2][0] * self[0][1] - self[0][0] * self[2][1]; 98 | let r31 = self[0][1] * self[1][2] - self[1][1] * self[0][2]; 99 | let r32 = self[1][0] * self[0][2] - self[0][0] * self[1][2]; 100 | let r33 = self[0][0] * self[1][1] - self[1][0] * self[0][1]; 101 | let m = Matrix3::new( 102 | Vector3::new(r11 * inv_det, r21 * inv_det, r31 * inv_det), 103 | Vector3::new(r12 * inv_det, r22 * inv_det, r32 * inv_det), 104 | Vector3::new(r13 * inv_det, r23 * inv_det, r33 * inv_det) 105 | ); 106 | Some(m) 107 | } 108 | } 109 | } 110 | 111 | impl One for Matrix4 { 112 | #[inline] 113 | fn one() -> Matrix4 { 114 | let y = T::one(); 115 | let l = T::zero(); 116 | Matrix4::new( 117 | Vector4::new(y, l, l, l), 118 | Vector4::new(l, y, l, l), 119 | Vector4::new(l, l, y, l), 120 | Vector4::new(l, l, l, y) 121 | ) 122 | } 123 | } 124 | 125 | impl GenSquareMat> for Matrix4 { 126 | #[inline] 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( 173 | tr.c1.truncate(j), 174 | tr.c2.truncate(j), 175 | tr.c3.truncate(j) 176 | ), 177 | 1 => Matrix3::new( 178 | tr.c0.truncate(j), 179 | tr.c2.truncate(j), 180 | tr.c3.truncate(j) 181 | ), 182 | 2 => Matrix3::new( 183 | tr.c0.truncate(j), 184 | tr.c1.truncate(j), 185 | tr.c3.truncate(j) 186 | ), 187 | 3 => Matrix3::new( 188 | tr.c0.truncate(j), 189 | tr.c1.truncate(j), 190 | tr.c2.truncate(j) 191 | ), 192 | _ => unreachable!(), 193 | }; 194 | let d = mat.determinant() * inv_det; 195 | if (i + j) & 1 == 1 { 196 | -d 197 | } else { 198 | d 199 | } 200 | }; 201 | let m = Matrix4::new( 202 | Vector4::new(cf(0, 0), cf(0, 1), cf(0, 2), cf(0, 3)), 203 | Vector4::new(cf(1, 0), cf(1, 1), cf(1, 2), cf(1, 3)), 204 | Vector4::new(cf(2, 0), cf(2, 1), cf(2, 2), cf(2, 3)), 205 | Vector4::new(cf(3, 0), cf(3, 1), cf(3, 2), cf(3, 3)) 206 | ); 207 | Some(m) 208 | } 209 | } 210 | } 211 | 212 | #[cfg(test)] 213 | mod test { 214 | 215 | use basenum::*; 216 | use mat::traits::GenSquareMat; 217 | use mat::mat::*; 218 | use mat::ctor::*; 219 | use num::{ One, Zero }; 220 | 221 | #[test] 222 | fn test_determinant() { 223 | let m2 = mat2(4., 5., 6., 7.); 224 | assert_eq!(m2.determinant(), -2.); 225 | assert_eq!(Mat3::one().determinant(), 1.); 226 | let m4 = mat4( 227 | 1., 0., 4., 0., 228 | 2., 1., 2., 1., 229 | 3., 2., 3., 1., 230 | 4., 3., 0., 0. 231 | ); 232 | assert_eq!(m4.determinant(), -7.); 233 | assert_eq!((m4 * m4).determinant(), 49.); 234 | assert_eq!(Mat4::one().determinant(), 1.); 235 | } 236 | 237 | #[test] 238 | fn test_inverse_mat2() { 239 | let yi = Mat2::one(); 240 | assert!(yi.inverse().is_some()); 241 | assert!(DMat2::zero().inverse().is_none()); 242 | let mat = mat2(1., 3., 2., 4.); 243 | let inv = mat.inverse().unwrap(); 244 | assert_close_to!(mat * inv, yi, 0.000001); 245 | assert_close_to!(inv * mat, yi, 0.000001); 246 | let m2 = mat2(1., 2., 2., 4.); 247 | assert!(m2.inverse().is_none()); 248 | } 249 | 250 | #[test] 251 | fn test_inverse_mat3() { 252 | let yi = Mat3::one(); 253 | assert!(yi.inverse().is_some()); 254 | assert_eq!(yi.inverse().unwrap(), yi); 255 | assert!(DMat3::zero().inverse().is_none()); 256 | let mat = mat3(5., 7., 11., -6., 9., 2., 1., 13., 0.); 257 | let inv = mat.inverse().unwrap(); 258 | assert_close_to!(mat * inv, yi, 0.000001); 259 | assert_close_to!(inv * mat, yi, 0.000001); 260 | } 261 | 262 | #[test] 263 | fn test_inverse_mat4() { 264 | let mat = mat4( 265 | 1., 0., 4., 0., 266 | 2., 1., 2., 1., 267 | 3., 2., 3., 1., 268 | 4., 3., 0., 0. 269 | ); 270 | let invm = mat4( 271 | 3./7., 12./7., -12./7., 4./7., 272 | -4./7., -16./7., 16./7., -3./7., 273 | 1./7., -3./7., 3./7., -1./7., 274 | -4./7., 5./7., 2./7., -3./7. 275 | ); 276 | assert_approx_eq!(mat.inverse().unwrap(), invm); 277 | assert_close_to!(mat.inverse().unwrap().inverse().unwrap(), mat, 0.000001); 278 | assert!(Mat4::one().inverse().is_some()); 279 | } 280 | } 281 | -------------------------------------------------------------------------------- /src/mat/traits.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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::{ BaseFloat, ApproxEq }; 25 | use vec::traits::GenFloatVec; 26 | use std::ops::{ Add, Sub, Neg, Mul, Div, Rem, Index, IndexMut }; 27 | use num::{ One, Zero }; 28 | 29 | /// Generic Matrix type. 30 | pub trait GenMat 31 | < 32 | T: BaseFloat, 33 | C: GenFloatVec 34 | > 35 | : Sized 36 | + Zero 37 | + Add 38 | + Sub 39 | + Div 40 | + Rem 41 | + Neg 42 | + Mul 43 | + Index 44 | + IndexMut 45 | + ApproxEq 46 | { 47 | /// Type of row vectors. 48 | type R: GenFloatVec; 49 | 50 | /// Type of transpose matrix. 51 | type Transpose: GenMat; 52 | 53 | /// Returns the transpose matrix. 54 | /// 55 | /// # Example 56 | /// 57 | /// ``` 58 | /// use glm::GenMat; // bing the method into scope. 59 | /// 60 | /// let m = glm::mat3x2(1., 2., 3., 4., 5., 6.); 61 | /// let tm = glm::mat2x3(1., 3., 5., 2., 4., 6.); 62 | /// assert_eq!(tm, m.transpose()); 63 | /// ``` 64 | fn transpose(&self) -> Self::Transpose; 65 | 66 | /// Component-wise multiplication. 67 | /// 68 | /// # Example 69 | /// 70 | /// ``` 71 | /// use glm::GenMat; // bing the method into scope. 72 | /// 73 | /// let m1 = glm::mat2(1., 2., 3., 4.); 74 | /// let m2 = glm::mat2(0., 0., -7., 0.5); 75 | /// assert_eq!(m1.mul_c(&m2), glm::mat2(0., 0., -21., 2.)); 76 | /// ``` 77 | fn mul_c(&self, rhs: &Self) -> Self; 78 | } 79 | 80 | /// Generic type of square matrix. 81 | pub trait GenSquareMat 82 | < 83 | T: BaseFloat, 84 | C: GenFloatVec, 85 | > 86 | : GenMat 87 | + One 88 | { 89 | /// Returns the determinant of a square matrix. 90 | /// 91 | /// # Example 92 | /// 93 | /// ``` 94 | /// use glm::GenSquareMat; 95 | /// 96 | /// let mat = glm::mat2(1., 3., 2., 4.); 97 | /// assert_eq!(mat.determinant(), -2.); 98 | /// ``` 99 | fn determinant(&self) -> T; 100 | 101 | /// Returns the inverse matrix of a square matrix, or `None` if the 102 | /// matrix is not invertible. 103 | fn inverse(&self) -> Option; 104 | } 105 | -------------------------------------------------------------------------------- /src/traits.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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::{ BaseNum, BaseInt, BaseFloat, SignedNum, ApproxEq }; 25 | use std::ops::{ Add, Mul, Sub, Div, Rem, Not, BitAnd, BitOr, BitXor, Shl, Shr }; 26 | use rand::Rand; 27 | use num::{ Float, One, Zero }; 28 | 29 | // TODO: use associated types to reduce redundant type parameters. 30 | 31 | /// Generic numeric type. 32 | pub trait GenNum 33 | : Copy 34 | + Sized 35 | + Clone 36 | + One 37 | + Zero 38 | + Div 39 | + Rem 40 | + Add 41 | + Mul 42 | + Rand 43 | { 44 | /// Constructs from a scalar number. 45 | fn from_s(x: E) -> Self; 46 | 47 | fn map(self, f: F) -> Self where F: Fn(E) -> E; 48 | 49 | fn zip(self, y: Self, f: F) -> Self where F: Fn(E, E) -> E; 50 | 51 | fn split(self, f: F) -> (Self, Self) where F: Fn(E) -> (E, E); 52 | 53 | fn map2(self, y: Self, f: F) -> (Self, Self) where F: Fn(E, E) -> (E, E); 54 | } 55 | 56 | macro_rules! impl_GenNum_for_scalar( 57 | ($t: ty) => { 58 | impl GenNum<$t> for $t { 59 | #[inline(always)] 60 | fn from_s(x: $t) -> Self { 61 | x 62 | } 63 | #[inline(always)] 64 | fn map $t>(self, f: F) -> $t { 65 | f(self) 66 | } 67 | #[inline(always)] 68 | fn zip $t>(self, y: $t, f: F) -> $t { 69 | f(self, y) 70 | } 71 | #[inline(always)] 72 | fn split ($t, $t)>(self, f: F) -> ($t, $t) { 73 | f(self) 74 | } 75 | #[inline(always)] 76 | fn map2 ($t, $t)>(self, y: $t, f: F) -> ($t, $t) { 77 | f(self, y) 78 | } 79 | } 80 | } 81 | ); 82 | 83 | /// Generic interger type. 84 | pub trait GenInt 85 | : GenNum 86 | + Eq 87 | + Not 88 | + BitAnd 89 | + BitOr 90 | + BitXor 91 | + Shl 92 | + Shr 93 | {} 94 | 95 | /// Generic signed integer type. 96 | /// 97 | /// # Note 98 | /// 99 | /// Only 32-bit integer is used in GLSL. 100 | pub trait GenIType: GenInt + SignedNum + Sub {} 101 | 102 | impl_GenNum_for_scalar! { i32 } 103 | impl GenInt for i32 {} 104 | impl GenIType for i32 {} 105 | 106 | /// Generic unsigned integer type. 107 | /// 108 | /// # Note 109 | /// 110 | /// Only 32-bit unsigned integer is used in GLSL. 111 | pub trait GenUType: GenInt {} 112 | 113 | impl_GenNum_for_scalar! { u32 } 114 | impl GenInt for u32 {} 115 | impl GenUType for u32 {} 116 | 117 | /// Generic float number type. 118 | pub trait GenFloat 119 | : GenNum 120 | + ApproxEq 121 | + SignedNum 122 | + Sub 123 | { 124 | /// Computes and returns `a * b + c`. 125 | fn fma(&self, b: &Self, c: &Self) -> Self; 126 | } 127 | 128 | pub trait GenType: GenFloat {} 129 | pub trait GenDType: GenFloat {} 130 | 131 | macro_rules! impl_GenFloat_for_scalar( 132 | ($t: ty, $gt: path) => { 133 | impl_GenNum_for_scalar! { $t } 134 | impl GenFloat<$t> for $t { 135 | fn fma(&self, b: &$t, c: &$t) -> $t { 136 | Float::mul_add(*self, *b, *c) 137 | } 138 | } 139 | impl $gt for $t {} 140 | } 141 | ); 142 | 143 | impl_GenFloat_for_scalar! { f32, GenType } 144 | impl_GenFloat_for_scalar! { f64, GenDType } 145 | 146 | /// Generic boolean type. 147 | pub trait GenBType: Eq {} 148 | 149 | impl GenBType for bool {} 150 | -------------------------------------------------------------------------------- /src/vec/swizzle.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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/vec/traits.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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::{ BaseNum, BaseFloat, Primitive }; 25 | use traits::{ GenBType, GenFloat, GenNum }; 26 | use std::ops::{ Index, IndexMut }; 27 | 28 | /// Generic vector type. 29 | pub trait GenVec 30 | : Copy 31 | + Index 32 | + IndexMut 33 | { 34 | /// Returns the dimension of the vector. 35 | /// 36 | /// # Example 37 | /// 38 | /// ``` 39 | /// use glm::GenVec; // bring the method into scope. 40 | /// assert_eq!(glm::IVec4::dim(), 4); 41 | /// ``` 42 | fn dim() -> usize; 43 | 44 | // XXX: swap(i, j) 45 | } 46 | 47 | /// Trait of all vector types that are GenNum. 48 | pub trait GenNumVec: GenNum + GenVec { 49 | 50 | /// Returns the sum of all components. 51 | // 52 | /// # Example 53 | /// 54 | /// ``` 55 | /// use glm::GenNumVec; // bring the method into scope. 56 | /// let v = glm::vec3(1., 2., 3.); 57 | /// assert_eq!(v.sum(), 6.0); 58 | /// ``` 59 | fn sum(&self) -> T; 60 | 61 | /// Multiplies all components. 62 | /// 63 | /// # Example 64 | /// 65 | /// ``` 66 | /// use glm::GenNumVec; // bring the method into scope. 67 | /// let v = glm::vec3(2., 3., 4.); 68 | /// assert_eq!(v.product(), 24.); 69 | /// ``` 70 | fn product(&self) -> T; 71 | 72 | /// Returns the minimal value of all components. 73 | /// 74 | /// # Example 75 | /// 76 | /// ``` 77 | /// use glm::GenNumVec; // bring the method into scope. 78 | /// let v = glm::vec3(1.0, 2.0, 3.0); 79 | /// assert_eq!(v.min(), 1.0); 80 | /// ``` 81 | fn min(&self) -> T; 82 | 83 | /// Returns the maximal value of all components. 84 | /// 85 | /// # Example 86 | /// 87 | /// ``` 88 | /// use glm::GenNumVec; // bring the method into scope. 89 | /// 90 | /// let v = glm::vec3(1.0, 2.0, 3.0); 91 | /// assert_eq!(v.max(), 3.0); 92 | /// ``` 93 | fn max(&self) -> T; 94 | } 95 | 96 | /// Generic type of vectors of float number. 97 | pub trait GenFloatVec: GenNumVec + GenFloat {} 98 | 99 | /// Generic boolean vector type. 100 | pub trait GenBVec: GenVec + GenBType { 101 | 102 | /// Returns `true` if there is any component of the receiver is `true`. 103 | /// 104 | /// # Example 105 | /// 106 | /// ``` 107 | /// use glm::{ GenBVec, bvec2 }; 108 | /// 109 | /// assert!(bvec2(true, false).any()); 110 | /// assert_eq!(bvec2(false, false).all(), false); 111 | /// ``` 112 | fn any(&self) -> bool; 113 | 114 | /// Returns `true` if all components of the receiver are `true`. 115 | /// 116 | /// # Example 117 | /// 118 | /// ``` 119 | /// use glm::{ GenBVec, bvec2 }; 120 | /// 121 | /// assert_eq!(bvec2(true, false).all(), false); 122 | /// assert_eq!(bvec2(true, true).all(), true); 123 | /// ``` 124 | fn all(&self) -> bool; 125 | 126 | /// Returns the component-wise logical complement of the receiver. 127 | /// 128 | /// # Example 129 | /// 130 | /// ``` 131 | /// use glm::{ GenBVec, bvec2 }; 132 | /// 133 | /// assert_eq!(bvec2(true, false).not(), bvec2(false, true)); 134 | /// ``` 135 | fn not(&self) -> Self; 136 | } 137 | -------------------------------------------------------------------------------- /src/vec/vec.rs: -------------------------------------------------------------------------------- 1 | // 2 | // GLSL Mathematics for Rust. 3 | // 4 | // Copyright (c) 2015 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::*; 25 | use traits::*; 26 | use super::traits::{ GenVec, GenNumVec, GenFloatVec, GenBVec }; 27 | use std::cmp::Eq; 28 | use std::mem; 29 | use std::ops::{ 30 | Add, Mul, Sub, Neg, Div, Rem, Not, BitAnd, BitOr, BitXor, Shl, Shr, 31 | Index, IndexMut, 32 | }; 33 | use rand::{ Rand, Rng }; 34 | use num::{ Float, One, Zero }; 35 | use quickcheck::{ Arbitrary, Gen }; 36 | 37 | // copied from `cgmath-rs/src/vector.rs`. 38 | macro_rules! fold( 39 | ($m: ident, { $x: expr, $y: expr }) => { 40 | $x.$m($y) 41 | }; 42 | ($m: ident, { $x: expr, $y: expr, $z: expr }) => { 43 | $x.$m($y).$m($z) 44 | }; 45 | ($m: ident, { $x: expr, $y: expr, $z: expr, $w: expr }) => { 46 | $x.$m($y).$m($z).$m($w) 47 | }; 48 | ); 49 | 50 | macro_rules! def_genvec( 51 | ( 52 | $t: ident, // name of the type to be defined, 53 | $n: expr, // dimension (2, 3, or 4), 54 | $($field: ident),+ // list of field names (e.g., "x, y, z"). 55 | ) => { 56 | #[repr(C)] 57 | #[derive(Copy, Clone, PartialEq, Debug)] 58 | pub struct $t { 59 | $(pub $field: T),+ 60 | } 61 | impl $t { 62 | #[inline(always)] 63 | pub fn new($($field: T),+) -> $t { 64 | $t { $($field: $field),+ } 65 | } 66 | #[inline(always)] 67 | pub fn from_array(ary: &[T; $n]) -> &$t { 68 | let r: &$t = unsafe { mem::transmute(ary) }; 69 | r 70 | } 71 | #[inline(always)] 72 | pub fn from_array_mut(ary: &mut [T; $n]) -> &mut $t { 73 | let r: &mut $t = unsafe { mem::transmute(ary) }; 74 | r 75 | } 76 | #[inline(always)] 77 | pub fn as_array(&self) -> &[T; $n] { 78 | let ary: &[T; $n] = unsafe { mem::transmute(self) }; 79 | ary 80 | } 81 | #[inline(always)] 82 | pub fn as_array_mut(&mut self) -> &mut [T; $n] { 83 | let ary: &mut [T; $n] = unsafe { mem::transmute(self) }; 84 | ary 85 | } 86 | } 87 | impl GenVec for $t { 88 | #[inline(always)] 89 | fn dim() -> usize { $n } 90 | } 91 | impl Index for $t { 92 | type Output = T; 93 | #[inline(always)] 94 | fn index<'a>(&'a self, i: usize) -> &'a T { 95 | self.as_array().index(i) 96 | } 97 | } 98 | impl IndexMut for $t { 99 | #[inline(always)] 100 | fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut T { 101 | self.as_array_mut().index_mut(i) 102 | } 103 | } 104 | impl Rand for $t { 105 | #[inline] 106 | fn rand(rng: &mut R) -> $t { 107 | $t {$($field: rng.gen()),+} 108 | } 109 | } 110 | impl Arbitrary for $t { 111 | fn arbitrary(g: &mut G) -> $t { 112 | // do not use `g.size()`. 113 | g.gen() 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 | impl Mul<$t> for $t { 147 | type Output = $t; 148 | #[inline(always)] 149 | fn mul(self, rhs: $t) -> $t { 150 | $t::new($(self.$field * rhs.$field),+) 151 | } 152 | } 153 | impl Mul for $t { 154 | type Output = $t; 155 | #[inline(always)] 156 | fn mul(self, rhs: T) -> $t { 157 | $t::new($(self.$field * rhs),+) 158 | } 159 | } 160 | impl Div<$t> for $t { 161 | type Output = $t; 162 | #[inline(always)] 163 | fn div(self, rhs: $t) -> $t { 164 | $t::new($(self.$field / rhs.$field),+) 165 | } 166 | } 167 | impl Div for $t { 168 | type Output = $t; 169 | #[inline(always)] 170 | fn div(self, rhs: T) -> $t { 171 | $t::new($(self.$field / rhs),+) 172 | } 173 | } 174 | impl Rem<$t> for $t { 175 | type Output = $t; 176 | #[inline(always)] 177 | fn rem(self, rhs: $t) -> $t { 178 | $t::new($(self.$field % rhs.$field),+) 179 | } 180 | } 181 | impl Rem for $t { 182 | type Output = $t; 183 | #[inline(always)] 184 | fn rem(self, rhs: T) -> $t { 185 | $t::new($(self.$field % rhs),+) 186 | } 187 | } 188 | impl One for $t { 189 | #[inline(always)] 190 | fn one() -> $t { 191 | let y = T::one(); 192 | $t { $($field: y),+ } 193 | } 194 | } 195 | impl Zero for $t { 196 | #[inline(always)] 197 | fn zero() -> $t { 198 | let l = T::zero(); 199 | $t { $($field: l),+ } 200 | } 201 | #[inline] 202 | fn is_zero(&self) -> bool { 203 | let l = T::zero(); 204 | $(self.$field == l) && + 205 | } 206 | } 207 | impl GenNum for $t { 208 | #[inline(always)] 209 | fn from_s(x: T) -> Self { 210 | $t { $($field: x),+ } 211 | } 212 | #[inline(always)] 213 | fn map T>(self, f: F) -> $t { 214 | $t::new($(f(self.$field)),+) 215 | } 216 | #[inline(always)] 217 | fn zip T>(self, y: $t, f: F) -> $t { 218 | $t::new($(f(self.$field, y.$field)),+) 219 | } 220 | #[inline] 221 | fn split (T, T)>(self, f: F) -> ($t, $t) { 222 | let ling = $t::::zero(); 223 | let mut a = ling; 224 | let mut b = ling; 225 | let dim = $t::::dim(); 226 | for i in 0..dim { 227 | let (c, d) = f(self[i]); 228 | a[i] = c; 229 | b[i] = d; 230 | } 231 | (a, b) 232 | } 233 | #[inline] 234 | fn map2 (T, T)>(self, y: Self, f: F) -> (Self, Self) { 235 | let ling = Self::zero(); 236 | let mut a = ling; 237 | let mut b = ling; 238 | let dim = Self::dim(); 239 | for i in 0..dim { 240 | let (c, d) = f(self[i], y[i]); 241 | a[i] = c; 242 | b[i] = d; 243 | } 244 | (a, b) 245 | } 246 | } 247 | impl GenNumVec for $t { 248 | #[inline(always)] 249 | fn sum(&self) -> T { 250 | fold!(add, { $(self.$field),+ }) 251 | } 252 | #[inline(always)] 253 | fn product(&self) -> T { 254 | fold!(mul, { $(self.$field),+ }) 255 | } 256 | #[inline(always)] 257 | fn min(&self) -> T { 258 | fold!(min, { $(self.$field),+ }) 259 | } 260 | #[inline(always)] 261 | fn max(&self) -> T { 262 | fold!(max, { $(self.$field),+ }) 263 | } 264 | } 265 | impl Neg for $t { 266 | type Output = $t; 267 | #[inline] 268 | fn neg(self) -> $t { 269 | $t::new($(-(self.$field)),+) 270 | } 271 | } 272 | impl Sub<$t> for $t { 273 | type Output = $t; 274 | #[inline(always)] 275 | fn sub(self, rhs: $t) -> $t { 276 | $t::new($(self.$field - rhs.$field),+) 277 | } 278 | } 279 | impl Sub for $t { 280 | type Output = $t; 281 | #[inline(always)] 282 | fn sub(self, rhs: T) -> $t { 283 | $t::new($(self.$field - rhs),+) 284 | } 285 | } 286 | impl SignedNum for $t { 287 | #[inline] 288 | fn abs(&self) -> $t { 289 | $t::new($(self.$field.abs()),+) 290 | } 291 | #[inline] 292 | fn sign(&self) -> $t { 293 | $t::new($(self.$field.sign()),+) 294 | } 295 | } 296 | impl Eq for $t {} 297 | impl Not for $t { 298 | type Output = Self; 299 | #[inline] 300 | fn not(self) -> Self { 301 | $t::new($(!self.$field),+) 302 | } 303 | } 304 | impl BitAnd for $t { 305 | type Output = Self; 306 | #[inline] 307 | fn bitand(self, rhs: T) -> Self { 308 | $t::new($(self.$field & rhs),+) 309 | } 310 | } 311 | impl BitAnd<$t> for $t { 312 | type Output = Self; 313 | #[inline] 314 | fn bitand(self, rhs: Self) -> Self { 315 | $t::new($(self.$field & rhs.$field),+) 316 | } 317 | } 318 | impl BitOr for $t { 319 | type Output = Self; 320 | #[inline] 321 | fn bitor(self, rhs: T) -> Self { 322 | $t::new($(self.$field | rhs),+) 323 | } 324 | } 325 | impl BitOr<$t> for $t { 326 | type Output = Self; 327 | #[inline] 328 | fn bitor(self, rhs: Self) -> Self { 329 | $t::new($(self.$field | rhs.$field),+) 330 | } 331 | } 332 | impl BitXor for $t { 333 | type Output = Self; 334 | #[inline] 335 | fn bitxor(self, rhs: T) -> Self { 336 | $t::new($(self.$field ^ rhs),+) 337 | } 338 | } 339 | impl BitXor<$t> for $t { 340 | type Output = Self; 341 | #[inline] 342 | fn bitxor(self, rhs: Self) -> Self { 343 | $t::new($(self.$field ^ rhs.$field),+) 344 | } 345 | } 346 | impl Shl for $t { 347 | type Output = Self; 348 | #[inline] 349 | fn shl(self, rhs: usize) -> Self { 350 | $t::new($(self.$field << rhs),+) 351 | } 352 | } 353 | impl Shr for $t { 354 | type Output = Self; 355 | #[inline] 356 | fn shr(self, rhs: usize) -> Self { 357 | $t::new($(self.$field >> rhs),+) 358 | } 359 | } 360 | impl GenInt for $t {} 361 | impl GenIType for $t {} 362 | impl GenUType for $t {} 363 | impl ApproxEq for $t { 364 | type BaseType = T; 365 | #[inline] 366 | fn is_close_to(&self, rhs: &$t, max_diff: T) -> bool { 367 | $(self.$field.is_close_to(&rhs.$field, max_diff)) && + 368 | } 369 | } 370 | impl GenFloat for $t { 371 | fn fma(&self, b: &$t, c: &$t) -> $t { 372 | $t::new($(Float::mul_add(self.$field, b.$field, c.$field)),+) 373 | } 374 | } 375 | impl GenFloatVec for $t {} 376 | impl GenType for $t {} 377 | impl GenDType for $t {} 378 | } 379 | ); 380 | 381 | def_genvec! { Vector2, 2, x, y } 382 | def_genvec! { Vector3, 3, x, y, z } 383 | def_genvec! { Vector4, 4, x, y, z, w } 384 | 385 | impl Vector2 { 386 | /// Extends _self_ to a `Vector3` by appending `z`. 387 | /// 388 | /// # Example 389 | /// 390 | /// ```rust 391 | /// use glm::*; 392 | /// 393 | /// let v2 = vec2(1., 2.); 394 | /// let v3 = vec3(1., 2., 3.); 395 | /// assert_eq!(v2.extend(3.), v3); 396 | /// ``` 397 | #[inline] 398 | pub fn extend(&self, z: T) -> Vector3 { 399 | Vector3 { x: self.x, y: self.y, z: z } 400 | } 401 | } 402 | 403 | impl Vector3 { 404 | /// Extends _self_ to a `Vector4` by appending `w`. 405 | /// 406 | /// # Example 407 | /// 408 | /// ```rust 409 | /// use glm::*; 410 | /// 411 | /// let v3 = vec3(1., 2., 3.); 412 | /// let v4 = vec4(1., 2., 3., 4.); 413 | /// assert_eq!(v3.extend(4.), v4); 414 | /// ``` 415 | #[inline] 416 | pub fn extend(&self, w: T) -> Vector4 { 417 | Vector4 { x: self.x, y: self.y, z: self.z, w: w } 418 | } 419 | 420 | /// Truncates _self_ to a `Vector2` by remove the `i`th element. 421 | /// 422 | /// Parameter `i` is `0` based index. 423 | /// 424 | /// # Panic 425 | /// 426 | /// It is a panic if i is larger than `2`. 427 | /// 428 | /// # Example 429 | /// 430 | /// ```rust 431 | /// use glm::*; 432 | /// 433 | /// let v3 = vec3(1., 2., 3.); 434 | /// let v2 = vec2(1., 3.); 435 | /// assert_eq!(v3.truncate(1), v2); 436 | /// ``` 437 | #[inline] 438 | pub fn truncate(&self, i: usize) -> Vector2 { 439 | match i { 440 | 0 => Vector2::new(self.y, self.z), 441 | 1 => Vector2::new(self.x, self.z), 442 | 2 => Vector2::new(self.x, self.y), 443 | _ => panic!("parameter i is out of range [{:?} > 2].", i) 444 | } 445 | } 446 | } 447 | 448 | impl Vector4 { 449 | /// Truncates _self_ to a `Vector3` by remove the `i`th element. 450 | /// 451 | /// Parameter `i` is `0` based index. 452 | /// 453 | /// # Panic 454 | /// 455 | /// It is a panic if i is larger than `3`. 456 | #[inline] 457 | pub fn truncate(&self, i: usize) -> Vector3 { 458 | match i { 459 | 0 => Vector3::new(self.y, self.z, self.w), 460 | 1 => Vector3::new(self.x, self.z, self.w), 461 | 2 => Vector3::new(self.x, self.y, self.w), 462 | 3 => Vector3::new(self.x, self.y, self.z), 463 | _ => panic!("parameter i is out of range [{:?} > 3].", i) 464 | } 465 | } 466 | } 467 | 468 | macro_rules! def_alias( 469 | ( 470 | $({ 471 | $a: ident, // type alias (e.g., Vec2 for Vector2), 472 | $t: ident, // type to be aliased, 473 | $et: ty, // element type, 474 | $ctor: ident, // constructor name (e.g., vec3), 475 | $($field: ident),+ // fields, 476 | }),+ 477 | ) => { 478 | $( 479 | pub type $a = $t<$et>; 480 | #[inline(always)] 481 | pub fn $ctor($($field: $et),+) -> $t<$et> { 482 | $t::new($($field),+) 483 | } 484 | )+ 485 | } 486 | ); 487 | 488 | def_alias! { 489 | { BVec2, Vector2, bool, bvec2, x, y }, 490 | { BVec3, Vector3, bool, bvec3, x, y, z }, 491 | { BVec4, Vector4, bool, bvec4, x, y, z, w }, 492 | 493 | { Vec2, Vector2, f32, vec2, x, y }, 494 | { Vec3, Vector3, f32, vec3, x, y, z }, 495 | { Vec4, Vector4, f32, vec4, x, y, z, w }, 496 | 497 | { DVec2, Vector2, f64, dvec2, x, y }, 498 | { DVec3, Vector3, f64, dvec3, x, y, z }, 499 | { DVec4, Vector4, f64, dvec4, x, y, z, w }, 500 | 501 | { IVec2, Vector2, i32, ivec2, x, y }, 502 | { IVec3, Vector3, i32, ivec3, x, y, z }, 503 | { IVec4, Vector4, i32, ivec4, x, y, z, w }, 504 | 505 | { UVec2, Vector2, u32, uvec2, x, y }, 506 | { UVec3, Vector3, u32, uvec3, x, y, z }, 507 | { UVec4, Vector4, u32, uvec4, x, y, z, w } 508 | } 509 | 510 | #[cfg(test)] 511 | mod test { 512 | 513 | use super::*; 514 | use num::One; 515 | use quickcheck::*; 516 | 517 | #[test] 518 | fn test_as_array() { 519 | fn prop(v3: Vec3) -> bool { 520 | let ary: &[f32; 3] = v3.as_array(); 521 | ary[0] == v3.x && 522 | ary[1] == v3.y && 523 | ary[2] == v3.z 524 | } 525 | quickcheck(prop as fn(Vec3) -> bool); 526 | } 527 | 528 | #[test] 529 | fn test_as_array_mut() { 530 | fn prop(v2: DVec2) -> bool { 531 | let DVec2 { x, y } = v2; 532 | let mut v = v2; 533 | let ary: &mut [f64; 2] = v.as_array_mut(); 534 | ary[0] = x + 1.; 535 | ary[1] = y * 2.; 536 | (x + 1.) == ary[0] && 537 | (y * 2.) == ary[1] 538 | } 539 | quickcheck(prop as fn(DVec2) -> bool) 540 | } 541 | 542 | #[test] 543 | fn test_index() { 544 | fn prop(v3: Vec3) -> bool { 545 | v3[0] == v3.x && 546 | v3[1] == v3.y && 547 | v3[2] == v3.z 548 | } 549 | quickcheck(prop as fn(Vec3) -> bool); 550 | } 551 | 552 | #[test] 553 | fn test_index_mut() { 554 | fn prop(iv: IVec3) -> bool { 555 | let mut miv = iv; 556 | miv[0] = iv.x + 1; 557 | miv[1] = iv.y + 1; 558 | miv[2] = iv.z + 1; 559 | miv == iv + IVec3::one() 560 | } 561 | quickcheck(prop as fn(IVec3) -> bool); 562 | } 563 | } 564 | --------------------------------------------------------------------------------