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 aUnitComplex
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 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-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
andglam::Vec2
. - Conversion between
na::Vector3
andglam::Vec3
. - Conversion between
na::Point2
andglam::Vec2
. - Conversion between
na::Point3
andglam::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
tona::Isometry2
(builds a translation-only isometry). - Conversion from
glam::Vec3
tona::Isometry3
(builds a translation-only isometry). - Conversion from
glam::Quat
tona::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();