The goal of this assignment is to create a simple modeling interface to view (perspective and orthographic), rotate, and manipulate Bezier patches. You will implement a program which renders a patch as a wireframe model or a smooth surface model from 4 different 3D viewpoints - 3 orthographic viewpints (from the front, side, and above), and one arbitrary perspective viewpoint. To manipulate the patch, your program should allow the user to toggle through all the control points and move them using the arrow keys (for moving in x and y) and the Page Up/Page Down (for moving in z).
Extra Credit (30 points): Implement picking to allow the user to move control points using the mouse rather than toggling between all the control points. Enable picking and moving of control points using the mouse only in the arbitrary perspective viewpoint.
Here is a sample executable with picking enabled in all 4 viewports. You need to press tab to get it into selection mode. Then you can select points in any of the viewports. Note that if you select in the front or right view, 4 hits will be registered. For your extra credit, enable picking and dragging in the arbitrary perspective view only. Note also that the shading is most apparent when you drastically deform the surface. This code is courtesy of my PhD student Lucy Xu with modifications from myself to enable picking and dragging.
The Bezier patch will reside in space between -10.0 and 10.0 along the x, y, and z axes. When your program starts up, initialize your patch so that all control points are on the plane, y = 0.0, from x = -5.0 to x = 5.0, and z = -5.0 to z = 5.0. The user should be able to press the Tab key to select different control points (tab from one point to the next). At each control point, Up/Down, Left/Right arrow keys and the Page Up/Page Down arrow keys should be used to move the control points. Your program should display the control points and render the surface as either a wireframe or smooth surface depending on the selected mode. Update the surface as control points are moved. Use GL_POINTS to render the control points. There are 16 control points for a patch. Draw a line between neighboring control points so that it is easier to determine the location of control points as shown below. The currently selected control point is colored red.
The user should be able to toggle between a wireframe rendering and a smooth surface rendering of the patch by pressing the m key. To render the surface, vary the 2 parametric variables, s and t, of the Bezier patch from 0.0 to 1.0. You can try different increments to see which provides the best visualization of the wireframe or surface (for example, try 0.05, 0.025, and 0.01). At each iteration, evaluate the Bezier function at (si, tj), (si, tj-1), (si- 1, tj-1), and (si-1, tj). Do not use glEvalMesh. Instead, implement your own function to evaluate the Bezier patch.
For a wireframe rendering, render the lines between the four points using GL_LINES in OpenGL. Note that you do not render a line across the diagonal between (si, tj) and (si-1, tj- 1), or (si-1, tj) and (si, tj- 1). Your wireframe rendering should not simply consist of lines between the 16 control points.
For a smooth surface rendering, you will need to compute the normal vector at each of the four points ((si, tj), (si, tj-1), (si-1, tj- 1), and (si-1, tj)). Then, compute shading based on the dot product between the normal vector and the light vector (N*L) and call glColor3f to set the color using the computed intensity (shading) for each vertex before calling glVertex3f. To compute the normal vector, first compute the unit tangent vectors, Ts and Tt, with respect to the parametric variables, s and t. The normal vector is the cross product, Ts x Tt, as shown below. Note that you may need to reverse the cross-product. Whichever order is appropriate, Ts x Tt or Tt x Ts, you should use this order consistently throughout the patch. The light position is static at (0, 10, 0) along the positive y-axis. When taking the dot product, N*L, to compute shading, be sure to normalize both N and L.
Your window should be split into 4 screens showing different viewpoints - orthographic front, side, and top views and an arbitrary perspective view as shown in the figure below. The example program, patchDraw.c and corresponding makefile, creates 4 different viewports. To specify a viewpoint for each viewport, you will need to load the projection matrix (GL_PROJECTION) using glMatrixMode. You will then use gluLookAt to specify the eye point, and glOrtho, and glFrustum or gluPerspective to specify the viewing transform for each viewport. You may need to experiment with how far from the front clipping plane you need to specify the eyepoint for the front/side/top views. You will also need to figure out the order in which the above functions should be called.
Your program should allow the arbitrary perspective viewpoint to be rotated using the arrow keys in the same manner as Assignment 3. That is, the viewpoint should be rotated when the user presses the up/down/left/right arrow keys. You do NOT need to implement zooming in/out.
Since the arrow keys are also used to move the control points, you can use the Tab key to change from manipulating control points to manipulating the viewpoint on the 17th tab (use the Tab key to cycle through the 16 control points and viewpoint manipulation). Note that you will need to change the parameters for gluLookAt in order to change the arbitrary viewpoint. In particular, the view-up vector will have to change appropriately to keep the view consistant as you rotate the viewpoint.
Modify the Key function to toggle between the different rendering modes when the user hits the letter m on the keyboard.
Modify the Key function to allow the user to go from selecting one control point to another by pressing the Tab key. When a point is selected, highlight it in a different color, and allow the user to move it using the Up/Down/Left/Right arrow keys and the Page Up/Page Down keys. For a Bezier patch, there are 16 control points.
On the 17th tab press, allow the user to use the arrow keys to rotate the arbitrary viewpoint rather than translate control points. The Tab key should cycle through 17 states - 16 states for each control point and 1 state to bring the program into a view manipulation mode.
Enable picking and moving of control points using the mouse only in the arbitrary perspective viewport. Here is a good tutorial on picking. The steps involved in picking using the mouse are loosely as follows.
Once you have identified the selected control point, you should drag the control point on the mouse move event. The control point should be moved within the plane that is incident to the control point and parallel to the image plane as shown:
The steps to update the location of the control point is as follows:
(Some of these requirements are for ease of grading)