CS40: Computer Graphics, Lab 6
Perspective Projection
By Jeff Kaufman
In this lab I extended the graphics library I started in
lab 2 by adding support for perspective
projections.
Mathematics
The task is conceptually pretty simple. We need to take the
world and align it with the viewer. At this point drawing the
scene as if it were 2D and ignoring the Z values would result in a
parallel projection: one where parallel lines are drawn as
parallel on the screen. This is not, however, the way a person
percieves the world; we have perspective. For a scene to be
realistic, more distant objects need to be relatively smaller.
This means that two lines that are always a meter apart need to
have fewer pixels between them as they get farther away.
The first transformation we can do with a matrix. It's
simply a matter multiplying every point in the world by a
translation matrix generated from the inverse of the
viewer's location. The rotation of the world to align with the
orientation of the viewer can be done by taking advantage of a
useful result from linear algebra, which tells us how to simply
make a matrix from three mutually orthoganal unit vectors which
will align each of those unit vectors with one of the three axies,
bringing the rest of the world along with it.
While it is not necessary for this projection, it is useful to
scale everything visible to be within a unit cube, the
cannonical view volume. When all points are in this
coordinate system, clipping becomes both simple and fast. Getting
the points into this coordinate system is a matter of multiplying
them by appropriate scale and translate matricies.
To add perspective we cannot use only matricies. We would need a
single matrix that could be used on all points and would modify
each point's x and y coordinates on the basis of their z
coordinate. What we can do instead is modify the fourth or
homogeneous coordinate of our points with a matrix and then later,
when it comes time to draw the point or the structure containing
that point, divide the x and y coordinates by the homogeneous
coordinate.
All of these manipulations are matrix manipulations, with the
exception of part of the perspective calculation, and they can
(almost) all be combined into one matrix by which every point is
multipled. This is pretty efficient, as we need calculate only
one matrix and need do only on matrix-vector multiplication for
each point. In hardware this would be better, as matrix
multiplications parallelize well.
Required Images
Two unit cubes (at [ 0.5, 0.5, 0.5 ]), straight on (from [ 0.5, 0.5, -2 ]) and
in three point perspective (from [ -1.7, 1.2, -3 ]):
The second cube looks pretty bad; some lines are off by a pixel.
This is not a problem with the perspective calculations, but
instead with my implementation of Bresenham's line drawing
algorithm.
Lab Questions
- The world space (x,y,z) values for the corners of the unit cube are:
- [ 0, 0, 0 ]
- [ 0, 0, 1 ]
- [ 0, 1, 1 ]
- [ 0, 1, 0 ]
- [ 1, 0, 0 ]
- [ 1, 0, 1 ]
- [ 1, 1, 1 ]
- [ 1, 1, 0 ]
The calculated values in screen space (x,y) for the corners in the
first image were:
- [ 75, 75 ]
- [ 70, 70 ]
- [ 70, 30 ]
- [ 75, 25 ]
- [ 27, 75 ]
- [ 30, 70 ]
- [ 30, 30 ]
- [ 25, 25 ]
The calculated values in screen space (x,y) for the corners in the
second image were:
- [ 55.31, 73.04 ]
- [ 71.11, 65.90 ]
- [ 71.64, 34.80 ]
- [ 55.46, 37.36 ]
- [ 27.12, 68.35 ]
- [ 45.12, 71.12 ]
- [ 45.01, 71.64 ]
- [ 26.51, 68.35 ]
- The distance between the center of projection (COP) and the view
reference point (VRP) is in our system represented by the parameter
d. With d at 2, we get the reference images above. The images below
have d as 1 and 4 respectively.
The most obvious change is that the cube looks smaller with smaller
values of d and larger with larger ones. But the screen space
length of the lines going into the screen remained the same, so
we're not simply moving closer or farther from the image, as
the pictures below do:
What this illustrates is that changing position and changing
zoom level are not the same thing, and d controls the zoom
level.
- The VUP vector indicates which direction is up for the
camera. Moving the VUP vector between vertical and
horizontal makes the cube appear to rotate:
-
Changing the view window squishes or stretches the image.
The two images below are again of the same cube, but this
time with the view window half and twice as wide as before:
- I did not do many extentions to this lab. I wrote
a function for adding cubes:
Module_addLineCube(Module* md, double
center_x, double center_y, double
center_z, double radius);
with an accompanying command wirecube x y z :
radius
for the module file format. I also wrote a
function for adding spheres:
Module_addLineSphere(Module* md, double
center_x, double center_y, double
center_z, double radius, double resoltion);
with an accompanying file format command command
wiresphere x y z : radius : resolution
. This
sphere is made by starting with a tetrahedron and recursively
breaking the lines at their midpoints, pushing these
midpoints out to the surface of the sphere, and connecting
the midpoints to make new lines. The
resolution
argument indicates how many breaks
to make. The images below, with links to movies, show the
sphere approximations for resolution
values
of 1 through 5.
There are many extra lines used in this method because of
the relative ordering of the recursion and the line drawing.
They are not visible because they are exact duplicates, but
they are slowing. I implemented the sphere this way so once
I implement Z-buffering I can modify it simply to draw solid
spheres.
Jeff Kaufman : 2006
cbr at sccs
dot swarthmore dot spam edu. Remove spam.
main page