Ultrashock Tutorials > Flash5 > Cameras in Flash  
 
by: Brandon Williams

Source File

 
Cameras in Flash
 

The purpose of this tutorial is to show an alternative to representing 3D environments in Flash. The method that is most popular and easiest to do is rotating about the x-, y-, and z-axes. The equations for these operations can be derived in a multitude of ways, but this tutorial will assume you already know how to use them. However, the equations will be used very little in this tutorial because they are not all that important in what we will be covering.

What is a Camera?

For this tutorial a camera is going to be a viewing system to see your 3D environment through. You would specify the camera's position and orientation (direction it is looking and 'spin' of the camera), and from that you would derive a rotation matrix that would transform the points in your environment to their position how they appear to the camera. The concept of a matrix and rotation matrix will be developed later in this tutorial. By the end of this tutorial you will be able to see what the box in the picture below looks like to the camera.



Why is a Camera better than doing Axis Rotations?

Using a camera in a 3D environment is magnitudes more powerful than rotating about the coordinate axes. Using a camera adds flexibility to navigating a 3D world. When using a camera you would keep the position of all the points in your environment fixed and simply move the camera through the world. While moving in a straight line you could easily rotate the camera around to see how your world looks from different positions, or you could simulate a 1st person perspective by moving the camera in the direction it is facing. These are all very difficult tasks to complete by rotating a world about the x-, y-, and z-axis, if not impossible.

Rotation about the Coordinate Axes and an Arbitrary Axis

Although not the focus of this tutorial, and not even used very much, the equations for rotations around axes should be shown. The derivations and thought process of the equations has been left out since this is simply background information.

