CS 148: Introductory to Computer Graphics

Final Assignment: It's time for fun and Games!


Due Dates:

Checkpoint 1  Tuesday, Aug 1, 2000
Checkpoint 2 Tuesday, Aug 7, 2000
Due:  Friday, Aug 11, 2000
On Friday, at the scheduled final time, there will be a demo in Sweet Hall of your game.
All team members are requested to be at the demo. You will get a chance to show off what
you did, and play other people's games.
There are absolutly NO LATE DAYS on this assignment.
Introduction

Throughout the quarter we explored different algorithms that are used in modeling, rendering and displaying. You will be asked to put your knowledge to the test while writing a simple 3D video game in openGL. As in some previous assignments, this result will be an interactive program: you will need to process different input events from the user (this includes BOTH mouse and keyboard input) while simultaneously simulating the events occurring in the game. This assignment will also give you a chance to show us how much you've learned about basic raster graphics techniques. You are required to use the OpenGL system for this assignment.

For purposes of this project, we consider a 3D video game to be an interactive 3D computer graphics application which has some goal and incorporates some concept of scoring or winning and losing. It is not required that your game idea be original. Definitely prioritize functionality over originality. If you have any questions about whether your idea meets the criteria for a 3D video game, please email cs48-help@cs.stanford.edu.

You are permitted (and encouraged) to form teams of 2-3 people and partition the work among the team members. The work expected from each team will be proportional to the size of the team. You can use the class newsgroup su.class.cs148 to find prospective team members.

Requirements

The bare basics (that everyone MUST implement) are as follows:

