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.
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.
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 ways of creating a vector. They are shown in the example bellow:
- Example 2D
- Example 3D
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);
use nalgebra::{Vector3, vector};
let v = Vector3::new(1.0, 2.0, 3.0); // Basic constructor.
let v = vector![1.0, 2.0, 3.0]; // Macro.
let v = [1.0, 2.0, 3.0].into(); // From<[T; 3]> conversion.
Accessing the components of a vector can be done by indexing or using its x,y,z fields:
let v = vector![1.0, 2.0, 3.0]; // 3D vector.
assert_eq!(v.x, 1.0); assert_eq!(v.y, 2.0); assert_eq!(v.z, 3.0);
assert_eq!(v[0], 1.0); assert_eq!(v[1], 2.0); assert_eq!(v[2], 3.0);
Points
Points are wrappers around vectors, but with a different 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:
- Example 2D
- Example 3D
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);
use nalgebra::{Point3, point};
let pt = Point3::new(1.0, 2.0, 3.0); // Basic constructor.
let pt = point![1.0, 2.0, 3.0]; // Macro.
let pt = [1.0, 2.0, 3.0].into(); // From<[T; 3]> conversion.
assert_eq!(pt.x, 1.0); assert_eq!(pt.y, 2.0); assert_eq!(pt.z, 3.0);
assert_eq!(pt[0], 1.0); assert_eq!(pt[1], 2.0); assert_eq!(pt[2], 3.0);
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 aUnitComplexnumber (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 aUnitQuaternion(a quaternion with a norm equal to 1).
Various ways of constructing an isometry are shown bellow:
- Example 2D
- Example 3D
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);
use nalgebra::{Isometry3, vector};
let iso = Isometry3::translation(1.0, 2.0, 3.0);
let iso = Isometry3::rotation(vector![0.1, 0.5, 0.7]); // The vector is the rotation in axis-angle format.
let iso = Isometry3::new(vector![1.0, 2.0, 3.0], vector![0.1, 0.5, 0.7]);
assert_eq!(iso.rotation.scaled_axis(), vector![0.1, 0.5, 0.7]);
assert_eq!(iso.translation.vector, vector![1.0, 2.0, 3.0]);
Isometries can be used to transform points and vectors using multiplication: isometry * point or isometry * vector.
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-glam013features will enable conversion from/to glam 0.13. - The
convert-glam014features will enable conversion from/to glam 0.14. - The
convert-glam015features will enable conversion from/to glam 0.15. - The same feature naming conversion will be used for the other supported version of glam.
The feature is already enabled by the bevy-rapier plugin. The selected version depends on the version of glam used by Bevy.
Here are examples of conversions these features enable:
- Conversion between
na::Vector2andglam::Vec2. - Conversion between
na::Vector3andglam::Vec3. - Conversion between
na::Point2andglam::Vec2. - Conversion between
na::Point3andglam::Vec3. - Conversion between
na::Isometry2and the tuple(glam::Vec2, f32). - Conversion between
na::Isometry3and the tuple(glam::Vec3, glam::Quat). - Conversion from
glam::Vec2tona::Isometry2(builds a translation-only isometry). - Conversion from
glam::Vec3tona::Isometry3(builds a translation-only isometry). - Conversion from
glam::Quattona::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();