glam

repository·main·Indexed 24 days ago

https://github.com/bitshifter/glam-rs

A high-performance 3D math library for Rust, optimized for games and graphics. It provides SIMD-accelerated linear algebra types including vectors, matrices, quaternions, and affine transformations. glam supports f32, f64, integer, and boolean types, utilizing column-major order and column vectors. It offers specialized camera constructors for right-handed and left-handed coordinate systems and supports no_std environments via the libm feature.

Tokens
7.6K
Snippets
17
Records
51
Agent score
78%

What's inside glam

  1. Overview of glam features and supported types

    main

    glam is a fast 3D math library for games and graphics. It provides a wide range of mathematical types across different scalar types.

    Key Type Groups:

    • f32 (Built-in): Vectors (Vec2, Vec3, Vec3A, Vec4), Square Matrices (Mat2, Mat3, Mat3A, Mat4), Quaternions (Quat), Affine transformations (Affine2, Affine3, Affine3A), and camera constructors via the camera module.
    • f64: DVec2, DVec3, DVec4, DMat2, DMat3, DMat4, DQuat, DAffine2, DAffine3, and camera constructors via dcamera.
    • Integers & Unsigned: Supports i8, u8, i16, u16, i32, u32, i64, u64, isize, and usize vectors.
    • Booleans: BVec2, BVec3, BVec4.

    Note: f32 and bool types are enabled by default. All other types are optional and can be disabled to improve compile times.

  2. How glam handles SIMD and performance

    main

    glam is designed for high performance by utilizing SIMD (Single Instruction, Multiple Data) instructions when available (such as SSE2 on x86/x86_64, NEON, or WASM SIMD).

    Key performance characteristics:

    • SIMD-first: It prioritizes using SIMD vector intrinsics for storage to achieve better performance than standard f32 types.
    • Automatic Fallback: If SIMD is not available on the target architecture, glam automatically falls back to using scalar types (like an array of f32) to ensure the code still runs correctly.
    • No Generics: To avoid the compile-time overhead and complexity of managing different storage types (e.g., Vec4<f32, __m128> vs Vec4<f32, [f32; 4]>), glam uses concrete types instead of generic parameters.
  3. Mathematical conventions in glam

    main

    Understanding how glam handles math is critical for correct transformations.

    Column Vectors and Matrix Order

    • glam uses column vectors. When transforming a vector with a matrix, the matrix is applied on the left: v' = Mv.
    • Matrices are stored in column-major order. Each column vector is stored in contiguous memory.

    Coordinate Systems

    • glam is coordinate system agnostic and supports both right-handed and left-handed conventions.
    • For cameras, use the camera module. Select the rh (right-handed) or lh (left-handed) sub-module based on your world space, then use the constructor corresponding to your graphics API (e.g., OpenGL, DirectX, Vulkan, or WebGPU).
  4. How glam uses traits and documentation

    main

    glam follows a specific pattern regarding Rust traits to balance usability and documentation clarity:

    • Concrete Types: Most core types (like Vec3) are concrete structs rather than trait interfaces. This ensures that all methods for a type are documented directly on the struct itself, making it easier for users to discover functionality.
    • Swizzle Traits: Swizzle methods (e.g., accessing components in different orders) are implemented via traits. This is done intentionally to prevent the documentation of the main vector structs from being cluttered by the large number of available swizzle combinations.
    • Component Access: glam uses the Deref trait to allow direct access to vector components (like .x, .y, etc.). This is achieved by dereferencing to an XYZ<T> structure. Note that if you encounter error messages mentioning XYZ types, it is a side effect of this Deref implementation used for component access.
  5. Supported primitive types and permutations

    main

    glam provides various permutations of vectors, quaternions, and matrices. While it avoids generics to keep compile times low, it supports the following primitive types:

    • f32 (Supports SIMD optimizations like SSE2, NEON, or WASM SIMD where available)
    • f64
    • i32
    • u32

    For f32 types, the library will attempt to use SIMD instructions but will provide a scalar fallback if the hardware does not support them.

  6. Enable SIMD in glam

    main

    glam uses 128-bit wide SIMD vector types for specific types (Vec3A, Vec4, Quat, Mat2, Mat3A, Mat4, Affine2, and Affine3A) on x86, x86_64, wasm32, and wasm64 architectures. These types are 16-byte aligned.

    How to enable SIMD on different targets:

    • x86_64: SSE2 is enabled by default.
    • x86: Add -C target-feature=+sse2 to RUSTFLAGS to enable SSE2.
    • aarch64: NEON is enabled by default.
    • wasm32/wasm64: Add -C target-feature=+simd128 to RUSTFLAGS to enable simd128.
    • Portable SIMD (Experimental): Enable the core-simd feature. This requires a nightly Rust compiler.
  7. Configure no_std support for glam

    main

    To use glam in a no_std environment, you must disable default features and provide an alternative math library like libm.

    Option 1: Direct dependency configuration

    [dependencies]
    glam = { version = "0.33.2", default-features = false, features = ["libm"] }

    Option 2: Supporting both std and no_std in your own crate You can define features in your Cargo.toml to allow users to choose between std and libm:

    [features]
    default = ["std"]
    std = ["glam/std"]
    libm = ["glam/libm"]
    
    [dependencies]
    glam = { version = "0.33.2", default-features = false }

    Option 3: Using the nostd-libm feature This feature always includes a libm dependency but allows users to override it with std if they prefer. This is the easiest way to allow your crate to compile with default features disabled without forcing a choice on the user.

    [features]
    default = ["std"]
    std = ["glam/std"]
    libm = ["glam/libm"]
    
    [dependencies]
    glam = { version = "0.33.2", default-features = false, features = ["nostd-libm"] }
  8. Understand glam's SIMD-optimized types

    main

    Many f32 types in glam use 128-bit SIMD vector types for storage and implementation, which generally provides better performance than primitive numeric types.

    Types with an A suffix (e.g., Vec3A, Mat3A, Affine3A) are SIMD alternatives to their scalar counterparts. These types are 16-byte aligned. For example, Vec3A uses 16 bytes of storage (including 4 bytes of padding) to enable SIMD, whereas Vec3 uses 12 bytes.

    Supported SIMD architectures include:

    • SSE2 on x86/x86_64
    • NEON on Aarch64
    • simd128 on WASM

    If SIMD is unavailable on the target, glam maintains 16-byte alignment and internal padding to ensure object sizes and layouts remain consistent across architectures, using scalar math fallbacks.

  9. DQuat: Double-precision quaternion type

    main
    A DQuat represents an orientation using a quaternion with f64 components. While intended to be unit length, successive operations may cause denormalization due to floating-point error. It supports standard mathematical operations including addition, subtraction, scalar multiplication/division, and quaternion multiplication (which combines rotations).
  10. Use glam's linear algebra conventions

    main

    glam uses column-major order for matrix storage and interprets vectors as column matrices (column vectors). This means when transforming a vector with a matrix, the matrix is applied on the left: matrix * vector.

    All angles are in radians. Use Rust's built-in f32::to_radians() or f64::to_radians() to convert from degrees.

    use glam::{Mat3, Vec3};
    let m = Mat3::IDENTITY;
    let x = Vec3::X;
    let v = m * x;
    assert_eq!(v, x);
  11. How left-handed camera view constructors work

    main

    In glam-rs, left-handed camera view constructors transform world space points into a specific view space characterized by:

    • Y-up
    • X-right
    • +Z-forward

    There are two primary ways to define the camera's orientation:

    1. Targeting a point (look_at): You provide an eye position and a center (focal point). The function calculates the direction vector internally.
    2. Targeting a direction (look_to): You provide an eye position and a dir (forward direction vector).

    Functions are categorized by their return type, allowing you to choose between a full transform (including translation) or just the rotation component.

  12. Construct right-handed camera view transforms

    main

    Use the look_at_* and look_to_* functions to create view transforms for right-handed world coordinate systems. These functions transform world space points into a right-handed Y-up view space (X-right, -Z-forward).

    Constructor Types

    • look_at_*: Targets a specific focal point (center). Requires eye, center, and up vectors.
    • look_to_*: Targets a specific forward direction (dir). Requires eye (for full transforms) or just dir (for rotation-only), and an up vector.

    Return Types

    • Full View Transform (Rotation + Translation): Returns Mat4, Affine3, or Affine3A.
    • View Rotation Only (No Translation): Returns Mat3, Mat3A, or Quat.