Assignment 3: OpenGL
Due: 10/27/00 at 11:59PM.
Overview
This assignment serves as an intoduction to the OpenGL graphics library.
You will required to generate a city scene which can be viewed interactively.
Emphasis is placed upon the implemention of OpenGL's basic capabilities
(e.g. shading. lighting, transparency, materials properties, etc.), their
use in generating more involved effects (e.g. shadows, reflections), and
imagination in creating a city with a "mood" and interesting effects.
Examples
Samples of projects from previous years (they created a room) are available
here
and here.
Below are some images from one solution (click to enlarge):
|
|
|
Transparency on table top
Reflection in the floor
Multiple light sources
|
Specular lighting on balls
Shadows on the table surface
Lamp is dynamic light source
|
Texture mapping on board
Full scene antialiasing
Replicated objects
|
What you Have to Do
The assignment is worth 20 points. The following is a list of features
that you may implement. The number in parentheses corresponds to how many
points it is worth. Options in bold are mandatory.
-
(1) Implement the Camera::draw(void)
for a perspective camera.
-
(1) Implement the Shape::draw(int
cplx) methods for all classes derived from Shape (triangle, sphere,
cone, cylinder, box, line, group).
-
(1) Implement the Light::draw(int
lightNum) for all classes derived from Light (point, directional, spot).
-
(1) Implement the Material::draw(void)
method for materials.
-
(1) Implement the Texture::draw(void)
method for textures.
-
(1) Implement the Scene::draw(int
cplx) method to draw the scene from the Draw function.
It should update the appropriate camera,
lights, etc. for the current viewpoint and then draw the shapes.
-
(1) Construct a city scene with several buildings.
-
(1) Include several everyday objects (e.g., cars, street lights,
plants, etc.) in your scene.
-
(1) Include at least one object (e.g., a car) that is instanced
several times with different transformations.
-
(1) Include at least one transparent surface (e.g., a glass building).
-
(1) Include at least three texture mapped surfaces, each with a
different texture (e.g., street signs, brick building facades, etc.).
-
(1) Include at least three point or spot light sources (e.g., street
lights, car headlights).
-
(1) Include at least one animated object (e.g., a car moving along
a road, a clock on a bell tower, etc.)
-
(1) Implement interactive camera controls - the camera should move
around the exterior of the scene, looking into the scene from outside,
using a "crystal ball' style interface for the exterior viewing scheme.
When the user holds the left button, moving the mouse left and right should
rotate the world left and right about the world's origin, and moving up
and down should rotate the world up and down about its origin. If
the user hold the middle button, then moving the mouse up and down should
zoom toward and away from the origin. When the user holds both buttons
, moving the mouse should translate the world in a plane parallel to the
view plane. This should alter the origin for the previously mentioned rotations,
so you might add a control to reset the origin should the user end up in
a strange state.
-
(1) Implement a "walkthrough" mouse user interface to facilitate moving
about the interior of the scene. For instance, holding down the left (right)
mouse button could move forward (backward) and turn in the direction of
the mouse cursor (left if the mouse is on the left side of the screen,
etc.) by an amount proportional to the mouse cursors distance to the center
of the window. In this case, you should implement a method for toggling
between interior walkthrough and exterior crystal ball interactive navigation
schemes (e.g., a menu item or keyboard command).
-
(1) Include a four-component texture (e.g., for a tree or person), where
the fourth component, alpha, represents the opacity of the surface.
-
(1) Include a "billboard" - a textured polygon that continually rotates
to face the viewer (e.g., for a lamp post or a tree).
-
(1) Include an object that responds to user mouse clicks (such as a light
switch which turns on/off a light when clicked on by the user).
-
(1) Include a mirror surface in your scene. Hint: Reflect the world about
the mirror and render it again through a stencil buffer.
-
(1) Include a curved surface drawn with NURBS (e.g., a sprial building
like the Guggenheim Museum)
-
(1) Include an object drawn with environment mapping.
-
(2) Include an articulated object (e.g., a crane) with a hierarchy of parts
at least 3 deep (e.g., upper arm, lower arm, hand) that move under interactive
control by keyboard and/or mouse commands. Hint: see the robotic arm example
in the OpenGL Programming Guide.
-
(2) Implement view frustum culling to improve rendering speed. Check bounding
volumes stored in the scene hierarchy to see whether they lie at least
partially within the view frustum before drawing their contents.
You get a third point if you combine this feature with an adaptive method
for increasing the attenuation due to fog while decreasing the far plane
distance whenever the frame rate gets too low (this is a trick common in
video games).
-
(2) Implement adaptive levels of detail to improve rendering speed. Continuously
vary the complexity of tesselated surfaces depending upon the distance
of the viewer from the object. Hint: use this with GLU cones, spheres,
cylinders which take arguments for their complexity.
-
(2) Implement an animated texture on the surface of an object in the scene
(e.g. a video board as in Times Square).
-
(2) Implement drawing of shadows on at least one surface (such as the ground).
Hint: See the OpenGL Programming Guide for the transformation which renders
objects onto a plane.
-
(3) Implement back-to-front ordering of primitives suitable for drawing
more than one transparent object in your scene.
-
(3) Implement particle effects (e.g. steam from a sewer grate). Hint: Maybe
try rendering randomly moving, small triangles with a texture map of a
dot on them... Make sure the effect is convincing.
-
(?) Impress us with something we hadn't considered...
By implementing all the required features, you get 14 points. There are
many ways to get more points:
-
(as listed above) implementing optional features,
-
(1) submitting 3D models you constructed,
-
(1) submitting images for the art contest,
-
(1) submitting a .mpeg or .avi movie with a sequence of images captured
from a continuous camera path, and
-
(2) winning the art contest.
It is possible to get more than 20 points. However, after 20 points, each
point is divided by 2, and after 22 points, each point is divided by 4.
Getting Started
You should use the code available at /u/cs426/3/, on the MECA
machines, as a starting point for your assignment.
An overview of the code you will be using can be found here.
An overview of the .ray file syntax can be found here.
We provide you with:
-
rayView.[cpp/h] The code responsible for running the interactive
user interface.
-
shape.h The abstract base class that all shapes must implement
-
group.[cpp/h] Code for the Shape subclass describing a scene-graph
-
rayFileInstance.[cpp/h] Code for the Shape subclass describing
the scene graph specified in a .ray file
-
triangle.[cpp/h] Code for the Shape subclass describing a
triangle
-
sphere.[cpp/h] Code for the Shape subclass describing a sphere
-
cone.[cpp/h] Code for the Shape subclass describing a cone
-
cylinder.[cpp/h] Code for the Shape subclass describing a
cylinder
-
box.[cpp/h] Code for the Shape subclass describing a box
-
line.[cpp/h] Code for the Shape subclass describing a line
segment
-
light.[cpp/h] The abstract base class that all l ights must implement
-
pointLight.[cpp/h] Code for the
Light subclass describing
a point light
-
directionalLight.[cpp/h] Code for the Light subclass describing
a directional light
-
spotLight.[cpp/h] Code for the
Light subclass describing
a spot light
-
main.cpp This parses apart the command line arguments and invokes
the raytracer
-
scene.[cpp/h] Code for the classes that store environmental information,
textures, materials, rayFiles etc.
-
geometry.[cpp/h] Most of the code for the geometric manipulation
you will need (matrix multiplication, vector addition etc.)
-
boundingBox.[cpp/h] Code for defining bounding boxes.
-
bmp.[cpp/h] Code responsible for reading and writing BMP files
-
implemented.[cpp/h] Code defining a global flag that specifies if
unimplemented methods should announce themselves when they are invoked.
-
RayFiles/: Directory containing a variety of .ray files.
-
viewer.dsp: Project file suitable for Visual C++ on Windows 2000
platform.
-
Makefile: A Makefile suitable for UNIX platforms.
After you copy the provided files to your directory, the first thing to
do is compile the program.
If you are developing on a Windows NT machine, double click on viewer.dsp
and select build from the build menu.
If you are developing on a UNIX machine, type make.
In either case an executable called viewer (or viewer.exe)
will be created.
How the Program Works
The program takes in to mandatory arguments, the input (.ray) file name.
It is invoked from the command line with:
% viewer -src in.ray
Additionally, you can specify height, width, and tesselation complexity
(100-1000) as follows:
% viewer -src in.ray -width w -height h -cplx
c
What Has Not Been (Completely) Implemented
The sublcasess of Shape must implement the Shape::draw(int
cplx) method. The list for which this is not implemented is:
The sublcasess of Light must implement the Light::draw(int
lightNum) method. The list for which this is not implemented is:
Additionally, these draw methods must be implemented:
Finally, the following functions need to be implemented to support the
interactive user interface:
What to Submit
You should submit:
-
the complete source code with a Makefile,
-
any *.ray files you created (optional),
-
the .mpeg movie for the movie feature (optional),
-
the images for the art contest (optional), and
-
a writeup.
The writeup should be a HTML document called assignment3.html
which may include other documents or pictures. It should be brief, describing
what you have implemented, what works and what doesn't, how you created
the art contest images and/or movies, and any relavent instructions on
how to run your interface.
Make sure the source code compiles in the MECA
workstations. If it doesn't, you will have to attend to a grading session
with a TA, and your grade will suffer.
Always remember the late policy
and the collaboration
policy.
Links
OpenGL Information
OpenGL Information from SGI
OpenGL Specification
and Manual Pages
GLUT Information
GLUT Specification
GLUT
Sample Programs
Hints
-
Note that OpenGL uses degrees, not radians.
-
Note that OpenGL's shininess and falloff coefficients range [0-128], not
[0-1].
-
Use display lists to radically immprove rendering speed.
-
Use glut menus to allow the user to select controls for your extra features
(e.g. number of jittered samples for anti-aliasing).
-
Stay tuned for more hints.
Notes
- For those of you who are interested, there is a glut command:
int glutGetModifiers(void)
That returns one of GLUT_ACTIVE_SHIFT, GLUT_ACTIVE_CTRL, or GLUT_ACTIVE_ALT to
specify if the appropriate button is depressed when the callback is being
handled. (Using this in conjuction with mouse buttons allows you to link
different events with a single mouse button.)
- Notes from the first precept are now available in
power point.
- If you use the gluBuild2DMipMaps command you may run into some
trouble if the dimensions of your image are not powers of two. (It says it
rescales automatically, but I ran into some trouble, so just to be on the safe
side you may want to rescale it yourself.)
- To clear up a question a number of people have asked: In order to draw
your scene your Draw function will have to both draw a .ray file and
then some other hard coded stuff. This does mean that your scene will work
with only one specific .ray file, but that's ok.
- You should be careful with your texture generation. It seems that texture
generating/binding does not work if you are within the scope of a
glBegin command.
- The issue of binary writing on WINNT is still in existance. Apparently
certain variables that were assumed to be global are not. Please be aware
of this and change all reads and writes of .bmp files to be binary.
Announcements
- A number of new .ray files have been added to the RayFiles directory. The
list includes several cars, a bicycle, two tree-like objects, a hydrant, and a
streetlight. Feel free to include these in your scene as you see fit. (If you
find 3D objects on the web that you would like to incorporate in your scene,
let us know and we may be able to convert them to the .ray format for you.)
- A bug has been discovered in the parser. There was an error in the way
that included .ray files were read in. The bug was in the Scene::parseShape
method in scene.cpp. The code has been updated to reflect the bug fix. For
those of you who have already implemented code in scene.cpp and don't want to
simply copy over your changes, the bug fix is essentially three very small
changes: In scene.cpp in the Scene::parseShape method, when ray_file_instance
is being read, (first strcmp), it gets read into a variable called shape. This
is bad. You should declare a local variable:
RayFileInstance* rayFileInstance;
and then change the lines:
shape=new RayFileInstance(&(rayFiles[temp]));
if(shape==NULL){
...
current->addShape(shape);
to the lines:
rayFileInstance=new RayFileInstance(&(rayFiles[temp]));
if(rayFileInstance==NULL){
...
current->addShape(rayFileInstance);
Stay tuned for more announcements.