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 dependencies
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 version of Rust is `1.68.2`.
312
313Raising the MSRV is treated as a non-breaking change, following Cargo's [semver guidance].
314
315`glam` itself and all of its features are expected to build with the MSRV unless otherwise
316documented. Optional dependencies are exempt, per Cargo's [support expectations]: they are not
317required to build with `glam`'s MSRV, so a feature that enables one may require a newer toolchain
318than `glam` itself.
319
320[semver guidance]: https://doc.rust-lang.org/cargo/reference/semver.html#env-new-rust
321[support expectations]: https://doc.rust-lang.org/cargo/reference/rust-version.html#support-expectations
322
323*/
324#![cfg_attr(not(feature = "std"), no_std)]
325#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))]
326#![deny(
327 rust_2018_compatibility,
328 rust_2018_idioms,
329 future_incompatible,
330 nonstandard_style
331)]
332// clippy doesn't like `to_array(&self)`
333#![allow(clippy::wrong_self_convention)]
334#![cfg_attr(
335 all(feature = "core-simd", not(feature = "scalar-math")),
336 feature(portable_simd)
337)]
338
339#[cfg(all(
340 not(feature = "std"),
341 not(feature = "libm"),
342 not(feature = "nostd-libm")
343))]
344compile_error!(
345 "You must specify a math backend. Consider enabling either `std`, `libm`, or `nostd-libm`."
346);
347
348// The `zerocopy` dependency is renamed to `zerocopy-08` (see Cargo.toml), but the
349// `zerocopy-derive` macros reference the crate as `zerocopy`. An `extern crate`
350// alias puts `zerocopy` in the crate root so the generated impls resolve without a
351// per-type `#[zerocopy(crate = "...")]` attribute.
352#[cfg(feature = "zerocopy-08")]
353extern crate zerocopy_08 as zerocopy;
354
355#[macro_use]
356mod macros;
357
358mod align16;
359mod deref;
360mod euler;
361mod features;
362
363#[cfg(feature = "rkyv-08")]
364pub use features::impl_rkyv_08 as rkyv_08;
365
366#[cfg(all(feature = "rkyv", not(feature = "rkyv-08")))]
367pub use features::impl_rkyv as rkyv;
368
369#[cfg(all(
370 target_arch = "aarch64",
371 not(any(feature = "core-simd", feature = "scalar-math"))
372))]
373mod neon;
374
375#[cfg(target_arch = "spirv")]
376mod spirv;
377
378#[cfg(all(
379 target_feature = "sse2",
380 not(any(feature = "core-simd", feature = "scalar-math"))
381))]
382mod sse2;
383
384#[cfg(all(
385 target_feature = "simd128",
386 not(any(feature = "core-simd", feature = "scalar-math"))
387))]
388mod wasm;
389
390#[cfg(all(feature = "core-simd", not(feature = "scalar-math")))]
391mod coresimd;
392
393#[cfg(all(
394 target_feature = "sse2",
395 not(any(feature = "core-simd", feature = "scalar-math"))
396))]
397use align16::Align16;
398
399/** `bool` vector mask types. */
400pub mod bool;
401pub use self::bool::*;
402
403pub mod camera;
404
405#[cfg(feature = "f64")]
406pub mod dcamera;
407
408/** `f32` vector, quaternion and matrix types. */
409pub mod f32;
410pub use self::f32::*;
411
412/** `f64` vector, quaternion and matrix types. */
413#[cfg(feature = "f64")]
414pub mod f64;
415#[cfg(feature = "f64")]
416pub use self::f64::*;
417
418/** `i8` vector types. */
419#[cfg(feature = "i8")]
420pub mod i8;
421#[cfg(feature = "i8")]
422pub use self::i8::*;
423
424/** `u8` vector types. */
425#[cfg(feature = "u8")]
426pub mod u8;
427#[cfg(feature = "u8")]
428pub use self::u8::*;
429
430/** `i16` vector types. */
431#[cfg(feature = "i16")]
432pub mod i16;
433#[cfg(feature = "i16")]
434pub use self::i16::*;
435
436/** `u16` vector types. */
437#[cfg(feature = "u16")]
438pub mod u16;
439#[cfg(feature = "u16")]
440pub use self::u16::*;
441
442/** `i32` vector types. */
443#[cfg(feature = "i32")]
444pub mod i32;
445#[cfg(feature = "i32")]
446pub use self::i32::*;
447
448/** `u32` vector types. */
449#[cfg(feature = "u32")]
450pub mod u32;
451#[cfg(feature = "u32")]
452pub use self::u32::*;
453
454/** `i64` vector types. */
455#[cfg(feature = "i64")]
456pub mod i64;
457#[cfg(feature = "i64")]
458pub use self::i64::*;
459
460/** `u64` vector types. */
461#[cfg(feature = "u64")]
462pub mod u64;
463#[cfg(feature = "u64")]
464pub use self::u64::*;
465
466/** `usize` vector types. */
467#[cfg(feature = "usize")]
468pub mod usize;
469#[cfg(feature = "usize")]
470pub use self::usize::*;
471
472/** `isize` vector types. */
473#[cfg(feature = "isize")]
474pub mod isize;
475#[cfg(feature = "isize")]
476pub use self::isize::*;
477
478/** The glam prelude, including all common types but excluding camera modules. */
479pub mod prelude;
480
481/** Traits adding swizzle methods to all vector types. */
482pub mod swizzles;
483pub use self::swizzles::{Vec2Swizzles, Vec3Swizzles, Vec4Swizzles};
484
485/** Rotation Helper */
486pub use euler::EulerRot;
487
488/** A trait for extending [`prim@f32`] and [`prim@f64`] with extra methods. */
489mod float;
490pub use float::FloatExt;