Skip to main content

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