Difference between revisions of "Project3S16"

From Immersive Visualization Lab Wiki
Jump to: navigation, search
(2. Scene Graph Engine (15 Points))
 
(58 intermediate revisions by 3 users not shown)
Line 1: Line 1:
Topics:
 
* Kevin will make pod
 
* Sky box with Textures
 
* View Frustum Culling
 
* Camera in scene graph: bear sits in pod (or bunny), switch to that perspective; other camera is outside view
 
 
* extra credit: split screen for both camera views?
 
 
project 4: roller coaster editor
 
 
 
 
=Project 3: Wedding Cake=
 
=Project 3: Wedding Cake=
  
In this project you will need to implement a scene graph to render a novel theme park ride. The ride is the Wedding Cake from the [https://www.youtube.com/watch?v=RVeHxUVkW4w Centrifuge Brain Project video] - the relevant part of the video starts 2:00 minutes into the clip.
+
In this project you will need to implement a scene graph to render a novel theme park ride. The ride is the Wedding Cake from the [https://youtu.be/RVeHxUVkW4w Centrifuge Brain Project video] - the relevant part of the video starts [https://youtu.be/RVeHxUVkW4w?t=1m53s 1:53 minutes into the clip].
 
   
 
   
 
The total score for this project is 100 points. Additionally, you can obtain up to 10 points of extra credit.
 
The total score for this project is 100 points. Additionally, you can obtain up to 10 points of extra credit.
  
==1. Sky Box (30 Points)==
+
==1. Sky Box (20 Points)==
  
Start with your code which includes camera movement, ideally with the mouse, but if you didn't get that to work the keyboard shortcuts will suffice.  
+
Start with code that uses your trackball code, and modify it to control the camera instead. (If you didn't get that to work the keyboard controls will suffice.)
  
Create a sky box for your scene. A sky box is a large, square box which is drawn around your entire scene. The inside walls of the box have pictures of a sky and a horizon. Sky boxes are typically cubic, which means that they consist of six square textures for the six sides of a cube. [http://www.f-lohmueller.de/pov_tut/skyboxer/skyboxer_3.htm Here is is a nice collection of textures for sky boxes], and [http://www.custommapmakers.org/skyboxes.php here is an even bigger one].  
+
Create a sky box for your scene. A sky box is a large, square box which is drawn around your entire scene. The inside walls of the box have pictures of a sky and a horizon. Sky boxes are typically cubic, which means that they consist of six square textures for the six sides of a cube. [http://learnopengl.com/#!Advanced-OpenGL/Cubemaps Here] is a great tutorial for sky boxes in modern OpenGL.
 +
 
 +
[http://www.f-lohmueller.de/pov_tut/skyboxer/skyboxer_3.htm Here is is a nice collection of textures for sky boxes], and [http://www.custommapmakers.org/skyboxes.php here is an even bigger one].  
  
 
Draw a cubic sky box and make it big enough to hold an entire theme park.
 
Draw a cubic sky box and make it big enough to hold an entire theme park.
Line 31: Line 22:
 
</pre>
 
</pre>
  
Use the following settings for your texture after your first <tt>glBindTexture</tt> for correct lighting and filtering settings:
+
Use the following settings for your texture after your first <code>glBindTexture(GL_TEXTURE_CUBE_MAP, id)</code> for correct lighting and filtering settings:
  
 
<pre>
 
<pre>
Line 41: Line 32:
  
 
   // Use bilinear interpolation:
 
   // Use bilinear interpolation:
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
 +
 
 
</pre>
 
</pre>
  
To familiarize yourself with texture mapping in OpenGL, we provide a [[texture.cpp | sample program]], which loads a PPM file and uses it as a texture for a quad. If you decide to use one of the above referenced sky box images, you will have to convert them from JPEG to PPM format. The free image processing tool [http://www.irfanview.com IrfanView] for Windows will do this for you. Alternatively, you can use a third party library such as [http://lonesock.net/soil.html SOIL] to natively load JPEG images.
+
To familiarize yourself with texture mapping in OpenGL, we provide [[Media:project3s16-texture.cpp | sample code]], which loads a PPM file and uses it as a texture for a quad. If you decide to use one of the above referenced sky box images, you will have to convert them from JPEG to PPM format. The free image processing tool [http://www.irfanview.com IrfanView] for Windows will do this for you. Alternatively, you can use a third party library such as [http://lonesock.net/soil.html SOIL] to natively load JPEG images.
  
==2. Scene Graph Engine (30 Points)==
+
'''Grading:'''
 +
* 5 points for functional camera controls with keyboard or mouse
 +
* 5 points for the sky box without textures
 +
* 5 points for the textures
 +
* 5 points for correct rendering of edges and corners (seamless edges)
 +
 
 +
==2. Scene Graph Engine (15 Points)==
  
 
Implement a scene graph structure to simplify rendering of the ride. Use the following hierarchy:
 
Implement a scene graph structure to simplify rendering of the ride. Use the following hierarchy:
  
[[Image:project4F14-scenegraph-half.jpg]]
+
[[Image:project3S16-scenegraph.jpg|500px]]
  
 
The classes should have at least the following functionality:
 
The classes should have at least the following functionality:
  
* Class <tt>Node</tt> should be abstract and serve as the common base class. It should implement an abstract draw method: <tt>virtual void draw(Matrix4 C) = 0</tt>, and also an abstract <tt>virtual void update() = 0</tt> method to separate bounding sphere updates from rendering.
+
* Class <tt>Node</tt> should be abstract and serve as the common base class. It should implement an abstract draw method: <tt>virtual void draw() = 0</tt>, and also an abstract <tt>virtual void update(glm::mat4 C) = 0</tt> method. (2 points)
* <tt>Group</tt> should store a list of pointers to child nodes (std::list<Node*>) and provide functionality to add and remove child nodes (addChild(), removeChild()). Its draw method needs to traverse the list of children and call each child node's draw function.
+
* <tt>Group</tt> should store a list of pointers to child nodes (std::list<Node*>) and provide functionality to add and remove child nodes (addChild(), removeChild()). Its draw method needs to traverse the list of children and call each child node's draw function. (2 points)
* <tt>Geode</tt> should be an abstract class. It should set OpenGL's ModelView matrix to the current C matrix, and have an abstract render function to render its geometry.
+
* <tt>Geode</tt> should be an abstract class. It should update the rendering matrix, and have a draw function to draw its geometry. (2 points)
* <tt>MatrixTransform</tt> should store a 4x4 transformation matrix M which is multiplied with matrix C, which is passed to the draw method.
+
* <tt>MatrixTransform</tt> should store a 4x4 transformation matrix M which is multiplied with matrix C, which is passed to the draw method. (3 points)
* <tt>Sphere</tt> should have a draw function which draws a sphere. You can use <tt>[https://www.opengl.org/documentation/specs/glut/spec3/node81.html glutSolidSphere]</tt> for that, or use your own tessellation algorithm.
+
* <tt>Cylinder</tt> should draw a cylinder, which you can load from [http://ivl.calit2.net/wiki/images/9/92/Cylinder.zip this OBJ file]. (3 points)
* <tt>Cube</tt> should have a draw function which draws a cube. You can use <tt>[https://www.opengl.org/documentation/specs/glut/spec3/node82.html glutSolidCube]</tt> for that, or use your own implementation of a cube.
+
* <tt>Pod</tt> should draw the [http://ivl.calit2.net/wiki/images/a/a2/Pod.zip OBJ model of a pod]. (3 points)
  
==3. The Wedding Cake Ride (20 Points)==
+
'''Notes:'''
 +
* Make sure your Cylinder and Pod classes only load the OBJ models from disk once.
 +
 
 +
==3. Building the Wedding Cake Ride (20 Points)==
  
 
First get your software ready to recursively traverse the scene graph for rendering by creating a root node of type Group and calling its draw() function with the identity matrix as its parameter.
 
First get your software ready to recursively traverse the scene graph for rendering by creating a root node of type Group and calling its draw() function with the identity matrix as its parameter.
  
We provide a 3D model of a pod for the ride. Use a cylinder for the vertical center post, and smaller cylinders for the horizontal arms that hold the pods.
+
Then create the Wedding Cake ride. The ride should have three levels, each with three big arms to hold another three arms with pods at the end, for a total of 27 pods. Use your Cylinder class for the vertical center post, and smaller instances of the Cylinder class for the horizontal arms, and smaller yet Cylinders to hold the pods.
  
===Rotation===
+
In this part of the project you do not need to animate the ride. We'll do that next.
The ride should have three levels of pods, each with three big arms to hold three pods each. The center post that holds everything should rotate, as well as each set of three pods, and also each pod should rotate about its pivot point.
+
  
===Translation===
+
'''Grading:'''
Each of the three arms on each of the three levels should be able to extend its length.
+
* 5 points for vertical main post.
 +
* 5 points for the horizontal arms that attach to the main post.
 +
* 5 points for the shorter horizontal arms that hold the pods.
 +
* 5 points for the pods.
  
 +
==4. Animating the Ride (30 Points)==
  
 +
Animate the Wedding Cake ride by modifying the following things (5 points each):
  
==3. Culling (30 Points)==
+
* Rotate the entire ride about its center post.
 +
* Rotate each set of three pods about its center.
 +
* Rotate each pod about itself.
 +
* Make the main, vertical post extend and contract.
 +
* Make the posts that extend horizontally from the center extend their length, independently from each other.
 +
* Make the horizontal arms that hold the pods change their lengths, independently from each other.
  
Add a bounding sphere (Vector3 for its center point, and a radius) to your <tt>Node</tt> class, and implement code to update the bounding box parameters in all other classes of your scene graph. You also need to add code to your <tt>Node</tt> class to display each node's bounding sphere as a wireframe sphere with <tt>[https://www.opengl.org/documentation/specs/glut/spec3/node81.html glutWireSphere]</tt>. Support the 'b' key to toggle these bounding spheres on and off. (10 points)
+
'''Notes:'''
 +
* For the purpose of extending and contracting the arms, don't use scale nodes because they would scale everything below them not only the cylinders. Instead, you could draw two cylinders for each arm, in the same place, and shift them apart to extend the length of the arm.
 +
* You don't have to sway the arms or posts individually like the later part in the video.
  
'''Note:''' You do not need to find the smallest possible bounding sphere, but you can approximate it:
+
==5. Bear Camera (15 Points)==
  
* Find minimum and maximum extents of your geometry in x,y and z (bounding box).
+
Use your Bear data set from the previous project to place the bear in one of the pods. You'll have to downscale it by adding a MatrixTransform node with a scale operation in front of it, and you'll also have to shift it so that it sits in the right place, and you may have to rotate it as well. Fiddle with it so the bear sits comfortably in the pod.
* The center of the bounding sphere is the center of the bounding box.
+
* The radius of the bounding sphere is equal to half the diameter of the bounding box.
+
  
At the least, the bounding sphere should not include any neighboring robots in their entirety.
+
[[File:Bearpod.png|200px]]
  
Extend the <tt>Node</tt> class to perform view frustum culling using the bounding spheres of the objects. If the bounding sphere of an object is completely outside of the view frustum, the object should be culled (not rendered). Your culling algorithm should make use of a utility function to test whether a bounding sphere intersects with a given plane, or whether the sphere is entirely on one side of the plane. (10 points)
+
Once Bear is in place, create a camera class for the scene graph and place a camera right in front of the Bear's face, to simulate what he sees(i.e. a POV camera). Add keyboard support('c') to switch between the outside view and the Bear's view. To calculate the camera matrix you will have to find the camera node and traverse the scene graph from this node up to the top, before you start the scene graph traversal to render the geometry.
 
+
Test your implementation by constructing a scene which consists of a sufficiently large amount of your robots to speed up rendering when object culling is used. (10 points)
+
 
+
* Create only one instance of your robot class, which you reference every time you render a robot. This saves a great deal of memory.
+
 
+
* Create a scene graph with two platoons of as many robots as it takes to render at around 20 fps. Distribute the robots of each platoon on a regular 2D grid.
+
 
+
* Choose the camera parameters so that many of the robots are located outside of the view frustum (off-screen), so that culling kicks in.  
+
 
+
* Use your rotation and scale routines to allow the user to rotate the camera and zoom in and out. You can modify the camera position either with your mouse control functions, or with keyboard keys of your choice.
+
 
+
* Compare the frame rates with and without object-level culling by supporting the keyboard key 'c' to toggle culling on and off, and displaying the rendering rate (frames per second) in the console window for every frame (frames_per_second = 1/rendering_time). Tweak the number of robots, their spatial density, and your camera parameters until your frame rate is substantially higher (50%+) with culling enabled.
+
 
+
'''Notes:'''
+
* All your robots need to be walking like in part 2. This means that you need to re-calculate the bounding spheres each frame, or use bounding spheres which contain the entire animation.
+
* For the calculation of the view frustum bounding planes you may want to take a look at [http://www.lighthouse3d.com/tutorials/view-frustum-culling/ the Lighthouse3D web site].
+
* To monitor memory consumption you can use the following tools:
+
** Windows: Visual Studio 2015's Diagnostics Tool, or Task Manager
+
** Mac: Activity Monitor
+
** Linux: top
+
 
+
This image illustrates the grid layout of the robots:
+
 
+
[[Image:robots.png]]
+
  
 
'''Grading:'''
 
'''Grading:'''
* -15 if camera can't be moved to demonstrate that culling works.
+
* 5 points for placing the bear in the pod.
 +
* 10 points for the camera view from the Bear's perspective.
  
==4. Animation (20 Points)==
+
==6. Extra Credit: Split Screen (10 Points)==
 
+
Animate the robots and the platoons like in [https://www.youtube.com/watch?v=PhHxPJSrPOw the above mentioned video]. Your animation needs to consist of at least 4 turns and changes of direction of the robots. The platoons need to move in different directions at least once (i.e., they can't be walking synchronously all the time). Make the platoons interleave each other like in the video. It is not critical that there is no collision between them, we will deal with that in the extra credit section. The animation needs to be running automatically, so you will need a way to script it.
+
 
+
'''Grading:'''
+
* -5 if robots don't turn in place
+
* -5 if the two platoons don't move independently
+
* -5 if the platoons make fewer than 4 turns
+
  
==5. Extra Credit: Collision Detection (10 Points)==
+
There are three extra credit options. You can do up to two of them, each of them gets you 5 extra points.
  
Implement a bounding sphere based collision detection algorithm and visually indicate when two or more robots collide. For example, you could draw the colliding robots' bounding spheres in red. Tweak the interleaving part of your animation so that the robots never intersect. Add a manual control mode to control the walking direction of each platoon independently so that you can force collisions. For instance, one platoon could be controlled with the WASD keys, the other with IJKL.
+
# Implement a split screen view which shows both the scene camera, as well as the view from the bear, side by side.
 +
# Create special event lighting for the Wedding Cake ride. Use at least three spot lights in different colors that are located on the ground and moving to illuminate the ride from different directions, by each following a different pod.
 +
# Make the motion of the ride more like in the video: bend the cylinders, extend them out more than just one cylinder length, etc.

Latest revision as of 18:56, 3 May 2016

Contents

Project 3: Wedding Cake

In this project you will need to implement a scene graph to render a novel theme park ride. The ride is the Wedding Cake from the Centrifuge Brain Project video - the relevant part of the video starts 1:53 minutes into the clip.

The total score for this project is 100 points. Additionally, you can obtain up to 10 points of extra credit.

1. Sky Box (20 Points)

Start with code that uses your trackball code, and modify it to control the camera instead. (If you didn't get that to work the keyboard controls will suffice.)

Create a sky box for your scene. A sky box is a large, square box which is drawn around your entire scene. The inside walls of the box have pictures of a sky and a horizon. Sky boxes are typically cubic, which means that they consist of six square textures for the six sides of a cube. Here is a great tutorial for sky boxes in modern OpenGL.

Here is is a nice collection of textures for sky boxes, and here is an even bigger one.

Draw a cubic sky box and make it big enough to hold an entire theme park.

Make sure single-sided rendering (triangle culling) is enabled with these lines somewhere in your code to ensure that you will never see the outside of the box:

glEnable(GL_CULL_FACE); 
glCullFace(GL_BACK); 

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);

  // Select GL_MODULATE to mix texture with polygon color for shading:
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

  // 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);

To familiarize yourself with texture mapping in OpenGL, we provide sample code, which loads a PPM file and uses it as a texture for a quad. If you decide to use one of the above referenced sky box images, you will have to convert them from JPEG to PPM format. The free image processing tool IrfanView for Windows will do this for you. Alternatively, you can use a third party library such as SOIL to natively load JPEG images.

Grading:

  • 5 points for functional camera controls with keyboard or mouse
  • 5 points for the sky box without textures
  • 5 points for the textures
  • 5 points for correct rendering of edges and corners (seamless edges)

2. Scene Graph Engine (15 Points)

Implement a scene graph structure to simplify rendering of the ride. Use the following hierarchy:

Project3S16-scenegraph.jpg

The classes should have at least the following functionality:

  • Class Node should be abstract and serve as the common base class. It should implement an abstract draw method: virtual void draw() = 0, and also an abstract virtual void update(glm::mat4 C) = 0 method. (2 points)
  • Group should store a list of pointers to child nodes (std::list<Node*>) and provide functionality to add and remove child nodes (addChild(), removeChild()). Its draw method needs to traverse the list of children and call each child node's draw function. (2 points)
  • Geode should be an abstract class. It should update the rendering matrix, and have a draw function to draw its geometry. (2 points)
  • MatrixTransform should store a 4x4 transformation matrix M which is multiplied with matrix C, which is passed to the draw method. (3 points)
  • Cylinder should draw a cylinder, which you can load from this OBJ file. (3 points)
  • Pod should draw the OBJ model of a pod. (3 points)

Notes:

  • Make sure your Cylinder and Pod classes only load the OBJ models from disk once.

3. Building the Wedding Cake Ride (20 Points)

First get your software ready to recursively traverse the scene graph for rendering by creating a root node of type Group and calling its draw() function with the identity matrix as its parameter.

Then create the Wedding Cake ride. The ride should have three levels, each with three big arms to hold another three arms with pods at the end, for a total of 27 pods. Use your Cylinder class for the vertical center post, and smaller instances of the Cylinder class for the horizontal arms, and smaller yet Cylinders to hold the pods.

In this part of the project you do not need to animate the ride. We'll do that next.

Grading:

  • 5 points for vertical main post.
  • 5 points for the horizontal arms that attach to the main post.
  • 5 points for the shorter horizontal arms that hold the pods.
  • 5 points for the pods.

4. Animating the Ride (30 Points)

Animate the Wedding Cake ride by modifying the following things (5 points each):

  • Rotate the entire ride about its center post.
  • Rotate each set of three pods about its center.
  • Rotate each pod about itself.
  • Make the main, vertical post extend and contract.
  • Make the posts that extend horizontally from the center extend their length, independently from each other.
  • Make the horizontal arms that hold the pods change their lengths, independently from each other.

Notes:

  • For the purpose of extending and contracting the arms, don't use scale nodes because they would scale everything below them not only the cylinders. Instead, you could draw two cylinders for each arm, in the same place, and shift them apart to extend the length of the arm.
  • You don't have to sway the arms or posts individually like the later part in the video.

5. Bear Camera (15 Points)

Use your Bear data set from the previous project to place the bear in one of the pods. You'll have to downscale it by adding a MatrixTransform node with a scale operation in front of it, and you'll also have to shift it so that it sits in the right place, and you may have to rotate it as well. Fiddle with it so the bear sits comfortably in the pod.

Bearpod.png

Once Bear is in place, create a camera class for the scene graph and place a camera right in front of the Bear's face, to simulate what he sees(i.e. a POV camera). Add keyboard support('c') to switch between the outside view and the Bear's view. To calculate the camera matrix you will have to find the camera node and traverse the scene graph from this node up to the top, before you start the scene graph traversal to render the geometry.

Grading:

  • 5 points for placing the bear in the pod.
  • 10 points for the camera view from the Bear's perspective.

6. Extra Credit: Split Screen (10 Points)

There are three extra credit options. You can do up to two of them, each of them gets you 5 extra points.

  1. Implement a split screen view which shows both the scene camera, as well as the view from the bear, side by side.
  2. Create special event lighting for the Wedding Cake ride. Use at least three spot lights in different colors that are located on the ground and moving to illuminate the ride from different directions, by each following a different pod.
  3. Make the motion of the ride more like in the video: bend the cylinders, extend them out more than just one cylinder length, etc.