|
|
|
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.
|
|
|