Rotations around the coordinate axes are the easiest. They can be derived using the sum identity for sine and cosine. Given the ordered triplet (x, y, z) and a rotation angle of q, the rotated ordered triplet (x', y', z') can be found with the following equations:

Rotation about the x-axis
 
x' = x
y' = y cos q - z sin q
z' = y sin q + z cos q
Rotation about the y-axis
x' = x cos q + z sin q
y' = y
z' = -x sin q + z cos q
Rotation abut the z-axis
x' = x cos q - y sin q
y' = x sin q + y cos q
z' = z
An important property to take note of is that a rotation around a certain axis does not affect the value of the axis' coordinate. For example, you rotate around the x-axis but the x-coordinate was not affected. Same goes for the y- and z-axis. This has to do with the fact that the axis at which you rotate about is an eigenvector of the rotation matrix formed. An eigenvector is a vector associated with a square matrix that when multiplied with the matrix it does not change in direction, but only in magnitude (and sometimes not even magnitude). The notion of an eigenvector will not be discussed in this tutorial, but it is still a very important and interesting subject if you wish to explore it on your own.

A much more useful method for rotation is the rotation about an arbitrary axis. What if you wanted to rotate around the axis that points from (0, 0, 0) to (2, 1, 3) rather than the coordinate axes. We are going to write the equation in its vector form first. We define x to be the current position of the point to be rotated, a to be the axis the point will rotate about, q to be the angle of rotation, and x' to be the rotated point. The three quantities x, x', and a are all vectors. For the equation to work a must also be a unit vector. If you are unsure of the terminology being used make sure to read the vector tutorial on this site first.
x' = p cos q + (a ´ p) sin q + a (a · p) (1 - cos q)
Although quite a long equation it can be implemented easily. Remember that the ´ operator is the cross product and it returns a vector, and the · operator is the dot product and it returns a scalar. Later on we will organize these messy equations into simple rotation matrices.

Linear Algebra

By far the most important subject when studying 3D is linear algebra. Linear algebra is most likely called 'linear' because the entire subject starts off with a systematic way of solving linear systems of equations. When looking to organize many equations containing many unknowns, brilliant mathematicians put the coefficients of the equations in one matrix, the variables in another matrix, and the solution to the equations in yet another matrix. You were then left with one equation that simply had matrices in it, which is just another mathematical object like a vector or scalar. The problem seemed less intimidating now and thus flourished linear algebra. Of course the once-upon-a-time connotation is not fully accurate, but ultimately the subject came about when mathematicians were faced with solving systems of linear equations.

Matrices

We have already learned of one mathematical object used in linear algebra: the vector. The next important object is the matrix. A matrix is a set of numbers arranged in a rectangular array. A matrix is two dimensional because it has rows and columns. The only size matrix we will be using is three by three and three by one matrices. They look something like this:
    / e11  e12  e13 \
M = | e21  e22  e23 |
    \ e31  e32  e33 /
 
    / e11 \
M = | e21 |
    \ e31 /
The notation of a matrix for us will be an upper-case bold letter, whereas a vector was a lower-case bold letter, and a scalar was a lower-case italic letter. To reference an element in a matrix we will use the notation 'e12' meaning the element in the 1st row and 2nd column.

There are only a few operations that we will be concerned with that can be done to matrices: multiplication, inversion, and transposition. Multiplication and transposition will be covered now, but inversion will be covered later. Let us first deal with multiplication because that is what will be used the most.

There are three types of multiplication that we are going to deal with. Multiplying a matrix with a scalar, multiplying a matrix with a vector, and multiplying two matrices. Multiplying a matrix with a scalar is by far the easiest operation. You simply multiply every element in the matrix with the scalar.
    / e11  e12  e13 \
M = | e21  e22  e23 |
    \ e31  e32  e33 /

        / e11  e12  e13 \   / s*e11  s*e12  s*e13 \
s M = s | e21 e22 e23 | = | s*e21 s*e22 s*e23 | \ e31 e32 e33 / \ s*e31 s*e32 s*e33 /
Multiplying a matrix and a vector together is a little bit trickier. Although matrix-vector multiplication are not exactly defined, we can imagine that the vector is simply a three by one matrix. Also, the product of a matrix and vector is another vector, or three by one matrix depending on how you look at it. The first thing to do is write out the problem:
    / m11  m12  m13 \
M = | m21  m22  m23 |
    \ m31  m32  m33 /
 
    / v11 \
V = | v21 |
    \ v31 /

/ m11 m12 m13 \ / v11 \ M V = | m21 m22 m23 | | v21 | \ m31 m32 m33 / \ v31 /
To find the resulting vector from the above multiplication you multiply the column matrix (the vector) with every row of the three by three matrix. When you multiply the vector with the first row of the three by three matrix you get the first element of the resulting vector, when you multiply the vector with the second row you get the second element, and so on. Performing the multiplication above gives you the following vector:
      / v11 * m11 + v21 * m12 + v31 * m13 \
M V = | v11 * m21 + v21 * m22 + v31 * m23 |
      \ v11 * m31 + v21 * m32 + v31 * m33 /
The same thing can be done with two dimensional vectors and two by two matrices.
    / m11  m12 \
M = \ m21  m22 /
 
    / v11 \
V = \ v21 /

/ m11 m12 \ / v11 \ / v11 * m11 + v21 * m12 \
M V = \ m21 m22 / \ v21 / = \ v11 * m21 + v21 * m22 /
Multiply two matrices together is even trickier. To multiply matrix A and B together you must multiply every row of A with every column of B. The product of two 3x3 matrices is another 3x3 matrix, and the product of two 2x2 matrices is another 2x2 matrix. To drive this home in the simplest way here is how you would multiply two 2x2 matrices:
    / a11  a12 \
A = \ a21  a22 /
 
    / b11  b12 \
B = \ b21  b22 /
 
     / b11*a11 + b21*a12   b12*a11 + b22*a12 \
AB = \ b11*a21 + b21*a22   b12*a21 + b22*a22 /
The best way to remember this is to treat B like a vector. If you simply neglect the second column and only look at the first (a vector since it is only a column matrix) then the first column of the product is the same as if you were multiplying a matrix and a vector together. Once you have the first column of the product matrix you can find the second column by neglecting the first column of B and only looking at the second (once again a vector). Multiplying A with that vector will give you the second column of the product matrix, and then you are done.

Multiplying two 3x3 matrices is the same except now you have to do the vector multiplication method three times, once for each column. Because there are so many elements to multiply for the product matrix each element of the product is going to be referenced as AB.e11, AB.e12, and so on. The general product matrix looks like this:
    / a11  a12  a13 \
A = | a21  a22  a23 |
\ a31 a32 a33 / / b11 b12 b13 \ B = | b21 b22 b23 |
\ b31 b32 b33 / AB.e11 = b11 * a11 + b21 * a12 + b31 * a13
AB.e12 = b12 * a11 + b22 * a12 + b32 * a13 AB.e13 = b13 * a11 + b23 * a12 + b33 * a13 AB.e21 = b11 * a21 + b21 * a22 + b31 * a23
AB.e22 = b12 * a21 + b22 * a22 + b32 * a23 AB.e23 = b13 * a21 + b23 * a22 + b33 * a23 AB.e31 = b11 * a31 + b21 * a32 + b31 * a33
AB.e32 = b12 * a31 + b22 * a32 + b32 * a33 AB.e33 = b13 * a31 + b23 * a32 + b33 * a33
That may seem somewhat cumbersome to memorize so I would not even recommend it. You can always reference this page or anything else so just know what matrix multiplication is, and what dimension matrices are formed from multiplying a matrix with a scalar, vector, or another matrix.

The transposition of a 3x3 matrix results in a matrix with the exact same dimensions and elements except with a permutation of the elements. Basically, you switch the eij (where i and j can be any number within the dimensions of the matrix) with the eji element. For example, in a 2x2 matrix the e11 and e22 elements stay the same (since i = j), but the e12 element is switched to e21 and vice versa.
    / m11  m12 \
M = \ m21  m22 /
/ m11 m21 \
MT = \ m12 m22 /
Take note that the transposition matrix is denoted with a superscript T. The transpose of a 3x3 matrix is nearly the same:
    / m11  m12  m13 \
M = | m21  m22  m23 |
    \ m31  m32  m33 /
/ m11 m21 m31 \
MT = | m12 m22 m32 | \ m13 m23 m33 /
Transposition is a very simple operation and will be very powerful later on.

Special Types of Matrices

If you were to multiply two matrices, A and B, together and the product was A, B would be called an identity matrix. An identity matrix is a matrix that does not change another matrix when they are multiplied together. Such a matrix is always denoted with I and looks like this:
    / 1 0 0 \
I = | 0 1 0 |
\ 0 0 1 /
And you can do away with the third row and column to get the 2x2 identity matrix equivalent. To show that the above is really the identity matrix we can multiply it will a general 3x3 matrix:
    / a11  a12  a13 \
A = | a21  a22  a23 |
\ a31 a32 a33 / / 1 0 0 \ B = | 0 1 0 |
\ 0 0 1 / AB.e11 = 1 * a11 + 0 * a12 + 0 * a13
AB.e12 = 0 * a11 + 1 * a12 + 0 * a13 AB.e13 = 0 * a11 + 0 * a12 + 1 * a13 AB.e21 = 1 * a21 + 0 * a22 + 0 * a23
AB.e22 = 0 * a21 + 1 * a22 + 0 * a23 AB.e23 = 0 * a21 + 0 * a22 + 1 * a23 AB.e31 = 1 * a31 + 0 * a32 + 0 * a33
AB.e32 = 0 * a31 + 1 * a32 + 0 * a33 AB.e33 = 0 * a31 + 0 * a32 + 1 * a33 -- which reduces down to -- AB.e11 = a11
AB.e12 = a12 AB.e13 = a13 AB.e21 = a21
AB.e22 = a22 AB.e23 = a23 AB.e31 = a31 AB.e32 = a32 AB.e33 = a33
Before we go on to another type of special matrix we are going to cover inversion of matrices briefly. Inverses of matrices is a very important operation in linear algebra. The reason why we are only briefly covering them will be known in a moment.

If you had a matrix, named A, the inverse of A would be such that when you multiplied the two together the product would be the identity matrix. Like this:
A-1 A = I
Take note that the inverse matrix is denoted with a superscript negative one. We are not going to discuss all the general methods of solving such a problem because that could easily add another fifty pages to this simple tutorial. However, we are going to find a way to get the inverse of a special type of matrices with a very easy operation soon.

The next special type of matrix we are going to look at are orthonormal matrices. To show what an orthonormal matrix is we are going to first associate each row of a matrix with a vector. Therefore, a 2x2 matrix is made up of two vectors and a 3x3 matrix is made up of three vectors:
a = < a1, a1, a3 >
b = < b1, b2, b3 >
c = < c1, c2, c3 >
 
    / a1  a2  a3 \
M = | b1  b2  b3 |
    \ c1  c2  c3 /
Given the above vectors and matrix, M can only be an orthonormal matrix if a, b, and c are unit vectors and if the dot product of each vector with each other vector is zero. Remember that zero for a dot product meant that the two vectors were perpendicular. Therefore an orthonormal matrix also means that the vectors a, b, and c are unit vectors and perpendicular. Also know that if we took the vectors a, b, and c to be the columns of the matrix rather than the rows, the test for whether a matrix was orthonormal or not would still hold, as will be shown now.

A very important property of orthonormal matrices is that their transpose is equal to their inverse. Meaning that you can find the inverse of an orthonormal matrix by simply taking its transpose.
MT = M-1
Usually inverting a matrix is a slow, CPU-intensive computation, but transposition is easily done and rather fast. The inverse of an orthonormal matrix is yet another orthonormal matrix. This is why it does not matter if you use the vectors as the rows or columns and the test for an orthonormal matrix still holds.

Another important property of orthonoraml matrices that the product of any two orthonormal matrices is another orthonormal matrix. This simple property will actually help you save CPU calculations, as you will see in the next section on rotation matrices.

Rotation Matrices

A rotation matrix is simply another name for an orthonormal matrix. If you multiply a vector (column matrix) by an orthonormal matrix you will perform some type of rotation on the vector (except for the trivial case of the identity matrix which does not perform any transformation). The very important link between why a rotation matrix and an orthonormal matrix are the same will be shown later.

For right now we are going to simply convert the equations that we came up with before for rotating a point around the x-, y-, and z-axis and an arbitrary axis into rotation matrices. Let us first start with a general rotation matrix and vector and see if we can find the appropriate values:
    / r11  r12  r13 \
R = | r21  r22  r23 |
    \ r31  r32  r33 /
 
v = < v1, v2, v3 >
Let us quickly look back at what the equations looked like for a rotation around the x-axis and see if we can find the values of the rotation matrix:
Rotation about the x-axis

x' = x
y' = y cos q - z sin q
z' = y sin q + z cos q
By looking at the above equations it would seem that the first row of the rotation matrix would be similar to the identity matrix since the x-component of the vector is unchanged. In fact, the first column would be part of the identity matrix too because the x-component does not show up anywhere in the calculation of the y- and z-component of the rotation vector. Then, only four elements of the 3x3 matrix are left to speculation, but those can been easily shown to come out like this:
     / 1    0       0  \ 
Rx = | 0  cos q  -sin q |
     \ 0  sin q   cos q /
Multiply the above with vector v gives you the following (to make it easier to read the vector is represented as a column matrix):
            /         x        \ 
v' = Rx v = | y cos q - z sin q |
            \ y sin q + z cos q / 
Without discussing them as much as the x-axis rotation matrix, the rotation matrices for the y- and z-axis can be expressed as follows:
     /  cos q  0  sin q \ 
Ry = |   0     1    0   |
     \ -sin q  0  cos q /

     / cos q  -sin q  0  \
Rz = | sin q   cos q  0  |
     \   0       0    1 /
It is slightly harder to come up with a rotation matrix for an arbitrary axis so it will not be complete shown. In fact, it takes a few 'far from common sense' steps to arrive at the matrix. For example, someone had the cleverness to substitute a cross product with a skew-symmetric matrix (a skew-symmetric matrix is one in which its transpose is equal to itself multiplied by the scalar negative one). The matrix looks like this (q is the rotation angle and a is the axis of rotation):
c = cos q
s = sin q
t = 1 - cos q

a = < x, y, z > / tx2 + c txy - sz txz + sy \ Ra = | txy + sz ty2 + c tyz - sx | \ txz - sy tyz + sx tz2 + c /
Now, from what we know about orthonormal matrices, their properties, and their relationship to rotation matrices, we can now discuss some very useful applications to three dimensional programming.

Let us say you have a rotation matrix for rotations about the x-axis. Every frame you multiply a point's position by this matrix, you update the position of the point, and you render it on the screen. What would happen if you rotated by an q, and then you want to undo that angle by rotating back to your old position? Your first instinct may be to simply construct a new rotation matrix with a negative q and then multiply point with that matrix. However, if you could find an inverse of the rotation matrix, a multiplication of that matrix with the point's position would simply undo the rotation and put it back in its original position (since a matrix and its inverse multiplied together produce an identity matrix). Then from what you know about orthonormal matrices you can easily find the inverse matrix without doing any addition sine or cosine calculations. The inverse of the four rotation matrices above are:
      / 1     0      0  \ 
RxT = | 0   cos q  sin q |
      \ 0  -sin q  cos q /
 
      / cos q  0  -sin q \ 
RyT = |  0     1    0    |
      \ sin q  0   cos q /
 
      /  cos q  sin q  0  \
RzT = | -sin q  cos q  0  |
      \    0      0    1 /
 
      / tx2 + c    txy + sz   txz - sy \
RaT = | txy - sz   ty2 + c    tyz + sx |
      \ txz + sy   tyz - sx   tz2 + c  /

Notice that the inverse of the rotation matrices only differ by a sign change here and there from their original form.

Another application of what we have learned is employed heavily by most of the major 3D graphics API's like OpenGL. Since the product of two orthonormal matrices is another orthonormal matrix you can simply concatenate many rotation matrices together to get your final rotation matrix. For example, if you were to do a rotation about the x-axis and then the y-axis you might have taken the point's position (x, y, z) and plugged it into the x-axis rotation equations to get the new position of the point. Then you plugged that new position into the y-axis rotation equations to get the final position of the point. However, we could do that exact same thing with matrices and eliminate a few of the arithmetic operations. If we get the rotation matrices for the x- and y-axis we can simply multiply those two together to get another rotation matrix, and finally multiply the point with that matrix to get its position after being rotated around the x- and y-axis.

This concept of concatenating matrices is used in OpenGL and DirectX. There is a main 4x4 matrix (most API's use 4x4 matrices because they use homogenous coordinates which was not discussed in this tutorial) that all points set through the API are multiplied by; this matrix starts off as the identity. Then, the user can perform rotations of the 3D environment through the use of a function, glRotatef (angle, axis_x, axis_y, axis_z) for OpenGL. This function multiplies the rotation matrix you specify with the current rotation matrix in the system. You can do this over and over, performing many rotations about tons of different axes and the matrix still stays orthonormal and remains a rotation matrix. Then at the end the points are multiplied by the final rotation matrix and they are rotated.

All of this saves calculations because in the end you are multiplying the points with only one rotation matrix; you could concatenate ten rotation matrices into one. Quite a powerful property of orthonormal matrices.

The Basics of a Basis

Much of linear algebra leads up to the very important concept of a basis. A complete detail of bases requires knowledge of many things like vector spaces, subspaces, linear combinations, linear dependence (independence), and more that is probably too conceptual to be of any interest for what our ultimate goal is. Therefore much of what linear algebra covers is going to be left out or watered down thoroughly.

To make visualization of a basis easier we will only be dealing with two dimensions, which means 2x2 matrices and vectors with only two components (two by one matrices). The concepts will be developed for three dimensions too (because it is essential to understanding cameras), but it is just harder to visualize.

A basis can be thought of as a set of vectors that define a coordinate system; specifically it is a matrix where its elements are made up of the vectors that defined the coordinate system. In applications to the real world it is sometimes to define a different coordinate system to work in other than the Cartesian x- and y-axis. In Special Relativity you deal with coordinate systems and inertial frames thoroughly. For us, bases are going to provide a simple way of changing between coordinate systems.

We learned in the vector tutorial that the unit vectors i and j were special vectors that point in the directions of the x- and y-axis respectively. These two vectors define what is called the standard basis. In matrix form you would put the components of i in the first column and the components of j in the second column. It would look like this:

      i  j 
    / 1  0 \
S = \ 0  1 /
Let us say we wanted to define a coordinate system that differed a little from the standard basis. The x-axis vector will now be <2, 1> and the y-axis will be <0, 3>. This new basis would look like this as a matrix:
    / 2  0 \
B = \ 1  3 /
And that is all there is to constructing a basis. You can do the same for three dimensions. This is what the standard basis looks like for three axes:
      i  j  k
    / 1  0  0 \
S = | 0  1  0 |
    \ 0  0  1 /
It is also useful to visualize the different coordinate systems.


The white lines represents the standard basis while the blue lines represents some arbitrary basis. If you were to print that picture out and plot a point at (2, 1) relative to the white lines it would approximately be the equivalent to the point (1.2, .1) relative to the blue lines. This brings up an important question: how can we find the position of a point in one coordinate system relative to another coordinate system? This is the fundamental problem that we will use bases to solve.

To illustrate this problem in a more useful situtation let us look at another coordinate system: one that differs from the standard basis by a rotation of the angle q. Such a coordinate system looks like this:



Looking at those two coordinate systems we could say that a point at (1, 1) in the rotated basis (blue) is approximately (.3, 1.4). Well, it can now be said that the approximation we just made is in fact an approximation of where a point at (1, 1) in the standard basis will be when rotated by an angle of q about the origin. This is because we could say that the blue and white coordinate systems start of lined up (q = 0). At this moment in time we plot a point at (1, 1) on the blue coordinate system. Then then twist the blue coordinate system so that it differs with the white by an angle of q. When this is done the point stays plotted relative to the blue axes, which means it rotates too. Finally, we mark where the point falls on the white coordinate system. If we can find the position of that mark then we have found the position of (1, 1) when rotated by an angle of q about the origin; that is what our approximation did.

Now, how can we come up with a general method of finding the coordinate of a point in the standard basis from knowing its position in an arbitrary basis (since we see that it can be very useful)? This is the rather easy part. Simply write out the matrix form of the basis and multiply the position of the point in that basis with the matrix. That will give you the point in the standard basis. For example, let us take the basis that we were dealing with before. We will call the x-axis vector v, where v = <2, 1>, and call the y-axis vector w, where w = <0, 3>. What would the position of the point (4, 2) relative to this new basis be in the standar basis? Here is the work (B is the basis matrix, p is the vector position of the point in B, and p' is the vector position of the point in the standard basis, S):

      v  w
    / 2  0 \
B = \ 1  3 /

p = < 4, 2 > / 2 0 \ / 4 \ p' = \ 1 3 / \ 2 / / 8 \ = \ 10 /
Now the basis just shown is not very useful because such a skewed arbitrary matrix does not represent all that much. The bases we will be most concerned with are going to be ones that differ from the standard basis by an angle of q like shown before. For these types of bases to work you must maintain two important properties of the vectors used: the vectors of the axes must be unit vectors and all the vectors must be orthogonal. In short, the basis matrix must be an orthonormal matrix.

We can come up with such a basis in two dimensions easily by remembering that the x-component of a unit vector is the cosine of the angle of the vector, and that the y-component of a unit vector is the sine of the angle. This means that already we know the x-axis vector of our new basis: v = < cos q, sin q >. To get a vector that is perpendicular to that vector we just remember a simple rule from algebra. The slope of a line is the change in y divided by the change in x: m = y / x. To get the value of a slope perpendicular to that you take the reciprocal (swap the numerator and denominator) and multiply the numerator by negative one: m^ = -x / y. We can use this same concept to construct and orthogonal vector. Here y is sin q and x is cos q, therefore the perpendicular vector, and happens to be the y-axis of the coordinate system, is: w = <-sin q, cos q>. Finally, the basis of the rotated coordinate system is:
    / cos q  -sin q \
B = \ sin q   cos q /
Now, if you know a point in the basis B, and you want to find its position in the standard basis, you can multiply it by that matrix. Or, in less mathematical terms, to rotate a point by an angle of q multiply it with the above matrix. Also, if you look closely you will see the above matrix is the exact same as the rotation matrix for about the z-axis. In fact, all the rotation matrices shown earlier are simply bases, each one differing from the standard basis by a mere angle. Before, you thought of it as rotating a point about the different axes with a few equations; now you can think of it as finding the position of a point in the standard basis from its position in a rotated coordinate system.

Application to the Camera

It is now time to relate the massive amount of information to what we wanted to do originally: develop a camera in Flash. In terms of what we have learned so far, what would best represent a camera? The answer is a basis. A camera is a coordinate system all of its own, where each axis is perpendicular to each other. It has an axis shooting out of the lens, an axis coming out of the top, and an axis out to the side. We are going to give some names to these vectors that will be used from now on: the axis coming out of the side of the camera is going to be the side vector, the vector coming out of the top is going to be the up vector, and the one pointing in the direction the camera is facing is going to be the out vector. Remember that all the axes must be unit vectors.


With some careful thought you can see that it takes really only two vectors to define a camera. One that points in the direction that the camera is looking, and another perpendicular to it to show its orientation around the out vector. If you only had the out vector then you would have an infinite number of orientations for the camera; you could simply 'spin' the camera about the out axis. That is what the side or up vector is for. You do not need both to completely define the camera, but you do need all three vectors to define the basis of the camera. Also, from our knowledge of vectors we know that if we are given two perpendicular vectors we can find a third perpendicular vector by taking the cross product. This means that if we are provided with any two of the camera's vectors the third is implied through the use of the cross product.

There is one difference in the bases that we talked about earlier and the basis of a camera. Before, all the bases we discussed shared the same point for the origin. This time, however, the bases will not since the camera can move anywhere in a 3D environment. In the following picture we have the point (x, y, z) relative to the origin being at (0, 0, 0). We also have a camera placed at (a, b, c).

 



Something that will be very important in a moment is to find the position of the point relative to the origin being at (a, b, c). To do this all you do is subtract (a, b, c) from (x, y, z). Doing this is pretty much just finding a vector that goes from (a, b, c) and points to (x, y, z). It is this vector that we will be interseted in when we want to transform the point to the camera's coordinate system.

Now we will derive the rotation matrix to apply to the vectors pointing from the camera to the points in the standard basis; this will complete the transformation and the points will finally be in the camera's coordinate system, ready to render. Your first instinct may be to simply put the components of the vectors into the columns of the rotation matrix. However, there is a little bit more that you need to do. Before, when dealing with bases, we were going from an arbitrary basis to the standard basis. This time, however, we are going from the standard basis to the camera's basis. This means an inverse transformation must be done, thus you simply take the inverse of the camera's basis for the final rotation matrix.

Although it may be hard to believe, you have learned everything you need to know about cameras. After covering all of the mathematics only a few things needed to be stated about cameras. Here is a quick reference of the steps taken to view an environment through a camera.
   1.) Position all the points in your environment relative
       to the x-, y-, and z-axis.
 
   2.) Position the camera somewhere out in space at (a, b, c).
 
   3.) Define the camera's coordinate axis vectors: side, up, out.
 
   4.) Make sure the camera's axes are orthogonal and unit vectors.
 
   5.) Loop through every point in the environment and subtract
       the camera's position vector <a, b, c> from the point's
       position vector <x, y, z> and store it in a temporary variable.

   6.) Create the rotation matrix from the camera's axis vectors:
