# CS 488: Assignment 3

## 'Defenda'

Out: 3/11/03

Due: 4/8/03 at 2:00pm

In this third assignment you will get to play with 3D computer graphics by implementing a 3D version of the early 80s game of Defender where you will create a perspective view window onto a 3D landscape that you can fly over.

Your program will read in a datafile called land.txt. This text file defines the landscape that you will be flying over.

The height of the landscape varies in integral values from 0 (low) to 9 (high).

For example, a very simple landscape file could be:

00000000000000000000
02222222222222333330
02221112222222377730
02221012222222379730
02221012222222377730
02211011222222333330
02210001222222222220
02211111222222222220
02222222222222222220
00000000000000000000

The data file literally draws out the landscape. Each character in the text file represents a 10 meter long by 10 meter wide patch of ground that is sitting at an elevation of n*5 meters. In this case the file shows a mountain in the North East corner and a valley on the West side running North to South. The maximum size of the landscape is 500 by 500 characters. The minimum size of the landscape is 10 by 10 characters. The landscape will be rectangular, but may not be square.

Since the height of each square polygon of the landscape is given in integer amounts, the question should arise about how to deal with the boundaries of adjacent squares that are not at the same height. The general solution is to draw a vertical square polygon at each boundary to cover the vertical distance between each adjacent square. This doesn't look incredibly nice, but it will do for now. We will do something nicer in Assignment 4.

When you draw the terrain, all of the terrain at level 0 should be in blue (water), at level 2-5 should be green, at level 6-8 should be brown (dirt), at level 9 is white (snow.) For the vertical polygons at the edge boundaries you can colour the top two vertices the colour of the top height, and the bottom two vertices the colour of the bottom height.

Your program will read in a second file called objects.txt that will contain a list of objects that sit on top of the landscape. This file will have the same number of rows and columns as the landscape file so that they will line up geographically. The objects specified include simple geometric shapes such as a red cube, and a yellow 4-sided pyramid. The contents of objects.txt will look like the following:

....................
.A.A.A.A.A.A........
....................
........C.C.C...A...
.........C.C........
........C.C.C.......
...X................
........A...A...A...
........A...A...A...
....................

Each object (e.g. A for Pyramid, or C for Cube) will sit on top of the landscape at the position shown - that is the bottom of the cube or pyramid will be at the height of the landscape at that same point as defined by the landscape file.

The format for each of the object files (e.g. cube.txt, pyramid.txt. etc) is given below. Each object has its centerpoint defined as (0,0,0) at the center of the object at groundlevel. The coordinate system for these objects has X and Y forming the plane of the ground and Z being the height above the ground. In this case a block segment is a block stretching from -2.5 to 2.5 in X and Y and stretching from 0 to 10 in Z. When placing the object on the landscape, the center of the object should be moved to the center of the square that the object resides on.

For example, cube.txt could look like the left column in the following table:

 6 number of polygons in the object (6) 1.0 0.0 0.0 RGB colour of the object (red) 4 number of vertices in the polygon (4) -2.5 -2.5 0 vertex 1 2.5 -2.5 0 vertex 2 2.5 -2.5 10 vertex 3 -2.5 -2.5 10 vertex 4 4 number of vertices in the polygon (4) 2.5 -2.5 0 vertex 1 2.5 2.5 0 vertex 2 2.5 2.5 10 vertex 3 2.5 -2.5 10 vertex 4 4 number of vertices in the polygon (4) 2.5 2.5 0 vertex 1 2.5 2.5 10 vertex 2 -2.5 2.5 10 vertex 3 -2.5 2.5 0 vertex 4 4 number of vertices in the polygon (4) -2.5 2.5 0 vertex 1 -2.5 2.5 10 vertex 2 -2.5 -2.5 10 vertex 3 -2.5- 2.5 0 vertex 4 4 number of vertices in the polygon (4) 2.5 -2.5 0 vertex 1 2.5 2.5 0 vertex 2 -2.5 2.5 0 vertex 3 -2.5 -2.5 0 vertex 4 4 number of vertices in the polygon (4) 2.5 -2.5 10 vertex 1 2.5 2.5 10 vertex 2 -2.5 2.5 10 vertex 3 -2.5 -2.5 10 vertex 4

And pyramid.txt could look like the left column in the following table:

 6 number of polygons in the object (6) 1.0 1.0 0.0 RGB colour of the object (yellow) 4 number of vertices in the polygon (4) -2.5 -2.5 0 vertex 1 2.5 -2.5 0 vertex 2 0.5 -0.5 10 vertex 3 -0.5 -0.5 10 vertex 4 4 number of vertices in the polygon (4) 2.5 -2.5 0 vertex 1 2.5 2.5 0 vertex 2 0.5 0.5 10 vertex 3 0.5 -0.5 10 vertex 4 4 number of vertices in the polygon (4) 2.5 2.5 0 vertex 1 0.5 0.5 10 vertex 2 -0.5 0.5 10 vertex 3 -2.5 2.5 0 vertex 4 4 number of vertices in the polygon (4) -2.5 2.5 0 vertex 1 -0.5 0.5 10 vertex 2 -0.5 -0.5 10 vertex 3 -2.5- 2.5 0 vertex 4 4 number of vertices in the polygon (4) 2.5 -2.5 0 vertex 1 2.5 2.5 0 vertex 2 -2.5 2.5 0 vertex 3 -2.5 -2.5 0 vertex 4 4 number of vertices in the polygon (4) 0.5 -0.5 10 vertex 1 0.5 0.5 10 vertex 2 -0.5 0.5 10 vertex 3 -0.5 -0.5 10 vertex 4

The file names for the objects can be hard-coded in the program but this should be done in such a way that it would be easy and obvious how to change them.

As in assignment 2, you will be using lines on this assignment rather than filled polygons for all of the objects on the screen. For a large landscape this means there could be many confusing lines on the screen. In assignment 4 we will use filled polygons and z-buffering to get around this problem, but for now on this assignment when you draw an object, you will progressively darken the colour of objects that are further away. That is, all objects within 100 meters of you are their given colour, all objects 2000 meters away from you are coloured black, and inbetween you linearly darken the colour appropriatly. Later on we will see how fog can be used to do this automatically but here you will be doing it manually. Note that this means that depending on the order that you draw the scene you may have black lines drawn on top of your coloured lines - which looks funky, but again we will solve this problem in assignment 4.

The user will control their craft using the IJLAZ keys:

• I - move forward (horizontally)
• J - rotate to the left
• L - rotate to the right
• A - move upwards
• Z - move downwards

The craft will start out at the position defined by the 'X' in the objects.txt file facing North (towards the top of the datafile) at a height 10 meters above the landscape height at that point. You should make sure that the user's craft doesnt leave the periphery, and doesnt go through the land moving either horizontally or vertically. The craft can just stop at the edge; it doesnt need to bounce as in the previous two assignments Since the craft can not move backwards, or strafe left or right, this should make collicion detection easier. The ship should move smootlhly and turn smoothly (that is it should not move square by square, or turn in 90 degree increments). In this assignment the craft is allowed to move through the cubes andy the pyramids on the surface.

The shell for this program is slightly different than that from the previous assignments. The major difference is that we are replacing the call to gluOrtho2D(LEFT_EDGE, RIGHT_EDGE, BOTTOM_EDGE, TOP_EDGE); which was at the beginning of the main function with a call to gluPerspective(60, 1, 1, 10000); which sits in the display function. gluPerspective specifies the field of view in degrees, the aspect ratio, and the near and far clipping planes. On the first two assignments the camera did not move through the scene - it remained stationary though the scene was dynamically changing. On this assignment we will be keeping the scene constant but moving the camera a lot. We will use gluLookAt() for this. gluPerspective gives the parameters of the camera defining its field of view; gluLookAt tells openGL where the camera is located and what direction it is pointed. It takes 9 floats as parameters. The first 3 are X, Y, Z of the camera's location. The second 3 are X, Y, Z of the point the camera is pointed at. The third 3 is a vector defining the 'up' direction. In the case of this assignment the first triple is where the user is located on the landscape, the second triple should be computed to be a point directly in the line of sight of the user, and the third triple is 0, 0, 1 setting +Z to be up (which is different than what shell3.c is set up to do.)

So at the beginning of each loop through the display function you should call:
gluPerspective()
gluLookAt()

to set up the correct view before drawing the scene.

For example, take a look at the new shell3.c file. When you compile and run this program the result will look a lot like what you saw with the first shell program, except for the background colour being blue here. But whereas the first shell had an orthographic projection of a 2D world, this one has a perspective projection on a 3D world - in this case the same world with a multicoloured triangle bouncing left to right across the screen.

If you look at the display function, you will see the following lines near the top which set the correct camera postion for each frame. Whenever the camera moves, gluLookAt needs to be updated, and since we will be moving the camera alot, we will just automatically reset the view each frame. Similar calls were made at the top of the main function before - you will notice they are not there anymore.

glMatrixMode(GL_PROJECTION);

gluPerspective(60, 1, 1, 10000);
gluLookAt(0, 0, 350, 0, 0, 0, 0, 1, 0);

glClearColor(0.0, 0.0, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT);

I would suggest taking some time and understanding why the new shell3 gives you a similar view to what you saw in shell1, though its done in a very different way. I would also suggest playing with the parameters to gluPerspective and gluLookAt in this exampe to see what affect they have on what is displayed on the screen.

You should set the user's movement speed and turning speed to some appropriate value for moving over the landscape on the O2s. As with the first two assignments, the update rate of the data will be separate from the update rate of the graphics (which will remain at a maximum of 20 frames per second.)

Your program should be well commented and be a good example of literate programming.

As with assignments 1 and 2, your program will be submitted electronically and you need to be sure that it compiles and runs on the SGI O2s in the CS lab.

As usual, I would suggest you get the program to work in sections. First I would deal with reading in a data file for a simple landscape with just the terrain. Then deal with moving over the terrain. Then deal with loading in the data file for the objects and drawing the objects on the landscape. After that deal with the collision detection routines.

Again, I would also highly recommend that you understand the code you are writing - you never know when you might need to reproduce it (hint hint).

I would also suggest that you take this opportunity to play with changing the parameters of the camera and seeing the affect those parameters have on the scene.