Project 3: 3D Interaction
This homework assignment consists of three parts, but only the first two are mandatory to get full credit (100 points). In the first part you will need to implement a trackball-like interaction method for your OBJ data sets from project 2. In the second part you will need to add translations and scale operations. In the third, optional part, you need to render translucent geometry.
This assignment is due on Friday, October 19. It will be introduced by TA Sid on Monday, October 15th at 2:30pm in lab 260.
1. Virtual Trackball (60 Points)
Implement a virtual trackball which allows a user to rotate an object interactively with the mouse. Your solution should translate holding the left mouse button while dragging the mouse into a rotation matrix, which you then use to rotate object space about the origin of the world coordinate system (i.e., the center of the rendering window). Rotations around all three coordinate axes should be supported, depending on where in the rendering window the user clicks.
A sample executable demonstrating the trackball functionality is available for Windows and Linux. If the executable does not work on your computer, here is a video of it. To access mouse coordinates, you will need to use GLUT's callback functions glutMouseFunc() and glutMotionFunc(). Note that successive trackball rotations must build on previous ones; at no point should the model snap back to a previous or default position.
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 a 3D virtual 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 around the y-axis. Vertical mouse movement exactly in the middle of the window should result in a rotation 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.
Support three coordinate systems: object coordinates, world coordinates, and camera coordinates. Design the rotation so that it only affect model matrix M.
Once you have calculated the trackball rotation matrix for a mouse drag, you will need to multiply it with the current object matrix. The new object matrix needs to be multiplied with the camera matrix and then transferred to OpenGL with the glLoadMatrix function.
Use one or more of the 3D models from project 2 as your test object. You will get points for the following accomplishments:
- The 3D model rotates (at all) when the mouse is clicked and dragged (20 points).
- The house responds to mouse movement correctly like a virtual trackball (e.g., mouse to the right -> house rotates to the right) (25 points).
- Clicking and dragging anywhere in the window, including close to the edge or corners of the window, does not crash the application (5 points).
- Consecutive clicks and drags continue rotating the model where it was left. Mouse clicks should never cause the model to 'jump' to an earlier orientation. (5 points)
- Add a reset function, triggered by the 'r' key. This reset should bring the 3D model back into its original orientation. (5 points)
2. Translation and Scale (40 Points)
Now you might want to look more closely at a 3D model, which requires more than just trackball rotation.
Holding down the middle mouse button (or the 'z' key) during mouse drags should cause a translation of the 3D model within the world coordinate system's x/y plane, by roughly the same amount as the cursor is moved. Repeated translations should add up. (20 points)
Holding down the right mouse button (or the 'x' key) during mouse drags should allow uniform scaling (resizing) of the data set, about the center of the world coordinate system (i.e., the center of the rendering window). Moving the mouse up should increase the size, moving it down should decrease it. Repeated scaling operations should add up. (20 points)
Pressing the 'r' key should reset the model matrix to the identity matrix, and thus undo all trackball rotations, translations and scales done with the mouse.
This video illustrates the concept. A data set is first rotated with a trackball function, using the left mouse button. Then, using the middle mouse button, the data set is moved around the screen plane. After that, the data set is scaled up and down with the right mouse button. Finally, the 'r' key is pressed to reset the model matrix to the identity matrix.
3. Optional Project: Translucent Geometry (10 Points)
Render the cube from the support code of project 1 with translucent faces, and another translucent cube next to it, to practice rendering translucent geometry.
To make the cubes translucent, replace the glColor3f call in the displayCallback() function with a glColor4f, and pass the alpha value (amount of translucency) in the fourth value. Use an alpha value of 0.5, unless your results look better with a different alpha value. You will also have to turn blending on with this code in your main function:
glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Copy the relevant sections from the support code for project 1 to your current C++ project, and integrate the Trackball and the pan/zoom functions from parts 1 and 2.
Add another translucent cube to the scene, next to the original one. Choose a suitable color for it, which should be different than the color of the first cube. Both cubes should remain fixed with respect to the world coordinate system. The problem you will encounter if you just render the two cubes now is that when you rotate your scene to overlap the cubes, sometimes the cube in the back will be visible, but sometimes it will not, even though it should always be visible through the one in the front.
To render the cubes correctly, you will have to sort all translucent geometry based on its distance from the camera, and then render the quads one at a time, from back to front. To sort the quads, calculate the center point of each quad, project it into camera coordinates, and use the resulting z value as the sorting criterion.
You will get points for the following accomplishments:
- Your cubes' faces are translucent. (2 points)
- There are two cubes. (2 points)
- The scene with the two cubes can be manipulated with the functions in parts 1 and 2. (2 points)
- The blending of the translucent geometry works correctly and uses geometry sorting. (4 points)