Matrices

The matrix is an exceptionally powerful mathematical tool that greatly simplifies the process of solving one or more equations with variables that have complex relationships with one another.

A matrix is a set of numbers arranged in uniform rows and columns.

OpenGL uses a column-major or column-primary layout for matrices.

Coordinate Spaces in OpenGL

A series of one or more transforms can be represented as a matrix, and multiplication by that matrix effectively moves a vector from one coordinate space to another.

  • Model Space
    Positions relative to a local origin. Also sometimes known as object space.
  • World Space
    Positions relative to a global origin.
  • View Space
    Positions relative to the viewer. Also sometimes called camera or eye space.
  • Clip Space
    Positions of vertices after projection into a nonlinear homogeneous coordinate.
  • Normalized device coordinate (NDC) Space
    Vertex coordinates are said to be in NDC after their clip space coordinates have been divided by their own w component.
  • Window Space
    Positions of vertices in pixels, relative to the origin of the window.

Coordinates can be moved from space to space by multiplying their vector representations by transformation matrices.

The Identity Matrix

The identity matrix contains all zeros except a series of ones that traverse the matrix diagonally. The 4 x 4 identity matrix looks like this:

图片说明

All identity matrices are square. Any identity matrix is its own transpose.

Multiplying a vertex by the identity matrix is equivalent to multiplying it by 1.

图片说明

The Translation Matrix

A translation matrix simply moves the vertices along one or more of the three axes. The formulation of a 4 x 4 matrix is as follows:

图片说明

In practice, position vectors are always encoded using four components with w being 1.0, whereas direction vectors are encoded either simply using three components, or as four components with w being 0.0.

    template <typename T>
    static inline Tmat4<T> translate(T x, T y, T z)
    {
        return Tmat4<T>(Tvec4<T>(1.0f, 0.0f, 0.0f, 0.0f),
                        Tvec4<T>(0.0f, 1.0f, 0.0f, 0.0f),
                        Tvec4<T>(0.0f, 0.0f, 1.0f, 0.0f),
                        Tvec4<T>(x, y, z, 1.0f));
    }

The Rotation Matrix

To rotate an object about one of the three coordinate axes, you have to devise a rotation matrix.

To rotate about the x axis, we use

图片说明

To rotate about the y axis, we use

图片说明

To rotate about the z axis, we use

图片说明

You can also perform a rotation around an arbitrary axis by specifying x, y, and z values for that vector. To see the axis of rotation, you can just draw a line from the origin to the point represented by (x,y,z).

The Scaling Matrix

A scaling transform changes the size of an object by expanding or contracting all the vertices along the three axes by the factors specified.

A scaling matrix has the following form:

图片说明

    template <typename T>
    static inline Tmat4<T> scale(T x, T y, T z)
    {
        return Tmat4<T>(Tvec4<T>(x, 0.0f, 0.0f, 0.0f),
                        Tvec4<T>(0.0f, y, 0.0f, 0.0f),
                        Tvec4<T>(0.0f, 0.0f, z, 0.0f),
                        Tvec4<T>(0.0f, 0.0f, 0.0f, 1.0f));
    }

The LookAt Matrix

At default the position of a camera is assumed to be centered at the origin and aligned along the negative z-axis. To orient the camera correctly, we need to have an origin, a point of interest and a direction that we consider to be up.

In the following math, e is the eye (camera) position, p is the point of interest, and u is the up vector.

First, construct our forward vector, f:

图片说明

(If we take the coordinates of a point of interest, subtract from that the position of our camera, and then normalize the resulting vector, we have a new vector that represents the direction of view from the camera to the point of interest. We call this the forward vector.)

Second, take the cross product of f and u to construct a side vector s:

图片说明

(Taking the cross product of those two vectors results in a third vector that is orthogonal to each of them and points sideways with respect to our camera. We call this the sideways vector.)

Third, construct a new up vector u' in our camera's reference:

图片说明

Then, construct a rotation matrix representing a reorientation into our newly constructed orthonormal basis:

图片说明

Finally, we have our lookout matrix by adding translation to the camera position:

