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` - By default, glam attempts to provide bit-for-bit identical results on all platforms.
264  Using this feature will enable platform specific optimizations that may not be identical to other
265  platforms. **Intermediate libraries should not use this feature and defer the decision to the
266  final binary build**.
267* `core-simd` - enables SIMD support via the portable simd module. This is an unstable feature which
268  requires a nightly Rust toolchain and `std` support.
269
270## Optional features
271
272All `glam` dependencies are optional, however some are required for tests
273and benchmarks.
274
275* `approx` - traits and macros for approximate float comparisons
276* `arbitrary` - implementations of `Arbitrary` trait for all `glam` types.
277* `bytemuck` - for casting into slices of bytes
278* `encase` - `encase` trait implementations for `glam` types.
279* `libm` - uses `libm` math functions instead of `std`
280* `mint` - for interoperating with other 3D math libraries
281* `rand` - implementations of `Distribution` trait for all `glam` types.
282* `rkyv` - implementations of `Archive`, `Serialize` and `Deserialize` for all
283  `glam` types. Note that serialization is not interoperable with and without the
284  `scalar-math` feature. It should work between all other builds of `glam`.
285  Endian conversion is currently not supported
286* `bytecheck` - to perform archive validation when using the `rkyv` feature
287* `serde` - implementations of `Serialize` and `Deserialize` for all `glam`
288  types. Note that serialization should work between builds of `glam` with and without SIMD enabled
289* `speedy` - implementations of `speedy`'s `Readable` and `Writable` for all `glam` types.
290* `zerocopy` - implementations of zerocopy traits for safe transmutes.
291
292## Minimum Supported Rust Version (MSRV)
293
294The minimum supported Rust version is `1.68.2`.
295
296*/
297#![doc(html_root_url = "https://docs.rs/glam/0.33.2")]
298#![cfg_attr(not(feature = "std"), no_std)]
299#![cfg_attr(target_arch = "spirv", feature(repr_simd))]
300#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))]
301#![deny(
302    rust_2018_compatibility,
303    rust_2018_idioms,
304    future_incompatible,
305    nonstandard_style
306)]
307// clippy doesn't like `to_array(&self)`
308#![allow(clippy::wrong_self_convention)]
309#![cfg_attr(
310    all(feature = "core-simd", not(feature = "scalar-math")),
311    feature(portable_simd)
312)]
313
314#[cfg(all(
315    not(feature = "std"),
316    not(feature = "libm"),
317    not(feature = "nostd-libm")
318))]
319compile_error!(
320    "You must specify a math backend. Consider enabling either `std`, `libm`, or `nostd-libm`."
321);
322
323#[macro_use]
324mod macros;
325
326mod align16;
327mod deref;
328mod euler;
329mod features;
330
331#[cfg(all(
332    target_arch = "aarch64",
333    not(any(feature = "core-simd", feature = "scalar-math"))
334))]
335mod neon;
336
337#[cfg(target_arch = "spirv")]
338mod spirv;
339
340#[cfg(all(
341    target_feature = "sse2",
342    not(any(feature = "core-simd", feature = "scalar-math"))
343))]
344mod sse2;
345
346#[cfg(all(
347    target_feature = "simd128",
348    not(any(feature = "core-simd", feature = "scalar-math"))
349))]
350mod wasm;
351
352#[cfg(all(feature = "core-simd", not(feature = "scalar-math")))]
353mod coresimd;
354
355#[cfg(all(
356    target_feature = "sse2",
357    not(any(feature = "core-simd", feature = "scalar-math"))
358))]
359use align16::Align16;
360
361/** `bool` vector mask types. */
362pub mod bool;
363pub use self::bool::*;
364
365pub mod camera;
366
367#[cfg(feature = "f64")]
368pub mod dcamera;
369
370/** `f32` vector, quaternion and matrix types. */
371pub mod f32;
372pub use self::f32::*;
373
374/** `f64` vector, quaternion and matrix types. */
375#[cfg(feature = "f64")]
376pub mod f64;
377#[cfg(feature = "f64")]
378pub use self::f64::*;
379
380/** `i8` vector types. */
381#[cfg(feature = "i8")]
382pub mod i8;
383#[cfg(feature = "i8")]
384pub use self::i8::*;
385
386/** `u8` vector types. */
387#[cfg(feature = "u8")]
388pub mod u8;
389#[cfg(feature = "u8")]
390pub use self::u8::*;
391
392/** `i16` vector types. */
393#[cfg(feature = "i16")]
394pub mod i16;
395#[cfg(feature = "i16")]
396pub use self::i16::*;
397
398/** `u16` vector types. */
399#[cfg(feature = "u16")]
400pub mod u16;
401#[cfg(feature = "u16")]
402pub use self::u16::*;
403
404/** `i32` vector types. */
405#[cfg(feature = "i32")]
406pub mod i32;
407#[cfg(feature = "i32")]
408pub use self::i32::*;
409
410/** `u32` vector types. */
411#[cfg(feature = "u32")]
412pub mod u32;
413#[cfg(feature = "u32")]
414pub use self::u32::*;
415
416/** `i64` vector types. */
417#[cfg(feature = "i64")]
418pub mod i64;
419#[cfg(feature = "i64")]
420pub use self::i64::*;
421
422/** `u64` vector types. */
423#[cfg(feature = "u64")]
424pub mod u64;
425#[cfg(feature = "u64")]
426pub use self::u64::*;
427
428/** `usize` vector types. */
429#[cfg(feature = "usize")]
430pub mod usize;
431#[cfg(feature = "usize")]
432pub use self::usize::*;
433
434/** `isize` vector types. */
435#[cfg(feature = "isize")]
436pub mod isize;
437#[cfg(feature = "isize")]
438pub use self::isize::*;
439
440/** The glam prelude, including all common types but excluding camera modules. */
441pub mod prelude;
442
443/** Traits adding swizzle methods to all vector types. */
444pub mod swizzles;
445pub use self::swizzles::{Vec2Swizzles, Vec3Swizzles, Vec4Swizzles};
446
447/** Rotation Helper */
448pub use euler::EulerRot;
449
450/** A trait for extending [`prim@f32`] and [`prim@f64`] with extra methods. */
451mod float;
452pub use float::FloatExt;