Math 155A - Introduction to Computer Graphics – Winter 2019
Instructor: 
Sam Buss,  Univ. of California, San Diego

Project #4 – Build a ground plane and surface of rotation with normals.
Due date: Friday, February 15, 9:00pm.

Goals: Create a parametric surface (namely, a portion of a surface of rotation) using triangle strips. Create a rectangular mesh for the ground plane using triangle strips. Dynamically change the resolution of the surface of rotation and the ground plane.  Correctly calculate normal for both objects.  Discover that wireframe objects, especially when combined with animation can look very three-dimensional.  Discover, however, that flat, solidly colored objects look much too flat and non-three-dimensional. 
    This project is based on Project #3. In addition, it will be used as the basis for Project #5, which will add materials and lighting to the scene.

What to hand in:  

·       Upload to gradescope, your main new source file MySurfaces.cpp. If there are major changes to MyInitial.cpp or any other source files, please upload those as well. Also, upload a PDF file showing two images: (a) your scene rendered in wireframe mode without normals, and (b) rendered in wireframe mode with normals.

·       Get an individual grading session with Professor Buss or a TA. Place your C++ files, executable, and Visual Studio solution together in a separate folder, in your PC computer account in the APM basement labs. (This should be under your networked storage so it is not subject to erasure.) The program must compile and run on these computers.  Grading will be personalized and one-on-one with a TA or with Sam Buss.  The grading should be completed by Friday, February 22 if possible.  

INSTRUCTIONS:

1.     Make sure to save copies of all your files from Project 3.  This is VERY IMPORTANT! When you start a new project in Step 6 below, be sure to make **copies** of your source files first. And afterwards, add the copies into the new project.

