glam/lib.rs
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`], [`Affine3`] and [`Affine3A`]
13 * camera: [`camera`] module with view and projection constructors
14* [`f64`](mod@f64) types
15 * vectors: [`DVec2`], [`DVec3`] and [`DVec4`]
16 * square matrices: [`DMat2`], [`DMat3`] and [`DMat4`]
17 * a quaternion type: [`DQuat`]
18 * affine transformation types: [`DAffine2`] and [`DAffine3`]
19 * camera: [`dcamera`] module with view and projection constructors
20* [`i8`](mod@i8) types
21 * vectors: [`I8Vec2`], [`I8Vec3`] and [`I8Vec4`]
22* [`u8`](mod@u8) types
23 * vectors: [`U8Vec2`], [`U8Vec3`] and [`U8Vec4`]
24* [`i16`](mod@i16) types
25 * vectors: [`I16Vec2`], [`I16Vec3`] and [`I16Vec4`]
26* [`u16`](mod@u16) types
27 * vectors: [`U16Vec2`], [`U16Vec3`] and [`U16Vec4`]
28* [`i32`](mod@i32) types
29 * vectors: [`IVec2`], [`IVec3`] and [`IVec4`]
30* [`u32`](mod@u32) types
31 * vectors: [`UVec2`], [`UVec3`] and [`UVec4`]
32* [`i64`](mod@i64) types
33 * vectors: [`I64Vec2`], [`I64Vec3`] and [`I64Vec4`]
34* [`u64`](mod@u64) types
35 * vectors: [`U64Vec2`], [`U64Vec3`] and [`U64Vec4`]
36* [`isize`](mod@isize) types
37 * vectors: [`ISizeVec2`], [`ISizeVec3`] and [`ISizeVec4`]
38* [`usize`](mod@usize) types
39 * vectors: [`USizeVec2`], [`USizeVec3`] and [`USizeVec4`]
40* [`bool`](mod@bool) types
41 * vectors: [`BVec2`], [`BVec3`], [`BVec3A`], [`BVec4`] and [`BVec4A`]
42
43All types are enabled by default. Only `f32` and `bool` types are built-in.
44All other types are optional and can be disabled if not needed for faster
45compile times.
46
47## SIMD
48
49`glam` is built with SIMD in mind. Many `f32` types use 128-bit SIMD vector types for storage
50and/or implementation. The use of SIMD generally enables better performance than using primitive
51numeric types such as `f32`.
52
53Some `glam` types use SIMD for storage meaning they are 16 byte aligned, these types include
54`Mat2`, `Mat3A`, `Mat4`, `Quat`, `Vec3A`, `Vec4`, `Affine2` and `Affine3A`. Types
55with an `A` suffix are a SIMD alternative to a scalar type, e.g. `Vec3` uses `f32` storage and
56`Vec3A` uses SIMD storage.
57
58When SIMD is not available on the target the types will maintain 16 byte alignment and internal
59padding so that object sizes and layouts will not change between architectures. Scalar
60math fallback implementations exist when SIMD is not available. It is intended to add support for
61other SIMD architectures once they appear in stable Rust.
62
63Currently only SSE2 on x86/x86_64, NEON on Aarch64, and simd128 on WASM are supported.
64
65## Vec3A and Mat3A
66
67`Vec3A` is a SIMD optimized version of the `Vec3` type, which due to 16 byte alignment results
68in `Vec3A` containing 4 bytes of padding making it 16 bytes in size in total. `Mat3A` is composed
69of three `Vec3A` columns.
70
71| Type | `f32` bytes | Align bytes | Size bytes | Padding |
72|:-----------|------------:|------------:|-----------:|--------:|
73|[`Vec3`] | 12| 4| 12| 0|
74|[`Vec3A`] | 12| 16| 16| 4|
75|[`Mat3`] | 36| 4| 36| 0|
76|[`Mat3A`] | 36| 16| 48| 12|
77
78`glam` treats [`Vec3`] as the default 3D vector type and [`Vec3A`] a special case for optimization.
79When methods need to return a 3D vector they will generally return [`Vec3`].
80
81There are [`From`] trait implementations for converting between [`Vec3`] and [`Vec3A`]. There is
82also a [`Vec3A::from_vec4`] method for converting from [`Vec4`] to [`Vec3A`], discarding the `w`
83element.
84
85```
86use glam::{Vec3, Vec3A, Vec4};
87
88let v4 = Vec4::new(1.0, 2.0, 3.0, 4.0);
89
90// Convert from `Vec4` to `Vec3A`, this is a no-op if SIMD is supported.
91// We use an explicit method here instead of a From impl as data is lost in the conversion.
92let v3a = Vec3A::from_vec4(v4);
93assert_eq!(Vec3A::new(1.0, 2.0, 3.0), v3a);
94
95// Convert from `Vec3A` to `Vec3`.
96let v3 = Vec3::from(v3a);
97assert_eq!(Vec3::new(1.0, 2.0, 3.0), v3);
98
99// Convert from `Vec3` to `Vec3A`.
100let v3a = Vec3A::from(v3);
101assert_eq!(Vec3A::new(1.0, 2.0, 3.0), v3a);
102```
103
104## Affine2, Affine3 and Affine3A
105
106`Affine2`, `Affine3` and `Affine3A` are composed of a linear transform matrix and a vector
107translation. They represent 2D and 3D affine transformations which are commonly used in games.
108
109`Affine3` is composed from `Vec3` and `Mat3` whereas `Affine3A` is composed from `Mat3A` and
110`Vec3A`. `Affine3A` will generally be faster but is 16 byte aligned and 64 bytes versus `Affine3`
111which is 48 bytes.
112
113The table below shows the performance advantage of `Affine2` over `Mat3A` and `Mat3A` over `Mat3`.
114
115| operation | `Mat3` | `Mat3A` | `Affine2` |
116|--------------------|-------------|------------|------------|
117| inverse | 11.4±0.09ns | 7.1±0.09ns | 5.4±0.06ns |
118| mul self | 10.5±0.04ns | 5.2±0.05ns | 4.0±0.05ns |
119| transform point2 | 2.7±0.02ns | 2.7±0.03ns | 2.8±0.04ns |
120| transform vector2 | 2.6±0.01ns | 2.6±0.03ns | 2.3±0.02ns |
121
122Performance is much closer between `Mat4` and `Affine3A` with the affine type being faster to
123invert.
124
125| operation | `Mat4` | `Affine3A` |
126|--------------------|-------------|-------------|
127| inverse | 15.9±0.11ns | 10.8±0.06ns |
128| mul self | 7.3±0.05ns | 7.0±0.06ns |
129| transform point3 | 3.6±0.02ns | 4.3±0.04ns |
130| transform point3a | 3.0±0.02ns | 3.0±0.04ns |
131| transform vector3 | 4.1±0.02ns | 3.9±0.04ns |
132| transform vector3a | 2.8±0.02ns | 2.8±0.02ns |
133
134Benchmarks were taken on an Intel Core i7-4710HQ.
135
136## Linear algebra conventions
137
138`glam` interprets vectors as column matrices (also known as column vectors) meaning when
139transforming a vector with a matrix the matrix goes on the left.
140
141```
142use glam::{Mat3, Vec3};
143let m = Mat3::IDENTITY;
144let x = Vec3::X;
145let v = m * x;
146assert_eq!(v, x);
147```
148
149Matrices are stored in memory in column-major order.
150
151All angles are in radians. Rust provides the `f32::to_radians()` and `f64::to_radians()` methods to
152convert from degrees.
153
154## Camera
155
156`glam` provides a [`camera`] module with view matrix (`look_at`, `look_to`) and
157projection matrix (`perspective`, `orthographic`, `frustum`) constructors.
158
159View functions transform world space points into Y-up view space. Choose [`camera::rh`] or
160[`camera::lh`] based on your world space handedness.
161
162Projection functions expect Y-up view space input with matching handedness. Within
163each sub-module, constructors are available for common graphics API conventions,
164including OpenGL, DirectX, Vulkan, and WebGPU.
165
166## Direct element access
167
168Because some types may internally be implemented using SIMD types, direct access to vector elements
169is supported by implementing the [`Deref`] and [`DerefMut`] traits.
170
171```
172use glam::Vec3A;
173let mut v = Vec3A::new(1.0, 2.0, 3.0);
174assert_eq!(3.0, v.z);
175v.z += 1.0;
176assert_eq!(4.0, v.z);
177```
178
179[`Deref`]: https://doc.rust-lang.org/std/ops/trait.Deref.html
180[`DerefMut`]: https://doc.rust-lang.org/std/ops/trait.DerefMut.html
181
182## glam assertions
183
184`glam` does not enforce validity checks on method parameters at runtime. For example methods that
185require normalized vectors as input such as `Quat::from_axis_angle(axis, angle)` will not check
186that axis is a valid normalized vector. To help catch unintended misuse of `glam` the
187`debug-glam-assert` or `glam-assert` features can be enabled to add checks to ensure that inputs
188are valid.
189
190## Vector swizzles
191
192`glam` vector types have functions allowing elements of vectors to be reordered, this includes
193creating a vector of a different size from the vectors elements.
194
195The swizzle functions are implemented using traits to add them to each vector type. This is
196primarily because there are a lot of swizzle functions which can obfuscate the other vector
197functions in documentation and so on. The traits are [`Vec2Swizzles`], [`Vec3Swizzles`] and
198[`Vec4Swizzles`].
199
200Note that the [`Vec3Swizzles`] implementation for [`Vec3A`] will return a [`Vec3A`] for 3 element
201swizzles, all other implementations will return [`Vec3`].
202
203```
204use glam::{swizzles::*, Vec2, Vec3, Vec3A, Vec4};
205
206let v = Vec4::new(1.0, 2.0, 3.0, 4.0);
207
208// Reverse elements of `v`, if SIMD is supported this will use a vector shuffle.
209let wzyx = v.wzyx();
210assert_eq!(Vec4::new(4.0, 3.0, 2.0, 1.0), wzyx);
211
212// Swizzle the yzw elements of `v` into a `Vec3`
213let yzw = v.yzw();
214assert_eq!(Vec3::new(2.0, 3.0, 4.0), yzw);
215
216// To swizzle a `Vec4` into a `Vec3A` swizzle the `Vec4` first then convert to
217// `Vec3A`. If SIMD is supported this will use a vector shuffle. The last
218// element of the shuffled `Vec4` is ignored by the `Vec3A`.
219let yzw = Vec3A::from_vec4(v.yzwx());
220assert_eq!(Vec3A::new(2.0, 3.0, 4.0), yzw);
221
222// You can swizzle from a `Vec4` to a `Vec2`
223let xy = v.xy();
224assert_eq!(Vec2::new(1.0, 2.0), xy);
225
226// And back again
227let yyxx = xy.yyxx();
228assert_eq!(Vec4::new(2.0, 2.0, 1.0, 1.0), yyxx);
229```
230
231## SIMD and scalar consistency
232
233`glam` types implement `serde` `Serialize` and `Deserialize` traits to ensure
234that they will serialize and deserialize exactly the same whether or not
235SIMD support is being used.
236
237The SIMD versions implement the `core::fmt::Debug` and `core::fmt::Display`
238traits so they print the same as the scalar version.
239
240```
241use glam::Vec4;
242let a = Vec4::new(1.0, 2.0, 3.0, 4.0);
243assert_eq!(format!("{}", a), "[1, 2, 3, 4]");
244```
245## Feature gates
246
247* `std` - the default feature, has no dependencies.
248* `all-types` - a default feature, enables `float-types`, `integer-types` and `size-types`
249* `float-types` - enables `f64` types
250* `integer-types` - enables `i8`, `i16`, `i32`, `i64`, `u8`, `u16`, `u32` and `u64` types
251* `size-types` - enables `isize` and `usize` types
252* `f64`, `i8`, `i16`, `i32`, `i64`, `isize`, `u8`, `u16`, `u32`, `u64`, `usize` - enables glam types
253 for the given intrinsic type
254* `nostd-libm` - uses `libm` math functions if `std` is not available
255* `scalar-math` - disables SIMD support and uses native alignment for all types.
256* `debug-glam-assert` - adds assertions in debug builds which check the validity of parameters
257 passed to `glam` to help catch runtime errors.
258* `glam-assert` - adds assertions to all builds which check the validity of parameters passed to
259 `glam` to help catch runtime errors.
260* `cuda` - forces `glam` types to match expected cuda alignment
261* `core-simd` - enables SIMD support via the portable simd module. This is an unstable feature which
262 requires a nightly Rust toolchain and `std` support.
263
264## Optional dependencies
265
266All `glam` dependencies are optional, however some are required for tests
267and benchmarks.
268
269Pre-1.0 dependencies that appear in `glam`'s public API use versioned feature names
270(e.g. `rand-010`), so a new version can be added without a breaking change.
271
272* `approx-05` - `approx` 0.5 traits and macros for approximate float comparisons.
273* `arbitrary` - implementations of `Arbitrary` trait for all `glam` types.
274* `bytemuck` - for casting into slices of bytes
275* `encase-012` - `encase` 0.12 trait implementations for `glam` types.
276* `encase-013` - `encase` 0.13 trait implementations for `glam` types.
277* `float_eq` - traits and macros for comparing float types using various tolerances.
278* `libm` - uses `libm` math functions instead of `std`
279* `mint-05` - `mint` 0.5 for interoperating with other 3D math libraries.
280* `rand-010` - `rand` 0.10 `Distribution` implementations for all `glam` types.
281* `rkyv-08` - `rkyv` 0.8 `Archive`, `Serialize` and `Deserialize` implementations for all
282 `glam` types, archiving to `glam::rkyv_08` types instead of the native type.
283* `bytecheck` - enables `rkyv`'s archive validation; only has an effect when the `rkyv-08`
284 feature is enabled
285* `serde` - implementations of `Serialize` and `Deserialize` for all `glam`
286 types. Note that serialization should work between builds of `glam` with and without SIMD enabled
287* `speedy-08` - `speedy` 0.8 implementations of `Readable` and `Writable` for all
288 `glam` types.
289* `zerocopy-08` - `zerocopy` 0.8 implementations of zerocopy traits for safe transmutes.
290
291## Minimum Supported Rust Version (MSRV)
292
293The minimum supported version of Rust is `1.85.0`.
294
295Raising the MSRV is treated as a non-breaking change, following Cargo's [semver guidance].
296
297`glam` itself and all of its features are expected to build with the MSRV unless otherwise
298documented. Optional dependencies are exempt, per Cargo's [support expectations]: they are not
299required to build with `glam`'s MSRV, so a feature that enables one may require a newer toolchain
300than `glam` itself.
301
302[semver guidance]: https://doc.rust-lang.org/cargo/reference/semver.html#env-new-rust
303[support expectations]: https://doc.rust-lang.org/cargo/reference/rust-version.html#support-expectations
304
305*/
306#![cfg_attr(not(feature = "std"), no_std)]
307#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))]
308#![deny(
309 rust_2018_compatibility,
310 rust_2018_idioms,
311 future_incompatible,
312 nonstandard_style
313)]
314// clippy doesn't like `to_array(&self)`
315#![allow(clippy::wrong_self_convention)]
316#![cfg_attr(
317 all(feature = "core-simd", not(feature = "scalar-math")),
318 feature(portable_simd)
319)]
320
321#[cfg(all(
322 not(feature = "std"),
323 not(feature = "libm"),
324 not(feature = "nostd-libm")
325))]
326compile_error!(
327 "You must specify a math backend. Consider enabling either `std`, `libm`, or `nostd-libm`."
328);
329
330// The `zerocopy` dependency is renamed to `zerocopy-08` (see Cargo.toml), but the
331// `zerocopy-derive` macros reference the crate as `zerocopy`. An `extern crate`
332// alias puts `zerocopy` in the crate root so the generated impls resolve without a
333// per-type `#[zerocopy(crate = "...")]` attribute.
334#[cfg(feature = "zerocopy-08")]
335extern crate zerocopy_08 as zerocopy;
336
337#[macro_use]
338mod macros;
339
340mod align16;
341mod deref;
342mod euler;
343mod features;
344
345#[cfg(feature = "rkyv-08")]
346pub use features::impl_rkyv_08 as rkyv_08;
347
348#[cfg(all(
349 target_arch = "aarch64",
350 not(any(feature = "core-simd", feature = "scalar-math"))
351))]
352mod neon;
353
354#[cfg(target_arch = "spirv")]
355mod spirv;
356
357#[cfg(all(
358 target_feature = "sse2",
359 not(any(feature = "core-simd", feature = "scalar-math"))
360))]
361mod sse2;
362
363#[cfg(all(
364 target_feature = "simd128",
365 not(any(feature = "core-simd", feature = "scalar-math"))
366))]
367mod wasm;
368
369#[cfg(all(feature = "core-simd", not(feature = "scalar-math")))]
370mod coresimd;
371
372#[cfg(all(
373 target_feature = "sse2",
374 not(any(feature = "core-simd", feature = "scalar-math"))
375))]
376use align16::Align16;
377
378/** `bool` vector mask types. */
379pub mod bool;
380pub use self::bool::*;
381
382pub mod camera;
383
384#[cfg(feature = "f64")]
385pub mod dcamera;
386
387/** `f32` vector, quaternion and matrix types. */
388pub mod f32;
389pub use self::f32::*;
390
391/** `f64` vector, quaternion and matrix types. */
392#[cfg(feature = "f64")]
393pub mod f64;
394#[cfg(feature = "f64")]
395pub use self::f64::*;
396
397/** `i8` vector types. */
398#[cfg(feature = "i8")]
399pub mod i8;
400#[cfg(feature = "i8")]
401pub use self::i8::*;
402
403/** `u8` vector types. */
404#[cfg(feature = "u8")]
405pub mod u8;
406#[cfg(feature = "u8")]
407pub use self::u8::*;
408
409/** `i16` vector types. */
410#[cfg(feature = "i16")]
411pub mod i16;
412#[cfg(feature = "i16")]
413pub use self::i16::*;
414
415/** `u16` vector types. */
416#[cfg(feature = "u16")]
417pub mod u16;
418#[cfg(feature = "u16")]
419pub use self::u16::*;
420
421/** `i32` vector types. */
422#[cfg(feature = "i32")]
423pub mod i32;
424#[cfg(feature = "i32")]
425pub use self::i32::*;
426
427/** `u32` vector types. */
428#[cfg(feature = "u32")]
429pub mod u32;
430#[cfg(feature = "u32")]
431pub use self::u32::*;
432
433/** `i64` vector types. */
434#[cfg(feature = "i64")]
435pub mod i64;
436#[cfg(feature = "i64")]
437pub use self::i64::*;
438
439/** `u64` vector types. */
440#[cfg(feature = "u64")]
441pub mod u64;
442#[cfg(feature = "u64")]
443pub use self::u64::*;
444
445/** `usize` vector types. */
446#[cfg(feature = "usize")]
447pub mod usize;
448#[cfg(feature = "usize")]
449pub use self::usize::*;
450
451/** `isize` vector types. */
452#[cfg(feature = "isize")]
453pub mod isize;
454#[cfg(feature = "isize")]
455pub use self::isize::*;
456
457/** The glam prelude, including all common types but excluding camera modules. */
458pub mod prelude;
459
460/** Traits adding swizzle methods to all vector types. */
461pub mod swizzles;
462pub use self::swizzles::{Vec2Swizzles, Vec3Swizzles, Vec4Swizzles};
463
464/** Rotation Helper */
465pub use euler::EulerRot;
466
467/** A trait for extending [`prim@f32`] and [`prim@f64`] with extra methods. */
468mod float;
469pub use float::FloatExt;
470
471// Private supertrait used to seal glam's public traits so that methods can be
472// added after 1.0 without breaking downstream implementors. See C-SEALED:
473// https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
474mod sealed {
475 pub trait Sealed {}
476}