图片说明

    template <typename T>
    static inline Tmat4<T> lookat(const vecN<T,3>& eye, const vecN<T,3>& center, const vecN<T,3>& up)
    {
        const Tvec3<T> f = normalize(center - eye);
        const Tvec3<T> upN = normalize(up);
        const Tvec3<T> s = cross(f, upN);
        const Tvec3<T> u = cross(s, f);
        const Tmat4<T> M = Tmat4<T>(Tvec4<T>(s[0], u[0], -f[0], T(0)),
                                Tvec4<T>(s[1], u[1], -f[1], T(0)),
                                Tvec4<T>(s[2], u[2], -f[2], T(0)),
                                Tvec4<T>(T(0), T(0), T(0), T(1)));

        return M * translate<T>(-eye);
    }

This matrix represents the position and orientation of your camera. In other words, this can be your view matrix.

Projection Transformations

The projection transformation is applied to your vertices after the model–view transformation. This projection actually defines the viewing volume and establishes clipping planes.

(The clipping planes are plane equations in 3D space that OpenGL uses to determine whether geometry can be seen by the viewer. )

Once your vertices are in view space, we need to get them into clip space, which we do by applying our projection matrix, which may represent a perspective or orthographic projection (or some other projection).

Perspective Matrices

A perspective projection shows scenes more as they appear in real life instead of as a blueprint. The hallmark of perspective projections is foreshortening, which makes distant objects appear smaller than nearby objects of the same size.

A commonly used perspective matrix is a frustum matrix. A frustum matrix is a projection matrix that produces a perspective projection such that clip space takes the shape of a rectangular frustum, which is a truncated rectangular pyramid.

Its parameters are the distance to the near and far planes and the world-space coordinate of the left, right, top, and bottom clipping planes. A frustrum matrix takes the following form:

图片说明

static inline mat4 frustum(float left, float right, float bottom, float top, float n, float f)
{
    mat4 result(mat4::identity());

    if ((right == left) ||
        (top == bottom) ||
        (n == f) ||
        (n < 0.0) ||
        (f < 0.0))
       return result;

    result[0][0] = (2.0f * n) / (right - left);
    result[1][1] = (2.0f * n) / (top - bottom);

    result[2][0] = (right + left) / (right - left);
    result[2][1] = (top + bottom) / (top - bottom);
    result[2][2] = -(f + n) / (f - n);
    result[2][3]= -1.0f;

    result[3][2] = -(2.0f * f * n) / (f - n);
    result[3][3] =  0.0f;

    return result;
}

Another common method for constructing a perspective matrix is to directly specify a field of view as an angle, an aspect ratio, and the view-space positions of the near and far planes.

static inline mat4 perspective(float fovy, float aspect, float n, float f)
{
    float q = 1.0f / tan(radians(0.5f * fovy));
    float A = q / aspect;
    float B = (n + f) / (n - f);
    float C = (2.0f * n * f) / (n - f);

    mat4 result;

    result[0] = vec4(A, 0.0f, 0.0f, 0.0f);
    result[1] = vec4(0.0f, q, 0.0f, 0.0f);
    result[2] = vec4(0.0f, 0.0f, B, -1.0f);
    result[3] = vec4(0.0f, 0.0f, C, 0.0f);

    return result;
}

Orthographic Matrices

In an orthographic (parallel) projection, all the polygons are drawn on screen with exactly the relative dimensions specified. Lines and polygons are mapped directly to the 2D screen using parallel lines, which means no matter how far away something is, it is still drawn the same size.

An orthographic projection matrix is simply a scaling matrix that linearly maps view-space coordinates into clip-space coordinates.

The parameters to construct the orthographic projection matrix are the left, right, top, and bottom coordinates in view space of the bounds of the scene, and the position of the near and far planes. The form of the matrix is

图片说明

static inline mat4 ortho(float left, float right, float bottom, float top, float n, float f)
{
    return mat4( vec4(2.0f / (right - left), 0.0f, 0.0f, 0.0f),
                 vec4(0.0f, 2.0f / (top - bottom), 0.0f, 0.0f),
                 vec4(0.0f, 0.0f, 2.0f / (n - f), 0.0f),
                 vec4((left + right) / (left - right), (bottom + top) / (bottom - top), (n + f) / (f - n), 1.0f) );
}