|
Table of Contents
|
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)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)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.
Rotation about the X-axis
To rotate a vertex by $\theta$ about the x-axis according to the right-hand rule, you would multiply by,
(3)Rotation about the Y-axis
To rotate a vertex by $\theta$ about the y-axis according to the right-hand rule, you would multiply by,
(4)Rotation about the Z-axis
To rotate a vertex by $\theta$ about the z-axis according to the right-hand rule, you would multiply by,
(5)Rotation About an Arbitrary Axis
Rotating about an arbitrary axis can be achieved many different ways using matrices, but we will use the steps outlined in class. These steps transform the arbitrary axis into the positive z-axis, perform the needed rotation, and then undo the previous transformations. Assuming the axis passes through the point $p$, and is in the direction $d$, to rotate by an angle of $theta$ according to the right-hand rule,
- Translate in the direction $-\vec{p}$, so that the axis passes through the origin
- Rotate about the z-axis by $\gamma _\vec{w}$
- Rotate about the x-axis by $\beta _{\vec{v}}$ or $- \beta _{\vec{v}}$, depending on which side of the yz-plane we are in.
- Rotate about the z-axis by $\theta$
- Rotate about the x-axis by $- \beta _{\vec{v}}$ or $\beta _{\vec{v}}$ using the opposite of what was done before.
- Rotate about the z-axis by $- \gamma _\vec{w}$
- Translate in the direction $\vec{p}$
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. One of the simplest 3D objects we could construct would be a tetrahedron. A tetrahedron has 4 vertices, as shown below.
This “simple” solid will require four 4x1 column vectors, or (more ideally) a 4x4 matrix. For the purposes of testing your code, we want to track the center of the tetrahedron, so we will add that on to our matrix as the fifth column.
(6)In Preparation
So that you have your own test cases for troubleshooting.
1. Compute a raw scaling that doubles in the $x$-direction, halves in the $y$-direction, and reflects across the $xy$-plane.
2. Compute a center scaling that doubles in the $x$-direction, halves in the $y$-direction, and reflects across the $xy$-plane.
3. Compute a 90-degree rotation about all three major axes.
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
- a rotation about an arbitrary axis operation
2. Create a program that transforms our hard-coded tetrahedron. Specifically, the program should:
- ask the user to enter the type of transformation (translation, raw scaling, scaling about a center, rotation about a major axis, or rotation about an arbitrary 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, point and direction of arbitrary axis)
- 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 preparation section.
4. Execute the above program, for your instructor’s verification.
Postlab Questions
- 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?
- 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.
- 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.
