Introduction to nalgebra

nalgebra is a general-purpose linear algebra library written in Rust. It has an extensive set of features including vectors, matrices, transformations, factorizations, etc. Because nalgebra is used extensively by Rapier and its API, the goal of this page is to give a very quick introduction to some basic features of nalgebra that you will need to use Rapier.

Vectors#

Vectors are matrices with a single column. They are used in Rapier to express various quantities like velocities forces, etc. Whereas nalgebra supports vectors of any size, Rapier mostly uses 2D and 3D vectors: the Vector2 and Vector3 type aliases form nalgebra.

info

Whenever you see the Vector type appearing in the API of Rapier, it means Vector2 if you are using the 2D version of Rapier, or Vector3 if you are using the 3D version of Rapier.

info

Whenever you see AngVector appearing in the API of Rapier, it means f32 (or f64) if you are using the 2D version of Rapier, or Vector3 if you are using the 3D version of Rapier.

There are various way of creating a vector. They are shown in the example bellow:

use nalgebra::{Vector2, vector};
let v = Vector2::new(1.0, 2.0); // Basic constructor.
let v = vector![1.0, 2.0]; // Macro.
let v = [1.0, 2.0].into(); // From<[T; 2]> conversion.

Accessing the components of a vector can be done by indexing or using its x,y fields:

let v = vector![1.0, 2.0]; // 2D vector.
assert_eq!(v.x, 1.0); assert_eq!(v.y, 2.0);
assert_eq!(v[0], 1.0); assert_eq!(v[1], 2.0);

Points#

Points are wrappers around vectors, but with a semantic than vectors. A point can be interpreted as a location in space whereas a vector can be seen as a direction or a displacement between two points. For example a contact between two shapes has contact points (the location of the contact in space) represented as points, and has a contact normal (the direction used to apply forces) represented as a vector.

Points are created/accessed in a way very similar to vectors:

use nalgebra::{Point2, point};
let pt = Point2::new(1.0, 2.0); // Basic constructor.
let pt = point![1.0, 2.0]; // Macro.
let pt = [1.0, 2.0].into(); // From<[T; 2]> conversion.
assert_eq!(pt.x, 1.0); assert_eq!(pt.y, 2.0);
assert_eq!(pt[0], 1.0); assert_eq!(pt[1], 2.0);
info

It is possible to access the vector wrapped by a point by accessing its coords field: pt.coords.

Isometries#

An isometry represents a rotation followed by a translation. Isometries are often used within Rapier to represent the position of a rigid-body or a collider. By position, we generally mean both the translation and the orientation of the rigid-body or collider.

  • In 2D, the translational part of an isometry is represented as a Vector2, and the rotational part is represented as a UnitComplex number (a complex number with a norm equal to 1).
  • In 3D the translational part of an isometry is represented as a Vector3, and the rotational part is represented as a UnitQuaternion (a quaternion with a norm equal to 1).

Various ways of constructing an isometry are shown bellow:

use nalgebra::{Isometry2, vector};
let iso = Isometry2::translation(1.0, 2.0);
let iso = Isometry2::rotation(0.5); // 0.5 is a rotation angle in radians.
let iso = Isometry2::new(vector![1.0, 2.0], 0.5);
assert_eq!(iso.rotation.angle(), 0.5);
assert_eq!(iso.translation.vector.x, 1.0);
assert_eq!(iso.translation.vector.y, 2.0);

Isometries can be used to transform points and vectors using multiplication: isometry * point or isometry * vector.

warning

Because points represent a location in space, isometry * point will rotate and translate the point. However, because vectors represent a direction, isometry * vector will only rotate the vector (the translation part of the isometry will be ignored).

Interoperability with glam#

glam is another linear-algebra library written in Rust. It is popular within the Rust game development community and is used by several popular crates like Bevy, macroquad, etc.

It is possible to convert nalgebra types from/to glam types (using the standard library's From and Into traits) by enabling one of the conversion cargo features of nalgebra:

  • The convert-glam013 features will enable conversion from/to glam 0.13.
  • The convert-glam014 features will enable conversion from/to glam 0.14.
  • The convert-glam015 features will enable conversion from/to glam 0.15.
  • The same feature naming conversion will be used for the other supported version of glam.

Here are examples of conversions these features enable:

  • Conversion between na::Vector2 and glam::Vec2.
  • Conversion between na::Vector3 and glam::Vec3.
  • Conversion between na::Point2 and glam::Vec2.
  • Conversion between na::Point3 and glam::Vec3.
  • Conversion between na::Isometry2 and the tuple (glam::Vec2, f32).
  • Conversion between na::Isometry3 and the tuple (glam::Vec3, glam::Quat).
  • Conversion from glam::Vec2 to na::Isometry2 (builds a translation-only isometry).
  • Conversion from glam::Vec3 to na::Isometry3 (builds a translation-only isometry).
  • Conversion from glam::Quat to na::Isometry3 (builds a rotation-only isometry).
// Here are just a few examples.
use nalgebra::{vector, Point2, Isometry3};
use glam::{Quat, Vec2, Vec3};
let na_vector = vector![1.0, 2.0, 3.0];
let glam_vector: Vec3 = na_vector.into();
let glam_vector = Vec2::new(1.0, 2.0);
let na_point: Point2<f32> = glam_vector.into();
let na_isometry: Isometry3<f32> =
(Vec3::new(0.1, 2.0, 0.0), Quat::from_rotation_x(0.4)).into();