2.     Download the file SurfProject4.zip from the web.  This zip file contains four (4) C++ source files, a file of shaders (SurfaceProj.glsl).  It also contains an executable MeshSurfDemo.exe.  (Full URL for the zip file is:
http://www.math.ucsd.edu/~sbuss/CourseWeb/Math155A_2019Winter/Project_4/SurfProject4.zip.)

3.     Run the executable on a PC.  You will see a scene with a surface of rotation and a letter "X".  Note the following commands act on the scene:

4.     Pressing the arrow keys changes the view position. 

a.      Pressing the “W” or “w” key toggles wire frame mode.  Note how flat and non-three-dimensional the objects look when filled in.  (We will fix this in project 5, when we add material properties and lights to the scene).

b.     Pressing the “C” or “c” key toggles culling of back faces. 

c.      Pressing the “M” or “m” key increases or decreases the mesh resolution on the spheres (ellipsoids) and cylinders. It also inceases the resolution of the ground plane and the surface of rotation.

d.     The animation can be turned off and on by pressing “R” or “r”. It can be put into single step mode by pressing “S” or “s”.  The animation can be made to run faster or slower by pressing “F” (faster) or “f” (slower).

e.      NEW: Pressing “N” or “n” cycles through three modes of visualizing surface normals. The first mode shows no surface normals. The second mode shows normal and wireframe mesh.  The third mode shows surface normals on top of the surface. (Try this last one in non-wireframe mode to see the difference.)

5.     Your job is to re-create this program -- sort of!!  However, you continue to use your own initial Project 3 instead using of the “S” in the Demo program.   You will re-create the surface of revolution as exactly as you can. 

6.     Form a NEW project and solution; integrate your project 3 code into the new project. Include the all supplied source files in the new project. (Again, save copies of your old source files!  Do not just include your Project 3 files in Project 4.)  The supplied source code handles all the keystroke commands, and draws a fixed 4x4 flat base plane, and a fixed, low resolution surface of rotation.   It has routines that need to be written for your Project 4 to form the surface of rotation and the ground plane.
The supplied source code should compile and run and show a non-meshable version of the scene once you get your Project 3 files integrated into the new project.  To integrate your Project 3 code into the new project

a.      Include most of the Project 3 files into your new Project 4. But do NOT include LetterProj.h, LetterProj.cpp or InitialProj.glsl

b.     Replace the supplied MyInitial.cpp with your own version of this file from Project 3. 

c.      Include the four new C++ files in the .zip file,  SurfaceProj.cpp, SurfaceProj.h, MySurfaces.cpp and MySurfaces.h into the new project.

d.     Add the SurfaceProj.glsl to the project.
IMPORTANT: Place an extra copy of SurfaceProj.glsl in the same folder as your Visual Studio project file if needed.

e.      Integrate your old MyInitial.cpp into the new code..  For this to work in the new project, you will need to make at least one changes in your MyInitial.cpp:

                                               i.     Replace the line  #include "InitialProj.h" with the line
 
#include "SurfaceProj.h"

f.      Make any other changes to get the code to work. If you made changes to MyInitial.h in your Project #3, please bring them into the new Project 4.

g.     If you made changes during Project 3 to InitialProj.cpp or any other source files, please also integrate those into the new project. This might happen, for instance, if you changed the controls for the animation.

h.     If you had to make changes for parts f. and g., make a note of them, as you will most likely need to do this again for Project 5.

i.      If you used a GlGeomTorus in  your Project #3, please download the latest version of GlGeomTorus.cpp (version 0.2) from the GlGeomShapes web page.  The old version does not generate the correct normals.

7.     There is a new source file: MySurfaces.cpp and the associated header file. This is the source file you will update for your Project 4 work. (Steps 8-16)

8.     The routine MyRemeshSurfaces() currently calls “Demo” routines that set the vertex information and element array information for rendering a ground plane and a circular surface of fixed mesh resolution.  The routine MyRenderSurfaces() currently calls “Demo” rendering routines to render these “Demo” versions of the ground plane and circular surface of fixed size.  You will replace these “Demo” routines with your own routines that generates a ground plane and a surface of rotation of variable mesh resolution.

9.     Examine the “Demo” code that generates the ground plane as a 4x4 mesh. It uses a new method of drawing with the glDrawElements command, which specifies a triangle strip by specifying the indices (called “elements”) of the vertices that belong to the triangle strip. You may look up online how this works, and we will discuss it in class on Friday. The vertex data is stored a VBO as before. The lists of elements are stored in a buffer called the “Element Array Buffer Object”, or EBO for short. The surface normal for the ground plane is set to the constant vector <0,1,0> by calling
glVertexAttrib3f(aNormal_loc, 0.0, 1.0, 0.0);
in the routine that renders the ground plane (the “floor”).  Find these things in the code, and understand how it all works.

10.  Examine the “Demo” code that generates the circular surface as a small mesh of triangle strips.  It uses the same kind of construction to use glDrawElements, but now the surface normals are also stored in the array with the vertex positions, and are loaded with the vertex positions into the VBO.  These surface normals are different for each vertex.

11.  Write code that generates the ground plane so that is can be dynamically meshed. This will be the two routines MyRemeshFloor and MyRenderFloor().

a.     MyRemeshFloor must

                                               i.     Allocate two arrays of the correct sizes using the C++ new operator.  (Optional: you may instead use std::vector if you prefer.)

                                             ii.     The global variable meshRes is defined in LetterProj.h and LetterProj.cpp, and it controls the mesh resolution.

                                            iii.     Fill the two arrays with the correct vertex positions in the array floorVerts and elements (vertex indices) in the array floorElements.  These will vary in size and contents based on the mesh resolution as specified by meshRes.

                                            iv.     Load the two arrays into the correct VBO and EBO.

                                              v.     Delete the two arrays to avoid memory leaks.

b.     MyRenderFloor must

                                               i.     Bind the vertex array for the floor

                                             ii.     Set all uniform variables and vertex attributes (color, normal, and modelview matrix) needed by the shader program.

                                            iii.     Loop to issue glDrawElement commands, one for each triangle strip.

c.      Hints for step a.iii.: To set the values in the array floorVerts of vertex positions you will want to use a nested pair of for loops to range over all the rectangularly-arranged vertices. Then, to set the values the array floorElements, you will again want to use a nested pair of for loops: the outer loop iterates over the triangle strips, and the inner one over elements within the triangle strip. If you have problems getting this code to work correctly, it is suggested to set meshRes to a small value (such as 3) and render only the first triangles of the first triangle strip. Once this works, you can try rendering more.  It is also suggested to use the debugger in single-step mode to see what is happening. You can examine individual values using the “Local” variables in the debugging window. Alternately, you can use “printf” to print part of the arrays to the console window.

12.  Write code that generates the surface of rotation. Place the surface of rotation in the front right quadrant of the ground plane, slightly above the ground plane.  The surface is a surface of rotation formed from the curve x*sin(x)/(x+1) for 0 ≤ x ≤ 2.7π, that is, x in [0, 2.7π].  You should scale and position the surface of rotation so that it looks approximately like the one in the supplied executable. It should be about the same size, and it should be above the base plane.  It should be constructed from triangle strips.  The general strategy to form this surface is the same as for the ground plane; however, now you must calculate and store a surface normal for each vertex.

13.  Keep your initial and its animation exactly the same as in Project 3! Please do not change it, but if you do, you must let the grader know ahead of time.    

14.  Your x*sin(x)/(x+1) surface should be well-formed: It should not have missing quads or triangles.  It should not have triangles that are drawn twice. It should have the front faces facing upward.  It should not have pixel-sized misalignments due to floating point round-off error.

15.  The keyboard controls that toggle back face culling and wireframe mode, and the mesh controls, should apply to all shapes in the scene. Check them carefully to make sure everything is OK

16.  Examine your normals carefully, using the “N” keystroke command. They should be pointing orthogonally out from the surface, and in the upward direction.  Examine this also at different mesh resolutions. Make sure the central normal on the surface of rotation is correct. Look at them in both wireframe mode and non-wireframe mode.

17.  Your finished program should look the similar to the supplied demo executable, except the "X" is replaced by your own creation and with animation from Project 3. It should support all the keystroke commands listed above including the ‘M’ and ‘N’ commands.

18.  Turn in the project to gradescope as described above.

Program grading: Scale of 0 to 10.  Personal grading session with a TA or Professor Sam Buss.

Suggestions on the x*sin(x)/(x+1) surface surface of rotation.  The best way to form this surface is to express it as a parametric function f(θ,r), where θ and r are scalar parameters.  The parameter r will control the radial distance from the center, the parameter θ will determine the rotation around the center of the surface of rotation.    The function r*sin(r)/(r+1) gives the height of the parametric surface, but this should be appropriately scaled to more-or-less match the shape in the demo program.   The scaling is best done with Mult_glScale commands. (Why? What happens to normals if you do the scaling in your to fill the VBO?)

The mesh detail for your surface must be controlled by the “m” and “M” commands as in the sample program supplied with the assignment. (Unfortunately, the “Shift Lock” key is not effective when capturing keystrokes by the method used in the code.)