Groups of two must implement all of the above plus:
  • Texture mapping. You must implement texture mapping for at least one of the 3D objects in your video game. In its most common form, texture mapping applies a detailed 2D image or pattern to 3D geometric    primitives. Texture mapping is used extensively in modern 3D video games to improve graphic realism.    Chapter 9 of the OpenGL Programming Guide describes how to implement a variety of texturing   techniques. There's a caveat to this: texture mapping takes a long time to render, so be careful what object you choose to have texture mapped, and use the information in the book to optimize this rendering.
  • one of the following:
  • Procedural and physically-based modeling. In addition to using scanned or hand-modeled objects to   populate the 3D worlds, some video games use procedurally computed models. In class on 7/27 we discussed one such example (the sierpinski pyramid). Chapter 20 of the textbook    describes examples of procedural modeling, including fractally-generated mountainous terrains and L-grammars for generating models of plants. Procedurally generated textures may be used to simulate  effects such as fire, smoke, and clouds.
  • Parametric curved surfaces. OpenGL can directly display only simple convex polygons; however, you might create a 3D model for your video game which includes smoothly curved surfaces represented mathematically by a small number of parameters. This was also discussed (not in great detail, though) on 7/27. Chapter 12 of the OpenGL Programming Guide describes how to represent and manage the display of smooth surfaces such as NURBS. Be wary about performance if you use NURBS in OpenGL; use them judiciously.
  • one of these two culling methodologies:
  • View frustum culling. In video games with complex 3D environments, it is necessary to limit the number of 3D primitives drawn each frame in order to maintain interactive rendering rates. One way to do this is to avoid drawing any 3D objects which are outside of the viewing frustum of the camera. You can pre-compute rough bounding volumes for hierarchical objects or parts of your 3D world, and then test each bounding volume to verify that some part of it intersects the view frustum before drawing its contained objects each frame.
  • Occlusion culling. Yet another way to maintain good game performance with complex environments is by performing occlusion culling. Similar to view frustum culling, this technique involves using a conservative computation to avoid drawing any parts of the 3D scene which won't be seen by the viewer because they are hidden behind other objects. For static environments such as buildings, you might pre-compute which regions of space (such as rooms) are impossible to see from other regions (due to occluding walls, for example). (Don't confuse occlusion culling with simple hidden-surface removal, which is required for your video game.)
  • Implement a PAUSE using the keyboard.
  • Groups of three must implement all of the above plus:
  • On-screen control panel. Many 3D video games reserve part of the display area for an on-screen control panel, which may include text or 2D graphical elements for user controls, scoreboards, etc. Flight  simulator games often use 2D graphical overlays on the 3D world for "Heads Up Displays (HUDs)." You can implement a control panel for your game using a variety of techniques in OpenGL, such as orthographic projection and the stencil buffer. Text primitives are not explicitly supported with OpenGL, but GLUT   provides commands to help render text strings.
  • Level of detail control. Another way to limit the number of 3D primitives drawn each frame is to implement level of detail (LOD) control in your game. One simple method of LOD control involves creating multiple versions of some of your 3D objects, varying in geometric complexity (such as 10, 100, and 1000 polygons). Then, before drawing the objects each frame, you can pick the most appropriate version of the object to render, depending on such metrics as the distance of the object from the viewer, the complexity of the current scene, or a user-selectable detail level.
  • Multipass rendering effects. OpenGL makes it possible to easily implement a wide variety of realistic rendering effects. Many of these effects can be achieved by drawing the scene multiple times for each     frame, varying one or more parameters each pass through the scene. Examples of such effects include soft    shadows, full scene antialiasing, motion blur, depth of field, bump-mapping, reflections, refractions, and    compositing. Good sources of information on implementing these and other effects are in Chapters 10 and 14 of the OpenGL Programming Guide, and in the OpenGL tutorials available on the Web.
  • Beyond this, there are extras for which you can get extra credit:
  • Hierarchical Scene Graph. Many 3D graphics applications maintain their constituent objects and sub-objects in a tree-like data structure called a hierarchical scene graph. The scene graph provides a logical organization for the objects in the 3D world, and allows for efficient constructs and operations such as instancing, hierarchical transforms, nested bounding volumes, and traversals of the scene graph for rendering or collision detection. 
  • Simulated dynamics. Your video game implementation might include modeling dynamic behaviors and  physics for objects in the 3D world. For example, the wheels of a vehicle might react realistically as they move over rough terrain, or a door might swing open differently depending on the force exerted by the player.
  • Advanced image-based techniques. In an effort to increase graphical realism and maintain fast performance, many video games mix traditional 3D graphics rendering with 2D image-based graphics. Although 2D texture mapping is an example of a basic image-based technique, more advanced techniques such as environment mapping, billboarding, and projective textures are possible. Other ideas for image-based techniques include precomputing multiple 2D images ("sprites") of a object from different orientations, and then choosing the most appropriate sprite to warp and render in the 3D scene.
  • Sound.- I do not recommend trying this. I did include some pointers to relevant documentation and sample sound effects- only for the hardy.
  • AI. Some video games include computer-controlled agents that require a significant degree of artificial intelligence. Many of the techniques taught in a basic AI course are applicable to video game development, and some links to more detailed information on game AI are included on the course Web page for the assignment. If you have any doubts about whether a technique you are using qualifies as "AI" for this assignment, ask us.
  • Game Design

    The first thing I'd like to say is: Don't overdo it on the game idea!

    Unless you'd really like to, you do NOT have to come up with a whole new game idea. Though Tetris is not allowed (no collision detection, not 3D), you are free to reproduce an existing video game. You have just two weeks to complete this assignment, so you must be realistic and set yourself some realistic goals. We do not expect to see Dune. We're looking for functionality and reasonable speed. I would recommend taking a known 2D game and making it 3D. To get some ideas, you might want to think along the lines of some of the following:
    <suggestions came from Pat Hanrahan>

  • 3D Space Invaders - In the 2D  version, the player moves a rocket launcher horizontally along the bottom of the screen, shooting missiles at rows of enemy ships that descend from above. When a missile hits an alien ship, both disintegrate. The ship rows move back and forth, and each time they switch direction they move downward. If a ship lands, the game is over. The ships also drop bombs periodically that fall towards the ground. If a bomb hits the rocket launcher, that round of the game is over. (This is similar to the game Missile Command.) The 3D versions would have the player's view from below (as the launcher) with the alien ships approaching you straight ahead. Shooting at them would have the same effect as before, only you'll have to show them exploding in 3D.
  • Asteroid - Asteroids is a simple game where you pilot a spaceship in an asteroid field, shooting asteroids to destroy them before they collide with you. Larger asteroids break into smaller asteroids as you shoot them. The smallest asteroids are simply destroyed when shot. You have a limited amount of sheild power to protect you from asteroids. If you are in a real fix, you can jump into "hyperspace" to get you out of a tight spot. In 3D, the ships are coming at you, and are shooting spherical objects at you.
  • Brickles- The player controls a rectangular paddle which can be moved in any direction on the screen to catch a ball that is reflected off the paddle and the wall (made of bricks). You can make the objective to get the ball to go into a certain goal on the wall, or to get the ball to hit every brick (you can either make the bricks disappear, or color them in a new color). The ball bounces off of the paddle and the walls and has a constant speed. You may want to have multiple goals and balls (maybe of different speeds and sizes) to make it more interesting.
  • Your game should be highly interactive; that is, your program should be constantly redrawing to generate moving objects, and requiring continuous input by the user or game player. By these criteria you should avoid card and board games. If you're at a total loss as to what to do, implement Astroids. It's a good starter game, and it is not difficult to get the basic functionality to work out. You can always add functionality and glitz.

    The last thing I'd like to say is: Don't overdo it on the game idea!

    Helpful Hints

    (1)

    This, again, is a more open ended assignment. You are expected to show me that all that assigned reading in the books did not go for not.  In order to assist and inspire you, There are a number of links that I want to point you to:
    http://www-cse.stanford.edu/class/cs148/links.html
    This page includes pointers to OpenGL tutorials, information on game development, useful utility programs, and sources for 3D models and other game content. Of course, you are responsible for understanding and implementing your own video game code. The policy I held last time about borrowing code is modified here a bit: you cannot take someone else's game and call it your own. You are allowed to look at other code with the functionality you are interested in, and copy at most a function or two (you must cite them as well). If you are concerned about breaching this rule, you can ask us. But generally, if you're concerned that you may be copying too much, you probably are.
    Please take advantage of the opportunity to consult us with questions concerning development of your particular video game. If there are computer graphics techniques not covered in the course that you would like to implement,we will usually be able to point you to an appropriate source of information.

    (2)
    Interactive 3D graphics programs such as video games place special demands on computer hardware. If your 3D world is particularly large or complex, or if you use certain OpenGL rendering features (such as texture mapping), you will probably need special graphics hardware in order to get real-time performance. Note that the SGI machines in Sweet Hall do not implement texture mapping in graphics hardware, so games making intensive use of texturing will suffer performance limitations on these systems. Modern PC  systems with fast 3D graphics accelerator cards will usually yield better texturing performance than the SGI machines in Sweet Hall. If you develop your game on multiple platforms, it will probably be useful to add options to disable expensive features (such as texturing) on request. The performance of your video game is important, so do not implement too many expensive rendering features if the gameplay is negatively impacted! There are some pointers on the Web page above to sources of information on maximizing OpenGL performance.


    (3)
    Most successful video games include richly detailed 3D models, textures, sounds, and other content for representing the game world and characters. You have several options available in creating the 3D models for your video game:
     

  • Simple models can be sketched on graph paper, and the coordinates manually typed into your source code.
  • Models can be procedurally generated, as mentioned above.
  • You can use a 3D modeling package and export the model in a format your program can read. The  links Web page  above will  contain pointers to several freely available modeling packages.
  • The GLUT library provides functions for drawing a few simple 3D shapes (sphere, cube, teapot, etc.)
  • You can find a wide variety of 3D models available on the Web (see the pointers on the assignment Web page). These may need to be converted to a format your program can use.

  • (4)
    In the course of designing and implementing your video game, keep in mind that CS148 is a computer graphics course. Focus your efforts on the computer graphics techniques underlying the game; don't spend the majority of your time on game design or object modeling if the graphics engine will suffer as a result! I'm not penalizing here for lack of originality- and functionality, at the end, is what counts (note that functionality does include efficiency in this case)

    (5)
    You are free to develop your video game on any computer platform that supports OpenGL, provided that you will be able to demonstrate your program at the required demonstration periods at Sweet Hall. If your program cannot run on the Sweet Hall elaine machines, you will be responsible for bringing a system on which to run your video game. You can collaborate with other groups in different demo time slots to bring a PC. Versions of OpenGL for most common computing platforms are available for download at sites pointed at from the links Web page, and the code Web page.

    To keep things simple, our recommendation is to develop your video game on the Sweet Hall Sun or SGI system. As you know by now, OpenGL is window system independent, so an additional toolkit is necessary to provide the necessary windowing and input event management; for this we recommend using the GLUT package. GLUT is used for all the examples in recent editions of the OpenGL Programming Guide, and is available for most all common computing platforms.

    Due Dates

    The first checkpoint will be on Tuesday, Aug 1st. On that date, before 5pm, please email us  (cs148-help@cs.stanford.edu) a short HTML file in which you tell us  your group name, who is in your group, division of labor (who's in charge of what), and a description of the game plan. In the description, please include the game objectives, the player's interaction (what actions cause what to happen in the game), a description of the 3D scene in which the game will take place, and a description of what objects move in the game.

    The second checkpoint will be on Tuesday, Aug 7th. On that date, you are asked to submit, or demo for me in person (at my office hours 8-11pm in Sweet Hall), the preliminary scene rednering with viewpoint change. Though you should already have some interaction working in this environment by this time, I just want to make sure that you aren't straggling. You should aim to have your entire scene draw, and animate any of the motion that will take place in the scene. This means that an Astroid-like game should have the enemy ships flying by. I do not expect to interact with your environment at this time, but some sort of motion about the scene is expected. I.e., I would like to change the viewpoint (to see that your 3D objects are rendering properly).

    Submission and demonstration will take place on Friday, Aug 11th. We will have a project demo in Sweet Hall. You will present what you did (3-5 min. talk of the features and the ideas), and demonstrate your game. The class will go from station to station to see the different projects. If things go according to plan, we will have two people from the gaming industry come to see your game, and give you their input (if you'd like).

    We will recompile your program and then attempt to play the game. Your grade will be based on the following criteria: 80% for implementing the functionality that we request, and 20% for the quality of the ``game play.'' Game play covers such factors as the overall refresh rate and interactivity, the aesthetics of the game (aliasing, etc), no annoying flickering, etc. Be forewarned, we will dock up to 10%, if your submission cannot be recompiled and executed. Please make sure that the instructions are clear on how to play the game. When you submit, call this program 4 (when you are prompted for it), and include the README just as you have in the past. In the README you must also specify who did what. You need only make one submission per group (it doesn't matter from whose account).


    QA: (some questions from past students):
     

    Q1. I am running the sample games from the remote SGI, but I am getting this error message:
    Warning: Attempt to call OpenGL function prior to calling glXMakeCurrent()
    Q2. Can I implement TETRIS for assignment 1?
    Q3. I would like to use images in my game. How can I do this?
    Q4. What do I do to start?
    Q5. Do I have to use both the mouse and keyboard?
    Q6. How can I have one of my functions called at a fixed time interval?
    Q7. My screen is flickering. How can I prevent this?
    Q8. What do glOrtho() and glViewport() do?
    Q9. What is the difference between glFlush() and glFinish()? (a.k.a.: Why is my program so slow?)
    Q10. How can I add sound to my program? note: I do not recommend this
    Q11. What do I need to do to use C++ with OpenGL?
    Q12. How can I disable or redefine a key- or mouse-button hander?

    Answers

    Q1. I am running the sample games from the remote SGI, but I am getting an error message. What is wrong?

     A1. Here's a checklist to follow. For this checklist, I will assume that you are logged on raptor13.stanford.edu from the machine jitter.stanford.edu, and you want to have your display shown on jitter.stanford.edu.

    1. Make sure jitter.stanford.edu has X11 and OpenGL. This can be accomplished by checking to see if /usr/lib/libX11* and /usr/lib/libGL* exist on jitter.stanford.edu.
    2. Make sure the DISPLAY environmental variable on raptor13.stanford.edu is set to "jitter.stanford.edu:0.0". This can be checked by typing "echo $DISPLAY". If your DISPLAY is set wrong, or else not set at all, you can set it by typing: "setenv DISPLAY jitter.stanford.edu:0.0".
    3. Make sure jitter.stanford.edu can accept X11/OpenGL commands from remote machines. This can be done by typing "xhost +" on jitter.stanford.edu.

    Q2. Can I implement TETRIS for assignment 1?

     A2. You may not implement TETRIS for this assignment: Implementing TETRIS has been an assignment for CS193D, a very popular Stanford class, and thus there is the possibility of encouraging honor code violations (code reuse for different classes).


    Q3. I would like to use images in my game. How can I do this?

     A3. To avoid writing code to read/write GIF files, use the public domain PBMPLUS (NETPBM) image libraries for I/O. These have also traditionally been available in

     /usr/class/cs248/netpbm

     We provide no support whatsoever for the NETPBM image libraries: they're just copied from the leland file system for your convenience (and to save you disk space).

     Once the image is in memory, you can write the image directly to the framebuffer using the routines discussed on page 237ff of the openGL programming guide. You could also paste the image onto some geometry using the texture mapping facilities of openGL; see chapter 9.


    Q4. What do I do to start?

    First, find (a) project partner(s) that you can work with (this means that your schedules match, you generally work at similar hours, can physically see eachother once in a while, and may also have some complementary skills).
    Second, discuss what you would like to implement, and write up the document for checkpoint 1.
    Third, choose a language you are all comfortable with.
    Forth, design the scene in details. For the second checkpoint, I want to see the fully integrated scene. You do not have to have the user interactions working completely by that point, but I should be able to move about the scene (or have some alien spaceships whizz past me).


    Q5. Do I have to use both the mouse and keyboard?

    A5. Yes - even if it means that one of them does something simple or silly. It's useful, though to have the mouse take care of the continuous input (like moving about the scene) where keyoard can control the discrete interactions (shoot, jump, throw, release, whatever single-point action you can think of).


    Q6. How can I have one of my functions called at a fixed time interval?

     A6. The auxilliary library won't do this. If you want to get objects to move at a constant rate, regardless of the speed of the underlying processor or the complexity of the scene you are drawing, then base the motions of your objects on gettimeofday(). See its man page for details on how to use it.


    Q7. My screen is flickering. How can I prevent this?

     A7. Use double buffering. Simply calling auxSwapBuffers() is not enough to make your program use double buffering. You must also ensure that you are calling auxInitDisplayMode() with AUX_DOUBLE as an argument, rather than AUX_SINGLE.
     
     


    Q8. What do glOrtho() and glViewport() do?

     A8. glOrtho(left, right, bottom, top, back, front) define the clipping frustum. Let us ignore back and front right for this assignment, since they refer to the Z value. By doing this call, first you specify that anything outside of the rectangle defined by left, right, bottom, and top is clipped because it is outside the drawing region. Furthermore, you define a scale for your coordinate system.

    If you have glOrtho(0, width, 0, height, -1, 1), then you are saying that your drawing area goes from (0, 0) to (width, height). To get the point in the middle of your drawing area, you should specify it with glVertex(w/2, h/2).

    Let's say, however, that you specify glOrtho(-1, 1, -1, 1, -1, 1). This means that the left side of your drawing region corresponds to -1, the right side of your drawing region corresponds to 1, the bottom of your drawing region corresponds to -1, and the top of your drawing region corresponds to 1. Now if you want a point in the middle of your drawing area, you should specify it with glVertex(0,0).

    glViewport(x, y, w, h) specifies the area of the window that the drawing region should be put into. It says that the bottom left corner of the drawing region corresponds to the window's (x, y) pixel, and (w, h) represent the number of pixels the drawing region should go in each direction. So if you wanted your drawing to go only into the bottom right quarter of your window, you would call glViewport(winWidth/2, 0, winWidth/2, winHeight/2). But typically, you want glViewport(0, 0, winWidth, winHeight) in order to cover the whole window.


    Q9. What is the difference between glFlush() and glFinish()? (a.k.a.: Why is my program so slow?)

     A9. glFlush() guarantees that all the GL calls made up to that point will complete execution in a finite amount of time after glFlush() returns, but doesn't specify exactly how soon after. glFinish() guarantees that all GL calls made up to that point will complete execution before glFinish() returns.

    So why do you care? If inside your redraw function you draw and then call glFlush(), then GL can queue up any number of drawing commands. What can happen is that your redraw function gets called 100 times (via your idle fuction, which in turn is called repeatedly when no events are pending), each time returning before the drawing is complete. Thus, you have 100 frames that have been submitted to GL, but not finished, and then you receive a keyboard/mouse event. Once you process that event, you will probably want to change your drawing. So you send the next frame, which is frame 101, and you have to wait for GL to do 100 frames before you get the frame resulting from your event. Hence, there is a big lag between the occurence of an event and drawing of it.

    To avoid this, you should use glFinish() so that the redraw function does not return until the drawing has finished. 


    Q10. How can I add sound to my program?

     A10. To simply play audio files from the command line, use playaiff, playaifc, or sfplay. To convert audio files between different formats, use sox. To play audio from your code, without using fork() and exec() to invoke one of the executables above, you have to suffer a bit...

    None of the raptors running IRIX 5.2 have the digital media development environment dmedia installed on them; dmedia includes man pages, such as the ones above, libraries, include files, sample code, etc. that allow your code to play sound. Hence, incorporating audio in your code is virtually impossible if you are developping on a raptor running IRIX 5.2. By contrast, the new machines, as well as those raptors upgraded to IRIX 5.3, will have dmedia installed on them.

    But even if you have access to a platform with dmedia, we still advise against putting time into adding audio to your game; instead, experiment more with the graphics. Finally, if you do decide to go ahead, type insight, and read part two of the IRIS Digital Media Programming Guide


    Q11. What do I need to do to use C++ with OpenGL?

     Nothing, really. C++ and OpenGL are fully compatible. However, pay attention to the following:


    Q12. How can I disable or redefine a key- or mouse-button hander?

     A12. This is not possible using the auxiliary library. Calling auxKeyDownFunc() repeatedly simply adds additional handlers for that event. When that event occurs, all of the handlers will get called. Attempting to disable the handler by calling auxKeyDownFunc() with a 0 or NULL second parameter will cause a segmentation fault (it simply adds this 0 to the table, and tries to call the function located at address 0).