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

Project #4 – Build a ground plane and surface of rotation with normals.
Due date: Friday, February 16, 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 normal.

·        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, named “Project4” as a suggestion, 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.  Your program must run on the PC lab, you must come into the PC lab and meet one of us.  As usual, you will have to show your source code, run the program, make changes on the spot to your program and recompile as requested by the grader, and be able to explain how your program works and why it renders what it does.  The grading should be completed by Friday, February 23 if possible.  


1.      Make sure to save copies of all your files from Project 3.  This is very important!

2.      Download the file from the web.  This zip file contains seventeen (17) C++ source and header files.  It also contains an executable MeshSurfDemo.exe.  (Full URL for the zip file is:

3.      Run the executable on a PC.  You will see a scene with a surface of rotation and a letter "S".  (That's my initial.).  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 by adding 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.

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. Include the all supplied source files in the new project. (Again, save copies of your old source files!  Do not overwrite them.)  The supplied source code handles all the keystroke commands, and draws the flat base plane, and a sphere that marks the position of the surface of rotation.   It has routines that you will need to rewrite 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.

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

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

                                                    i.     Replace the line  #include "ShaderMgrLTR.h" with the line       #include "ShaderMgrLTR2.h"

                                                  ii.     Replace the two lines
mySphere.InitializeAttribLocations(aPos_loc);    myCylinder.InitializeAttribLocations(aPos_loc);
mySphere.InitializeAttribLocations(aPos_loc,aNormal_loc);    myCylinder.InitializeAttribLocations(aPos_loc, aNormal_loc);
so that the spheres and cylinders will have surface normals.

c.      If you made changes to MyInitial.h in your Project #3, please bring them into the new Project 4.

d.      If you made changes to LetterProj.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.

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

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.

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 renders 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 fans.  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<float> 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 needed uniform vertex attributes (color, normal, and modelview matrix).

                                                 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 sin(x)/x for 0 ≤ x ≤ 5π, that is, x in [0,5π].  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 (sin r)/r 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.

16.   Your finished program should look the similar to the supplied demo executable, except the "S" 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.

17.   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 (sin r)/r 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 (sin r)/r 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 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.)