Matrix Transformations

# Learning Objectives

Extend your vector class to perform multiplication by a matrix that will scale, translate, or rotate a 3D object.

# Introduction

Matrix multiplication is the mathematical workhorse used for rendering motion. With it, transformations of all kinds can be performed. These include scaling, translations, rotations, reflections, and shearing. This experiment will lay the foundation to perform all of them, but implement only the first three.

# Matrix Multiplication

Ideally, since a matrix is not the same kind of object as a vector, an integer, a float, or any other object, we should create (or use) a matrix class to work with matrices. It is up to you if you want to create a new class called Matrix3D or to just repeatedly call on your Vector3D class to simulate a matrix. A matrix can be considered as an array of vectors. Specifically, if we have the equation, $A\vec{v}=\vec{v}^{\prime}$, where A is a matrix and $\vec{v}$ and $\vec{v}^\prime$ are vectors, then we shall think of the components of these objects in the following manner:

(1)
\begin{align} A\vec{v}=\vec{v}^{\prime}\\ \left [ \begin{array}{cccc} a_{11} & a_{12} & a_{13} & a_{14} \\ a_{21} & a_{22} & a_{23} & a_{24} \\ a_{31} & a_{32} & a_{33} & a_{34} \\ a_{41} & a_{42} & a_{43} & a_{44} \\ \end{array} \right ] \left [ \begin{array}{c} v_x\\ v_y\\ v_z\\ v_w\\ \end{array} \right ] &=& \begin{bmatrix} \mbox{Row One}\cdot v\\ \mbox{Row Two}\cdot v\\ \mbox{Row Three}\cdot v\\ \mbox{Row Four}\cdot v\\ \end{bmatrix} \end{align}

The matrix A is the 4x4 matrix above and is treated as an array of four row-vectors, where $n$ is the row number (from 1 to 4). Similarly, vector $\vec{v}$ has components (which are scalars, not vectors). The column vector on the right-hand side of the equation is $\vec{v}^\prime$ , and its components are the dot products of the rows of A with $\vec{v}$. But this dot product is 4-dimensional, so you will need to create a new dot product method to handle this. Note: Do not edit your current dot product method, as we still need that 3-dimensional version for all the other vector things we do.

