In this tutorial, we will look at a number of ways to transform objects, rendering them in different locations and orientations in the world. And we will also solve the secret of why we overcomplicated everything with those matrices.
Throughout this series of tutorials, we have discussed a number of different spaces. We have seen OpenGL-defined spaces like normalized device coordinate (NDC) space, clip-space, and window space. And we have seen user-defined spaces like camera space. But we have yet to formally discuss about what a space actually is.
A space is a shorthand term for a coordinate system. For the purposes of this conversation, a coordinate system or space consists of the following:
The dimensionality of the space. 2D, 3D, 4D, etc.
A series of vectors in those dimensions that define the axes of the space. The directions do not have to be orthogonal (at right-angles) to one another, but there must be one axis per dimension. Each axis vector in the space has a name, like X, Y, Z, etc. These are called the basis vectors of a space.
A location in the space that defines the central origin point. The origin is the point from which all other points in the space are derived.
An area within this space in which points are valid. Outside of this range, positions are not valid. The range can be infinite depending on the space.
A position or vertex in a space is defined as the sum of the basis vectors, where each basis vector is multiplied by a scalar value called a coordinate. Geometrically, this looks like the following:
These are two different coordinate systems. The same coordinate, in this case (2, 2) (each basis vector is added twice) can have two very different positions, from the point of view of a neutral observer. What is interesting to note is that (2, 2) is the same value in their own coordinate system. This means that a coordinate itself is not enough information to know what it means; one must also know what coordinate system it is in before you can know anything about it.
The numerical version of the coordinate system equation is as follows:
The geometric version is all well and good when dealing with the geometric basis vectors and origin point. The origin point is just a position, and the basis vectors are simply drawn. But what does it mean to give actual numbers to these concepts in the numerical version? A position, like the origin point, is itself a coordinate. Which means that it must be defined relative to some coordinate system. The same goes for the basis vectors.
Ultimately, this means that we cannot look numerically at a single coordinate system. Since the coordinate values themselves are meaningless without a coordinate system, a coordinate system can only be numerically expressed in relation to another coordinate system.
Technically, the geometric version of coordinate systems works the same way. The length of the basis vectors in the geometric diagrams are relative to our own self-imposed sense of length and space. Essentially, everything is relative to something, and we will explore this in the near future.
In the more recent tutorials, the ones dealing with perspective projections, we have been taking positions in one coordinate system (space) and putting them in another coordinate system. Specifically, we had objects in camera space that we moved into clip space. The process of taking a coordinate in one space and specifying it as a coordinate in another space is called transformation. The coordinate's actual meaning has not changed; all that has changed is the coordinate system that this coordinate is relative to.
We have seen a number of coordinate system transformations. OpenGL implements the transformation from clip-space to NDC space and the transformation from NDC to window space. Our shaders implement the transformation from camera space to clip-space, and this was done using a matrix. Perspective projection (and orthographic, for that matter) are simply a special kind of transformation.
This tutorial will cover a large number of different kinds of transform operations and how to implement them in OpenGL.
Before we begin, we must define a new kind of space: model space. This is a user-defined space, but unlike camera space, model space does not have a single definition. It is instead a catch-all term for the space that a particular object begins in. Coordinates in buffer objects, passed to the vertex shaders as vertex attributes are de facto in model space.
There are an infinite variety of model spaces. Each object one intends to render can, and often does, have its own model space, even if the difference between these spaces is only in the origin point. Model spaces for an object are generally defined for the convenience of the modeller or the programmer who intends to use that model.
The transformation operation being discussed in this tutorial is the transform from model space to camera space. Our shaders already know how to handle camera-space data; all they need is a way to transform from model space to camera space.