1 /*! 2 # glam 3 4 `glam` is a simple and fast linear algebra library for games and graphics. 5 6 ## Features 7 8 * [`f32`](mod@f32) types 9 * vectors: [`Vec2`], [`Vec3`], [`Vec3A`] and [`Vec4`] 10 * square matrices: [`Mat2`], [`Mat3`], [`Mat3A`] and [`Mat4`] 11 * a quaternion type: [`Quat`] 12 * affine transformation types: [`Affine2`] and [`Affine3A`] 13 * [`f64`](mod@f64) types 14 * vectors: [`DVec2`], [`DVec3`] and [`DVec4`] 15 * square matrices: [`DMat2`], [`DMat3`] and [`DMat4`] 16 * a quaternion type: [`DQuat`] 17 * affine transformation types: [`DAffine2`] and [`DAffine3`] 18 * [`i16`](mod@i16) types 19 * vectors: [`I16Vec2`], [`I16Vec3`] and [`I16Vec4`] 20 * [`u16`](mod@u16) types 21 * vectors: [`U16Vec2`], [`U16Vec3`] and [`U16Vec4`] 22 * [`i32`](mod@i32) types 23 * vectors: [`IVec2`], [`IVec3`] and [`IVec4`] 24 * [`u32`](mod@u32) types 25 * vectors: [`UVec2`], [`UVec3`] and [`UVec4`] 26 * [`i64`](mod@i64) types 27 * vectors: [`I64Vec2`], [`I64Vec3`] and [`I64Vec4`] 28 * [`u64`](mod@u64) types 29 * vectors: [`U64Vec2`], [`U64Vec3`] and [`U64Vec4`] 30 * [`bool`](mod@bool) types 31 * vectors: [`BVec2`], [`BVec3`] and [`BVec4`] 32 33 ## SIMD 34 35 `glam` is built with SIMD in mind. Many `f32` types use 128-bit SIMD vector types for storage 36 and/or implementation. The use of SIMD generally enables better performance than using primitive 37 numeric types such as `f32`. 38 39 Some `glam` types use SIMD for storage meaning they are 16 byte aligned, these types include 40 `Mat2`, `Mat3A`, `Mat4`, `Quat`, `Vec3A`, `Vec4`, `Affine2` an `Affine3A`. Types 41 with an `A` suffix are a SIMD alternative to a scalar type, e.g. `Vec3` uses `f32` storage and 42 `Vec3A` uses SIMD storage. 43 44 When SIMD is not available on the target the types will maintain 16 byte alignment and internal 45 padding so that object sizes and layouts will not change between architectures. There are scalar 46 math fallback implementations exist when SIMD is not available. It is intended to add support for 47 other SIMD architectures once they appear in stable Rust. 48 49 Currently only SSE2 on x86/x86_64 is supported as this is what stable Rust supports. 50 51 ## Vec3A and Mat3A 52 53 `Vec3A` is a SIMD optimized version of the `Vec3` type, which due to 16 byte alignment results 54 in `Vec3A` containing 4 bytes of padding making it 16 bytes in size in total. `Mat3A` is composed 55 of three `Vec3A` columns. 56 57 | Type | `f32` bytes | Align bytes | Size bytes | Padding | 58 |:-----------|------------:|------------:|-----------:|--------:| 59 |[`Vec3`] | 12| 4| 12| 0| 60 |[`Vec3A`] | 12| 16| 16| 4| 61 |[`Mat3`] | 36| 4| 36| 0| 62 |[`Mat3A`] | 36| 16| 48| 12| 63 64 Despite this wasted space the SIMD implementations tend to outperform `f32` implementations in 65 [**mathbench**](https://github.com/bitshifter/mathbench-rs) benchmarks. 66 67 `glam` treats [`Vec3`] as the default 3D vector type and [`Vec3A`] a special case for optimization. 68 When methods need to return a 3D vector they will generally return [`Vec3`]. 69 70 There are [`From`] trait implementations for converting from [`Vec4`] to a [`Vec3A`] and between 71 [`Vec3`] and [`Vec3A`] (and vice versa). 72 73 ``` 74 use glam::{Vec3, Vec3A, Vec4}; 75 76 let v4 = Vec4::new(1.0, 2.0, 3.0, 4.0); 77 78 // Convert from `Vec4` to `Vec3A`, this is a no-op if SIMD is supported. 79 let v3a = Vec3A::from(v4); 80 assert_eq!(Vec3A::new(1.0, 2.0, 3.0), v3a); 81 82 // Convert from `Vec3A` to `Vec3`. 83 let v3 = Vec3::from(v3a); 84 assert_eq!(Vec3::new(1.0, 2.0, 3.0), v3); 85 86 // Convert from `Vec3` to `Vec3A`. 87 let v3a = Vec3A::from(v3); 88 assert_eq!(Vec3A::new(1.0, 2.0, 3.0), v3a); 89 ``` 90 91 ## Affine2 and Affine3A 92 93 `Affine2` and `Affine3A` are composed of a linear transform matrix and a vector translation. The 94 represent 2D and 3D affine transformations which are commonly used in games. 95 96 The table below shows the performance advantage of `Affine2` over `Mat3A` and `Mat3A` over `Mat3`. 97 98 | operation | `Mat3` | `Mat3A` | `Affine2` | 99 |--------------------|-------------|------------|------------| 100 | inverse | 11.4±0.09ns | 7.1±0.09ns | 5.4±0.06ns | 101 | mul self | 10.5±0.04ns | 5.2±0.05ns | 4.0±0.05ns | 102 | transform point2 | 2.7±0.02ns | 2.7±0.03ns | 2.8±0.04ns | 103 | transform vector2 | 2.6±0.01ns | 2.6±0.03ns | 2.3±0.02ns | 104 105 Performance is much closer between `Mat4` and `Affine3A` with the affine type being faster to 106 invert. 107 108 | operation | `Mat4` | `Affine3A` | 109 |--------------------|-------------|-------------| 110 | inverse | 15.9±0.11ns | 10.8±0.06ns | 111 | mul self | 7.3±0.05ns | 7.0±0.06ns | 112 | transform point3 | 3.6±0.02ns | 4.3±0.04ns | 113 | transform point3a | 3.0±0.02ns | 3.0±0.04ns | 114 | transform vector3 | 4.1±0.02ns | 3.9±0.04ns | 115 | transform vector3a | 2.8±0.02ns | 2.8±0.02ns | 116 117 Benchmarks were taken on an Intel Core i7-4710HQ. 118 119 ## Linear algebra conventions 120 121 `glam` interprets vectors as column matrices (also known as column vectors) meaning when 122 transforming a vector with a matrix the matrix goes on the left. 123 124 ``` 125 use glam::{Mat3, Vec3}; 126 let m = Mat3::IDENTITY; 127 let x = Vec3::X; 128 let v = m * x; 129 assert_eq!(v, x); 130 ``` 131 132 Matrices are stored in memory in column-major order. 133 134 All angles are in radians. Rust provides the `f32::to_radians()` and `f64::to_radians()` methods to 135 convert from degrees. 136 137 ## Direct element access 138 139 Because some types may internally be implemented using SIMD types, direct access to vector elements 140 is supported by implementing the [`Deref`] and [`DerefMut`] traits. 141 142 ``` 143 use glam::Vec3A; 144 let mut v = Vec3A::new(1.0, 2.0, 3.0); 145 assert_eq!(3.0, v.z); 146 v.z += 1.0; 147 assert_eq!(4.0, v.z); 148 ``` 149 150 [`Deref`]: https://doc.rust-lang.org/std/ops/trait.Deref.html 151 [`DerefMut`]: https://doc.rust-lang.org/std/ops/trait.DerefMut.html 152 153 ## glam assertions 154 155 `glam` does not enforce validity checks on method parameters at runtime. For example methods that 156 require normalized vectors as input such as `Quat::from_axis_angle(axis, angle)` will not check 157 that axis is a valid normalized vector. To help catch unintended misuse of `glam` the 158 `debug-glam-assert` or `glam-assert` features can be enabled to add checks ensure that inputs to 159 are valid. 160 161 ## Vector swizzles 162 163 `glam` vector types have functions allowing elements of vectors to be reordered, this includes 164 creating a vector of a different size from the vectors elements. 165 166 The swizzle functions are implemented using traits to add them to each vector type. This is 167 primarily because there are a lot of swizzle functions which can obfuscate the other vector 168 functions in documentation and so on. The traits are [`Vec2Swizzles`], [`Vec3Swizzles`] and 169 [`Vec4Swizzles`]. 170 171 Note that the [`Vec3Swizzles`] implementation for [`Vec3A`] will return a [`Vec3A`] for 3 element 172 swizzles, all other implementations will return [`Vec3`]. 173 174 ``` 175 use glam::{swizzles::*, Vec2, Vec3, Vec3A, Vec4}; 176 177 let v = Vec4::new(1.0, 2.0, 3.0, 4.0); 178 179 // Reverse elements of `v`, if SIMD is supported this will use a vector shuffle. 180 let wzyx = v.wzyx(); 181 assert_eq!(Vec4::new(4.0, 3.0, 2.0, 1.0), wzyx); 182 183 // Swizzle the yzw elements of `v` into a `Vec3` 184 let yzw = v.yzw(); 185 assert_eq!(Vec3::new(2.0, 3.0, 4.0), yzw); 186 187 // To swizzle a `Vec4` into a `Vec3A` swizzle the `Vec4` first then convert to 188 // `Vec3A`. If SIMD is supported this will use a vector shuffle. The last 189 // element of the shuffled `Vec4` is ignored by the `Vec3A`. 190 let yzw = Vec3A::from(v.yzwx()); 191 assert_eq!(Vec3A::new(2.0, 3.0, 4.0), yzw); 192 193 // You can swizzle from a `Vec4` to a `Vec2` 194 let xy = v.xy(); 195 assert_eq!(Vec2::new(1.0, 2.0), xy); 196 197 // And back again 198 let yyxx = xy.yyxx(); 199 assert_eq!(Vec4::new(2.0, 2.0, 1.0, 1.0), yyxx); 200 ``` 201 202 ## SIMD and scalar consistency 203 204 `glam` types implement `serde` `Serialize` and `Deserialize` traits to ensure 205 that they will serialize and deserialize exactly the same whether or not 206 SIMD support is being used. 207 208 The SIMD versions implement the `core::fmt::Debug` and `core::fmt::Display` 209 traits so they print the same as the scalar version. 210 211 ``` 212 use glam::Vec4; 213 let a = Vec4::new(1.0, 2.0, 3.0, 4.0); 214 assert_eq!(format!("{}", a), "[1, 2, 3, 4]"); 215 ``` 216 217 ## Feature gates 218 219 All `glam` dependencies are optional, however some are required for tests 220 and benchmarks. 221 222 * `std` - the default feature, has no dependencies. 223 * `approx` - traits and macros for approximate float comparisons 224 * `bytemuck` - for casting into slices of bytes 225 * `libm` - uses `libm` math functions instead of `std`, required to compile with `no_std` 226 * `mint` - for interoperating with other 3D math libraries 227 * `rand` - implementations of `Distribution` trait for all `glam` types. 228 * `rkyv` - implementations of `Archive`, `Serialize` and `Deserialize` for all 229 `glam` types. Note that serialization is not interoperable with and without the 230 `scalar-math` feature. It should work between all other builds of `glam`. 231 Endian conversion is currently not supported 232 * `bytecheck` - to perform archive validation when using the `rkyv` feature 233 * `serde` - implementations of `Serialize` and `Deserialize` for all `glam` 234 types. Note that serialization should work between builds of `glam` with and without SIMD enabled 235 * `scalar-math` - disables SIMD support and uses native alignment for all types. 236 * `debug-glam-assert` - adds assertions in debug builds which check the validity of parameters 237 passed to `glam` to help catch runtime errors. 238 * `glam-assert` - adds assertions to all builds which check the validity of parameters passed to 239 `glam` to help catch runtime errors. 240 * `cuda` - forces `glam` types to match expected cuda alignment 241 * `fast-math` - By default, glam attempts to provide bit-for-bit identical 242 results on all platforms. Using this feature will enable platform specific 243 optimizations that may not be identical to other platforms. **Intermediate 244 libraries should not use this feature and defer the decision to the final 245 binary build**. 246 * `core-simd` - enables SIMD support via the portable simd module. This is an 247 unstable feature which requires a nightly Rust toolchain and `std` support. 248 249 ## Minimum Supported Rust Version (MSRV) 250 251 The minimum supported Rust version is `1.58.1`. 252 253 */ 254 #![doc(html_root_url = "https://docs.rs/glam/0.25.0")] 255 #![cfg_attr(not(feature = "std"), no_std)] 256 #![cfg_attr(target_arch = "spirv", feature(repr_simd))] 257 #![deny( 258 rust_2018_compatibility, 259 rust_2018_idioms, 260 future_incompatible, 261 nonstandard_style 262 )] 263 // clippy doesn't like `to_array(&self)` 264 #![allow(clippy::wrong_self_convention)] 265 #![cfg_attr( 266 all(feature = "core-simd", not(feature = "scalar-math")), 267 feature(portable_simd) 268 )] 269 270 #[macro_use] 271 mod macros; 272 273 mod align16; 274 mod deref; 275 mod euler; 276 mod features; 277 278 #[cfg(target_arch = "spirv")] 279 mod spirv; 280 281 #[cfg(all( 282 target_feature = "sse2", 283 not(any(feature = "core-simd", feature = "scalar-math")) 284 ))] 285 mod sse2; 286 287 #[cfg(all( 288 target_feature = "simd128", 289 not(any(feature = "core-simd", feature = "scalar-math")) 290 ))] 291 mod wasm32; 292 293 #[cfg(all(feature = "core-simd", not(feature = "scalar-math")))] 294 mod coresimd; 295 296 #[cfg(all( 297 target_feature = "sse2", 298 not(any(feature = "core-simd", feature = "scalar-math")) 299 ))] 300 use align16::Align16; 301 302 /** `bool` vector mask types. */ 303 pub mod bool; 304 pub use self::bool::*; 305 306 /** `f32` vector, quaternion and matrix types. */ 307 pub mod f32; 308 pub use self::f32::*; 309 310 /** `f64` vector, quaternion and matrix types. */ 311 pub mod f64; 312 pub use self::f64::*; 313 314 /** `i16` vector types. */ 315 pub mod i16; 316 pub use self::i16::*; 317 318 /** `u16` vector types. */ 319 pub mod u16; 320 pub use self::u16::*; 321 322 /** `i32` vector types. */ 323 pub mod i32; 324 pub use self::i32::*; 325 326 /** `u32` vector types. */ 327 pub mod u32; 328 pub use self::u32::*; 329 330 /** `i64` vector types. */ 331 pub mod i64; 332 pub use self::i64::*; 333 334 /** `u64` vector types. */ 335 pub mod u64; 336 pub use self::u64::*; 337 338 /** Traits adding swizzle methods to all vector types. */ 339 pub mod swizzles; 340 pub use self::swizzles::{Vec2Swizzles, Vec3Swizzles, Vec4Swizzles}; 341 342 /** Rotation Helper */ 343 pub use euler::EulerRot; 344 345 /** A trait for extending [`prim@f32`] and [`prim@f64`] with extra methods. */ 346 mod float; 347 pub use float::FloatExt; 348