Lab 4. Three-Dimensional Transformations and the Two-Dimensional Viewing Pipeline

M. Stone and A. Pshenichkin. 10.02.04.

Note: While this write-up describes the tasks we did in preparation for Lab 4, it and Lab 5 were completed simultaneously. Thus, some of our techniques here utilize our Lab 5 code.

Transformations in Two and Three Dimensions

The most basic set of transformations - translate, rotate, and scale - are linear transformations, and thus can be represented using matrices. In two dimensions, they are 3x3 matrices. To avoid complications later, we treat these 3x3 matrices as 4x4 matrices with indentity rows and columns.

In three dimensions, a matrix-defined rotation fails when you look along the z-axis since orientation info gets lost. The solution is to use a nicer formulation, such as a quaternion. A quaternion is a representation of coordinates in three-space as three complex coordinates representing an axis and a real part based on the angle of rotation about that axis. We used 3D Game Engine Design's description of quaternions, as it was very detailed. Our Quaternion class supports the +, -, *=, and /= operations between two quaternions, and can convert the information it stores into angle/axis and matrix forms.

Rather than applying a linear transformation to a target, all of our functions generate transformation matrices (hence names like Translation rather than Translate). The advantage of such an approach is that it allows us to compute a good deal of the matrix multiplications involved in the graphics pipeline once (or once per view or frame) and simply store the results.

To the two-dimensional equivalents of all of these transformations are merely special cases of the 3-D forms, and are very easy to generate given a standard method for performing the aforementioned transformations in three dimensions.

Modeling System

Since creating objects out of primitives is time-consuming and complicated, a method for saving those objects as models, thereby allowing one to only create the object once and thereafter modify it just as one would a primitive, is highly desirable. To this end (and also because it is required), we implemented modeling in our graphics sytem.

A much more thorough description of our modeling system can be found in Lab 5 (Hierarchical Modeling System).

Models allow us to take complex tasks and greatly simplify them. Creating the spaceship in orbit around the planet was as simple as writing a model for it once and then applying a different rotation to it to create each frame.

The Rendering Pipeline in Two Dimensions

Basically, the rendering pipeline is just a series of transformations applied to a set of points.

Our scene consists of a tree of SceneNodes, which are then traversed by a Buffer Visitor. Calling visit on a SceneNode recurses down through the scene graph, collecting color and transformation information. When a leaf node (a primitive) is reached, our program concatenates all of the transform and color data (nodes have a getCombinedTransform function), essentially flattening the many Rotations, Scales, and Translations along the path down to a single transformation matrix. It then saves this information in the RenderBuffer and goes on to the next SceneNode. This procedure creates a scene from our hierarchical model tree. Perspective transformations, also known as the View Transformation Matrix, can then be applied over this. Moving one's view and transforming everything in the scene are mathemtically identical, so this operation is performed simply by putting another matrix in front of the buffered scene objects before rendering them.

With the rendering system in place, designing scenes was a fairly simple task. The orbiting Enterprise, or example, merely uses a for loop to vary the Rotation parameters.

Sample Images

References

Eberly, David. 3D Game Engine Design. 2000, Morgan Kaufmann.


M. Stone and A. Pshenichkin.