Valley Flight 2000 by Yi-Ren Ng **Runs on: Raptors **How to play: The aim of the game is to fly through the hoops as quickly as possible. Flying through hoops garners you points: more points the smaller the hoop is. Extra points for style. Well, not really more points for style, but you can imagine that and the game is even better. You must pass through the ring to get the points; colliding with the ring gets you no points and slows you down. The time ticks away in the top left corner. The speed meter is in the lower right corner, and the current score is next to the meter. Clicking and dragging in the window changes direction of plane. Left and right are as you would expect; drag-up causes plane to pitch forward, drag- down causes plane to pitch backward. A-button accelerates. S-button decelerates. V-button switches between three viewpoints. The default viewpoint stays at a fixed distance behind the plane. The second viewpoint is a "long-shot", with the camera flyinn down the center of the valley -- beware that in this view the plane may not be visible if you are flying too close to the edge of the valley; however, this view best shows of the realistic dynamics of the plane, and often shows the best reflection of the plane in the water.) The third viewpoint is from the pilot's perspective. Resizing the window to be very large on the Raptors works well if texture mapping is off. Various features: 1-button: Toggles the visibility of the scoreboard on/off 2-button: Toggles reflections on/off 3-button: Toggles TEXTURE MAPPING on/off 4-button: Toggles antialiasing of the scoreboard on/off It looks coolest with everything turned on, but on the raptors you can't really play it with texture-mapping, because the frame rate will be too slow. Playing with reflections is okay, but on a busy raptor it might be best to turn everything off for high frame rates. P-button pauses the game. A cheat is the 0-button, which stops the plane -- this is a good way to decelerate very quickly to catch a hoop. [Also, if you change the viewpoint to be the pilot's viewpoint, hit 0, then fly at the water, you can watch your reflection flying really fast straight at you. It's cool.] **Optional Assignment Requirements 1. On-screen control panel. The control panel shows the time, score and velocity. It is implemented with a combination of bitmap-drawing and polygons under an orthographic projection. The numbers are a Helvetica font, rendered with Photoshop. The background of each digit image is used to calculate the appropriate alpha for the bitmap in OpenGL, so that the digits look smooth, and antialias appropriately to the background in the scene. This looks far superior to the glut font support methods. The speed bar is generated with a circular parametric equation, drawn to the screen under an orthographic projection that is scaled to pixels -- this ensures that the speed bar looks the same size no matter the size of the screen. 2. View frustum culling. The most complex objects in the scene are the rings, which are spaced far apart. As the first step in keeping rendering rates interactive, the rings are culled from the scene before rendering if they are not within the viewing frustum. The check is made by testing for intersection between the bounding box of each ring and the frustum. The valley walls were not culled because they are relatively simple geometrically, and did not significantly alter the rendering time when absent -- this suggested that frustum culling in that case would not be of any benefit. 3. Level of detail control. As the second step in keeping rendering rates interactive, the level of detail of the rings was modified depending on the viewing distance. There are three levels of detail, precomputed and stored in display lists. Up close, the rings are rendered with a high number of polygons, and far away, they are approximated by pentagon-shaped polyhedrons with a much lower polygon count. 4. Procedural modelling. The valley walls are generated completely with functions. The degrees of freedom to generate the walls are defined parametrically. The parameter is the distance from the start of the flight path, scaled to the range t = [0,1]. The first degree of freedom is the shape of the flight path itself, (x, y, z) = f(t). The second degree of freedom is the perpendicular distance from the flight path to the walls of the valley r(t) = distance to right wall, l(t) = distance to left wall. The height of the valley walls h(t) = the height of the valley walls. Finally, the slope angle of the walls is a degree of freedom. theta(t) determines how steep the walls of the valley are. Each of these is a function, either in valley.cc, or flightpath.cc, so it is very easy to completely change the shape of the valley, just by changing the functions in these locations. The code is built in abstract classes, so new subclasses could easily be defined for additional, different levels -- I didn't have time to do this. 5. Collision detection Collision detection is perfermed between the plane, the walls of the valley, and of course the rings. The rings are most interesting, so I'll describe those first. The rings are represented by a perpendicular (x,y) displacement from the flight-path. As the plane passes each ring, it is checked whether the plane collided with it, missed it, or passed through it. The corners of the plane's bounding box are tested to see whether they enter the inner and outer radii of each ring that was passed. If any corner passed through the outer ring, the plane either passed through the ring, or collided with it (otherwise the plane missed the ring completely). To pass through the ring, each corner of the plane's bounding box must pass through the inner loop of the ring. If the plane passes through the ring, points are scored. If the plane collides with the ring, it is slowed down, thrown off in an odd direction, and the screen flashes red. Note that even if the plane is going very fast, it is tested for collision with every ring that is passed. The sides of the valley define where the plane can be. Thus, given the parametrization of the valley as described in 4. above, as the plane moves, its "desired position" is compared to the valley-volume, and the "actual" position of the plane is clamped so that it is within the volume. In this way, the plane collides with the sides of the valley, and cannot pass through them (note that in some viewpoints the camera can temporarily be outside the valley, but the plane is still within the valley.) 6. Simulated dynamics The plane obeys Newtonian physics, except for gravity. The velocity vector for the plane is carefully tracked so that the plane faces in the direction that it is moving -- this is evident in all three viewpoints, but perhaps most clearly in the "long-shot" viewpoint. Furthermore, the plane banks at an appropriate angle when it is going around a bend in the flight path -- you can see this best by going into a long shot view (v-button), then moving the plane near the water, accelerating (do this reasonably quickly). As it goes around a bend, it will bank. The physics for banking are as follows: the plane is assumed to have a lift vector. To go around a corner, it needs a perpendicular acceleration. Thus, the plane should tilt at the appropriate angle so that the component of the lift vector that is perpendicular to the direction of motion equals the required perpendicular acceleration. Solving this system determines the appropriate tilt of the plane. (This was scaled by a constant, so that it looks good.) 7. Multipass rendering effects In order to give a stronger sense for where the hoops and plane are spatially, the entire scene is reflected in the water. This is done with the technique described in the reflectdino.c example in glut. Stencil buffer was not used; instead, the scene was carefully designed to be enclosed in such a way that the reflected scene would always be visible only through the reflected surface (that is, unlike the dino example, you cannot fly underneath the river to see that the scene has just been reflected and re-rendered.) There are three lights in the scene, and these are correctly reflected as well. In addition, the scoreboard speed meter was antialiased using the accumulation buffer and jittering. This is an option that can be turned on with the 4-button. To achieve reasonably (through still slow) rendering rates, only the bounding box of the speed meter is antialiased. The pixels for the underlying scene are copied out; then the speedmeter is rendered over it, erased with the underlying copied pixels, jittered and rerendered 8 times. Each time, the pixels are accumulated, and the average accumulated value is returned as an antialiased speed meter. **Game Content The plane was obtained from http://www.agfastudio.com/agfastudio/support/epic3d1.html The texture for the water is a sky-texture; unfortunately, I can't remember where I got it. **Resources I got the reflection code from reflectdino.c, modifying it to include all the components of my scene, as well as the lighting specific to my game environment. **Miscellaneous I had to spend a lot of time tuning sections of code, and eliminating excessive geometry in order to get the rendering rates interactive. This is one of the reasons why the valley walls are relatively untextured, although their global geometry is quite complex. **A description for the web page: Valley Flight 2000 simulates a scenic flight through a river canyon. The canyon walls are parametrically defined, and the motion of the plane is smooth and realistic. The entire scene is reflected in the textured river surface. Win points for flying through hoops, but don't crash into them!