Matrices¶
Matrices are an ordered set of columns and form a linear combination with the elements of a vector as weights when multiplied with a vector. In computer graphics they are used to apply transformations to vectors. While vectors are in ℝ4, matrices are in ℝ4×4.
Transformations¶
Various kinds of transformations exist:
-
Linear transform. A transform in which vector addition and scalar multiplication is preserved.
-
Affine transform. A transform that includes a linear transform and a translation. Parallelism of lines remain unchanged, but lengths and angles may not. A concatenation of affine transforms is affine.
-
Orthogonal transform. A transform whose columns are orthogonal or perpendicular to each other. The inverse of an orthogonal matrix is equal to its transpose. A concatenation of orthogonal matrices is orthogonal.
Affine transforms are: translation, rotation, uniform scaling, and orthographic projection. Perspective projection is not affine because the parallelism of the lines is changed. Rotations are orthogonal transforms.
Applying transformations¶
A vector can be transformed by multiplying it with some matrix:
Vector_B : constant Vector_Type := Matrix_A * Vector_A;
The vector Vector_B
can then be again transformed by yet another matrix.
This creates a chain or sequence of transformations to a vector.
A single matrix can describe the sequence of transformations by concatenating
the transformation matrices using multiplication:
Matrix_C : constant Matrix_Type := Matrix_B * Matrix_A;
Tip
It is more efficient to perform A * (B * V)
than A * B * V
where V
is a vector.
The latter will perform one matrix-matrix and one matrix-vector
multiplication, while the former will perform two matrix-vector
multiplications.
Summary
Matrix multiplication is associative: A * (B * C) = (A * B) * C
.
Matrix multiplication is not commutative
Matrix multiplication is not commutative: A * B /= B * A
.
Translation¶
A vector can be translated by multiplying it with a translation matrix
created with the function T
:
Offset : constant Vector_Type := (1.0, 2.0, 0.0, 1.0);
Moved_Vertex : constant Vector_Type := T (Offset) * Vertex;
Alternatively, the +
operator can be used:
Moved_Vertex : constant Vector_Type := Offset + Vertex;
The inverse of a translation is equal to the negated offset: T-1 (t) = T (-t).
Rotation¶
A vector can be rotated around the x-axis with Rx
, y-axis with Ry
, z-axis with Rz
,
or any arbitrary axis with function R
. The given Angle
must be in radians.
The returned matrix is orthogonal and affine.
For example:
Axis : constant Vector_Type := (1.0, 2.0, 0.0, 1.0);
Angle : constant Element_Type := 0.5 * Ada.Numerics.Pi;
Rotated_Vertex : constant Vector_Type := R (Axis, Angle) * Vertex;
Additional instances of Rx
, Ry
, Rz
, and R
exist with an
extra parameter Point
that describe the center of the rotation.
Without this extra parameter, the rotation will happen around the origin.
A rotation matrix is orthogonal and thus the inverse is equal to its transpose:
Vertex : constant Vertex_Type := Transpose (Rotation_Matrix) * Rotated_Vertex;
and equal to a rotation described by the negated angle: R-1 (a, o) = R (a, -o).
From A to B¶
A matrix describing the rotation from a vector A to B can be created
with another instance of R
:
Matrix_A_To_B : constant Vector_Type := R (From => Vector_A, To => Vector_B);
Quaternions¶
Quaternions describe rotations with 4 numbers
instead of a 16 (like a 4 × 4 matrix).
Unlike the Euler transform, they are not affected by something called 'gimbal lock'.
A quaternion is implemented as a vector and can be converted to a
rotation matrix with another instance of function R
:
Matrix_A : constant Matrix_Type := R (Vectors.Vector4 (Quaternion_A));
An extra parameter Point
can be provided to rotate around the given point
instead of the origin.
Euler parameters¶
Given a rotation matrix, the Euler parameters yaw, pitch, and roll can
be extracted using the function Euler
:
Yaw_Pitch_Roll : constant Vector_Type := Euler (Rotation_Matrix);
with Rotation_Matrix
begin some rotation matrix. The angles are in radians.
The W
component is always zero and the yaw is zero if the pitch is ± 90 degrees.
Scaling¶
Vectors can be scaled using the function S
. The X
, Y
, and Z
components
describe the amount by which a vector is scaled in the corresponding axis.
The W
component is ignored.
The transformation is affine if all three axes are scaled by the same amount.
Alternatively, the *
operator can be used for a uniform scaling:
Factor : constant := 2.0;
Scaled_Vertex : constant Vector_Type := Factor * Vertex;
The inverse of a scaling is equal to the reciprocal of the factors: S-1 (s) = S (1/sx, 1/sy, 1/sz).
Projections¶
TODO FOV, Perspective, Orthographic