Project4SP15
Contents |
Project 4: Light and Shade
This project is on OpenGL lighting and shading, and adds support for the mouse.
The project is due on Friday, May 1st, 2015 at 1pm. You need to present your results in the CSE basement labs as usual, grading starts at 12:15pm.
The homework discussion for this project will be on Monday, April 27th.
From this project on, we will no longer use our software rasterizer. Feel free to start the project with your code for project 2.
In this project we will use the cube, bunny, dragon and bear data sets from the last two projects, but you will no longer need to support the house. Your application should switch between the four models with the function keys: use the previous mapping of 'F1', 'F4', 'F5' and 'F6' for these models, or consolidate them into the range of 'F1' through 'F4' if you prefer. Nothing should auto-spin like the cube did in assignment 1.
1. Mouse Control (30 Points)
It is time to support the mouse to control your 3D models. Add functionality to allow the following operations on the displayed 3D model:
- While the left mouse button is pressed and the mouse is moved, rotate the model about the center of your graphics window. This is an extension of the orbit function ('o' key), but it should orbit the model around a sphere, not just a circle. We will refer to this operation as "trackball rotation". This video shows how this should work.
- When the right mouse button is pressed and the mouse is moved, move the model in the plane of the screen (similar to what the 'x' and 'y' keys did). Scale this operation so that when the model is in the screen space z=0 plane, the model follows your mouse pointer as closely as possible. If you don't have a right mouse button, use your mouse button along with a function key (Shift, Control, Alt, etc.) to enter this mode.
- Use the mouse wheel to move the model along the screen space z axis (i.e., in and out of the screen = push back and pull closer). You can access it with the callback function glutMouseWheelFunc, but this is not available in all versions of GLUT (try FreeGLUT). If you don't have a mouse wheel, use a different function key and mouse cursor up/down.
- Retain the functionality of the 's'/'S' keys to scale the model about its object space origin. The other keyboard functions for the control of the 3D models are no longer needed, but it does not hurt to keep them supported. To keep the normals of your 3D models pointing in the right directions, put the following OpenGL command in the initialization part of your code: glEnable(GL_NORMALIZE).
Notes on Mouse Support in GLUT
To access the mouse x and y coordinates, you should use GLUT's callback function glutMouseFunc(), which gets called when you press a mouse button, and glutMotionFunc(), which gets called repeatedly while you hold the button down and move the mouse. Note that successive trackball rotations must build on previous ones; at no point should the model snap back to a previous or default position.
Notes on the Trackball Rotation
The figure below illustrates how to translate mouse movement into a rotation axis and angle. m0 and m1 are consecutive 2D mouse positions. These positions define two locations v and w on an invisible 3D sphere that fills the rendering window. Use their cross product as the rotation axis a = v x w, and the angle between v and w as the rotation angle.
Horizontal mouse movement exactly in the middle of the window should result in a rotation just around the y-axis. Vertical mouse movement exactly in the middle of the window should result in a rotation just around the x-axis. Mouse movements in other areas and directions should result in rotations about an axis a which is not parallel to any single coordinate axis, and is determined by the direction the mouse is moved in.
Once you have calculated the trackball rotation matrix for a mouse drag, you will need to multiply it with the object-to-world transformation matrix of the object you are rotating.
For step by step instructions, take a look at this tutorial. Note that the tutorial was written for Windows messages, instead of GLUT mouse functions. This means that you'll need to replace the "CSierpinskiSolidsView::OnLButtonDown" function with "glutMouseFunc", "CSierpinskiSolidsView::OnMouseMove" with "glutMotionFunc", etc. To help you understand the code here is a line-by-line commented version of the trackBallMapping function:
Vec3f CSierpinskiSolidsView::trackBallMapping(CPoint point) // The CPoint class is a specific Windows class. Either use separate x and y values for the mouse location, or use a Vector3 in which you ignore the z coordinate. { Vec3f v; // Vector v is the synthesized 3D position of the mouse location on the trackball float d; // this is the depth of the mouse location: the delta between the plane through the center of the trackball and the z position of the mouse v.x = (2.0*point.x - windowSize.x) / windowSize.x; // this calculates the mouse X position in trackball coordinates, which range from -1 to +1 v.y = (windowSize.y - 2.0*point.y) / windowSize.y; // this does the equivalent to the above for the mouse Y position v.z = 0.0; // initially the mouse z position is set to zero, but this will change below d = v.Length(); // this is the distance from the trackball's origin to the mouse location, without considering depth (=in the plane of the trackball's origin) d = (d<1.0) ? d : 1.0; // this limits d to values of 1.0 or less to avoid square roots of negative values in the following line v.z = sqrtf(1.001 - d*d); // this calculates the Z coordinate of the mouse position on the trackball, based on Pythagoras: v.z*v.z + d*d = 1*1 v.Normalize(); // Still need to normalize, since we only capped d, not v. return v; // return the mouse location on the surface of the trackball }
Grading:
- -5 if rotation is not in world coordinates
- -5 if object's size changes when rotating
- -10 if there is no zoom
- -5 if rotation is in opposite direction
- -10 if rotation is not cumulative
2. Light Sources (50 Points)
In this part we add more light sources and control them as if they were 3D models. Before you add the light sources, change the colors of your 3D models to be white - this is so that the effect of the light sources can clearly be seen.
Write classes to manage lights and their properties (Light). Instead of the default light source from the previous assignments, create three light sources: a directional light, a point light and a spot light. Give them initial colors, positions, and directions of your choice. Each needs to have a different color, clearly distinguishable from the other two. The spot light should always point to the center of the window coordinate system.
To visually indicate where the light sources are, draw a glutSolidSphere in the location of the point light, and a glutSolidCone in the location of the spot light - the wide end pointing in the direction of the spot, the cone angle should equal the opening angle of the spot.
Make the lights user controllable: make them selectable with the number keys '1', '2', and '3' (for the directional, point and spot lights, respectively). De-select by pressing the same number again. Print a message in your text window indicating which light is selected.
When a light source is selected, your mouse and keyboard controls should only affect this light source (not the 3D model or the other lights; when no light is selected, your controls should affect only the model, not the light sources). You need to support the following functions for your light sources:
- Directional light: trackball rotations to change the light direction
- Point light: trackball rotations to rotate the light around the center of the window; scaling with the mouse wheel or the 's'/'S' keys should affect the distance of the light from the origin of the world coordinate system
- Spot light: everything the point light does, plus: when the right mouse button is held down, mouse up/down should make the spot wider/narrower, left/right should make the spot edge sharper/blurrier. Make sure the spot keeps pointing at the center of your window coordinate system even when its position is changed.
Notes:
- For detailed information and sample code, see Chapter 5 of the OpenGL Programming Guide, as well as the OpenGL Lighting FAQ.
- By default, OpenGL uses a simplified model for the calculation of the highlights. For a more realistic model add this command to your main() function: glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE).
- The model color should be white, but this does not mean that the models should show up in bright white - the color should be affected by the light sources instead.
Grading:
- -10 if the spot light is indistinguishable from a point light (spot too wide)
- -5 if point or spot light have no visual representations as described (-10 if neither is correctly displayed)
- -5 for each light if light source representation and source of light don't match
- -5 for each 3D model that isn't white
3. Materials (20 Points)
Associate different material properties with each of the 3D model files: make some more shiny, others more diffuse. Use colors other than white. The differences in shininess must be obvious - use extreme settings if you need to.
Grading:
- -10 if it is hard to tell whether an object is shinier or more diffuse than another.
- -10 if it is hard to tell the colors of your objects apart.
4. Extra Credit (10 Points)
There are two things to get extra credit for. Each of them will get you 5 points of extra credit.
a) Specular cube: The cube model will not show proper specular reflection, even if you assign specular material properties to it. Similarly to the video we watched in class, this can be fixed by tessellating each of its faces out of many small quads. Change the geometry of the cube to consist of at least a 100x100 array of quads for each face (more if your computer allows it without slowing down, or less if it's very slow). Then change its material properties to contain a significant amount of specular reflection, move the point light close to the surface of the cube and demonstrate the difference between the finer tessellated cube and the original one by toggling between the two modes with the 't' key.
b) Color editor: Add a visual editor to allow the custom modification of the colors of your models and light sources. Use the 'c' key to toggle the color editor. The editor needs to allow the user to set the color in all three dimensions, and it needs to be mouse controlled. A simple way to do this are three sliders for red, green and blue (RGB). A little bit more practical would be sliders which select hue, saturation and brightness (HSV). A good coverage of the conversion between RGB and HSV can be found here.
An example for a more visual editor is this one, which separates the selection of the hue from saturation and brightness:
Or this one, which separates brightness from saturation and hue; the image on the right explains what the color wheel consists of: