# CMSC 435/634: Introduction to Computer Graphics

## Assignment 3 Viewing Due October 18, 2006

Fri Sep 29 14:34 EDT 2006

### Assignment Overview

For this assignment, you will be modifying your last assignment to drive a vehicle around on your random planetoid. You will replace the former parallel projection with a perspective projection from the point of view of a person sitting in a vehicle approximately 1 meter above the ground. You will also replace the mouse motion handler with a new one that maps horizontal mouse motion to looking left and right and vertical mouse motion to speeding up and slowing down your vehicle speed. The view should tip to align with the landscape as you move. You are free to start at any location you choose on the planetoid (so you can assume you know the starting triangle if that makes things easier for you), but you should not constrain the user's ability to drive around the planetoid in any way.

### 634 required

Include a mode with a third-person perspective viewpoint slightly above and behind your vehicle. When in this mode, you should render a simple model of your vehicle on the landscape. Allow a user to toggle between this mode and the vehicle point of view mode with the 'v' key.

### Extra credit (for everyone)

Write up a short proposal for how your project could be extended into a submission for the Hidden Agenda contest (www.hiddenagenda.com). This contest is for games designed by college students to be both fun and educational for middle-school students. If you try for the extra credit, be sure to read all of the contest rules. Submit your proposal as a a text file named game.txt in your assignment directory. You should specifically tell us how the game will be played, and which of the approved subjects your game would teach and how. Unlike the assignment, the contest allows the use of specific additional game development tools, as well as a team of up to eight. How would you extend and partition your project to use these additional resources?

### Project Details

To figure out the position of your vehicle and the up-vector for the view, you will first need to figure out which triangle you are in. The basic operation you will need is a point in spherical triangle test. Whatever radius is used for the triangle vertices, the triangle is always guaranteed to cap a triangluar wedge from the center of the sphere. You can tell if a point is in this wedge, and therefore in the triangle, by evaluating the plane equations for the sides of the wedge. Each side plane is defined by the origin and two of the triangle vertices. If your location passes all three plane equations, you know you are inside that triangle.

 V0×V1 • P ≥ 0 V1×V2 • P ≥ 0 V2×V0 • P ≥ 0

There are two alternate ways to use this test to find your location. The first is to update your 'current triangle' incrementally whenever one of the plane equations has the wrong sign. Since it is possible to move across multiple triangles in a frame (especially if you leave a triangle at or one of its vertices), you should keep updating until you have found the final triangle containing the new position. The second method is to first find the top-level octahedron triangle containing the viewpoint, then recursively apply the triangle test to find which of the four subtriangles contain the viewpoint until you get to the smallest triangles for the current level of subdivision.

Once you know which triangle your vehicle is sitting on, you will need to construct barycentric coordinates for your position in the triangle (see section 2.11 in the book), and interpolate the per-vertex positions to find your location, and the per-vertex normals to find your up vector. Perspective projection should be applied in the OpenGL projection matrix stack (glMatrixMode(GL_PROJECTION)), while viewing transformations should be applied in the OpenGL model/view matrix stack (glMatrixMode(GL_MODELVIEW)). It is probably easiest to move the view matrix setup into your draw function and just update state in your motion function.

You make continuous motion by making changes each frame then redrawing. Normally, GLUT only calls your draw function if something it knows about changes. However, if you call glutPostRedisplay() inside your draw function, it will cause GLUT to call your draw function again for a new frame as soon as the current frame is complete (the mouse motion handler already does this to force a redraw when the mouse moves). To animate continuous motion, decide your speed in meters per second, figure out how much time has elapsed using gettimeofday(), then move your viewpoint an appropriate distance forward and adjust the position and view to remain on the surface.

### Strategy

Plan ahead! Know how you're going to find the position and view vector. Once you have a plan, implement in stages that each produce a visible result. While it is not part of the assigned project, it may also be useful to set up extra keys to show debugging results. For example, a key that switches from the perspective view to an 'assignment 2' view with the vehicle triangle marked in a different color or vehicle postion marked by a glutSolidSphere could be helpful if you are having trouble debugging your position code.

If your assignment 2 did not work, you can get a working sample version from me after you have turned in your final version of assignment 2. However, I would encourage you to start from your own assignment 2 code if at all possible. Problems with your assignment 2 will not count against your assignment 3 grade, but you should at least have some landscape height and smooth per-vertex normals.

You may find the following OpenGL calls helpful to complete the assignment:

• Reset the current matrix to a 4x4 identity matrix: glLoadIdentity()
• Set up perspective: glFrustum(left, right, bottom, top, near, far) or gluPerspective(fov,aspect,near,far)
• Look-at transform from point eye to center point, with up vector projecting vertically on the screen: gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ)
• Translate: glTranslatef(x,y,z)
• Rotate around an axis through the origin: glRotatef(degrees, axis_x, axis_y, axis_z)
• Apply an arbitrary 4x4 transformation matrix: glMultMatrix(matrix)
• Push and pop matrix state: glPushMatrix(), glPopMatrix()
• Draw several common shapes: glutSolidSphere, glutSolidCone, glutSolidCube, glutSolidTorus, glutSolidTetrahedron, glutSolidOctahedron, glutSolidIcosahedron, glutSolidDodecahedron, glutSolidTeapot