public static Vector3D SomeTransformation(Vector3D vertex)
{
Vector3D row1 = new Vector3D(x,y,z,w); // Row 1 of the transformation matrix
Vector3D row2 = new Vector3D(x,y,z,w); // Row 2 of the transformation matrix
Vector3D row3 = new Vector3D(x,y,z,w); // Row 3 of the transformation matrix
Vector3D row4 = new Vector3D(x,y,z,w); // Row 4 of the transformation matrix
Vector3D result = new Vector3D(vertex.4dDot(row1),vertex.4dDot(row2),vertex.4dDot(row3),vertex.4dDot(row4) ; // Matrix multiplication result of [Transformation][Vertex]
return result
}

# Performing the Transformation

Having addressed the issues surrounding 4D dot products and constructors, you should now be able to add a method to your code that multiplies a vector by a matrix. But in game programming, we normally do not multiply by a completely general matrix. Our interest is in multiplying only by those matrices which correspond to physical situations. In this experiment, that means multiplying by a scaling matrix, by a translation matrix, or by a rotation matrix. We can simplify the mathematics and the coding greatly if we concentrate only on those situations, and write three separate methods, one for scaling, one for translations, and one for rotations.

## Translation

To translate an object we saw that this can be accomplished by matrix addition or matrix multiplication. Matrix addition is much more efficient, but matrix multiplication allows us to concatenate several transformations. Since this method is only going to translate, you could use vector addition.

## Raw Scaling

To raw scale your vertex by a factor of $S_x$ in the x-direction, a factor of $S_y$ in the y-direction, and a factor of $S_z$ in the x-direction, you will be multiplying by,

(2)
\begin{bmatrix} S_x & 0 & 0 & 0\\ 0 & S_y & 0 & 0\\ 0 & 0 & S_z & 0\\ 0 & 0 & 0 & 1\\ \end{bmatrix}

## Center Scaling

Since the raw scaling matrix has some unintended effects, you should also include a scaling operation in your code that would scale about a center. Such an operation would have as input both the scaling parameters and vertex to be scaled. It would then translate the center to the origin, scale, and then return the center to its original location. This method could simply call on the previous two methods of translation and raw scaling.

To rotate a vertex by $\theta$ about the x-axis according to the right-hand rule, you would multiply by,

(3)
\begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & \cos \theta & -\sin \theta & 0\\ 0 & \sin \theta & \cos \theta & 0\\ 0 & 0 & 0 & 1\\ \end{bmatrix}

To rotate a vertex by $\theta$ about the y-axis according to the right-hand rule, you would multiply by,

(4)
\begin{bmatrix} \cos \theta & 0 & \sin \theta & 0\\ 0 & 1 & 0 & 0\\ -\sin \theta & 0 & \cos \theta & 0\\ 0 & 0 & 0 & 1\\ \end{bmatrix}

To rotate a vertex by $\theta$ about the z-axis according to the right-hand rule, you would multiply by,

(5)
\begin{bmatrix} \cos \theta & -\sin \theta & 0 & 0\\ \sin \theta & \cos \theta & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1\\ \end{bmatrix}

# The Object

Although we have spent considerable time discussing the matrix, the object on which the matrix operates is also important. A single vector may represent a single point on the object, but most objects cannot be represented by a single point. A rectangular solid will have eight vertices. Aspects of symmetry may allow you to represent a rectangular solid by fewer than eight vertices, but if your object has the ability to be deformed (into something where faces may no longer be parallel), then all eight vertices will be required to completely represent the object. Therefore, this “simple” solid will require eight 4x1 column vectors, or (more ideally) a 4x8 matrix. Since we have not defined general matrix multiplication in our code, we will treat this solid as an array of eight vectors, and we can perform any matrix operations on the object by looping over the eight different vertices of the object.

# In Preparation

1. Design your own 3D object, and give the coordinates of its vertices using homogeneous coordinates at a location away from the origin. (To truly be a 3D object, it must have at least four noncollinear points. But if you make your object too complicated, you may not be able to easily interpret the results.)

2. Give the 4x4 matrix that would perform a raw scaling of your object with a 15% increase in length in the x-direction, a 25% decrease in the y-direction, and reflecting it in the z-direction. Then do the multiplication on your object and obtain the new coordinates. (Of course, this scaling will have unintended translation effects.)

3. Estimate the center of your object. Translate this center to the origin, then perform the scaling described in question #2, then return the center to the original location. What are the new coordinates?

4. Rotate your object by 90 degrees about the y-axis by the right-hand rule.

# Laboratory Procedures

1. Extend your 3D vector class to include the following new methods:

• a general constructor for a 4D vector for storing matrix rows.
• a 4D dot product operation using x, y, z, and w
• a translation operation
• a raw scaling operation
• a scaling about a center operation
• a rotation about the x-axis operation
• a rotation about the y-axis operation
• a rotation about the z-axis operation

2. Create a program that transforms the object you chose in prelab question #1. Specifically, the program should:

• ask the user for the vertices of the object
• ask the user for the center of the object
• ask the user to enter the type of transformation (translation, raw scaling, scaling about a center, or rotation about a major axis)
• ask the user for the needed parameters for that type of transformation (i.e. scaling factors, translation directions, axis of rotation, and angle of rotation)
• perform the transformation
• report the new vertices
• report the new center
• repeatedly ask for new transformations until terminated by the user

3. Test your code with the operations described in the prelab questions.

4. Execute the above program, for your instructor’s verification.

5. Save your class files! We will use them again in the rotation lab.

# Postlab Questions

1. In this lab, we just asked the user for the center of the object. In general, what you need is the center of mass or centroid of the geometric figure which can be difficult. What might be an easy way to approximate the center of a set of vertices?
2. Can you think of an object that would have a center that is not on the object itself? Sketch a picture of this object with its center labeled.
3. The 3D rotation functions about the coordinate axes can be used to rotate a 2D object about the origin in a 2D world. Explain how.
4. Suppose a 3D object has an axis of rotation that does not pass through the origin but is parallel to the z-axis. Explain how to do this rotation using only basic transformations.
5. Suppose a 3D object has an axis of rotation that does not pass through the origin and is not parallel to the z-axis. Explain how to do this rotation using only basic transformations.
page revision: 25, last edited: 27 Oct 2022 17:02