gt
to specify the Georgia Tech graphics library. All of the
code that you write should be placed in a file called
matlib.c. Below is the list of routines that you will
create for this assignment.
gtInitialize() gtPushMatrix() gtPopMatrix()
gtInitialize command initializes the matrix stack,
which consists of creating a single identity matrix and making it the
only matrix on the matrix stack. The gtPushMatrix
command replicates the matrix at the top of the matrix stack and
places this new matrix on top of the stack. This new top matrix is
now the current transformation matrix. The gtPopMatrix
command pops the top matrix off the stack, causing the next matrix
down to become the current transformation matrix. An error message
should be printed if a pop is attempted when only one matrix is on the
stack. You matrix stack should allow up to 10 matrices to be stored.
You should print an error message if the matrix stack overflows or
underflows.
gtTranslate(float tx, float ty, float tz)
gtScale(float sx, float sy, float sz)
gtRotate(float angle, float ax, float ay, float az)
angle degrees about the axis
(ax, ay, az). The rotation is counter-clockwise as one
looks from the position (ax, ay, az) towards the origin.
For example, the command gtRotate(30.0, 1.0, 0.0, 0.0)
specifies a 30 degree rotation counter-clockwise around the
X-axis.
/* all parameters are floats */ gtLookAt(fx, fy, fz, ax, ay, az, ux, uy, uz)
CTM = CTM *
V, where V is the view matrix. The command
translates the From = (fx, fy, fz) vector to the origin,
it rotates the line segment connecting From to At =
(ax, ay, az) onto the negative Z-axis, and it
rotates the Up vector = (ux, uy, uz) onto
the YZ-plane. We will provide most of this code
for you. Our implementation will perform all of the
necessary vector cross-products and normalizations and so on, and will
produce a 4x4 matrix that specifies the proper transformation. You
will only have to modify the code that is provided so that it works
with your matrix multiply and matrix stack routines. The sample code
for this will be in a file called view.c, and you should
incorporate this code in your own source file.
gtPerspective(float fovy, float aspect, float near, float far)
Z-axis. The value fovy is an angle in
degrees that describes the vertical field of view. The value
aspect describes the ratio of the viewing frustum's width
to its height. The near and far values
specify the distances along the negative Z-axis at which
to perform near and far clipping in Z. The values of
near and far should always be positive for
the gtPerspective command. We are following the
conventions of OpenGL here, but this can be a point of confusion. The
command gtPerspective(60, 1, 20, 100) will clip away
portions of any lines that are outside of the range (-20, -100) in the
Z dimension.
gtOrtho(float left, float right, float bottom, float top, float near, float far)
Z-axis. The six values passed to
this routine describe a box to which all lines will be clipped. The
left and right values specify the minimum
and maximum x values that will be mapped to the left and
right edges of the framebuffer. The bottom and
top values specify the y values that map to the
bottom and top edges of the framebuffer. The near and
far values specify clipping distances (not values) along
the negative Z-axis, just as in
gtPerspective. The values for near and
far may be either positive or negative for
gtOrtho. Note that negative values indicate clipping
planes that are behind the viewer (along the positive
Z-axis).
gtBegin() gtEnd() gtVertex3f(float x, float y, float z)
gtBegin and gtEnd commands signal the
start and end of a list of endpoints for line segments that are to be
drawn. Each call to the routine gtVertex3f between these
two commands specifies a 3D vertex that is a line endpoint. White
lines are drawn between successive odd/even pairs of these vertices.
If, for example, the four vertices v1, v2,
v3, v4 are given in four sequential
gtVertex3f commands then two line segments will be drawn,
one between v1 and v2 and another between
v3 and v4. You should draw the lines corresponding
to each pair of vertices as soon as you have both vertices. This
means that you have no need to store more than two vertices at any
time.
The vertices of the lines are modified in turn by the current
transformation matrix and then by which ever projection was most
recently described (gtOrtho or
gtPerspective). Only one of gtOrtho or
gtPerspective is in effect at any one time. These
projections do not affect the matrix stack and the
current transformation matrix.
gtBeginGraphics(int width, int height)
width pixels
horizontally and height pixels vertically. Other
commands will allow you to modify the contents of the framebuffer and
write it out to a file.
gtGetFramebufferSize(int *w, int *h)
w and h point to.
gtClear(int r, int g, int b)
gtWriteFramebuffer(char *filename)
gtEndGraphics()
Two routines will be provided for you that will perform the necessary clipping and drawing of lines. This means that there is no need for you to write any clipping or line drawing code. These routines are:
near_far_clip(near, far, x0, y0, z0, x1, y1, z1)
near and far clip
distances along the Z-axis. The near and
far values are floats. The other six values are pointers
to floats so that they may be altered by the routine.
draw_line(float x0, float y0, float x1, float y1)
All of the above commands will be placed in the file gtGraphics.c,
and you should compile and link this file together with your code. As
an example of using the above commands, a simple program called
square.c will also be provided. This program will create an image
file called square.ppm which you can look at by typing xv
square.ppm.
linedraw.c and it makes use of the CLI routines. You
will find it easy to test your newly-created graphics commands by
linking to this program and then reading in various test files that
draw different shapes. Here is an example test file:
clear ortho -100 100 -100 100 -10 40 begin vertex 0 0 0 vertex 50 0 0 endIf the above file was called
simple.cli, you should be
able to invoke the linedraw program and then type the
following at the prompt:
linedraw> read simple linedraw> write simple.ppmThis will read in the text of
simple.cli and interpret
the commands, calling the corresponding gt graphics
commands. The result should be an image file called
simple.ppm that contains a horizontal line segment that
starts at the center of the screen and ends midway from the center to
the window's right edge. You should view the resulting image by
typing xv simple.ppm.
We will be providing several such test files that you can use to test your code.
draw_line routine.
You can do this by making modifications to the square.c
program. Second, implement the matrix stack and the
gtTranslate and gtScale commands. Test them
out by applying the current transformation matrix to the line
endpoints and then just draw lines by ignoring the
Z-values. Third, write the gtOrtho command.
This should be fairly straightforward once you have already drawn some
lines by ignoring the Z-values of the transformed
vertices. This is the right time to add near/far clipping. Fourth,
implement the gtPerspective command. The best way to
test out this routine is to carefully work out some simple test cases
on paper and match the execution of your code with these worked-out
examples. Finish by implementing the gtRotate command.
Logically this command should be implemented together with
gtScale and gtTranslate, but it is a little tricker to
write.
You will need to create and manipulate matrices and vertices in order to implement the transformation routines. Here are possible definitions:
typedef float gtMatrix [4][4]; typedef float gtVertex [3];Because the last row of a typical transformation matrix is 0 0 0 1, you may instead choose to use 4 by 3 matrices. You may also decide to explicitly store the 1 that is the fourth element of a homogeneous coordinate of a vertex, in which case your
gtVertex
definition will consist of four floats instead of three. Two
important routines that you will need to write are matrix-matrix
multiplication and matrix-vector multiplication. Your choices of data
structures will affect the details of these routines.
Programming tip: You will be writing subroutines that perform
operations such as matrix multiply. It is easy to accidentally write
a routine that clobbers some of the results if the routine is called
using the same matrix more than once. For example, the invocation
mult_matrices(a, b, b) is meant to multiply a times b and put the
result in b. If you are not careful, however, you will overwrite part
of b before you use all of the values in that matrix. The best way to
avoid this is to place all your results into a temporary matrix and
then copy the results to the final destination when you are finished.
~cs4391/proj1/assignmenton College of Computing UNIX machines.
To submit your program, put your project files in a directory on a College of Computing UNIX machine, then execute the following command in that directory:
shar matlib.c | elm -s "proj1" cs4391@cc.gatech.eduIf you used C++ and modified the
makefile or other files
we provided: subsitute matlib.c with those file names on
the shar command line.
The shar and elm commands are in the
/usr/local/bin directory.