side = < Sx, Sy, Sz > up = < Ux, Uy, Uz > out = < Ox, Oy, Oz >

[ Sx Sy Sz ]
R = [ Ux Uy Uz ] [ Ox Oy Oz ] 7.) Multiply the temporary position vector of the point by the
above matrix. 8.) Render the tranformed point.
The Code

I have provided a starting point for you to use a camera with three classes for vectors, matrices, and cameras. The classes are fully documented so you should read them just as you read this tutorial. Practice using them for a little while, see how I coded it, and I think you will find they are very easy to use. You may even want to write your own if you think of a better way to do things.

When viewing the demo file provided remember that this is not the usually rotation about the coordinate axes. It is as if you were a camera man for a television show and you can move the camera around and rotate it to view everything from different angles. It may take a second to see what is going on, but I can guarantee that it is much easier to use, faster, and many times easier to control. In the demo the arrow keys control the orientation of the camera. The up and down arrows rotate the camera about its side axis, and the left and right arrows rotate about the world y-axis. The world y-axis is used because it is a much more natural feeling. If you were developing a flight simulator you would use the camera's up vector because it would rotate around that. The W and S keys translate the camera in the direction of the out vector, the A and D keys translate in the direction of the side vector, and the Q and E keys elevate the camera up and down.

Good luck.

 
©2001 Ultrashock.com Inc. - All rights reserved