Expand description
§Strongly typed vector math with glam
This crate uses bytemuck to implement a zero-cost1 strongly typed interface on top of glam.
The API is similar to euclid, but more ergonomic (although YMMV).
One of the API design goals of glam is to avoid complexity by not going
bananas with traits and generics. This crate is the opposite. But it does
allow you to easily drop down to plain glam when needed.
See the docs module for detailed documentation.
§Step-By-Step Quickstart Guide
- Declare your units by defining a “unit” type (can be empty, doesn’t need any traits to be derived).
- Implement
Unitfor that struct.Unit::Scalardetermines the primitive type used in vector components. - The scalar must be
f32,f64,i32,u32,i64,u64,i16, oru16. - The basic primitive scalars are also units in their own right (“untyped”).
§Example
use glamour::prelude::*;
struct MyUnit;
impl Unit for MyUnit {
type Scalar = f32;
}
// Start using your new unit:
let vector: Vector4<MyUnit> = Vector4 { x: 1.0, y: 2.0, z: 3.0, w: 4.0 };
let size: Size2<MyUnit> = Size2 { width: 100.0, height: 200.0 };
// Use untyped units when needed:
let vector_untyped: &Vector4<f32> = vector.as_untyped();
// Use glam when needed:
let vector_raw: glam::Vec4 = vector.to_raw();See the documentation module for more examples.
§Feature gates
std- enables theglam/stdfeature. Enabled by default.libm- required to compile withno_std(transitively enablesglam/no_std).mint- enables conversion to/fromminttypes.encase: Enables implementations of [encase::ShaderType] for vector and matrix types, which enables them for use in GPU shaders.scalar-math: Don’t use SIMD vector instructions, even if they are supported by the target architecture. Note that this flag is required to run tests under Miri, due to vector instructions not being supported. Transitively enables theglam/scalar-mathfeature.wasmtime: (Experimental) This enables implementations ofLower/Lifton all types, so they can be used in generated bindings for WIT components (wasmtime::component::bindgen!()). Glamour types can be used on both sides (host and guest), and can be passed “toll-free” between the two sides given a compatible type declaration in a WIT world, but limitations apply: Due to the way thewasmtimederive macros work, only plain scalar units can be used (soVector4<f32>is supported, but notVector4<MyFloatUnit>).facet: (Experimental) Adds support forfacetto all types.
§Advantages
- Structural type construction is sometimes better because it doesn’t rely on
positional arguments. It also allows us to give more meaningful names to
things - for example, the members of
Size2are calledwidthandheight, rather thanxandy. - The user is able to easily drop down to plain
glamtypes when needed.
§Over plain glam
- Lifts some correctness checks to the type system. This can prevent certain common bugs, such as using a vector from one coordinate space in a context that logically expects a different coordinate space.
- Improves API comprehension and code readability by annotating expectations as part of function signatures.
- Distinguishing between points, vectors, and sizes can also prevent certain classes of bugs. For example, the “transform” operation in 3D is different for points and vectors.
§Over euclid
- Type names are more concise (single generic parameter instead of two).
- Support for
bytemuck.
§Disadvantages
- The API is heavily reliant on metaprogramming tricks. A complex maze of traits is required to support the goals. The trade-off can be summed up as: simplicity, ergonomics, type-safety - pick two. This crate picks ergonomics and type-safety.
- Generic struct definitions have trait bounds. This is usually considered an antipattern in Rust, but we need to encode two things with one type parameter to support structural construction of vector types, so it is unavoidable.
§Compared to glam
- Due to its simplicity,
glamis a very approachable API. glamis able to support a wide range of transformation primitives (e.g.glam::Affine3A,glam::Quat, etc.), and the user has a lot of flexibility to choose the most performant kind for their use case. These are simply unimplemented inglamour.
§Compared to euclid
- The same unit tag cannot be used with different scalars.
- Any type cannot be used as the unit tag - it must implement
Unit.
§Goals
- Strongly typed linear algebra primitives.
-
Bitwise compatibility with
glam. - First-class field struct expression support in vector types.
- Support direct memory mapping (e.g. upload to GPU buffers).
-
Support
no_std. -
Adhere to
glamAPI conventions - “principle of least surprise”. - Add only a few additional geometric primitives, like rects, transforms, and axis-aligned boxes.
-
Impose no runtime overhead at all (compared to using
glamdirectly). Comprehensive benchmarks pending. - 100% test coverage.
§Non-goals
- Complex linear algebra. Use nalgebra or Euclid instead.
- Vector sizes beyond 4 dimensions (the maximum supported by
glam). - Type parameterization on vector/matrix size.
- Non-square matrices.
- Wrapping all of the
glamAPI. Instead, we make it really easy (and performant) to drop down toglamtypes when needed. - Hiding the
glamAPI. It’s OK to useglamtypes in public APIs. - The “
AoSoA” pattern (“extra wide” vector types). Use ultraviolet instead.
§Performance
All operations should perform exactly the same as their glam counterparts.
There is a zero-tolerance policy for overhead in release builds.
However, debug build performance is also important in some cases. For example, for a video game it can make the difference between being playable or not in debug mode.
This crate should be expected to incur an overhead of about a factor 2 compared
to glam in debug builds. This may be alleviated in the future, but it seems
that even glam itself does not go out of its way to perform well in debug
builds.
Zero-cost at runtime, in release builds. This crate may increase compile times and make debug builds slower due to increased code size. ↩
Re-exports§
pub use traits::Contains;pub use traits::Intersection;pub use traits::Transparent;pub use traits::Union;
Modules§
Macros§
- point
- Construct a
Point2,Point3, orPoint4depending on the number of arguments. Usable in const contexts. - point2
- Construct a
Point2. Usable in const contexts. - point3
- Construct a
Point3. Usable in const contexts. - point4
- Construct a
Point4. Usable in const contexts. - size
- Construct a
Size2orSize3depending on the number of arguments. Usable in const contexts. - size2
- Construct a
Size2. Usable in const contexts. - size3
- Construct a
Size3. Usable in const contexts. - vec2
- Construct a
Vector2. Usable in const contexts. - vec3
- Construct a
Vector3. Usable in const contexts. - vec4
- Construct a
Vector4. Usable in const contexts. - vector
- Construct a
Vector2,Vector3, orVector4depending on the number of arguments. Usable in const contexts.
Structs§
- Angle
- Angle in radians.
- Box2
- 2D axis-aligned box represented as “min” and “max” points.
- Box3
- 3D axis-aligned box.
- Matrix2
- 2x2 column-major matrix.
- Matrix3
- 3x3 column-major matrix.
- Matrix4
- 4x4 column-major matrix.
- Point2
- 2D point.
- Point3
- 3D point.
- Point4
- 4D point.
- Rect
- 2D axis-aligned rectangle represented as “origin” and “size”.
- Size2
- 2D size.
- Size3
- 3D size.
- Transform2
- 2D transform represented as a 3x3 column-major matrix.
- Transform3
- 3D transform represented as a 4x4 column-major matrix.
- Vector2
- 2D vector.
- Vector3
- 3D vector.
- Vector4
- 4D vector.
Traits§
- Angle
Consts - Strongly typed angle constants.
- Float
Angle Ext - Convenience trait to create strongly typed angles from floats.
- Float
Scalar - Floating-point scalar types (
f32andf64). - Float
Unit - Convenience trait implemented for all
Units with a floating-point scalar type. - IntUnit
- Convenience trait implemented for all
Units with an integer scalar type. - Scalar
- All types that can serve as components of a SIMD type in
glam. - Signed
Scalar - Signed scalar types (
i32,f32,f64, etc.). - Signed
Unit - Convenience trait implemented for all
Units with a signed scalar type. - Swizzle
- Vector swizzling by const generics.
- Transform
Map - The mapping operation from one unit to another through a transform.
- Unit
- The name of a coordinate space.
- Vec2
Swizzles - Vec3
Swizzles - Vec4
Swizzles