Project3F20
Contents |
Project 3: Amusement Park Ride
In this project you will need to implement a scene graph to render an amusement park ride which consists of a number of objects that are part of a hierarchy.
This project implements the following skills from the lectures:
- texturing
- sky box
- environment mapping
- scene graph
The user of your program should be able to control a variety of options within your simulation using the keyboard. You may choose which keys control which functions, but make sure they are clearly documented in either a text file named README.txt which you add to the main directory of your code, or in your video (narration or text overlays). The following interactive controls should be available to the user:
- Start/stop the animation of each of the levels of your motion hierarchy separately.
- Move around within the simulation (by moving the camera): left, right, up or down, as well as turn left or right.
The total score for this project is 100 points. Additionally, you can obtain up to 10 points of extra credit.
There will not be a discussion on November 11th because of Veterans Day. Instead, this project will be introduced in lecture on Tuesday, November 10th.
We recommend starting with your code from project 2 and removing the rendering of the 3D models. In this project you are going to render all new objects, using your own implementation of a scene graph.
Sky Box (20 Points)
Create a sky box for your scene, to give it a nice background. Here is a great tutorial for sky boxes and how to implement them in modern OpenGL.
Here is is a nice collection of textures for sky boxes. Make sure the width and height of your sky box textures are powers of two, we recommend 512x512 pixels. You are allowed to create your own sky box if you want, many smartphones can capture 360 degree panorama images which you would need to turn into a cube map.
Choose a sky box texture. Then create a cubic sky box and make it very large by giving it coordinates from -500 to +500. Check to see if the textures align correctly at the edges - if not you may need to rotate some of the textures. There should not be any visible seams.
Make sure single-sided rendering (backface culling) is enabled. If your sky box is defined with the triangles' normals facing outward (like the example in the discussion slides), use the following code lines to ensure that the user will never see the outside of the box:
glEnable(GL_CULL_FACE); glCullFace(GL_FRONT);
If your normals point inward, you need to use GL_BACK instead of GL_FRONT in the above code.
Use the following settings for your texture after your first glBindTexture(GL_TEXTURE_CUBE_MAP, id)
for correct lighting and filtering settings:
// Make sure no bytes are padded: glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Use bilinear interpolation: glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Use clamp to edge to hide skybox edges: glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Grading:
- -5 if sky box works but is not seamless
- -3 if backface culling is not enabled, or it is enabled but the wrong faces are culled
Environment Mapping (20 Points)
Create code to tessellate a disco ball style sphere (ie, create vertices and normals for a sphere with a relatively low number of rectangular faces, ie, quads). Its surface should look like polished metal, so you need to use environment mapping on it. The tessellation level (which determines the number of quads used in the model) needs to be adjustable (up and down in small increments) by the user of your software with keyboard keys of your choice. This sphere needs to become part of your amusement park ride later, but we recommend implementing it beforehand so that you can test it out separately. Unless you don't get to render the ride, you don't need to show this sphere separately in your demo (although you could).
Feel free to use code from the internet to generate the sphere, such as this one.
The Cube map tutorial explains how environment mapping is done with a sky box as the environment. Feel free to follow it and use the code from the site to make it work in your code. The goal is to have the sky box reflect on the sphere, to give the impression of the sphere's surface being polished metal (i.e., act like a perfect mirror).
The image below shows an example of a sphere with environment mapping in a sky box:
Grading:
- -10 if reflection looks somewhat like the skybox but is off by a lot
- -5 if reflection is upside down but otherwise correct
Scene Graph Engine (25 Points)
To create a ride with multiple moving parts, we need to first implement a simple scene graph structure for our rendering engine. This scene graph should consist of at least three nodes: Node (5 points), Transform (10 points) and Geometry (10 points). You are free to add more scene graph node types as you see fit.
- Class Node should be abstract and serve as the common base class. It should implement the following class methods:
- an abstract draw method: virtual void draw(Matrix4 C)=0
- an abstract virtual void update()=0 method to separate bounding sphere updates from rendering
- Transform should be derived from Node and have the following features:
- store a 4x4 transformation matrix M
- store a list of pointers to child nodes (std::list<Node*>)
- provide a class methods to add a child node (addChild()) to the list
- its draw method needs to traverse the list of children and call each child node's draw function
- when draw(C) is called, multiply matrix M with matrix C.
- Geometry should be derived from Node and have the following features:
- set the modelview matrix to the current C matrix
- an initialization method to load a 3D model (OBJ file) whose filename is passed to it (init(string filename). Your OBJ loader from project 2 should work.
- have a class method which draws the 3D model associated with this node.
Ride Design (25 Points)
Now that we have the scene graph classes, it is time to put them to work. Build your own amusement park ride using the addChild methods.
Your design needs to include the following features:
- You need to have a ground plane for the ride.
- The ride must be anchored to the ground (can't be floating in space).
- Your disco ball sphere must be part of the design. It can occur once or multiple times.
- Your hierarchy needs to be at least three levels deep. For instance a ferris wheel which spins around its center with cars that rotate so they are always aligned with gravity, with the cars rotating about their vertical axis (see first picture below).
- Drawing the same object multiple times in different positions, orientations, and/or with different scaling factors.
- Moving objects over time, including rotations not centered at the origin, linear motion (changing direction at the end points) and compound motions.
- Use normal based lighting for the surfaces of all your ride geometries. This means that you need to have normals for all your 3D objects.
High resolution objects are not required for this simulation. Adequate results can be achieved with a simple cube, cone, cylinder, and possibly sphere if they are scaled appropriately.
Here a few links to basic geometries you are welcome to use. You are also allowed to use the OBJ files from projects 1 and 2.
- Cube
- Cone
- Cylinder
- Sphere
Here a few examples of rides (but yours needs to have a sky box and a disco ball also):
Once you've created your scene graph, you need to get your rendering engine ready to recursively traverse the scene graph for rendering by creating a root node of type Transform and calling its draw() function with the identity matrix as its parameter.
Animation and Interaction (10 Points)
- Animate your amusement park ride to make it look like it would when it is running, by changing the matrices in the Transform nodes.
- Allow the user to start/stop the animation of each of the levels of your motion hierarchy separately. (For example: if you're making a ferris wheel: the '1' key starts/stops the rotation of the ferris wheel itself, the '2' key starts/stops the rotation of the cars around the horizontal axis to keep them level with the ground, the '3' key starts/stops the rotation of the cars about their vertical axis.)
- Give the user keyboard or mouse control to move around within the simulation (by moving the camera): the user needs to be able to move left, right, up or down, as well as turn left or right. The up vector of the camera should always point straight up in the world (no banking or pitching the view).
Extra Credit (Up to 10 Points Max.)
Choose from the following options. The points add up to a maximum of 10 points.
- Create a camera node and attach it to one of the leaf nodes of your scene graph, for instance showing a rider's view. Allow switching between this view and the default observer view with a keyboard key. (3 points)
- Create a custom cube map for your sky box using your smartphone in 360 degree panorama capture mode, or a dedicated 360 degree panorama camera. (5 points)
- Create a custom, non-trivial object (not a basic mathematical shape or derived from one) with a 3D modeling tool (e.g., Blender), or find a free model on the internet which you add to your amusement park scene. It needs to be textured. (5 points)
- Dynanmic environment mapping: have the disco ball reflect not just the sky box, but also all the components of your ride. (10 points)