Download - Computer Graphics Through OpenGL: From Theory to

137
Computer Graphics Through OpenGL: From Theory to Experiments by Sumanta Guha Chapman & Hall/CRC v

Transcript of Download - Computer Graphics Through OpenGL: From Theory to

Page 1: Download - Computer Graphics Through OpenGL: From Theory to

Computer Graphics ThroughOpenGL: From Theory toExperiments

by Sumanta Guha

Chapman & Hall/CRC

v

Page 2: Download - Computer Graphics Through OpenGL: From Theory to
Page 3: Download - Computer Graphics Through OpenGL: From Theory to

Experimenter Software(Prepared by Chansophea Chuon and Sumanta Guha)

This file is to help you run the book experiments. It’s in pdf format listingall the book experiments, with clickable hyperlinks on top of each. Foralmost all experiments there is one link, which works in Windows, MacOS and Linux environments, to bring up the program file, and another tobring up the Windows project, which, of course, works only in a Windowsenvironment. Since source code is not available for the three experiments inthe first chapter, the reader is pointed to a folder with Windows and Macexecutables.

For experiments asking simply to run a book program, Experimenterbrings that program up, while for those asking that a program be modifiedsignificantly, the modified program – the modification being made either inthe code or comments – comes up. For example, an experiment often asks youto replace a part of a book program with a block of code listed in the textand, possibly, in a file in the ExperimenterSource/CodeModifications

folder, as well, for easy copy-and-paste. In this case, Experimenter will throwup the modified program either ready to run or needing only a block tobe uncommented, saving you the trouble of typing or pasting. For trivialmodifications of a program, though, Experimenter links to just the program,leaving you to make changes.

Note: The names of the folders in ExperimenterSource – e.g., Experiment-RotateTeapotMore for Experiment 4.7 of the text – mostly do not appearin the text itself and are of little relevance.

Experimenter is meant as a convenience; it certainly is not mandatoryin order to run the programs or experiments, which all work perfectly wellstand-alone. However, because of the way it is organized, Experimentermakes it easy to run the programs as one follows the text so we stronglyrecommend that readers use it.

Installing and using Experimenter : Download the directory Experimenter-

Source from the book’s website www.sumantaguha.com and install it as asubfolder of the same folder where you have Experimenter.pdf (the fileyou are reading, also to be found at the book’s site). It’s best to use Adobe vii

Page 4: Download - Computer Graphics Through OpenGL: From Theory to

Reader to open Experimenter.pdf as other pdf readers might not be ableto resolve the hyperlinks. Windows users should note that Experimenterwill be slow in bringing up each project the first time, as various config fileshave to be generated locally; it should be fast after that.

If you need to learn how to set up an environment in which to run OpenGLcode, then you will find a guide at the book’s website www.sumantaguha.comto installing OpenGL and running the programs on various platforms.

Adding your own experiments to Experimenter : Presuming you are usingLatex, first include the hyperref package in your document. In our case,we did so with the line

\usepackage[pdftex]{hyperref}

Subsequently, add hyperlinks as follows (a sample from Experimenter’s Latexfile):

Click for \ic{square.cpp}~~~

\href{run:ExperimenterSource/Chapter2/Square/square.cpp}

{{\color{red}\ic{Program}}}~~~

\href{run:ExperimenterSource/Chapter2/Square/Square.vcxproj}

{{\color{red}\ic{Windows Project}}}

Once you have created your own Experimenter-like document with clickablehyperlinks, you can mix and match pages of it with Experimenter by usinga pdf document manipulating tool.

We hope you find Experimenter of help as you read the book. All feedbackis welcome: send mail to [email protected].

viii

Page 5: Download - Computer Graphics Through OpenGL: From Theory to

Part I

Hello World

1

Page 6: Download - Computer Graphics Through OpenGL: From Theory to
Page 7: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 1An Invitation to ComputerGraphics

Executables for Windows and the Mac are in the folderExperimenterSource/Chapter1/Ellipsoid.

Experiment 1.1. Open ExperimenterSource/Chapter1/Ellipsoid and,hopefully, you’ll be able to run at least one of the two executables therefor the Ellipsoid program – one for Windows and one for the Mac. Theprogram draws an ellipsoid (an egg shape). The left of Figure 1.16 showsthe initial screen. There’s plenty of interactivity to try as well. Press any ofthe four arrow keys, as well as the page up and down keys, to change theshape of the ellipsoid, and ‘x’, ‘X’, ‘y’, ‘Y’, ‘z’ and ‘Z’ to turn it.

It’s a simple object, but the three-dimensionality of it comes acrossrather nicely does it not? As with almost all surfaces that we’ll be drawingourselves, the ellipsoid is made up of triangles. To see these press the spacebar to enter wireframe mode. Pressing space again restores the filled mode.Wireframe reveals the ellipsoid to be a mesh of triangles decorated withlarge points. A color gradient has apparently been applied toward the polesas well.

Drawing an ellipsoid with many triangles may seem a hard way to dothings. Interestingly, and often surprisingly for the beginner, OpenGL offersthe programmer only a tiny set of low-level geometric primitives with whichto make objects – in fact, points, lines and triangles are, basically, it. So,a curved 3D object like an ellipsoid has to be made, or, more accurately,approximated , using triangles. But, as we shall see as we go along, theprocess really is not all that difficult.

That’s it. There’s really not much more to this program: no lighting orblending or other effects you may have heard of as possible using OpenGL 3

Page 8: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 1

An Invitation to

Computer Graphics

(understandably, as the program was written just a few weeks into thesemester). It’s just a bunch of colored triangles and points laid out in 3Dspace. The magic is in those last two words: 3D space. 3D modeling is allabout making things in 3D – not a flat plane – to create an illusion of depth,even when viewing on a flat plane (the screen). End

Executables for Windows and the Mac are in the folderExperimenterSource/Chapter1/AnimatedGarden.

Experiment 1.2. Our next program is animated. It creates a gar-den which grows and grows and grows. You will find executables inExperimenterSource/Chapter1/AnimatedGarden. Press enter to start theanimation; enter again to stop it. The delete key restarts the animation,while the period key toggles between the camera rotating and not. Again, thespace key toggles between wireframe and filled. The middle of Figure 1.16 isa screenshot a few seconds into the animation.

As you can see from the wireframe, there’s again a lot of triangles (in fact,the flowers might remind you of the ellipsoid from the previous program).The plant stems are thick lines and, if you look carefully, you’ll spot pointsas well. The one special effect this program has that Ellipsoid did not isblending, as is not hard to see. End

Executables for Windows and the Mac are in the folderExperimenterSource/Chapter1/Dominos.

Experiment 1.3. Our final program is a movie which shows a RubeGoldberg domino effect with “real” dominos. The executables are inExperimenterSource/Chapter1/Dominos. Simply press enter to start andstop the movie. The screenshot on the right of Figure 1.16 is from part waythrough.

This program has a bit of everything – textures, lighting, cameramovement and, of course, a nicely choreographed animation sequence, amongothers. Neat, is it not? End

4

Page 9: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 2On to OpenGL and 3D ComputerGraphics

Click for square.cpp Program Windows Project

Experiment 2.1. Run square.cpp.

Note: Visit the book’s website www.sumantaguha.com for a guide on howto install OpenGL and run our programs on various platforms.∗

In the OpenGL window appears a black square over a white background.Figure 2.1 is an actual screenshot, but we’ll draw it as in Figure 2.2, bluishgreen standing in for white in order to distinguish it from the paper. We aregoing to understand next how the square is drawn, and gain some insight aswell into the workings behind the scene. End

Click for square.cpp Program Windows Project

Experiment 2.2. Change the glutInitWindowSize() parameter valuesof square.cpp∗ – first to glutInitWindowSize(300, 300) and thenglutInitWindowSize(500, 250). The square changes in size, and evenshape, with the OpenGL window. Therefore, coordinate values appear notto be in any kind of absolute units on the screen. End

∗If your program compiles but doesn’t run, this might be because your graphics carddoesn’t support OpenGL 4.3. See the note following item 2 in Section 2.11 for what to doin this case.

∗When we refer to square.cpp, or any program.cpp, it’s always to the original versionin a folder in the ExperimenterSource directory, so if you’ve modified the code for anearlier experiment you’ll need to copy back the original. 5

Page 10: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 2

On to OpenGL and

3D Computer

Graphics

Click for square.cpp modified Program Windows Project

Experiment 2.3. Change only the viewing box of square.cpp by replac-ing glOrtho(0.0, 100.0, 0.0, 100.0, -1.0, 1.0) with glOrtho(-100,

100.0, -100.0, 100.0, -1.0, 1.0). The location of the square in thenew viewing box is different and, so as well, the result of shoot-and-print.Figure 2.11 explains how. End

Click for square.cpp Program Windows Project

Experiment 2.4. Change the parameters of glutInitWindowPosition(x,y) in square.cpp from the current (100, 100) to a few different values todetermine the location of the origin (0, 0) of the computer screen, as well asthe orientation of the screen’s own x-axis and y-axis. End

Click for square.cpp modified Program Windows Project

Experiment 2.5. Add another square by inserting the following rightafter the code for the original square in square.cpp (Block 2):

glBegin(GL POLYGON);

glVertex3f(120.0, 120.0, 0.0);

glVertex3f(180.0, 120.0, 0.0);

glVertex3f(180.0, 180.0, 0.0);

glVertex3f(120.0, 180.0, 0.0);

glEnd();

From the value of its vertex coordinates the second square evidently liesentirely outside the viewing box.

If you run now there’s no sign of the second square in the OpenGLwindow! This is because OpenGL clips the scene to within the viewing boxbefore rendering, so that objects or parts of objects drawn outside are notrendered. Clipping is a stage in the graphics pipeline. We’ll not worry aboutits implementation at this time, only the effect it has. End

Click for square.cpp modified Program Windows Project

Experiment 2.6. For a more dramatic illustration of clipping, first replacethe square in the original square.cpp with a triangle; in particular, replacethe polygon code with the following (Block 3):

glBegin(GL POLYGON);

glVertex3f(20.0, 20.0, 0.0);

glVertex3f(80.0, 20.0, 0.0);

glVertex3f(80.0, 80.0, 0.0);

glEnd();6

Page 11: Download - Computer Graphics Through OpenGL: From Theory to

See Figure 2.13. Next, lift the first vertex up the z-axis by changing itto glVertex3f(20.0, 20.0, 0.5); lift it further by changing its z-value to1.5 (Figure 2.14 is a screenshot), then 2.5 and, finally, 10.0. Make sure youbelieve that what you see in the last three cases is indeed a triangle clippedto within the viewing box – Figure 2.15 may be helpful. End

Click for square.cpp Program Windows Project

Experiment 2.7. The color of the square in square.cpp is specified bythe three parameters of the glColor3f(0.0, 0.0, 0.0) statement in thedrawScene() routine, each of which gives the value of one of the threeprimary components, blue, green and red .

Determine which of the three parameters of glColor3f() specifies theblue, green and red components by setting in turn each to 1.0 and the othersto 0.0. In fact, verify the following table:

Call ColorglColor3f(0.0, 0.0, 0.0) BlackglColor3f(1.0, 0.0, 0.0) RedglColor3f(0.0, 1.0, 0.0) GreenglColor3f(0.0, 0.0, 1.0) BlueglColor3f(1.0, 1.0, 0.0) YellowglColor3f(1.0, 0.0, 1.0) MagentaglColor3f(0.0, 1.0, 1.0) CyanglColor3f(1.0, 1.0, 1.0) White

End

Click for square.cpp modified Program Windows Project

Experiment 2.8. Add the additional color declaration statement gl-

Color3f(1.0, 0.0, 0.0) just after the existing one glColor3f(0.0, 0.0,

0.0) in the drawing routine of square.cpp so that the foreground colorblock becomes

// Set foreground (or drawing) color.

glColor3f(0.0, 0.0, 0.0);

glColor3f(1.0, 0.0, 0.0);

The square is drawn red because the current value of the foreground color isred when each of its vertices is specified. End

Click for square.cpp modified Program Windows Project 7

Page 12: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 2

On to OpenGL and

3D Computer

Graphics

Experiment 2.9. Replace the polygon declaration part of square.cppwith the following to draw two squares (Block 5):

glColor3f(1.0, 0.0, 0.0);

glBegin(GL POLYGON);

glVertex3f(20.0, 20.0, 0.0);

glVertex3f(80.0, 20.0, 0.0);

glVertex3f(80.0, 80.0, 0.0);

glVertex3f(20.0, 80.0, 0.0);

glEnd();

glColor3f(0.0, 1.0, 0.0);

glBegin(GL POLYGON);

glVertex3f(40.0, 40.0, 0.0);

glVertex3f(60.0, 40.0, 0.0);

glVertex3f(60.0, 60.0, 0.0);

glVertex3f(40.0, 60.0, 0.0);

glEnd();

A small green square appears inside a larger red one (Figure 2.17).Obviously, this is because the foreground color is red for the first square,but green for the second. One says that the color red binds to the firstsquare – or, more precisely, to each of its four specified vertices – and greento the second square. These bound values specify the color attribute of eithersquare. Generally, the values of those state variables which determine howit is rendered collectively form a primitive’s attribute set.

Flip the order in which the two squares appear in the code by cuttingthe seven statements that specify the red square and pasting them afterthose to do with the green one. The green square is overwritten by the redone and no longer visible because OpenGL draws in code order .

End

Click for square.cpp modified Program Windows Project

Experiment 2.10. Replace the polygon declaration part of square.cppwith (Block 6):

glBegin(GL POLYGON);

glColor3f(1.0, 0.0, 0.0);

glVertex3f(20.0, 20.0, 0.0);

glColor3f(0.0, 1.0, 0.0);

glVertex3f(80.0, 20.0, 0.0);

glColor3f(0.0, 0.0, 1.0);

glVertex3f(80.0, 80.0, 0.0);

glColor3f(1.0, 1.0, 0.0);

glVertex3f(20.0, 80.0, 0.0);

glEnd();8

Page 13: Download - Computer Graphics Through OpenGL: From Theory to

The different color values bound to the four vertices of the square are evidentlyinterpolated over the rest of the square as you can see in Figure 2.18. In fact,this is most often the case with OpenGL: numerical attribute values specifiedat the vertices of a primitive are interpolated throughout its interior. In alater chapter we’ll see exactly what it means to interpolate and how OpenGLgoes about the task. End

Click for square.cpp modified Program Windows Project

Experiment 2.11. Replace glBegin(GL POLYGON) with glBegin(GL -

POINTS) in square.cpp and make the point size bigger with a call toglPointSize(5.0), so that the part drawing the polygon is now

glPointSize(5.0); // Set point size.

glBegin(GL POINTS);

glVertex3f(20.0, 20.0, 0.0);

glVertex3f(80.0, 20.0, 0.0);

glVertex3f(80.0, 80.0, 0.0);

glVertex3f(20.0, 80.0, 0.0);

glEnd();

End

Click for square.cpp modified Program Windows Project

Experiment 2.12. Continue, replacing GL POINTS with GL LINES, GL -

LINE STRIP and, finally, GL LINE LOOP. End

Click for square.cpp modified Program Windows Project

Experiment 2.13. Replace the polygon declaration part of square.cppwith (Block 8):

glBegin(GL TRIANGLES);

glVertex3f(10.0, 90.0, 0.0);

glVertex3f(10.0, 10.0, 0.0);

glVertex3f(35.0, 75.0, 0.0);

glVertex3f(30.0, 20.0, 0.0);

glVertex3f(90.0, 90.0, 0.0);

glVertex3f(80.0, 40.0, 0.0);

glEnd();

End

Click for square.cpp modified Program Windows Project 9

Page 14: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 2

On to OpenGL and

3D Computer

Graphics

Experiment 2.14. In fact, it’s often easier to decipher a 2D primitiveby viewing it in outline. Accordingly, continue the preceding experimentby inserting the call glPolygonMode(GL FRONT AND BACK, GL LINE) in thedrawing routine and, further, replacing GL TRIANGLES with GL TRIANGLE -

STRIP. The relevant part of the display routine then is as below:

// Set polygon mode.

glPolygonMode(GL FRONT AND BACK, GL LINE);

// Draw a triangle strip.

glBegin(GL TRIANGLE STRIP);

glVertex3f(10.0, 90.0, 0.0);

glVertex3f(10.0, 10.0, 0.0);

glVertex3f(35.0, 75.0, 0.0);

glVertex3f(30.0, 20.0, 0.0);

glVertex3f(90.0, 90.0, 0.0);

glVertex3f(80.0, 40.0, 0.0);

glEnd();

End

Click for square.cpp modified Program Windows Project

Experiment 2.15. Replace the polygon declaration part of square.cppwith (Block 9):

glBegin(GL TRIANGLE FAN);

glVertex3f(10.0, 10.0, 0.0);

glVertex3f(15.0, 90.0, 0.0);

glVertex3f(55.0, 75.0, 0.0);

glVertex3f(80.0, 30.0, 0.0);

glVertex3f(90.0, 10.0, 0.0);

glEnd();

Apply both the filled and outlined drawing modes. End

Click for square.cpp modified Program Windows Project

Experiment 2.16. Replace the polygon declaration of square.cpp with(Block 10):

glBegin(GL POLYGON);

glVertex3f(20.0, 20.0, 0.0);

glVertex3f(50.0, 20.0, 0.0);

glVertex3f(80.0, 50.0, 0.0);

glVertex3f(80.0, 80.0, 0.0);

glVertex3f(20.0, 80.0, 0.0);

glEnd();10

Page 15: Download - Computer Graphics Through OpenGL: From Theory to

You see a convex 5-sided polygon (Figure 2.22(a)). End

Click for square.cpp modified Program Windows Project

Experiment 2.17. Replace the polygon declaration of square.cpp with(Block 11):

glBegin(GL POLYGON);

glVertex3f(20.0, 20.0, 0.0);

glVertex3f(80.0, 20.0, 0.0);

glVertex3f(40.0, 40.0, 0.0);

glVertex3f(20.0, 80.0, 0.0);

glEnd();

Display it both filled and outlined using appropriate glPolygonMode()

calls. A non-convex quadrilateral is drawn in either case (Figure 2.22(b)).Next, keeping the same cycle of vertices as above, list them starting withglVertex3f(80.0, 20.0, 0.0) instead (Block 12):

glBegin(GL POLYGON);

glVertex3f(80.0, 20.0, 0.0);

glVertex3f(40.0, 40.0, 0.0);

glVertex3f(20.0, 80.0, 0.0);

glVertex3f(20.0, 20.0, 0.0);

glEnd();

Make sure to display it both filled and outlined. When filled it’s a triangle,while outlined it’s a non-convex quadrilateral (Figure 2.22(c)) identical tothe one output earlier! Because the cyclic order of the vertices is unchanged,shouldn’t it be as in Figure 2.22(b) both filled and outlined? End

Click for circle.cpp Program Windows Project

Experiment 2.18. Run circle.cpp. Increase the number of vertices inthe line loop

glBegin(GL LINE_LOOP);

for(i = 0; i < numVertices; ++i)

{glColor3f((float)rand()/(float)RAND MAX,

(float)rand()/(float)RAND MAX,

(float)rand()/(float)RAND MAX);

glVertex3f(X + R * cos(t), Y + R * sin(t), 0.0);

t += 2 * PI / numVertices;

}glEnd(); 11

Page 16: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 2

On to OpenGL and

3D Computer

Graphics

by pressing ‘+’ till it “becomes” a circle, as in the screenshot of Figure 2.24.Press ‘-’ to decrease the number of vertices. The randomized colors are justa bit of eye candy. End

Click for parabola.cpp Program Windows Project

Experiment 2.19. Run parabola.cpp. Press ‘+/-’ to increase/decreasethe number of vertices of the approximating line strip. Figure 2.26 is ascreenshot with enough vertices to make a smooth-looking parabola.

The vertices are equally spaced along the x-direction. The parametricequations implemented are

x = 50 + 50t, y = 100t2, z = 0, −1 ≤ t ≤ 1

the constants being chosen so that the parabola is centered in the OpenGLwindow. End

Click for circularAnnuluses.cpp Program Windows Project

Experiment 2.20. Run circularAnnuluses.cpp. Three identical-looking red circular annuluses (Figure 2.29) are drawn in three differentways:

i) Upper-left: There is not a real hole. The white disc overwrites the reddisc as it appears later in the code.

glColor3f(1.0, 0.0, 0.0);

drawDisc(20.0, 25.0, 75.0, 0.0);

glColor3f(1.0, 1.0, 1.0);

drawDisc(10.0, 25.0, 75.0, 0.0);

Note: The first parameter of drawDisc() is the radius and theremaining three the coordinates of the center.

ii) Upper-right: There is not a real hole either. A white disc is drawncloser to the viewer than the red disc thus blocking it out.

glEnable(GL DEPTH TEST);

glColor3f(1.0, 0.0, 0.0);

drawDisc(20.0, 75.0, 75.0, 0.0);

glColor3f(1.0, 1.0, 1.0);

drawDisc(10.0, 75.0, 75.0, 0.5);

glDisable(GL DEPTH TEST);12

Page 17: Download - Computer Graphics Through OpenGL: From Theory to

Observe that the z-value of the white disc’s center is greater than thered disc’s. We’ll discuss the mechanics of one primitive blocking outanother momentarily.

iii) Lower: A true circular annulus with a real hole.

if (isWire) glPolygonMode(GL FRONT, GL LINE);

else glPolygonMode(GL FRONT, GL FILL);

glColor3f(1.0, 0.0, 0.0);

glBegin(GL TRIANGLE STRIP);

. . .glEnd();

Press the space bar to see the wireframe of a triangle strip. End

Click for helix.cpp Program Windows Project

Experiment 2.21. Okay, run helix.cpp now. All we see is a circle as inFigure 2.33(a)! There’s no sign of any coiling up or down. The reason, ofcourse, is that the orthographic projection onto the viewing face flattens thehelix. Let’s see if it makes a difference to turn the helix upright, in particular,so that it coils around the y-axis. Accordingly, replace the statement

glVertex3f(R * cos(t), R * sin(t), t - 60.0);

in the drawing routine with

glVertex3f(R * cos(t), t, R * sin(t) - 60.0);

Hmm, not a lot better (Figure 2.33(b))! End

Click for helix.cpp modified Program Windows Project

Experiment 2.22. Fire up the original helix.cpp program. Replaceorthographic projection with perspective projection; in particular, replacethe projection statement

glOrtho(-50.0, 50.0, -50.0, 50.0, 0.0, 100.0);

with

glFrustum(-5.0, 5.0, -5.0, 5.0, 5.0, 100.0);

You can see a real spiral now (Figure 2.36(a)). View the upright version aswell (Figure 2.36(b)), replacing

glVertex3f(R * cos(t), R * sin(t), t - 60.0); 13

Page 18: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 2

On to OpenGL and

3D Computer

Graphics

with

glVertex3f(R * cos(t), t, R * sin(t) - 60.0);

A lot better than the orthographic version is it not?! End

Click for moveSphere.cpp Program Windows Project

Experiment 2.23. Run moveSphere.cpp, which simply draws a movablesphere in the OpenGL window. Press the left, right, up and down arrowkeys to move the sphere, the space bar to rotate it and ‘r’ to reset.

The sphere appears distorted as it nears the periphery of the window,as you can see from the screenshot in Figure 2.37. Can you guess why?Ignore the code, especially unfamiliar commands such as glTranslatef()

and glRotatef(), except for the fact that the projection is perspective.This kind of peripheral distortion of a 3D object is unavoidable in any

viewing system which implements the synthetic-camera model. It happenswith a real camera as well, but we don’t notice it as much because the fieldof view when snapping pictures is usually quite large and objects of interesttend to be centered. End

Click for hemisphere.cpp Program Windows Project

Experiment 2.24. Run hemisphere.cpp, which implements exactly thestrategy just described. You can verify this from the snippet that draws thehemisphere:

for(j = 0; j < q; j++)

{// One latitudinal triangle strip.

glBegin(GL TRIANGLE STRIP);

for(i = 0; i <= p; i++)

{glVertex3f(R * cos((float)(j+1)/q * PI/2.0) *

cos(2.0 * (float)i/p * PI),

R * sin((float)(j+1)/q * PI/2.0),

R * cos((float)(j+1)/q * PI/2.0) *

sin(2.0 * (float)i/p * PI));

glVertex3f(R * cos((float)j/q * PI/2.0) *

cos(2.0 * (float)i/p * PI),

R * sin((float)j/q * PI/2.0),

R * cos((float)j/q * PI/2.0) *

sin(2.0 *(float)i/p * PI));

}glEnd();

}14

Page 19: Download - Computer Graphics Through OpenGL: From Theory to

Increase/decrease the number of longitudinal slices by pressing ‘P/p’.Increase/decrease the number of latitudinal slices by pressing ‘Q/q’. Turnthe hemisphere about the axes by pressing ‘x’, ‘X’, ‘y’, ‘Y’, ‘z’ and ‘Z’. SeeFigure 2.40 for a screenshot. End

Click for hemisphere.cpp Program Windows Project

Experiment 2.25. Playing around a bit with the code will help clarifythe construction of the hemisphere:

(a) Change the range of the hemisphere’s outer loop from

for(j = 0; j < q; j++)

to

for(j = 0; j < 1; j++)

Only the bottom strip is drawn. The keys ‘P/p’ and ‘Q/q’ still work.

(b) Change it again to

for(j = 0; j < 2; j++)

Now, the bottom two strips are drawn.

(c) Reduce the range of both loops:

for(j = 0; j < 1; j++)

. . .for(i = 0; i <= 1; i++)

. . .

The first two triangles of the bottom strip are drawn.

(d) Increase the range of the inner loop by 1:

for(j = 0; j < 1; j++)

. . .for(i = 0; i <= 2; i++)

. . .

The first four triangles of the bottom strip are drawn. End

15

Page 20: Download - Computer Graphics Through OpenGL: From Theory to
Page 21: Download - Computer Graphics Through OpenGL: From Theory to

Part II

Tricks of the Trade

17

Page 22: Download - Computer Graphics Through OpenGL: From Theory to
Page 23: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 3An OpenGL Toolbox

Click for squareAnnulus1.cpp Program Windows Project

Experiment 3.1. Run squareAnnulus1.cpp. A screenshot is seen inFigure 3.1(a). Press the space bar to see the wireframe in Figure 3.1(b).

It is a plain-vanilla program which draws the square annulus dia-grammed in Figure 3.2 using a single triangle strip defined by a giantglBegin(GL TRIANGLE STRIP)-glEnd() block containing 10 vertices andtheir color attributes (the last two vertices being identical to the first two inorder to close the strip).

End

Click for squareAnnulus2.cpp Program Windows Project

Experiment 3.2. Run squareAnnulus2.cpp.It draws the same annulus as squareAnnulus1.cpp, except that the

vertex coordinates and color data are now separately stored in two-dimensional global arrays, vertices and colors, respectively. Moreover, ineach iteration, the loop

glBegin(GL_TRIANGLE_STRIP);

for(int i = 0; i < 10; ++i)

{glColor3fv(colors[i%8]);

glVertex3fv(vertices[i%8]);

}glEnd();

retrieves a vector of coordinate values by the pointer form (also called vectorform) of vertex declaration, namely, glVertex3fv(*pointer), and as well avector of color values with the pointer form glColor3fv(*pointer). End 19

Page 24: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 3

An OpenGL Toolbox

Click for squareAnnulus3.cpp Program Windows Project

Experiment 3.3. Run squareAnnulus3.cpp.It again draws the same colorful annulus as before. The coordinates and

color data of the vertices are stored in one-dimensional global vertex arrays,vertices and colors, respectively, as in squareAnnulus2.cpp, except, now,the arrays are flat and not 2D (because of the way C++ stores array data,we could, in fact, have specified vertices and colors as 2D arrays exactlyas in squareAnnulus2.cpp if we had so wanted). End

Click for squareAnnulus4.cpp Program Windows Project

Experiment 3.4. Run squareAnnulus4.cpp.The code is even more concise with the single call

glDrawElements(GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, stripIndices)

replacing the entire glBegin(GL TRIANGLE STRIP)-glEnd() block. End

Click for squareAnnulusAndTriangle.cpp Program Windows Project

Experiment 3.5. Run squareAnnulusAndTriangle.cpp, which adds atriangle inside the annulus of the squareAnnulus*.cpp programs. SeeFigure 3.3 for a screenshot. End

Click for hemisphereMultidraw.cpp Program Windows Project

Experiment 3.6. Run hemisphereMultidraw.cpp, whose sole purpose isto draw the loop

for(j = 0; j < q; j++)

{// One latitudinal triangle strip.

glBegin(GL_TRIANGLE_STRIP);

...

}

of triangle strips in hemisphere.cpp using the single

glMultiDrawElements(GL_TRIANGLE_STRIP, count, GL_UNSIGNED_BYTE,

(const void **)indices, q)

command instead. End

Click for squareAnnulusVBO.cpp Program Windows Project20

Page 25: Download - Computer Graphics Through OpenGL: From Theory to

Experiment 3.7. Fire up squareAnnulusVBO.cpp, which modifies square-Annulus4.cpp to store vertex-related data in VBOs. There is a simpleanimation, too, through periodically changing color values in a VBO.Figure 3.5 is a screenshot, colors having already changed. End

Click for hemisphereMultidrawVBO.cpp Program Windows Project

Experiment 3.8. Run hemisphereMultidrawVBO.cpp. The code, whichbuffers the vertex and index data of hemisphereMultidraw.cpp along thelines of vbo.cpp, should be intelligible to one who followed our analysis ofthe latter program. End

Click for squareAnnulusAndTriangleVAO.cpp Program Windows

Project

Experiment 3.9. Run squareAnnulusAndTriangleVAO.cpp. This pro-gram builds on squareAnnulusVBO.cpp. We add to it the triangle fromsquareAnnulusAndTriangle.cpp in order to have two VAOs. Note, however,that we separate out the vertex coordinates and color arrays of the triangle,as intertwined they are difficult to manage in a VBO. The outputs of thecurrent program and squareAnnulusAndTriangle.cpp are identical. End

Click for helixList.cpp Program Windows Project

Experiment 3.10. Run helixList.cpp, which shows many copies of thesame helix, variously transformed and colored. Figure 3.6 is a screenshot.End

Click for multipleLists.cpp Program Windows Project

Experiment 3.11. Run multipleLists.cpp. See Figure 3.7 for ascreenshot. Three display lists are defined in the program: to draw ared triangle, a green rectangle and a blue pentagon, respectively. End

Click for fonts.cpp Program Windows Project

Experiment 3.12. Run fonts.cpp. Displayed are the various fontsavailable through the FreeGLUT library. See Figure 3.9. End

Click for mouse.cpp Program Windows Project 21

Page 26: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 3

An OpenGL Toolbox

Experiment 3.13. Run mouse.cpp. Click the left mouse button to drawpoints on the canvas and the right one to exit. Figure 3.10 is a screenshot of“OpenGL” scrawled in points. End

Click for mouseMotion.cpp Program Windows Project

Experiment 3.14. Run mouseMotion.cpp, which enhances mouse.cpp

by allowing the user to drag the just-created point using the mouse with theleft button still pressed. End

Click for mouseWheel.cpp Program Windows Project

Experiment 3.15. Run mouseWheel.cpp, which further enhances mouse-Motion.cpp with the capability to change the size of the points drawn byturning the mouse wheel. End

Click for moveSphere.cpp Program Windows Project

Experiment 3.16. Run moveSphere.cpp, a program we saw earlier inExperiment 2.23, where you can see a screenshot as well. Press the left,right, up and down arrow keys to move the sphere, the space bar to rotateit and ‘r’ to reset.

Note how the specialKeyInput() routine is written to enable the arrowkeys to change the location of the sphere. Subsequently, this routine isregistered in main() as the handling routine for non-ASCII entry. End

Click for menus.cpp Program Windows Project

Experiment 3.17. Run menus.cpp. Press the right mouse button formenu options which allow you to change the color of the initially red squareor exit. Figure 3.12 is a screenshot. End

Click for lineStipple.cpp Program Windows Project

Experiment 3.18. Run lineStipple.cpp. Press the space bar to cyclethrough stipples. A screenshot is shown in Figure 3.13. End

Click for canvas.cpp Program Windows Project22

Page 27: Download - Computer Graphics Through OpenGL: From Theory to

Experiment 3.19. Run canvas.cpp, a simple program to draw on a flatcanvas with menu and mouse functionality.

Left click on an icon to select it. Then left click on the drawing area todraw – click once to draw a point, twice to draw a line or rectangle. Rightclick for a pop-up menu. Figure 3.15 is a screenshot. End

Click for glutObjects.cpp Program Windows Project

Experiment 3.20. Run glutObjects.cpp. Press the arrow keys to cyclethrough the various FreeGLUT objects and ‘x/X’, ‘y/Y’ and ‘z/Z’ to turnthem. End

Click for clippingPlanes.cpp Program Windows Project

Experiment 3.21. Run clippingPlanes.cpp, which augments circular-Annuluses.cpp with two additional clipping planes which can be toggledon and off by pressing ‘0’ and ‘1’, respectively.

The first plane clips off the half-space −z + 0.25 < 0, i.e., z > 0.25,removing the floating white disc of the annulus on the upper-right. Thesecond one clips off the half-space x+ 0.5y < 60.0, which is the space belowan angled plane parallel to the z-axis. Figure 3.18 is a screenshot of bothclipping planes activated. End

Click for hemisphere.cpp Program Windows Project

Experiment 3.22. Run hemisphere.cpp.The initial OpenGL window is a square 500× 500 pixels. Drag a corner

to change its shape, making it tall and thin. The hemisphere is distortedto become ellipsoidal (Figure 3.23(a)). Replace the perspective projectionstatement

glFrustum(-5.0, 5.0, -5.0, 5.0, 5.0, 100.0);

with

gluPerspective(90.0, 1.0, 5.0, 100.0);

As this is equivalent to the original glFrustum() call, there is still distortionif the window’s shape is changed. Next, replace the projection statementwith

gluPerspective(90.0, (float)w/(float)h, 5.0, 100.0);

which sets the aspect ratio of the viewing frustum equal to that of theOpenGL window. Resize the window – the hemisphere is no longer distorted(Figure 3.23(b))! End 23

Page 28: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 3

An OpenGL Toolbox

Click for viewports.cpp Program Windows Project

Experiment 3.23. Run viewports.cpp where the screen is split into twoviewports with contents a square and a circle, respectively. Figure 3.25 is ascreenshot.

A vertical black line is drawn (in the program) at the left end of thesecond viewport to separate the two. As the aspect ratio of both viewportsdiffers from that of the viewing face, the square and circle are squashedlaterally. End

Click for windows.cpp Program Windows Project

Experiment 3.24. Run windows.cpp, which creates two top-level win-dows (Figure 3.26). End

24

Page 29: Download - Computer Graphics Through OpenGL: From Theory to

Part III

Movers and Shapers

25

Page 30: Download - Computer Graphics Through OpenGL: From Theory to
Page 31: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 4Transformation, Animation andViewing

Click for box.cpp Program Windows Project

Experiment 4.1. Run box.cpp, which shows an axis-aligned – i.e., withsides parallel to the coordinate axes – FreeGLUT wireframe box of dimensions5× 5× 5. Figure 4.1 is a screenshot. Note the foreshortening – the back ofthe box appears smaller than the front – because of perspective projectionin the viewing frustum specified by the glFrustum() statement.

Comment out the statement

glTranslatef(0.0, 0.0, -15.0);

What do you see now? Nothing ! We’ll explain why momentarily. End

Click for box.cpp modified Program Windows Project

Experiment 4.2. Successively replace the translation command ofbox.cpp with the following, making sure that what you see matches yourunderstanding of where the command places the box. Keep in mindforeshortening, as well as clipping to within the viewing frustum.

1. glTranslatef(0.0, 0.0, -10.0)

2. glTranslatef(0.0, 0.0, -5.0)

3. glTranslatef(0.0, 0.0, -25.0)

4. glTranslatef(10.0, 10.0, -15.0) 27

Page 32: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 4

Transformation,

Animation and

Viewing

End

Click for box.cpp modified Program Windows Project

Experiment 4.3. Add a scaling command, in particular, replace themodeling transformation block of box.cpp with (Block 1∗):

// Modeling transformations.

glTranslatef(0.0, 0.0, -15.0);

glScalef(2.0, 3.0, 1.0);

Figure 4.4 is a screenshot – compare with the unscaled box of Figure 4.1.End

Click for box.cpp modified Program Windows Project

Experiment 4.4. An object less symmetric than a box is more interestingto work with. Care for a teapot? Accordingly, change the modelingtransformation and object definition part of box.cpp to (Block 2):

// Modeling transformations.

glTranslatef(0.0, 0.0, -15.0);

glScalef(1.0, 1.0, 1.0);

glutWireTeapot(5.0); // Teapot.

Of course, glScalef(1.0, 1.0, 1.0) does nothing and we see the originalunscaled teapot (Figure 4.6).

Next, successively change the scaling parameters by replacing the scalingcommand with the ones below. In each case, make sure your understandingof the command matches the change that you see in the shape of the teapot.

1. glScalef(2.0, 1.0, 1.0)

2. glScalef(1.0, 2.0, 1.0)

3. glScalef(1.0, 1.0, 2.0) End

Click for box.cpp modified Program Windows Project

Experiment 4.5. Replace the cube of box.cpp with a square whose sidesare not parallel to the coordinate axes. In particular, replace the modelingtransformation and object definition part of that program with (Block 3):

∗To cut-and-paste you can find the block in text format in the filechap4codeModifications.txt in the directory ExperimenterSource/CodeModifications.28

Page 33: Download - Computer Graphics Through OpenGL: From Theory to

// Modeling transformations.

glTranslatef(0.0, 0.0, -15.0);

// glScalef(1.0, 3.0, 1.0);

glBegin(GL LINE LOOP);

glVertex3f(4.0, 0.0, 0.0);

glVertex3f(0.0, 4.0, 0.0);

glVertex3f(-4.0, 0.0, 0.0);

glVertex3f(0.0, -4.0, 0.0);

glEnd();

See Figure 4.8(a). Verify by elementary geometry that the line loop forms asquare with sides of length 4

√2 angled at 45◦ to the axes.

Uncomment the scaling. See Figure 4.8(b). The square now seemsskewed to a non-rectangular parallelogram. Mathematically verify that thenew vertices after the transformation (x, y, z) 7→ (x, 3y, z) is applied to thesquare’s vertices are indeed those of a parallelogram. End

Click for box.cpp modified Program Windows Project

Experiment 4.6. Add a rotation command by replacing the modelingtransformation and object definition part – we prefer a teapot – of box.cppwith (Block 4):

// Modeling transformations.

glTranslatef(0.0, 0.0, -15.0);

glRotatef(60.0, 0.0, 0.0, 1.0);

glutWireTeapot(5.0);

Figure 4.9 is a screenshot.The rotation command glRotatef(A, p, q, r) rotates each point of

an object about an axis from the origin O = (0, 0, 0) to the point (p, q, r).The amount of rotation is A◦, measured counter-clockwise looking from(p, q, r) to the origin. In this experiment, then, the rotation is 60◦ CCW(counter-clockwise) looking down the z-axis. End

Click for box.cpp modified Program Windows Project

Experiment 4.7. Continuing with Experiment 4.6, successively replacethe rotation command with the ones below, in each case trying to matchwhat you see with your understanding of how the command should turn theteapot. (It can occasionally be a bit confusing because of the perspectiveprojection.)

1. glRotatef(60.0, 0.0, 0.0, -1.0) 29

Page 34: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 4

Transformation,

Animation and

Viewing

2. glRotatef(-60.0, 0.0, 0.0, 1.0)

3. glRotatef(60.0, 1.0, 0.0, 0.0)

4. glRotatef(60.0, 0.0, 1.0, 0.0)

5. glRotatef(60.0, 1.0, 0.0, 1.0) End

Click for box.cpp modified Program Windows Project

Experiment 4.8. Appropriately modify box.cpp to compare the effectsof each of the following pairs of rotation commands:

1. glRotatef(60.0, 0.0, 0.0, 1.0) and glRotatef(60.0, 0.0, 0.0,

5.0)

2. glRotatef(60.0, 0.0, 2.0, 2.0) and glRotatef(60.0, 0.0, 3.5,

3.5)

3. glRotatef(60.0, 0.0, 0.0, -1.0) and glRotatef(60.0, 0.0, 0.0,

-7.5)

There is no difference in each case. One concludes that the rotation commandglRotatef(A, p, q, r) is equivalent to glRotatef(A,αp, αq, αr), where α isany positive scalar. End

Click for box.cpp modified Program Windows Project

Experiment 4.9. Apply three modeling transformations by replacing themodeling transformations block of box.cpp with (Block 5):

// Modeling transformations.

glTranslatef(0.0, 0.0, -15.0);

glTranslatef(10.0, 0.0, 0.0);

glRotatef(45.0, 0.0, 0.0, 1.0);

It seems the box is first rotated 45◦ about the z-axis and then translatedright 10 units. See Figure 4.13(a). The first translation glTranslatef(0.0,

0.0, -15.0), of course, serves to “kick” the box down the z-axis into theviewing frustum.

Next, interchange the last two transformations, namely, the rightwardtranslation and the rotation, by replacing the modeling transformationsblock with (Block 6):

// Modeling transformations.

glTranslatef(0.0, 0.0, -15.0);

glRotatef(45.0, 0.0, 0.0, 1.0);

glTranslatef(10.0, 0.0, 0.0);30

Page 35: Download - Computer Graphics Through OpenGL: From Theory to

It seems that the box is now first translated right and then rotated aboutthe z-axis causing it to “rise”. See Figure 4.13(b). End

Click for box.cpp modified Program Windows Project

Experiment 4.10. Replace the entire display routine of the originalbox.cpp with (Block 10):

void drawScene(void)

{glClear(GL COLOR BUFFER BIT);

glColor3f(0.0, 0.0, 0.0);

glLoadIdentity();

// Modeling transformations.

glTranslatef(0.0, 0.0, -15.0);

// glRotatef(45.0, 0.0, 0.0, 1.0);

glTranslatef(5.0, 0.0, 0.0);

glutWireCube(5.0); // Box.

//More modeling transformations.

glTranslatef(0.0, 10.0, 0.0);

glutWireSphere(2.0, 10, 8); // Sphere.

glFlush();

}

See Figure 4.15(a) for a screenshot. The objects are a box and a sphere.End

Click for box.cpp modified Program Windows Project

Experiment 4.11. Continuing with the previous experiment, uncommentthe glRotatef() statement. Figure 4.15(b) is a screenshot.

Again, the individual placements are fairly straightforward. Workingbackwards from where it is created we see that, after being translated to (5.0,10.0, 0.0), the sphere is rotated 45◦ counter-clockwise about the z-axis and,of course, finally pushed 15 units in the −z direction. We’ll not computethe exact final coordinates of its center. The individual placement of thebox is simple to parse as well and left to the reader.

It’s the relative placement which is particularly interesting in this case.The sphere is no longer vertically above the box, though the transformationbetween them is still glTranslatef(0.0, 10.0, 0.0)! Before trying toexplain what’s going on, let’s return to the basics for a moment. End 31

Page 36: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 4

Transformation,

Animation and

Viewing

Click for box.cpp modified Program Windows Project

Experiment 4.12. Repeat Experiment 4.11. The modeling transformationand object definition part are as below (Block 11):

// Modeling transformations.

glTranslatef(0.0, 0.0, -15.0);

glRotatef(45.0, 0.0, 0.0, 1.0);

glTranslatef(5.0, 0.0, 0.0);

glutWireCube(5.0); // Box.

//More modeling transformations.

glTranslatef (0.0, 10.0, 0.0);

glutWireSphere (2.0, 10, 8); // Sphere.

First, comment out the last two statements of the first modelingtransformations block as below (the first translation is always needed toplace the entire scene in the viewing frustum):

// Modeling transformations.

glTranslatef(0.0, 0.0, -15.0);

// glRotatef(45.0, 0.0, 0.0, 1.0);

// glTranslatef(5.0, 0.0, 0.0);

glutWireCube(5.0); // Box.

//More modeling transformations.

glTranslatef (0.0, 10.0, 0.0);

glutWireSphere (2.0, 10, 8); // Sphere.

The output is as depicted in Figure 4.17(a).Next, uncomment glTranslatef(5.0, 0.0, 0.0) as below:

// Modeling transformations.

glTranslatef(0.0, 0.0, -15.0);

// glRotatef(45.0, 0.0, 0.0, 1.0);

glTranslatef(5.0, 0.0, 0.0);

glutWireCube(5.0); // Box.

//More modeling transformations.

glTranslatef (0.0, 10.0, 0.0);

glutWireSphere (2.0, 10, 8); // Sphere.

The output is as in Figure 4.17(b). Finally, uncomment glRotatef(45.0,

0.0, 0.0, 1.0) as follows:32

Page 37: Download - Computer Graphics Through OpenGL: From Theory to

x

z z

z

y

(a)

glRotatef(45.0, 0.0, 0.0, 1.0)

glTranslatef(5.0, 0.0, 0.0)

x

y

(b)

(c)

xy

O O

O

Figure 4.1: Transitions of the box, the box’s local coordinates system (bold) and thesphere. The world coordinate system, which never changes, coincides with the box’sinitial local.

// Modeling transformations.

glTranslatef(0.0, 0.0, -15.0);

glRotatef(45.0, 0.0, 0.0, 1.0);

glTranslatef(5.0, 0.0, 0.0);

glutWireCube(5.0); // Box.

//More modeling transformations.

glTranslatef (0.0, 10.0, 0.0);

glutWireSphere (2.0, 10, 8); // Sphere.

glFlush();

The result is seen in Figure 4.17(c). Figure 4.17 shows the box’s localcoordinate system as well after each transition. Observe that the sphere isalways 10 units vertically above the box in the latter’s coordinate system, asone would expect from the glTranslatef (0.0, 10.0, 0.0) call betweenthe two. End

Click for relativePlacement.cpp Program Windows Project33

Page 38: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 4

Transformation,

Animation and

Viewing

Experiment 4.13. Run relativePlacement.cpp. Pressing the up arrowkey once causes the last statement, viz. drawBlueMan, of the following pieceof code to be executed:

glScalef(1.5, 0.75, 1.0);

glRotatef(30.0, 0.0, 0.0, 1.0);

glTranslatef(10.0, 0.0, 0.0);

drawRedMan; // Also draw grid in his local coordinate system.

glRotatef(45.0, 0.0, 0.0, 1.0);

glTranslatef(20.0, 0.0, 0.0);

drawBlueMan;

With each press of the up arrow we go back a statement and successivelyexecute that statement and the ones that follow it. The statements executedare written in black text, the rest white. Pressing the down arrow key goesforward a statement. Figure 4.18 is a screenshot after all transformationsfrom the scaling on have been executed. End

Click for box.cpp modified Program Windows Project

Experiment 4.14. We want to create a human-like character. Our planis to start by drawing the torso as an elongated cube and placing a roundsphere as its head directly on top of the cube (no neck for now). To this endreplace the drawing routine of box.cpp with (Block 12):

void drawScene(void)

{glClear(GL_COLOR_BUFFER_BIT);

glColor3f(0.0, 0.0, 0.0);

glLoadIdentity();

glTranslatef(0.0, 0.0, -15.0);

glScalef(1.0, 2.0, 1.0);

glutWireCube(5.0); // Box torso.

glTranslatef(0.0, 7.0, 0.0);

glutWireSphere(2.0, 10, 8); // Spherical head.

glFlush();

}

Our calculations are as follows: (a) the scaled box is 5× 10× 5 and, beingcentered at the origin, is 5 units long in the +y direction; (b) the sphereis of radius 2; (c) therefore, if the sphere is translated 5 + 2 = 7 in the +ydirection, then it should sit exactly on top of the box (see Figure 4.19(a)).

It doesn’t work: the sphere is no longer round and is, moreover, someways above the box (Figure 4.19(b)). Of course, because the sphere is34

Page 39: Download - Computer Graphics Through OpenGL: From Theory to

transformed by glScalef(1.0, 2.0, 1.0) as well! So, what to do? Asolution is to isolate the scaling by placing it within a push-pop pair as below(Block 13):

void drawScene(void)

{glClear(GL_COLOR_BUFFER_BIT);

glColor3f(0.0, 0.0, 0.0);

glLoadIdentity();

glTranslatef(0.0, 0.0, -15.0);

glPushMatrix();

glScalef(1.0, 2.0, 1.0);

glutWireCube(5.0); // Box torso.

glPopMatrix();

glTranslatef(0.0, 7.0, 0.0);

glutWireSphere(2.0, 10, 8); // Spherical head.

glFlush();

}

The resulting screenshot is Figure 4.19(c), which shows a round head on aneckless torso as desired. End

Click for rotatingHelix1.cpp Program Windows Project

Experiment 4.15. Run rotatingHelix1.cpp where each press of spacecalls the increaseAngle() routine to turn the helix. Note the glutPostRedisplay()command in increaseAngle() which asks the screen to be redrawn. Keepingthe space bar pressed turns the helix continuously. Figure 4.21 is a screenshot.

End

Click for rotatingHelix2.cpp Program Windows Project

Experiment 4.16. Run rotatingHelix2.cpp, a slight modification ofrotatingHelix1.cpp, where pressing space causes the routines increaseAngle()and NULL (do nothing) to be alternately specified as idle functions.

The speed of animation is determined by the processor speed – inparticular, the speed at which frames can be redrawn – and the user cannotinfluence it. End

Click for rotatingHelix3.cpp Program Windows Project 35

Page 40: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 4

Transformation,

Animation and

Viewing

Experiment 4.17. Run rotatingHelix3.cpp, another modification ofrotatingHelix1.cpp, where the particular timer function animate() callsitself recursively after animationPeriod number of msecs., by means ofits own glutTimerFunc(animationPeriod, animate, 1) statement. Theparameter value 1 passed to animate() is not used in this program. Theroutine increaseAngle() called by animate() turns the helix as before.Figure 4.22 shows the animation scheme.

The user can vary the speed of animation by changing the value ofanimationPeriod by pressing the up and down arrow keys. End

Click for rotatingHelixFPS.cpp Program Windows Project

Experiment 4.18. Run rotatingHelixFPS.cpp, which enhances rotat-ingHelix2.cpp adding the routine frameCounter() to count the number oftimes the drawScene() routine is called, equivalently, the number of framesdrawn, per second. The fps is output every second to the debug window.

The way this works is by drawScene() incrementing the globalframeCount every time it is called, and frameCounter() outputting thevalue of frameCount each second – because of its final glutTimerFunc(1000,frameCounter, 1) statement, frameCounter() calls itself after a second– as well as resetting the value of frameCount to 0. The if conditionalin frameCounter() is so that no fps is output when it is first called frommain() with the value passed being 0. End

Click for rotatingHelix2.cpp modified Program Windows Project

Experiment 4.19. Disable double buffering in rotatingHelix2.cpp byreplacing GLUT DOUBLE with GLUT SINGLE in the glutInitDisplayMode()

call in main, and replacing glutSwapBuffers() in the drawing routine withglFlush(). Ghostly is it not?! End

Click for ballAndTorus.cpp Program Windows Project

Experiment 4.20. Run ballAndTorus.cpp. Press space to start theball both flying around (longitudinal rotation) and in and out (latitudinalrotation) of the torus. Press the up and down arrow keys to change thespeed of the animation. Press ‘x/X’, ‘y/Y’ and ‘z/Z’ to change the viewpoint.Figure 4.24 is a screenshot.

The animation of the ball is interesting and we’ll deconstruct it. Commentout all the modeling transformations in the ball’s block, except the lasttranslation, as follows:36

Page 41: Download - Computer Graphics Through OpenGL: From Theory to

// Begin revolving ball.

// glRotatef(longAngle, 0.0, 0.0, 1.0);

// glTranslatef(12.0, 0.0, 0.0);

// glRotatef(latAngle, 0.0, 1.0, 0.0);

// glTranslatef(-12.0, 0.0, 0.0);

glTranslatef(20.0, 0.0, 0.0);

glColor3f(0.0, 0.0, 1.0);

glutWireSphere(2.0, 10, 10);

// End revolving ball.

The ball is centered at (20, 0, 0), its start position, by glTranslatef(20.0,

0.0, 0.0). See Figure 4.25. There is no animation.The ball’s intended latitudinal rotation is in and out of the circle C1

through the middle of the torus. C1’s radius, called the outer radius of thetorus, is 12.0, as specified by the second parameter of glutWireTorus(2.0,12.0, 20, 20). Moreover, C1 is centered at the origin and lies on thexy-plane. Therefore, ignoring longitudinal motion for now, the latitudinalrotation of the ball from its start position is about the line L through (12, 0, 0)parallel to the y-axis (L is tangent to C1). This rotation will cause theball’s center to travel along the circle C2 centered at (12, 0, 0), lying on thexz-plane, of radius 8.

As glRotatef() always rotates about a radial axis, how does one obtainthe desired rotation about L, a non-radial line? Employ the Trick (seeExample 4.2 if you don’t remember). First, translate left so that L is alignedalong the y-axis, then rotate about the y-axis and, finally, reverse the firsttranslation to bring L back to where it was. This means uncommenting thecorresponding three modeling transformations as below:

// Begin revolving ball.

// glRotatef(longAngle, 0.0, 0.0, 1.0);

glTranslatef(12.0, 0.0, 0.0);

glRotatef(latAngle, 0.0, 1.0, 0.0);

glTranslatef(-12.0, 0.0, 0.0);

glTranslatef(20.0, 0.0, 0.0);

glColor3f(0.0, 0.0, 1.0);

glutWireSphere(2.0, 10, 10);

// End revolving ball.

Press space to view only latitudinal rotation.

Note: The two consecutive translation statements could be combined intoone, but then the code would be less easy to parse. 37

Page 42: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 4

Transformation,

Animation and

Viewing

Finally, uncomment glRotatef(longAngle, 0.0, 0.0, 1.0) to im-plement longitudinal rotation about the z-axis. The angular speed oflongitudinal rotation is set to be five times slower than that of latitudinalrotation – the increments to longAngle and latAngle in the animate()

routine being 1◦ and 5◦, respectively. This means the ball winds in and outof the torus five times before it completes one trip around it. End

Click for ballAndTorus.cpp modified Program Windows Project

Experiment 4.21. We want to add a satellite that tags along with theball of ballAndTorus.cpp. The following piece of code added to the endof the drawing routine – just before glutSwapBuffers() – does the job(Block 14):

glTranslatef(4.0, 0.0, 0.0);

// Satellite

glColor3f(1.0, 0.0, 0.0);

glutWireSphere(0.5, 5, 5);

See Figure 4.26 for a screenshot. For a revolving satellite add the followinginstead (Block 15):

glRotatef(10*latAngle, 0.0, 1.0, 0.0);

glTranslatef(4.0, 0.0, 0.0);

// Satellite

glColor3f(1.0, 0.0, 0.0);

glutWireSphere(0.5, 5, 5);

Observe how Proposition 4.1 is being applied in both cases to determinethe motion of the satellite relative to the ball by means of transformationstatements between the two. End

Click for throwBall.cpp Program Windows Project

Experiment 4.22. Run throwBall.cpp, which simulates the motion of aball thrown with a specified initial velocity subject to the force of gravity.Figure 4.27 is a screenshot.

Press space to toggle between animation on and off. Press the right/leftarrow keys to increase/decrease the horizontal component of the initialvelocity, up/down arrow keys to increase/decrease the vertical componentof the initial velocity and the page up/down keys to increase/decreasegravitational acceleration. Press ‘r’ to reset. The values of the initial velocitycomponents and of gravitational acceleration are displayed on the screen.

End38

Page 43: Download - Computer Graphics Through OpenGL: From Theory to

Click for ballAndTorusWithFriction.cpp Program Windows Project

Experiment 4.23. Run ballAndTorusWithFriction.cpp, which modi-fies ballAndTorus.cpp to simulate an invisible viscous medium throughwhich the ball travels.

Press space to apply force to the ball. It has to be kept pressed in orderto continue applying force. The ball comes to a gradual halt after the key isreleased. Increase or decrease the level of applied force by using the up anddown arrow keys. Increase or decrease the viscosity of the medium using thepage up and down keys. Press ‘x/X’, ‘y/Y’ and ‘z/Z’ to rotate the scene.

End

Click for clown3.cpp with parts corresponding to clown1.cpp and clown2.cpp

identified Program Windows Project

Experiment 4.24. We start with simply a blue sphere for the head. Seeclown1.cpp which has the following drawing routine (note that clown1.cppand clown2.cpp are not separate programs but incremental stages ofclown3.cpp which is in ExperimenterSource/Chapter4):

void drawScene(void)

{glClear(GL COLOR BUFFER BIT);

glLoadIdentity();

// Place scene in frustum.

glTranslatef(0.0, 0.0, -9.0);

// Head.

glColor3f(0.0, 0.0, 1.0);

glutWireSphere(2.0, 20, 20);

glutSwapBuffers();

}

Figure 4.29(a) is a screenshot.Next, we want a green conical hat. The command glutWireCone(base,

height, slices, stacks) draws a wireframe cone of base radius base andheight height. The base of the cone lies on the xy-plane with its axis alongthe z-axis and its apex pointing in the positive direction of the z-axis. SeeFigure 4.30(a). The parameters slices and stacks determine the fineness ofthe mesh (not shown in the figure).

Accordingly, insert the lines

// Hat.

glColor3f(0.0, 1.0, 0.0);

glutWireCone(2.0, 4.0, 20, 20); 39

Page 44: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 4

Transformation,

Animation and

Viewing

in clown1.cpp after the call that draws the sphere, so that the drawingroutine becomes (Block 17):

void drawScene(void)

{glClear(GL COLOR BUFFER BIT);

glLoadIdentity();

// Place scene in frustum.

glTranslatef(0.0, 0.0, -9.0);

// Head.

glColor3f(0.0, 0.0, 1.0);

glutWireSphere(2.0, 20, 20);

// Hat.

glColor3f(0.0, 1.0, 0.0);

glutWireCone(2.0, 5.0, 20, 20);

glutSwapBuffers();

}

Not good! Because of the way glutWireCone() aligns, the hat coversthe clown’s face. This is easily fixed. Translate the hat 2 units up the z-axisand rotate it −90◦ about the x-axis to arrange it on top of the head. Finally,rotate it a rakish 30◦ about the z-axis! Here’s the modified drawing routineof clown1.cpp at this point (Block 18):

void drawScene(void)

{glClear(GL COLOR BUFFER BIT);

glLoadIdentity();

// Place scene in frustum.

glTranslatef(0.0, 0.0, -9.0);

// Head.

glColor3f(0.0, 0.0, 1.0);

glutWireSphere(2.0, 20, 20);

// Transformations of the hat.

glRotatef(30.0, 0.0, 0.0, 1.0);

glRotatef(-90.0, 1.0, 0.0, 0.0);

glTranslatef(0.0, 0.0, 2.0);

// Hat.

glColor3f(0.0, 1.0, 0.0);

glutWireCone(2.0, 5.0, 20, 20);

glutSwapBuffers();40

Page 45: Download - Computer Graphics Through OpenGL: From Theory to

}

Let’s add a brim to the hat by attaching a torus to its base. The commandglutWireTorus(inRadius, outRadius, sides, rings) draws a wireframetorus of inner radius inRadius (the radius of a circular section of the torus),and outer radius outRadius (the radius of the circle through the middle ofthe torus). The axis of the torus is along the z-axis and centered at theorigin. See Figure 4.30(b). Insert the call glutWireTorus(0.2, 2.2, 10,

25) right after the call that draws the cone, so the drawing routine becomes(Block 19):

void drawScene(void)

{glClear(GL COLOR BUFFER BIT);

glLoadIdentity();

// Place scene in frustum.

glTranslatef(0.0, 0.0, -9.0);

// Head.

glColor3f(0.0, 0.0, 1.0);

glutWireSphere(2.0, 20, 20);

// Transformations of the hat and brim.

glRotatef(30.0, 0.0, 0.0, 1.0);

glRotatef(-90.0, 1.0, 0.0, 0.0);

glTranslatef(0.0, 0.0, 2.0);

// Hat.

glColor3f(0.0, 1.0, 0.0);

glutWireCone(2.0, 5.0, 20, 20);

// Brim.

glutWireTorus(0.2, 2.2, 10, 25);

glutSwapBuffers();

}

Observe that the brim is drawn suitably at the bottom of the hat andstays there despite modeling transformations between head and hat – aconsequence of Proposition 4.1.

To animate, let’s spin the hat about the clown’s head by rotating itaround the y-axis. We rig the space bar to toggle between animation onand off and the up/down arrow keys to change speed. All updates so far areincluded in clown2.cpp. Figure 4.29(b) is a screenshot.

What’s a clown without little red ears that pop in and out?! Sphereswill do for ears. An easy way to bring about oscillatory motion is to makeuse of the function sin(angle) which varies between −1 and 1. Begin by 41

Page 46: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 4

Transformation,

Animation and

Viewing

translating either ear a unit distance from the head, and then repeatedlytranslate each a distance of sin(angle), incrementing angle each time.

Note: A technicality one needs to be aware of in such applications is thatangle is measured in degrees in OpenGL syntax, e.g., in glRotatef(angle,p, q, r), while the C++ math library assumes angles to be given in radians .Multiplying by π/180 converts degrees to radians.

The ears and head are physically separate, though. Let’s connect themwith springs! Helixes are springs. We borrow code from helix.cpp, butmodify it to make the length of the helix 1, its axis along the x-axis and itsradius 0.25. As the ears move, either helix is scaled along the x-axis so thatit spans the gap between the head and an ear. The completed program isclown3.cpp, of which a screenshot is seen in Figure 4.29(c). End

Click for floweringPlant.cpp Program Windows Project

Experiment 4.25. Run floweringPlant.cpp, an animation of a flowerblooming. Press space to start and stop animation, delete to reset, and‘x/X’, ‘y/Y’ and ‘z/Z’ to change the viewpoint. Figure 4.31 is a screenshot.

End

Click for box.cpp modified Program Windows Project

Experiment 4.26. Replace the translation command glTranslatef(0.0,

0.0, -15.0) of box.cpp with the viewing command gluLookAt(0.0, 0.0,

15.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) so that the drawing routine is asbelow (Block 20):

void drawScene(void)

{glClear(GL COLOR BUFFER BIT);

glColor3f(0.0, 0.0, 0.0);

glLoadIdentity();

// Viewing transformation.

gluLookAt(0.0, 0.0, 15.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

glutWireCube(5.0); // Box.

glFlush();

}

There is no change in what is viewed. The commands glTranslatef(0.0,

0.0, -15.0) and gluLookAt(0.0, 0.0, 15.0, 0.0, 0.0, 0.0, 0.0,

1.0, 0.0) are exactly equivalent .42

Page 47: Download - Computer Graphics Through OpenGL: From Theory to

Note: A convenient way to compare side-by-side the output of two piecesof code is to put them into the two drawing routines of windows.cpp ofChapter 3. End

Click for boxWithLookAt.cpp Program Windows Project

Experiment 4.27. Continue the previous experiment, or run boxWith-

LookAt.cpp, successively changing only the parameters centerx , centery ,centerz – the middle three – of the gluLookAt() call to the following:

1. 0.0, 0.0, 10.0

2. 0.0, 0.0,−10.0

3. 0.0, 0.0, 20.0

4. 0.0, 0.0, 15.0 End

Click for boxWithLookAt.cpp modified Program Windows Project

Experiment 4.28. Restore the original boxWithLookAt.cpp programwith its gluLookAt(0.0, 0.0, 15.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)

call and, again, first replace the box with a glutWireTeapot(5.0). Run:a screenshot is shown in Figure 4.37(a). Next, successively change theparameters upx , upy , upz – the last three parameters of gluLookAt() – tothe following:

1. 1.0, 0.0, 0.0 (Figure 4.37(b))

2. 0.0,−1.0, 0.0 (Figure 4.37(c))

3. 1.0, 1.0, 0.0 (Figure 4.37(d))

Screenshots of the successive cases are shown in Figures 4.37(b)-(d). Thecamera indeed appears to rotate about its line of sight, the z-axis, so thatits up direction points along the up vector (upx , upy , upz ) each time. End

Click for boxWithLookAt.cpp modified Program Windows Project

Experiment 4.29. Replace the wire cube of boxWithLookAt.cpp with aglutWireTeapot(5.0) and replace the gluLookAt() call with:

gluLookAt(0.0, 0.0, 15.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0) 43

Page 48: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 4

Transformation,

Animation and

Viewing

The vector los = (0.0, 0.0, 0.0)− (15.0, 0.0, 0.0) = (−15.0, 0.0, 0.0), which isdown the z-axis. The component of up = (1.0, 1.0, 1.0), perpendicular to thez-axis, is (1.0, 1.0, 0.0), which then is the up direction. Is what you see thesame as Figure 4.37(d), which, in fact, is a screenshot for gluLookAt(0.0,

0.0, 15.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0)? End

Click for box.cpp modified Program Windows Project

Experiment 4.30. Replace the display routine of box.cpp with (Block 21):

void drawScene(void)

{glClear(GL COLOR BUFFER BIT);

glColor3f(0.0, 0.0, 0.0);

glLoadIdentity();

// Viewing transformation.

gluLookAt(0.0, 0.0, 15.0, 15.0, 0.0, 0.0, 0.0, 1.0, 0.0);

// Modeling transformation block equivalent

// to the preceding viewing transformation.

// glRotatef(45.0, 0.0, 1.0, 0.0);

// glTranslatef(0.0, 0.0, -15.0);

glutWireCube(5.0);

glFlush();

}

Run. Next, both comment out the viewing transformation anduncomment the modeling transformation block following it. Run again.The displayed output, shown in Figure 4.47, is the same in both cases. Thereason, as Figures 4.48(a)-(c) explain, is that the viewing transformation isequivalent to the modeling transformation block. In particular, the formeris undone by the latter. End

Click for spaceTravel.cpp Program Windows Project

Experiment 4.31. Run spaceTravel.cpp. The left viewport shows aglobal view from a fixed camera of a conical spacecraft and 40 stationaryspherical asteroids arranged in a 5 × 8 grid. The right viewport showsthe view from a front-facing camera attached to the tip of the craft. SeeFigure 4.51 for a screenshot of the program.44

Page 49: Download - Computer Graphics Through OpenGL: From Theory to

Press the up and down arrow keys to move the craft forward and backwardand the left and right arrow keys to turn it. Approximate collision detectionis implemented to prevent the craft from crashing into an asteroid.

The asteroid grid can be changed in size by redefining ROWS and COLUMNS.The probability that a particular row-column slot is filled is specified as apercentage by FILL PROBABILITY – a value less than 100 leads to a non-uniform distribution of asteroids. End

Click for spaceTravel.cpp modified Program Windows Project

Experiment 4.32. Run spaceTravel.cpp with ROWS and COLUMNS bothincreased to 100. The spacecraft now begins to respond so slowly to key inputthat its movement seems clunky, unless, of course, you have a super-fastcomputer (in which case, increase the values of ROWS and COLUMNS evenmore). End

Click for animateMan1.cpp Program Windows Project

Experiment 4.33. Run animateMan1.cpp. This is a fairly complexprogram to develop a sequence of key frames for a man-like figure, whichcan subsequently be animated. In addition to its spherical head, the figureconsists of nine box-like body parts which can rotate about their joints. SeeFigure 4.54. All parts are wireframe. We’ll explain the program next. End

Click for animateMan2.cpp Program Windows Project

Experiment 4.34. Run animateMan2.cpp. This is simply a pared-downversion of animateMan1.cpp, whose purpose is to animate the sequence ofconfigurations listed in the file animateManDataIn.txt, likely generatedfrom the develop mode of animateMan1.cpp. Press ‘a’ to toggle betweenanimation on/off. As in animateMan1.cpp, pressing the up or down arrowkey speeds up or slows down the animation. The camera functionalities viathe keys ‘r/R’ and ‘z/Z’ remain as well. Think of animateMan1.cpp as thestudio and animateMan2.cpp as the movie.

The current contents of animateManDataIn.txt cause the man to do ahandspring over the ball. Figure 4.56 is a screenshot. End

Click for ballAndTorusShadowed.cpp Program Windows Project

Experiment 4.35. Run ballAndTorusShadowed.cpp, based on ballAnd-

Torus.cpp, but with additional shadows drawn on a checkered floor. Press 45

Page 50: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 4

Transformation,

Animation and

Viewing

space to start the ball traveling around the torus and the up and down arrowkeys to change its speed. Figure 4.57 is a screenshot. End

Click for selection.cpp Program Windows Project

Experiment 4.36. Run selection.cpp, which is inspired by a similarprogram in the red book. It uses selection mode to determine the identityof rectangles, drawn with calls to drawRectangle(), which intersect theviewing volume created by the projection statement glOrtho (-5.0, 5.0,

-5.0, 5.0, -5.0, 5.0), this being a 10×10×10 axis-aligned box centeredat the origin. Figure 4.59 is a screenshot. Hit records are output to thecommand window. In the discussion following, we parse the program carefully.

End

Click for ballAndTorusPicking.cpp Program Windows Project

Experiment 4.37. Run ballAndTorusPicking.cpp, which preserves allthe functionality of ballAndTorus.cpp upon which it is based and adds thecapability of picking the ball or torus with a left click of the mouse. Thepicked object blushes. See Figure 4.62 for a screenshot. End

46

Page 51: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 5Inside Animation: The Theory ofTransformations

Click for box.cpp modified Program Windows Project

Experiment 5.1. Fire up box.cpp and insert a rotation command – infact, the same one as in the previous exercise – just before the box definitionso that the transformation and object definition part of the drawing routinebecomes:

// Modeling transformations.

glTranslatef(0.0, 0.0, -15.0);

glRotatef(90.0, 0.0, 1.0, 1.0);

glutWireCube(5.0); // Box.

The rotation command asks to rotate 90◦ about the line l from the originthrough (0, 1, 1). See Figure 5.24(a) for the displayed output.

Let’s try now, instead, to use the strategy suggested above to express thegiven rotation in terms of rotations about the coordinate axes. Figure 5.24(b)illustrates the following simple scheme. Align l along the z-axis by rotatingit 45◦ about the x-axis. Therefore, the given rotation should be equivalentto (1) a rotation of 45◦ about the x-axis, followed by (2) a rotation of 90◦

about the z-axis followed, finally, by a (3) rotation of −45◦ about the x-axis.Give it a whirl. Replace the single rotation command glRotatef(90.0,

0.0, 1.0, 1.0) with a block of three as follows:

// Modeling transformations.

glTranslatef(0.0, 0.0, -15.0);

glRotatef(-45.0, 1.0, 0.0, 0.0); 47

Page 52: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 5

Inside Animation:

The Theory of

Transformations

glRotatef(90.0, 0.0, 0.0, 1.0);

glRotatef(45.0, 1.0, 0.0, 0.0);

glutWireCube(5.0); // Box.

Seeing is believing, is it not?! End

Click for manipulateModelviewMatrix.cpp Program Windows Project

Experiment 5.2. Run manipulateModelviewMatrix.cpp. Figure 5.30is a screenshot, although in this case we are really more interested in thetransformations in the program rather than its visual output.

The gluLookAt(0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)

statement we understand to multiply the current modelview matrix on theright by the matrix of its equivalent modeling transformation. The currentmodelview matrix is changed again by the glMultMatrixf(matrixData)

call, which multiplies it on the right by the matrix corresponding to a rotationof 45◦ about the z-axis, equivalent to a glRotatef(45.0, 0.0, 0.0, 1.0)

call. It’s changed one last time by glScalef(1.0, 2.0, 1.0).The current modelview matrix is output to the command window initially

and then after each of the three modelview transformations. We’ll see nextif the four output values match our understanding of the theory. End

Click for shear.cpp Program Windows Project

Experiment 5.3. Run shear.cpp. Press the left and right arrow keysto move the ball. The box begins to shear when struck by the ball. SeeFigure 5.34.

The shear matrix is explicitly computed in the code and multiplied fromthe right into the current modelview matrix via a glMultMatrix() call.

End

48

Page 53: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 6Advanced Animation Techniques

Click for spaceTravel.cpp Program Windows Project

Experiment 6.1. First, run the program spaceTravel.cpp with itscurrent values of ROWS and COLUMNS, being the size of the asteroid grid,as 8 and 5, respectively. Move the spacecraft with the arrow keys. Next,increase both ROWS and COLUMNS to 100. Figure 6.1 is a screenshot. Thespacecraft now begins to respond sluggishly to the arrow keys, at least on atypical desktop. You may have to pump up even more the values of ROWSand COLUMNS if yours is exceptionally fast. End

Click for spaceTravelFrustumCulled.cpp Program Windows Project

Experiment 6.2. Run spaceTravelFrustumCulled.cpp, which enhancesspaceTravel.cpp with optional quadtree-based frustum culling. Pressingspace toggles between frustum culling enabled and disabled. As before, thearrow keys maneuver the craft.

The current size of the asteroid field is 100× 100. Dramatic isn’t it, thespeed-up from frustum culling?!

Note: Make sure the file intersectionDetectionRoutines.cpp is in thesame directory as spaceTravelFrustumCulled.cpp.

Note: When the number of asteroids is large, the display may take a whileto come up because of pre-processing to build the quadtree structure.

End

Click for occlusion.cpp Program Windows Project 49

Page 54: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 6

Advanced Animation

Techniques

Experiment 6.3. Run occlusion.cpp, which initially shows only a greenrectangle. Use the arrow keys to move a solid red cube into view from behindthe rectangle (see Figure 6.6). Press the space bar, which is a toggle, toreveal a red wire sphere contained in the box. The sphere is our “complex”object, while the cube, of course, is its bounding box. We’ll analyze thisprogram next. End

Click for occlusionConditionalRendering.cpp Program Windows

Project

Experiment 6.4. Run occlusionConditionalRendering.cpp. Themajor change from occlusion.cpp is in the following code block in thedrawing routine, where the rendering of the sphere is made conditional uponthe outcome of the query with id query. The parameter GL QUERY WAIT

says to wait for the query to complete.

glBeginConditionalRender(query, GL QUERY WAIT);

glutWireSphere(0.5, 16, 10);

glEndConditionalRender();

Since OpenGL knows itself what not to render if the query outcome is zero,there is no need for user-instigated determination of results, so the variablesresult and resultAvailable are now gone. End

Click for eulerAngles.cpp Program Windows Project

Experiment 6.5. Run eulerAngles.cpp, which shows an L, similar tothe one in Figure 6.8(a), whose orientation can be interactively changed.

The original orientation of the L has its long leg lying along the z-axisand its short leg pointing up parallel to the y-axis. Pressing ‘x/X’, ‘y/Y’ and‘z/Z’ changes the L’s Euler angles and delete resets. The Euler angle valuesare displayed on-screen. Figure 6.9 is a screenshot of the initial configuration.

End

Click for interpolateEulerAngles.cpp Program Windows Project

Experiment 6.6. Run interpolateEulerAngles.cpp, which is based oneulerAngles.cpp. It simultaneously interpolates between the tuples (0, 0, 0)and (0, 90, 0) and between (0, 0, 0) and (−90, 90, 90). Press the left and rightarrow keys to step through the interpolations (delete resets). For the firstinterpolation (green L) the successive tuples are (0, angle, 0) and for thesecond (red L) they are (−angle, angle, angle), angle changing by 5 at eachstep in both.50

Page 55: Download - Computer Graphics Through OpenGL: From Theory to

The paths are different! The green L seems to follow the intuitivelystraighter path by keeping its long leg always on the xz-plane as it rotatesabout the y-axis, while the red L arcs above the xz-plane, as diagrammed inFigure 6.10. Figure 6.11 is a screenshot of interpolateEulerAngles.cpppart way through the interpolation. End

Click for eulerAngles.cpp Program Windows Project

Experiment 6.7. Run eulerAngles.cpp again.Press ‘x’ and ‘X’ a few times each – the L turns longitudinally. Reset by

pressing delete. Press ‘y’ and ‘Y’ a few times each – the L turns latitudinally.Reset. Press ‘z’ and ‘Z’ a few times each – the L twists. There appear tobe three physical degrees of freedom of the L derived from rotation aboutthe three coordinate axes which we might descriptively term, respectively,longitudinal, latitudinal and “twisting”.

Now, from the initial configuration of eulerAngles.cpp press ‘y’ tillβ = 90. Next, press ‘z’ or ‘Z’ – the L twists. Then press ‘x’ or ‘X’ – the Lstill twists! End

Click for quaternionAnimation.cpp Program Windows Project

Experiment 6.8. Run quaternionAnimation.cpp, which applies thepreceding ideas to animate the orientation of our favorite rigid body, anL, with the help of quaternions. Press ‘x/X’, ‘y/Y’ and ‘z/Z’ to changethe orientation of the blue L, whose current Euler angles are shown on thedisplay. Its start orientation is the currently fixed red L. See Figure 6.16 fora screenshot.

Pressing enter at any time begins an animation of the red L from thestart to the blue’s current orientation. Press the up and down arrow keys tochange the speed and delete to reset. End

51

Page 56: Download - Computer Graphics Through OpenGL: From Theory to
Page 57: Download - Computer Graphics Through OpenGL: From Theory to

Part IV

Geometry for the HomeOffice

53

Page 58: Download - Computer Graphics Through OpenGL: From Theory to
Page 59: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 7Convexity and Interpolation

Click for square.cpp modified Program Windows Project

Experiment 7.1. Replace the polygon declaration part of our old favoritesquare.cpp with the following (Block 1∗):

glBegin(GL TRIANGLES);

glColor3f(1.0, 0.0, 0.0);

glVertex3f(20.0, 20.0, 0.0);

glColor3f(0.0, 1.0, 0.0);

glVertex3f(80.0, 20.0, 0.0);

glColor3f(0.0, 0.0, 1.0);

glVertex3f(80.0, 80.0, 0.0);

glEnd();

Observe how OpenGL interpolates vertex color values throughout the triangle.Figure 7.7 is a screenshot. End

Click for interpolation.cpp Program Windows Project

Experiment 7.2. Run interpolation.cpp, which shows the interpolatedcolors of a movable point inside a triangle with red, green and blue vertices.The triangle itself is drawn white. See Figure 7.8 for a screenshot.

As the arrow keys are used to move the large point, the height of eachof the three vertical bars on the left indicates the weight of the respectivetriangle vertex on the point’s location. The color of the large point itself isinterpolated (by the program) from those of the vertices. End

∗To cut-and-paste you can find the block in text format in the filechap7codeModifications.txt in the directory ExperimenterSource/CodeModifications. 55

Page 60: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 7

Convexity and

Interpolation

Click for convexHull.cpp Program Windows Project

Experiment 7.3. Run convexHull.cpp, which shows the convex hull of8 points on a plane. Use the space bar to select a point and the arrow keysto move it. Figure 7.14 is a screenshot.

Note: The program implements a very inefficient (but easily coded)algorithm to compute the convex hull of a set F as the union of all triangleswith vertices in F . End

56

Page 61: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 8Triangulation

Click for invalidTriangulation.cpp Program Windows Project

Experiment 8.1. Run invalidTriangulation.cpp, which implementsexactly the invalid triangulation {ABC,DBC,DAE} of the rectangle inFigure 8.3(d). Colors have been arbitrarily fixed for the five vertices A-E.Press space to interchange the order that ABC and DBC appear in thecode. Figure 8.4 shows the difference. End

Click for square.cpp modified Program Windows Project

Experiment 8.2. Replace the polygon declaration of square.cpp with(Block 11):

glBegin(GL POLYGON);

glVertex3f(20.0, 20.0, 0.0);

glVertex3f(80.0, 20.0, 0.0);

glVertex3f(40.0, 40.0, 0.0);

glVertex3f(20.0, 80.0, 0.0);

glEnd();

Display it both filled and outlined using appropriate glPolygonMode calls.A non-convex quadrilateral is drawn in either case (Figure 8.7(a)).

Next, keeping the same cycle of vertices as above, list them starting withglVertex3f(80.0, 20.0, 0.0) instead (Block 2):

glBegin(GL POLYGON);

glVertex3f(80.0, 20.0, 0.0);

1To cut-and-paste you can find the block in text format in the filechap8codeModifications.txt in the directory ExperimenterSource/CodeModifications. 57

Page 62: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 8

Triangulation

glVertex3f(40.0, 40.0, 0.0);

glVertex3f(20.0, 80.0, 0.0);

glVertex3f(20.0, 20.0, 0.0);

glEnd();

Make sure to display it both filled and outlined. When filled it’s a triangle,while outlined it’s a non-convex quadrilateral identical to the one outputearlier (see Figure 8.7(b))! Because the cyclic order of the vertices isunchanged, shouldn’t it be as in Figure 8.7(a) both filled and outlined?

End

58

Page 63: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 9Orientation

Click for square.cpp modified Program Windows Project

Experiment 9.1. Replace the polygon declaration part of square.cppwith (Block 11):

glPolygonMode(GL FRONT, GL LINE);

glPolygonMode(GL BACK, GL FILL);

glBegin(GL POLYGON);

glVertex3f(20.0, 20.0, 0.0);

glVertex3f(80.0, 20.0, 0.0);

glVertex3f(80.0, 80.0, 0.0);

glVertex3f(20.0, 80.0, 0.0);

glEnd();

This simply adds the two glPolygonMode() statements to the originalsquare.cpp. In particular, they specify that front-facing polygons are to bedrawn in outline and back-facing ones filled. Now, the order of the verticesis (20.0, 20.0, 0.0), (80.0, 20.0, 0.0), (80.0, 80.0, 0.0), (20.0, 80.0, 0.0), whichappears CCW from the viewing face. Therefore, the square is drawn inoutline.

Next, rotate the vertices cyclically so that the declaration becomes(Block 2):

glPolygonMode(GL FRONT, GL LINE);

glPolygonMode(GL BACK, GL FILL);

glBegin(GL POLYGON);

glVertex3f(20.0, 80.0, 0.0);

glVertex3f(20.0, 20.0, 0.0);

glVertex3f(80.0, 20.0, 0.0);

1To cut-and-paste you can find the block in text format in the filechap9codeModifications.txt in the directory ExperimenterSource/CodeModifications. 59

Page 64: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 9

Orientation

glVertex3f(80.0, 80.0, 0.0);

glEnd();

As the vertex order remains equivalent to the previous one, the square isstill outlined.

Reverse the listing next (Block 3):

glPolygonMode(GL FRONT, GL LINE);

glPolygonMode(GL BACK, GL FILL);

glBegin(GL POLYGON);

glVertex3f(80.0, 80.0, 0.0);

glVertex3f(80.0, 20.0, 0.0);

glVertex3f(20.0, 20.0, 0.0);

glVertex3f(20.0, 80.0, 0.0);

glEnd();

The square is drawn filled as the vertex order now appears CW from thefront of the viewing box. End

Click for square.cpp modified Program Windows Project

Experiment 9.2. Replace the polygon declaration part of square.cppwith (Block 5):

glPolygonMode(GL FRONT, GL LINE);

glPolygonMode(GL BACK, GL FILL);

glBegin(GL TRIANGLES);

// CCW

glVertex3f(20.0, 80.0, 0.0);

glVertex3f(20.0, 20.0, 0.0);

glVertex3f(50.0, 80.0, 0.0);

//CCW

glVertex3f(50.0, 80.0, 0.0);

glVertex3f(20.0, 20.0, 0.0);

glVertex3f(50.0, 20.0, 0.0);

// CW

glVertex3f(50.0, 20.0, 0.0);

glVertex3f(50.0, 80.0, 0.0);

glVertex3f(80.0, 80.0, 0.0);

// CCW

glVertex3f(80.0, 80.0, 0.0);

glVertex3f(50.0, 20.0, 0.0);

glVertex3f(80.0, 20.0, 0.0);

glEnd();60

Page 65: Download - Computer Graphics Through OpenGL: From Theory to

The specification is for front faces to be outlined and back faces filled,but, as the four triangles are not consistently oriented, we see both outlinedand filled triangles (Figure 9.11(a)). End

Click for square.cpp modified Program Windows Project

Experiment 9.3. Continuing the previous experiment, next replace thepolygon declaration part of square.cpp with (Block 6):

glPolygonMode(GL FRONT, GL LINE);

glPolygonMode(GL BACK, GL FILL);

glBegin(GL TRIANGLE STRIP);

glVertex3f(20.0, 80.0, 0.0);

glVertex3f(20.0, 20.0, 0.0);

glVertex3f(50.0, 80.0, 0.0);

glVertex3f(50.0, 20.0, 0.0);

glVertex3f(80.0, 80.0, 0.0);

glVertex3f(80.0, 20.0, 0.0);

glEnd();

The resulting triangulation is the same as before, but, as it’s consistentlyoriented, we see only outlined front faces. (Figure 9.11(b)). End

Click for squareOfWalls.cpp Program Windows Project

Experiment 9.4. Run squareOfWalls.cpp, which shows four rectangularwalls enclosing a square space. The front faces (the outside of the walls)are filled, while the back faces (the inside) are outlined. Figure 9.12(a) is ascreenshot.

The triangle strip of squareOfWalls.cpp consists of eight triangles whichare consistently oriented, because triangles in a strip are always consistentlyoriented. End

Click for threeQuarterSphere.cpp Program Windows Project

Experiment 9.5. Run threeQuarterSphere.cpp, which adds one half ofa hemisphere to the bottom of the hemisphere of hemisphere.cpp. Thetwo polygon mode calls ask the front faces to be drawn filled and back onesoutlined. Turn the object about the axes by pressing ‘x’, ‘X’, ‘y’, ‘Y’, ‘z’and ‘Z’.

Unfortunately, the ordering of the vertices is such that the outside ofthe hemisphere appears filled, while that of the half-hemisphere outlined.Figure 9.12(b) is a screenshot. Likely, this would not be intended in a 61

Page 66: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 9

Orientation

real design application where one would, typically, expect a consistent lookthroughout one side.

Such mixing up of orientation is not an uncommon error when assemblingan object out of multiple pieces. Fix the problem in the case ofthreeQuarterSphere.cpp in four different ways:

(a) Replace the loop statement

for(i = 0; i <= p/2; i++)

of the half-hemisphere with

for(i = p/2; i >= 0; i--)

to reverse its orientation.

(b) Interchange the two glVertex3f() statements of the half-hemisphere,again reversing its orientation.

(c) Place the additional polygon mode calls

glPolygonMode(GL FRONT, GL LINE);

glPolygonMode(GL BACK, GL FILL);

before the half-hemisphere so that its back faces are drawn filled.

(d) Call

glFrontFace(GL CCW)

before the hemisphere definition and

glFrontFace(GL CW)

before the half-hemisphere to change the front-face default to be CW-facing for the latter.

Of the four, either (a) or (b) is to be preferred because they go to thesource of the problem and repair the object, rather than hide it with thehelp of state variables, as do (c) and (d). End

Experiment 9.6. Make a Mobius band as follows.Take a long and thin strip of paper and draw two equal rows of triangles

on one side to make a triangulation of the strip as in the bottom of Figure 9.13.Turn the strip into a Mobius band by pasting the two end edges togetherafter twisting one 180◦. The triangles you drew on the strip now make atriangulation of the Mobius band.

Try next to orient the triangles by simply drawing a curved arrow ineach, in a manner such that the entire triangulation is consistently oriented.Were you able to?! End62

Page 67: Download - Computer Graphics Through OpenGL: From Theory to

Click for sphereInBox1.cpp Program Windows Project

Experiment 9.7. Run sphereInBox1.cpp, which draws a green ballinside a red box. Press up or down arrow keys to open or close the box.Figure 9.15(a) is a screenshot of the box partly open.

Ignore the statements to do with lighting and material propertiesfor now. The command glCullFace(face) where face can be GL FRONT,GL BACK or GL FRONT AND BACK, is used to specify if front-facing or back-facing or all polygons are to be culled. Culling is enabled with a call toglEnable(GL CULL FACE) and disabled with glDisable(GL CULL FACE).

You can see at the bottom of the drawing routine that back-facingtriangles of the sphere are indeed culled, which makes the program moreefficient because these triangles are hidden in any case behind the front-facingones.

Comment out the glDisable(GL CULL FACE) call and open the box.Oops! Some sides of the box have disappeared as you can see in Figure 9.15(b).The reason, of course, is that the state variable GL CULL FACE is set whenthe drawing routine is called the first time so that all back-facing triangles,including those belonging to the box, are eliminated on subsequent calls.

End

Click for sphereInBox1.cpp modified Program Windows Project

Experiment 9.8. Here’s a trick often used in 3D design environments likeMaya and Studio Max to open up a closed space. Suppose you’ve finisheddesigning a box-like room and now want to work on objects inside it. Agood way to do this is to remove only the walls obscuring your view of theinside and leave the rest; that the obscuring walls are either all front-facingor all back-facing means a cull will do the trick. Let’s see this in action.

Insert the pair of statements

glEnable(GL CULL FACE);

glCullFace(GL FRONT);

in the drawing routine of sphereInBox1.cpp just before the glDrawElements()calls. The top and front sides of the box are not drawn, leaving its interiorvisible. Figure 9.15(c) is a screenshot. End

Click for squareOfWallsReflected.cpp Program Windows Project

Experiment 9.9. Run squareOfWallsReflected.cpp, which is square-

OfWalls.cpp with the following additional block of code, including aglScalef(-1.0, 1.0, 1.0) call, to reflect the scene about the yz-plane. 63

Page 68: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 9

Orientation

// Block to reflect the scene about the yz-plane.

if (isReflected)

{. . .glScalef(-1.0, 1.0, 1.0);

// glFrontFace(GL CW);

}else

{. . .// glFrontFace(GL CCW);

}

The original walls are as in Figure 9.16(a). Press space to reflect. Keepingin mind that front faces are filled and back faces outlined, it seems thatglScalef(-1.0, 1.0, 1.0) not only reflects, but turns the square of wallsinside out as well, as you can see in Figure 9.16(b). End

64

Page 69: Download - Computer Graphics Through OpenGL: From Theory to

Part V

Making Things Up

65

Page 70: Download - Computer Graphics Through OpenGL: From Theory to
Page 71: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 10Modeling in 3D Space

Click for parabola.cpp Program Windows Project

Experiment 10.1. Compare the outputs of circle.cpp, helix.cpp andparabola.cpp, all drawn in Chapter 2.

The sample is chosen uniformly from the parameter space in all threeprograms. The output quality is good for both the circle – after pressing ‘+’a sufficient number of times for a dense enough sample – and the helix. Theparabola, however, shows a difference in quality between its curved bottomand straighter sides, the sides becoming smoother more quickly than thebottom. In curves such as this, one may want to sample non-uniformly, inparticular, more densely from parts of greater curvature. End

Click for astroid.cpp Program Windows Project

Experiment 10.2. Run astroid.cpp, which was written by modifyingcircle.cpp to implement the parametric equations

x = cos3 t, y = sin3 t, z = 0, 0 ≤ t ≤ 2π

for the astroid of Exercise 10.2. Figure 10.9 is a screenshot. End

Click for cylinder.cpp Program Windows Project

Experiment 10.3. Run cylinder.cpp, which shows a triangular meshapproximation of a circular cylinder, given by the parametric equations

x = f(u, v) = cosu, y = g(u, v) = sinu, z = h(u, v) = v, 67

Page 72: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 10

Modeling in 3D Space

for (u, v) ∈ [−π, π]× [−1, 1]. Pressing arrow keys changes the fineness of themesh. Press ‘x/X’, ‘y/Y’ or ‘z/Z’ to turn the cylinder itself. Figure 10.28 isa screenshot. End

Click for helicalPipe.cpp Program Windows Project

Experiment 10.4. Without really knowing what to expect (honestly!) wetweaked the parametric equations of the cylinder to the following:

x = cosu+ sin v, y = sinu+ cos v, z = u, (u, v) ∈ [−π, π]× [−π, π]

It turns out the resulting shape looks like a helical pipe – run helical-

Pipe.cpp. Figure 10.31 is a screenshot.Functionality is the same as for cylinder.cpp: press the arrow keys to

coarsen or refine the triangulation and ‘x/X’, ‘y/Y’ or ‘z/Z’ to turn the pipe.Looking at the equations again, it wasn’t too hard to figure out how this

particular surface came into being. See the next exercise. End

Click for torus.cpp Program Windows Project

Experiment 10.5. Run torus.cpp, which applies the parametric equa-tions deduced above in the template of cylinder.cpp (simply swapping newf, g and h function definitions into the latter program). The radii of thecircular trajectory and the profile circle are set to 2.0 and 0.5, respectively.Figure 10.35 is a screenshot.

Functionality is the same as for cylinder.cpp: press the arrow keysto coarsen or refine the triangulation and ‘x/X’, ‘y/Y’ or ‘z/Z’ to turn thetorus. End

Click for torusSweep.cpp Program Windows Project

Experiment 10.6. Run torusSweep.cpp, modified from torus.cpp toshow the animation of a circle sweeping out a torus. Press space to togglebetween animation on and off. Figure 10.36 is a screenshot part way throughthe animation. End

Click for table.cpp Program Windows Project

Experiment 10.7. These equations are implemented in table.cpp, againusing the template of cylinder.cpp. Press the arrow keys to coarsen orrefine the triangulation and ‘x/X’, ‘y/Y’ or ‘z/Z’ to turn the table. SeeFigure 10.39 for a screenshot of the table.68

Page 73: Download - Computer Graphics Through OpenGL: From Theory to

Note that the artifacts at the edges of the table arise because samplepoints may not map exactly to corners (0,−8), (4,−8), . . . , (0, 8) of the profiledrawn in Figure 10.38(a) – which can be avoided by including always t values0, 4, 5, 8, 22, 31, 32 and 42 in the sample grid. End

Click for doublyCurledCone.cpp Program Windows Project

Experiment 10.8. The plan above is implemented in doublyCurled-

Cone.cpp, again using the template of cylinder.cpp, with the value of Aset to π/4 and a to 0.05. Press the arrow keys to coarsen or refine thetriangulation and ‘x/X’, ‘y/Y’ or ‘z/Z’ to turn the cone. Figure 10.41 is ascreenshot. End

Click for extrudedHelix.cpp Program Windows Project

Experiment 10.9. Run extrudedHelix.cpp, which extrudes a helix,using yet again the template of cylinder.cpp. The parametric equationsof the extrusion are

x = 4cos(10πu), y = 4sin(10πu), z = 10πu+ 4v, 0 ≤ u, v ≤ 1

the constants being chosen to size the object suitably. As the equation for zindicates, the base helix is extruded parallel to the z-axis. Figure 10.42 is ascreenshot. End

Click for bilinearPatch.cpp Program Windows Project

Experiment 10.10. Run bilinearPatch.cpp, which implements pre-cisely Equation (10.20). Press the arrow keys to refine or coarsen thewireframe and ‘x/X’, ‘y/Y’ or ‘z/Z’ to turn the patch. Figure 10.47 is ascreenshot. End

Click for hyperboloid1sheet.cpp Program Windows Project

Experiment 10.11. Run hyperboloid1sheet.cpp, which draws a trian-gular mesh approximation of a single-sheeted hyperboloid with the help ofthe parametrization

x = cosu sec v, y = sinu sec v, z = tan v, u ∈ [−π, π], v ∈ (−π/2, π/2)

Figure 10.51(a) is a screenshot. In the implementation we restrict v to[−0.4π, 0.4π] to avoid ±π/2 where sec is undefined. End 69

Page 74: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 10

Modeling in 3D Space

Click for gluQuadrics.cpp Program Windows Project

Experiment 10.12. Run gluQuadrics.cpp to see all four GLU quadrics.Press the left and right arrow keys to cycle through the quadrics and ‘x/X’,‘y,Y’ and ‘z/Z’ to turn them. The images in Figure 10.52 were, in fact,generated by this program. End

Click for glutObjects.cpp Program Windows Project

Experiment 10.13. Run glutObjects.cpp, a program we originally sawin Chapter 3. Press the left and right arrow keys to cycle through the variousFreeGLUT objects and ‘x/X’, ‘y/Y’ and ‘z/Z’ to turn them. Among otherobjects you see all five regular polyhedra, both in solid and wireframe. End

Click for tetrahedron.cpp Program Windows Project

Experiment 10.14. Run tetrahedron.cpp. The program draws a wire-frame tetrahedron of edge length 2

√2 which can be turned using the ‘x/X’,

‘y/Y’ and ‘z/Z’ keys. Figure 10.56 is a screenshot. End

Click for bezierCurves.cpp Program Windows Project

Experiment 10.15. Run bezierCurves.cpp. Press the up and downarrow keys to select an order between 2 and 6 on the first screen. Pressenter to proceed to the next screen where the control points initially lie on astraight line. Press space to select a control point and then the arrow keysto move it. Press delete to start over. Figure 10.65 is a screenshot for order6.

In addition to the black Bezier curve, drawn in light gray is its controlpolygon, the polyline through successive control points. Note how the Beziercurve tries to mimic the shape of its control polygon. End

Click for bezierCurveWithEvalCoord.cpp Program Windows Project

Experiment 10.16. Run bezierCurveWithEvalCoord.cpp, which drawsa fixed Bezier curve of order 6. See Figure 10.66 for a screenshot. End

Click for bezierCurveWithEvalMesh.cpp Program Windows Project

Experiment 10.17. Run bezierCurveWithEvalMesh.cpp. This programis the same as bezierCurveWithEval.cpp except that, instead of calls toglEvalCoord1f(), the pair of statements70

Page 75: Download - Computer Graphics Through OpenGL: From Theory to

glMapGrid1f(50, 0.0, 1.0);

glEvalMesh1(GL LINE, 0, 50);

are used to draw the approximating polyline.The call glMapGrid1f(n, t1, t2) specifies an evenly-spaced grid of

n + 1 sample points in the parameter interval, starting at t1 and endingat t2. The call glEvalMesh1(mode, p1, p2) works in tandem with theglMapGrid1f(n, t1, t2) call. For example, if mode is GL LINE, then itdraws a line strip through the mapped sample points, starting with theimage of the p1th sample point and ending at the image of the p2th one,which is a polyline approximation of part of the Bezier curve. End

Click for bezierCurveTangent.cpp Program Windows Project

Experiment 10.18. Run bezierCurveTangent.cpp. The blue curve maybe shaped by selecting a control point with the space key and moving it withthe arrow keys. Visually verify that the two curves meet smoothly whentheir control polygons meet smoothly. Figure 10.68 is a screenshot of such aconfiguration. End

Click for bezierSurface.cpp Program Windows Project

Experiment 10.19. Run bezierSurface.cpp, which allows the userherself to shape a Bezier surface by selecting and moving control pointsoriginally in a 6× 4 grid. Drawn in black actually is a 20× 20 quad meshapproximation of the Bezier surface. Also drawn in light gray is the controlpolyhedron, which is the polyhedral surface with vertices at control points.

Press the space and tab keys to select a control point. Use the left/rightarrow keys to move the selected control point parallel to the x-axis, theup/down arrow keys to move it parallel to the y-axis, and the page up/downkeys to move it parallel to the z-axis. Press ‘x/X’, ‘y/Y’ and ‘z/Z’ to turnthe surface. Figure 10.69 is a screenshot. End

Click for bezierCanoe.cpp Program Windows Project

Experiment 10.20. Run bezierCanoe.cpp. Repeatedly press the rightarrow key for a design process that starts with a rectangular Bezier patch,and then edits the control points in each of three successive steps until acanoe is formed. The left arrow reverses the process. Press ‘x/X’, ‘y/Y’ and‘z/Z’ to turn the surface.

The initial configuration is a 6 × 4 array of control points placed in arectangular grid on the xz-plane, making a rectangular Bezier patch.

The successive steps are: 71

Page 76: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 10

Modeling in 3D Space

(1) Lift the two end columns of control points up in the y-direction andbring them in along the x-direction to fold the rectangle into a deeppocket.

(2) Push the middle control points of the end columns outwards along thex-direction to plump the pocket into a “canoe” with its front and backopen.

(3) Bring together the two halves of each of the two end rows of controlpoints to stitch closed the erstwhile open front and back. Figure 10.70is a screenshot after this step.

End

Click for torpedo.cpp Program Windows Project

Experiment 10.21. Run torpedo.cpp, which shows a torpedo composedof a few different pieces, including bicubic Bezier patch propeller blades:

(i) Body: GLU cylinder.

(ii) Nose: hemisphere.

(iii) Three fins: identical GLU partial discs.

(iv) Backside: GLU disc.

(v) Propeller stem: GLU cylinder.

(vi) Three propeller blades: identical bicubic Bezier patches (control pointsarranged by trial-and-error).

Press space to start the propellers turning. Press ‘x/X’, ‘y/Y’ and ‘z/Z’to turn the torpedo. Figure 10.73 is a screenshot. End

Click for fractals.cpp Program Windows Project

Experiment 10.22. Run fractals.cpp, which draws three differentfractal curves – a Koch snowflake, a variant of the Koch snowflake anda tree – all within the framework above, by simply switching source-sequelspecs! Press the left/right arrow keys to cycle through the fractals and theup/down arrow keys to change the level of recursion. Figure 10.78 shows allthree at level 4. End

72

Page 77: Download - Computer Graphics Through OpenGL: From Theory to

Part VI

Lights, Camera, Equation

73

Page 78: Download - Computer Graphics Through OpenGL: From Theory to
Page 79: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 11Color and Light

Click for sphereInBox1.cpp Program Windows Project

Experiment 11.1. Run again sphereInBox1.cpp, which we ran the firsttime in Section 9.4. Press the up-down arrow keys to open or close the box.Figure 11.18 is a screenshot of the box partly open. We’ll use this programas a running example to explain much of the OpenGL lighting and materialcolor syntax. End

Click for lightAndMaterial1.cpp Program Windows Project

Experiment 11.2. Run lightAndMaterial1.cpp.The ball’s current ambient and diffuse reflectances are identically set to

a maximum blue of {0.0, 0.0, 1.0, 1.0}, its specular reflectance to the highestgray level {1.0, 1.0, 1.0, 1.0} (i.e., white), shininess to 50.0 and emission tozero {0.0, 0.0, 0.0, 1.0}.

Press ‘a/A’ to decrease/increase the ball’s blue Ambient and diffusereflectance. Pressing ‘s/S’ decreases/increases the gray level of its Specularreflectance. Pressing ‘h/H’ decreases/increases its sHininess, while pressing‘e/E’ decreases/increases the blue component of the ball’s Emission.

The program has further functionalities which we’ll explain as theybecome relevant. End

Click for lightAndMaterial2.cpp Program Windows Project

Experiment 11.3. Run lightAndMaterial2.cpp.The white light’s current diffuse and specular are identically set to a

maximum of {1.0, 1.0, 1.0, 1.0} and it gives off zero ambient light. The 75

Page 80: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 11

Color and Light

green light’s attributes are fixed at a maximum diffuse and specular of{0.0, 1.0, 0.0, 1.0}, again with zero ambient. The global ambient is a lowintensity gray at {0.2, 0.2, 0.2, 1.0}.

Press ‘w’ or ‘W’ to toggle the White light off and on. Pressing ‘g’ or‘G’ toggles the Green light off and on. Press ‘d/D’ to decrease/increase thegray level of the white light’s Diffuse and specular intensity (the ambientintensity never changes from zero). Pressing ‘m/M’ decreases/increases thegray intensity of the global aMbient. Rotate the white light about the ballby pressing the arrow keys.

This program, too, has added functionality which we’ll need later. End

Click for lightAndMaterial1.cpp Program Windows Project

Experiment 11.4. Run lightAndMaterial1.cpp.Reduce the specular reflectance of the ball. Both the white and green

highlights begin to disappear, as it’s the specular components of the reflectedlights which appear as specular highlights. End

Click for lightAndMaterial1.cpp Program Windows Project

Experiment 11.5. Restore the original values of lightAndMaterial1.cpp.Reduce the diffuse reflectance gradually to zero. The ball starts to lose its

roundness until it looks flat as a disc. The reason for this is that the ambientintensity, which does not depend on eye or light direction, is uniform acrossvertices of the ball and cannot, therefore, provide the sense of depth thatobtains from a contrast in color values across the surface. Diffuse light, onthe other hand, which varies across the surface depending on light direction,can provide an illusion of depth.

Even though there is a specular highlight, sensitive to both eye and lightdirection, it’s too localized to provide much depth contrast. Reducing theshininess does spread the highlight but the effect is not a realistic perceptionof depth.Moral : Diffusive reflectance lends three-dimensionality.

Figure 11.20 shows the ball starting with only ambient reflectance, thenadding in diffuse and specular.

End

Click for lightAndMaterial1.cpp Program Windows Project

Experiment 11.6. Restore the original values of lightAndMaterial1.cpp.Now reduce the ambient reflectance gradually to zero. The ball seems

to shrink! This is because the vertex normals turn away from the viewer at76

Page 81: Download - Computer Graphics Through OpenGL: From Theory to

the now hidden ends of the ball, scaling down the diffuse reflectance there(recall the cos θ term in the diffusive reflectance equation (11.7)). The resultis that, with no ambient reflectance to offset the reduction in diffuse, theends of the ball are dark.Moral : Ambient reflectance provides a level of uniform lighting over a surface.

End

Click for lightAndMaterial1.cpp Program Windows Project

Experiment 11.7. Restore the original values of lightAndMaterial1.cpp.Reduce both the ambient and diffuse reflectances to nearly zero. It’s

like the cat disappearing, leaving only its grin! Specular light is clearly forhighlights and not much else. End

Click for lightAndMaterial1.cpp Program Windows Project

Experiment 11.8. Run lightAndMaterial1.cpp with its original values.With its current high ambient, diffuse and specular reflectances the ball

looks a shiny plastic. Reducing the ambient and diffuse reflectances makesfor a heavier and less plastic appearance. Restoring the ambient and diffuseto higher values, but reducing the specular reflectance makes it a less shinyplastic. Low values for all three of ambient, diffuse and specular reflectancesgive the ball a somewhat wooden appearance. End

Click for lightAndMaterial2.cpp Program Windows Project

Experiment 11.9. Run lightAndMaterial2.cpp.Reduce the white light’s diffuse and specular intensity to 0. The ball

becomes a flat dull blue disc with a green highlight. This is because theball’s ambient (and diffuse) is blue and cannot reflect the green light’s diffusecomponent, losing thereby three-dimensionality.

Raising the white global ambient brightens the ball, but it still looks flatin the absence of diffusive light. End

Click for Nate’s site

Experiment 11.10. Nate Robins has a bunch of great tutorial programsat the site [100]. This is a good time to run his lightmaterial tutorial, whichallows the user to control a set of parameters as well. End

Click for spotlight.cpp Program Windows Project 77

Page 82: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 11

Color and Light

Experiment 11.11. Run spotlight.cpp. The program is primarily todemonstrate spotlighting, the topic of a forthcoming section. Nevertheless,press the page-up key to see a multi-colored array of spheres. Figure 11.21is a screenshot.

Currently, the point of interest in the program is the invocation of thecolor material mode for the front-face ambient and diffuse reflectances bymeans of the last two statements in the initialization routine, viz.

glEnable(GL COLOR MATERIAL);

glColorMaterial(GL FRONT, GL AMBIENT AND DIFFUSE);

and subsequent coloring of the spheres in the drawing routine by glColor4f()

statements. End

Click for litTriangle.cpp Program Windows Project

Experiment 11.12. Run litTriangle.cpp, which draws a single triangle,whose front is coded red and back blue, initially front-facing and lit two-sided.Press the left and right arrow keys to turn the triangle and space to toggletwo-sided lighting on and off. See Figure 11.23 for screenshots.

Notice how the back face is dark when two-sided lighting is disabled –this is because the normals are pointing oppositely of the way they shouldbe. End

Click for lightAndMaterial2.cpp Program Windows Project

Experiment 11.13. Press ‘p’ or ‘P’ to toggle between Positional anddirectional light in lightAndMaterial2.cpp.

The white wire sphere indicates the positional light, while the whitearrow the incoming directional light. End

Click for lightAndMaterial1.cpp Program Windows Project

Experiment 11.14. Run lightAndMaterial1.cpp. The current valuesof the constant, linear and quadratic attenuation parameters are 1, 0 and 0,respectively, so there’s no attenuation. Press ‘t/T’ to decrease/increase thequadratic aTtenuation parameter. Move the ball by pressing the up/downarrow keys to observe the effect of attenuation. End

Click for spotlight.cpp Program Windows Project78

Page 83: Download - Computer Graphics Through OpenGL: From Theory to

Experiment 11.15. Run spotlight.cpp, which shows a bright whitespotlight illuminating a multi-colored array of spheres. A screenshot wasshown earlier in Figure 11.21.

Press the page up/down arrows to increase/decrease the angle of thelight cone. Press the arrow keys to move the spotlight. Press ‘t/T’ to changethe spotlight attenuation factor. A white wire mesh is drawn along the lightcone boundary. End

Click for spotlight.cpp Program Windows Project

Experiment 11.16. Run again spotlight.cpp. Note the change invisibility of the balls near the cone boundary as the attenuation changes.End

Click for checkeredFloor.cpp Program Windows Project

Experiment 11.17. Run checkeredFloor.cpp, which creates a checkeredfloor drawn as an array of flat shaded triangle strips. See Figure 11.26. Flatshading causes each triangle in the strip to be painted with the color of thelast of its three vertices, according to the order of the strip’s vertex list.

End

Click for sphereInBox1.cpp Program Windows Project

Experiment 11.18. Run again sphereInBox1.cpp. The normal vectorvalues at the eight box vertices of sphereInBox1.cpp, placed in the arraynormals[], are

[±1/√

3 ± 1/√

3 ± 1/√

3]T

each corresponding to one of the eight possible combinations of signs. End

Click for sphereInBox2.cpp Program Windows Project

Experiment 11.19. Run sphereInBox2.cpp, which modifies sphereIn-

Box1.cpp. Press the arrow keys to open or close the box and space to togglebetween two methods of drawing normals.

The first method is the same as that of sphereInBox1.cpp, specifyingthe normal at each vertex as an average of incident face normals. The secondcreates the box by first drawing one side as a square with the normal ateach of its four vertices specified to be the unit vector perpendicular to thesquare, then placing that square in a display list and, finally, drawing it six 79

Page 84: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 11

Color and Light

times appropriately rotated. Figure 11.34(b) shows the vertex normals tothree faces. Figure 11.35 shows screenshots of the box created with andwithout averaged normals. End

Click for litCylinder.cpp Program Windows Project

Experiment 11.20. Run litCylinder.cpp, which builds upon cyl-

inder.cpp using the normal data calculated above, together with colorand a single directional light source. Press ‘x/X’, ‘y/Y’ and ‘z/Z’ to turnthe cylinder. The functionality of being able to change the fineness of themesh approximation has been dropped. Figure 11.39 is a screenshot. End

Click for litDoublyCurledCone.cpp Program Windows Project

Experiment 11.21. The program litDoublyCurledCone.cpp, in fact,applies the preceding equations for the normal and its length. Press ‘x/X’,‘y/Y’, ‘z/Z’ to turn the cone. See Figure 11.41 for a screenshot.

As promised, litDoublyCurledCone.cpp is pretty much a copy oflitCylinder.cpp, except for the different f(), g(), h(), fn(), gn() andhn() functions, as also the new normn() to compute the normal’s length.

End

Click for litCylinderProgrammedNormals.cpp Program Windows

Project

Experiment 11.22. Run litCylinderProgrammedNormals.cpp. Press‘x/X’, ‘y/Y’, ‘z/Z’ to turn the cylinder. Figure 11.42 is a screenshot. End

Click for litBezierCanoe.cpp Program Windows Project

Experiment 11.23. Run litBezierCanoe.cpp. Press ‘x/X’, ‘y/Y’, ‘z/Z’to turn the canoe. You can see a screenshot in Figure 11.44.

This program illuminates the final shape of bezierCanoe.cpp ofExperiment 10.20 with a single directional light source. Other than theexpected command glEnable(GL AUTO NORMAL) in the initialization routine,an important point to notice about litBezierCanoe.cpp is the reversal ofthe sample grid along the u-direction. In particular, compare the statement

glMapGrid2f(20, 1.0, 0.0, 20, 0.0, 1.0)

of litBezierCanoe.cpp with80

Page 85: Download - Computer Graphics Through OpenGL: From Theory to

glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0)

of bezierCanoe.cpp. This change reverses the directions of one of thetangent vectors evaluated at each vertex by OpenGL and, correspondingly,that of the normal (which is the cross-product of the two tangent vectors).

Modify litBezierCanoe.cpp by changing

glMapGrid2f(20, 1.0, 0.0, 20, 0.0, 1.0);

back to bezierCanoe.cpp’s

glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0);

Wrong normal directions! The change from bezierCanoe.cpp is necessary.Another solution is to leave glMapGrid2f() as it is in bezierCanoe.cpp,instead making a call to glFrontFace(GL CW). End

Click for shipMovie.cpp Program Windows Project

Experiment 11.24. Run shipMovie.cpp. Pressing space start ananimation sequence which begins with a torpedo traveling toward a movingship and which ends on its own after a few seconds. Figure 11.45 is ascreenshot as the torpedo nears the ship. End

Click for sizeNormal.cpp Program Windows Project

Experiment 11.25. Run sizeNormal.cpp based on litTriangle.cpp.The ambient and diffuse colors of the three triangle vertices are set to

red, green and blue, respectively. The normals are specified separately aswell, initially each of unit length perpendicular to the plane of the triangle.

However, pressing the up/down arrow keys changes (as you can see) thesize, but not the direction, of the normal at the red vertex. Observe thecorresponding change in color of the triangle. Figure 11.47 is a screenshot.

End

Click for sizeNormal.cpp modified Program Windows Project

Experiment 11.26. Run sizeNormal.cpp after placing the statementglEnable(GL NORMALIZE) at the end of the initialization routine. Press theup/down arrow keys. The triangle no longer changes color (though thewhite arrow still changes in length, of course, because its size is that of theprogram-specified normal). End

81

Page 86: Download - Computer Graphics Through OpenGL: From Theory to
Page 87: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 12Texture

Click for loadTextures.cpp Program Windows Project

Experiment 12.1. Run loadTextures.cpp, which loads an externalimage of a shuttle launch as one texture and generates internally a chessboardimage as another.

The program paints both the external and the procedural texture onto asquare. Figure 12.5 shows the two. Press space to toggle between them, theleft and right arrow keys to turn the square and delete to reset it.

Important : Our own texture images are in the folder ExperimenterSource/-Textures.

Our programs all use the particular routine getbmp() to read in externalimage files, which is in the associated source file getbmp.cpp, and includedin the application program via the header getbmp.h. Because getbmp() iswritten to accept input image files in uncompressed 24-bit color RGB bmpformat, image files in other formats must first be converted, which can bedone using image-editing software like Windows Paint, GIMP and AdobePhotoshop.

Note, though, that the input file is written internally into a 32-bit RGBAformat, the A (alpha) field allowing for use in blending applications. End

Click for loadTextures.cpp modified Program Windows Project

Experiment 12.2. Replace every 1.0 in each glTexCoord2f() commandof loadTextures.cpp with 0.5 so that the polygon specification is (Block 11):

1To cut-and-paste you can find the block in text formatin the file chap12codeModifications.txt in the directoryExperimenterSource/CodeModifications. 83

Page 88: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 12

Texture

glBegin(GL POLYGON);

glTexCoord2f(0.0, 0.0); glVertex3f(-10.0, -10.0, 0.0);

glTexCoord2f(0.5, 0.0); glVertex3f(10.0, -10.0, 0.0);

glTexCoord2f(0.5, 0.5); glVertex3f(10.0, 10.0, 0.0);

glTexCoord2f(0.0, 0.5); glVertex3f(-10.0, 10.0, 0.0);

glEnd();

The lower left quarter of the texture is interpolated over the square(Figure 12.8(a)). Make sure to see both the launch and chessboard textures!

End

Click for loadTextures.cpp modified Program Windows Project

Experiment 12.3. Restore the original loadTextures.cpp and delete thelast vertex from the polygon so that the specification is that of a triangle(Block 2):

glBegin(GL POLYGON);

glTexCoord2f(0.0, 0.0); glVertex3f(-10.0, -10.0, 0.0);

glTexCoord2f(1.0, 0.0); glVertex3f(10.0, -10.0, 0.0);

glTexCoord2f(1.0, 1.0); glVertex3f(10.0, 10.0, 0.0);

glEnd();

Exactly as expected, the lower-right triangular half of the texture isinterpolated over the world-space triangle (Figure 12.8(b)).

Change the coordinates of the last vertex of the world-space triangle(Block 3):

glBegin(GL POLYGON);

glTexCoord2f(0.0, 0.0); glVertex3f(-10.0, -10.0, 0.0);

glTexCoord2f(1.0, 0.0); glVertex3f(10.0, -10.0, 0.0);

glTexCoord2f(1.0, 1.0); glVertex3f(0.0, 10.0, 0.0);

glEnd();

Interpolation is clearly evident now. Parts of both launch and chessboardare skewed by texturing, as the triangle specified by texture coordinates isnot similar to its world-space counterpart (Figure 12.8(c)).

Continuing, change the texture coordinates of the last vertex (Block 4):

glBegin(GL POLYGON);

glTexCoord2f(0.0, 0.0); glVertex3f(-10.0, -10.0, 0.0);

glTexCoord2f(1.0, 0.0); glVertex3f(10.0, -10.0, 0.0);

glTexCoord2f(0.5, 1.0); glVertex3f(0.0, 10.0, 0.0);

glEnd();

The textures are no longer skewed as the triangle in texture space issimilar to the one being textured (Figure 12.8(d)). End84

Page 89: Download - Computer Graphics Through OpenGL: From Theory to

Click for loadTextures.cpp modified Program Windows Project

Experiment 12.4. Restore the original loadTextures.cpp and replacelaunch.bmp with cray2.bmp, an image of a Cray 2 supercomputer. Viewthe original images in the Textures folder and note their sizes: the launchis 512 × 512 pixels while the Cray 2 is 512 × 256. As you can see, the Cray2 is scaled by half width-wise to fit the square polygon. End

Click for loadTextures.cpp modified Program Windows Project

Experiment 12.5. Restore the original loadTextures.cpp and thenchange the coordinates of only the third world-space vertex of the texturedpolygon (Block 5):

glBegin(GL POLYGON);

glTexCoord2f(0.0, 0.0); glVertex3f(-10.0, -10.0, 0.0);

glTexCoord2f(1.0, 0.0); glVertex3f(10.0, -10.0, 0.0);

glTexCoord2f(1.0, 1.0); glVertex3f(20.0, 0.0, 0.0);

glTexCoord2f(0.0, 1.0); glVertex3f(-10.0, 10.0, 0.0);

glEnd();

The launch looks odd. The rocket rises vertically, but the flames underneathare shooting sideways! Toggle to the chessboard and it’s instantly clearwhat’s going on. Figure 12.9 shows both textures. End

Click for loadTextures.cpp modified Program Windows Project

Experiment 12.6. Restore the original loadTextures.cpp and changethe texture coordinates of the polygon as follows (Block 7):

glBegin(GL POLYGON);

glTexCoord2f(-1.0, 0.0); glVertex3f(-10.0, -10.0, 0.0);

glTexCoord2f(2.0, 0.0); glVertex3f(10.0, -10.0, 0.0);

glTexCoord2f(2.0, 2.0); glVertex3f(10.0, 10.0, 0.0);

glTexCoord2f(-1.0, 2.0); glVertex3f(-10.0, 10.0, 0.0);

glEnd();

It seems that the texture space is tiled using the texture. See Figure 12.11.In particular, the texture seems repeated in every unit square of texture

space with integer vertex coordinates. As the world-space polygon is mappedto a 3 × 2 rectangle in texture space, it is painted with six copies of thetexture, each scaled to an aspect ratio of 2:3. The scheme itself is indicatedFigure 12.12. End

Click for loadTextures.cpp modified Program Windows Project 85

Page 90: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 12

Texture

Experiment 12.7. Change the texture coordinates again by replacingeach −1.0 with −0.5 (Block 8):

glBegin(GL POLYGON);

glTexCoord2f(-0.5, 0.0); glVertex3f(-10.0, -10.0, 0.0);

glTexCoord2f(2.0, 0.0); glVertex3f(10.0, -10.0, 0.0);

glTexCoord2f(2.0, 2.0); glVertex3f(10.0, 10.0, 0.0);

glTexCoord2f(-0.5, 2.0); glVertex3f(-10.0, 10.0, 0.0);

glEnd();

Again it’s apparent that the texture space is tiled with the specified textureand that the world-space polygon is painted over with its rectangular imagein texture space. End

Click for loadTextures.cpp modified Program Windows Project

Experiment 12.8. Restore the original loadTextures.cpp and thenchange the texture coordinates as below, which is the same as inExperiment 12.6 (Block 7):

glBegin(GL POLYGON);

glTexCoord2f(-1.0, 0.0); glVertex3f(-10.0, -10.0, 0.0);

glTexCoord2f(2.0, 0.0); glVertex3f(10.0, -10.0, 0.0);

glTexCoord2f(2.0, 2.0); glVertex3f(10.0, 10.0, 0.0);

glTexCoord2f(-1.0, 2.0); glVertex3f(-10.0, 10.0, 0.0);

glEnd();

Next, replace the GL REPEAT parameter in the

glTexParameteri(GL TEXTURE 2D, GL TEXTURE WRAP S, GL REPEAT);

statement of both the loadExternalTextures() and loadProcedural-

Textures() routines with GL CLAMP so that it becomes

glTexParameteri(GL TEXTURE 2D, GL TEXTURE WRAP S, GL CLAMP);

This causes the wrapping mode to be clamped in the s-direction. It’sprobably easiest to understand what happens in this mode by observing inparticular the chessboard texture: see Figure 12.13. Texture s coordinatesgreater than 1 are clamped to 1, those less than 0 to 0. Precisely, instead ofthe texture space being tiled with the texture, points with coordinates (s, t),where s > 1, obtain their color values from the point (1, t), while those withcoordinates (s, t), where s < 0, obtain them from (0, t). End

Click for loadTextures.cpp modified Program Windows Project86

Page 91: Download - Computer Graphics Through OpenGL: From Theory to

Experiment 12.9. Continue the previous experiment by clamping thetexture along the t-direction as well. In particular, replace the GL REPEAT

parameter in the

glTexParameteri(GL TEXTURE 2D, GL TEXTURE WRAP T, GL REPEAT);

statement with GL CLAMP. We leave the reader to parse the output. End

Click for fieldAndSky.cpp Program Windows Project

Experiment 12.10. Run fieldAndSky.cpp, where a grass texture is tiledover a horizontal rectangle and a sky texture clamped to a vertical rectangle.There is the added functionality of being able to transport the camera overthe field by pressing the up and down arrow keys. Figure 12.14 shows ascreenshot.

As the camera travels, the grass seems to shimmer – flash and scintillateare terms also used to describe this phenomenon. This is our first encounterwith the aliasing problem in texturing. Any visual artifact which arises owingto the finite resolution of the display device and the correspondingly “large”size of individual pixels – at least to the extent that they are discernible tothe human eye – is said to be caused by aliasing. End

Click for fieldAndSky.cpp modified Program Windows Project

Experiment 12.11. Change to linear filtering in fieldAndSky.cpp byreplacing every GL NEAREST with GL LINEAR. The grass still shimmers thoughless severely. The sky seems okay with either GL NEAREST or GL LINEAR.End

Click for fieldAndSkyFiltered.cpp Program Windows Project

Experiment 12.12. Run fieldAndSkyFiltered.cpp, identical to field-

AndSky.cpp except for additional filtering options. Press the up/down arrowkeys to move the camera and the left/right ones to cycle through filters forthe grass texture. Messages at the top identify the current filters. End

Click for compareFilters.cpp Program Windows Project

Experiment 12.13. Run compareFilters.cpp, where one sees side-by-side identical images of a shuttle launch bound to a square. Press the upand down arrow keys to move the squares. Press the left arrow key to cyclethrough filters for the image on the left and the right arrow key to do likewise 87

Page 92: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 12

Texture

for the one on the right. Messages at the top say which filters are currentlyapplied. Figure 12.19 is a screenshot of the initial configuration.

Compare, as the squares move, the quality of the textures delivered bythe various min filters. Of course, if one of the four mipmap-based minfilters – GL NEAREST MIPMAP NEAREST through GL LINEAR MIPMAP LINEAR –is applied, then the particular mipmap actually chosen by OpenGL dependson the screen space occupied by the square. End

Click for mipmapLevels.cpp Program Windows Project

Experiment 12.14. Run mipmapLevels.cpp, where the mipmaps are sup-plied by the program, rather than generated automatically by glGenerate-

Mipmap(). The mipmaps are very simple: just differently colored squareimages, created by the routine createMipmaps(), starting with the blue64× 64 mipmapRes64 down to the black 1× 1 mipmapRes1. Commands ofthe form

glTexImage2D(GL TEXTURE 2D, level, GL RGBA, width, height,0, GL RGBA, GL UNSIGNED BYTE, image);

each binds a width × height mipmap image to the current texture index,starting with the highest resolution image with level parameter 0, and witheach successive image of lower resolution having one higher level all the wayup to 6.

Move the square using the up and down arrow keys. As it grows smallera change in color indicates a change in the currently applied mipmap.Figure 12.20 is screenshot after the first change. As the min filter setting isGL NEAREST MIPMAP NEAREST, a unique color, that of the closest mipmap, isapplied to the square at any given time. End

Click for texturedTorus.cpp Program Windows Project

Experiment 12.15. Run texturedTorus.cpp, which shows the shuttlelaunch texture mapped onto a torus. Figure 12.22 is a screenshot. Press‘x’-‘Z’ to turn the torus. End

Click for texturedTorpedo.cpp Program Windows Project

Experiment 12.16. Run texturedTorpedo.cpp, which textures parts ofthe torpedo of torpedo.cpp – from Experiment 10.21 – as you can see inthe screenshot in Figure 12.24. Press space to start the propeller turning.End88

Page 93: Download - Computer Graphics Through OpenGL: From Theory to

Click for texturedTorusAnimated.cpp Program Windows Project

Experiment 12.17. Run texturedTorusAnimated.cpp, which animatesthe launch texture of texturedTorus.cpp by applying a translation to thecurrent texture matrix. Press space to toggle between animation on andoff, the up and down arrow keys to change its speed and ‘x’-‘Z’ to turn thetorus.

The modification of texturedTorus.cpp is simple. In particular, thefollowing block of code in the drawing routine does the trick by enteringtexture matrix mode and applying a translation in the t-direction, effectivelytranslating the texture coordinates in the t-direction:

glMatrixMode(GL_TEXTURE);

glLoadIdentity();

glTranslatef(0.0, shift, 0.0);

glMatrixMode(GL_MODELVIEW);

The rest of the modification of texturedTorus.cpp is in managing theanimation. End

Click for fieldAndSkyLit.cpp Program Windows Project

Experiment 12.18. Run fieldAndSkyLit.cpp, which applies lighting tothe scene of fieldAndSky.cpp with help of the GL MODULATE option. Thelight source is directional – imagine the sun – and its direction controlledusing the left and right arrow keys, while its intensity can be changed usingthe up and down arrow keys. A white line indicates the direction andintensity of the sun. Figure 12.26(a) is a mid-morning screenshot.

The material colors are all white, as is the light. The normal to thehorizontal grassy plane is vertically upwards. Strangely, we use the samenormal for the sky’s vertical plane, because using its “true” value towardthe positive z-direction has the unpleasant, but expected, consequence of asky that doesn’t darken together with land. End

Click for litTexturedCylinder.cpp Program Windows Project

Experiment 12.19. Run litTexturedCylinder.cpp, which adds a labeltexture and a can top texture to litCylinder.cpp. Press ‘x’-‘Z’ to turnthe can. Figure 12.26(b) is a screenshot.

Most of the program is routine – the texture coordinate generation is, infact, a near copy of that in texturedTorus.cpp – except for the followinglighting model statement in setup() which we’re using for the first time:

glLightModeli(GL LIGHT MODEL COLOR CONTROL, GL SEPARATE SPECULAR COLOR) 89

Page 94: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 12

Texture

We had briefly encountered this statement as an OpenGL lighting modeloption in Section 11.4. It causes a modification of OpenGL’s GL MODULATE

procedure: the specular color components are separated and not multipliedwith the corresponding texture color components, as are the ambient anddiffuse, but added in after. The result is that specular highlights are preservedrather than blended with the texture. End

Click for multitexture.cpp Program Windows Project

Experiment 12.20. Run multitexture.cpp, which interpolates betweennight and day sky texture. Press the left/right arrow keys to transitionbetween night and day. Figure 12.27 shows stages in the transition. End

90

Page 95: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 13Special Visual Techniques

Click for blendRectangles1.cpp Program Windows Project

Experiment 13.1. Run blendRectangles1.cpp, which draws two translu-cent rectangles with their alpha values equal to 0.5, the red one being closerto the viewer than the blue one. The code order in which the rectangles aredrawn can be toggled by pressing space. Figure 13.2 shows screenshots ofeither order. End

Click for blendRectangles2.cpp Program Windows Project

Experiment 13.2. Run blendRectangles2.cpp, which draws threerectangles at different distances from the eye. The closest one at depth 0.5 isvertical and a translucent red (α = 0.5), the next one at depth 0.7 is angledand opaque green (α = 1), while the farthest at depth 0.9 is horizontal anda translucent blue (α = 0.5). Figure 13.3(a) is a screenshot of the output. 91

Page 96: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 13

Special Visual

Techniques

(a) (b) (c)

Figure 13.1: Screenshots of blendRectangles2.cpp: (a) Original (b) With rectanglesre-ordered to blue, green, red in the code (c) New ordering seen from the −z-direction.

The scene is clearly not authentic as no translucency is evident in eitherof the two areas where the green and blue rectangles are behind the red.The fault is not OpenGL’s as it is rendering as it’s supposed to with depthtesting, as we see next. End

Click for blendRectangles2.cpp modified Program Windows Project

Experiment 13.3. Rearrange the rectangles and insert two glDepth-

Mask() calls in the drawing routine of blendRectangles2.cpp as follows:

// Draw opaque objects, only one.

drawGreenRectangle();

glDepthMask(GL FALSE); // Make depth buffer read-only.

// Draw translucent objects.

drawBlueRectangle();

drawRedRectangle();

glDepthMask(GL TRUE); // Make depth buffer writable.

Try both gluLookAt(. . ., 0.0, 0.0, -1.0, . . .) and gluLookAt(. . .,0.0, 0.0, 1.0, . . .) to see the rectangles from the front and back.Interchange the drawing order of the two translucent rectangles as well.The scene is authentic in every instance. End

Click for sphereInGlassBox.cpp Program Windows Project

Experiment 13.4. Run sphereInGlassBox.cpp, which makes the sidesof the box of sphereInBox2.cpp glass-like by rendering them translucently.92

Page 97: Download - Computer Graphics Through OpenGL: From Theory to

Only the unaveraged normals option of sphereInBox2.cpp is implemented.Press the up and down arrow keys to open or close the box and ‘x/X’, ‘y/Y’and ‘z/Z’ to turn it.

The opaque sphere is drawn first and then the translucent box sides,after making the depth buffer read-only. A screenshot is Figure 13.5(a).

End

Click for fieldAndSkyTexturesBlended.cpp Program Windows

Project

Experiment 13.5. Run fieldAndSkyTexturesBlended.cpp, which isbased on fieldAndSkyLit.cpp. Press the arrow keys to move the sun.As the sun rises the night sky morphs into a day sky (yes, we saw this verysame morph as an application of multitexturing, using the interpolationcombiner, in Section 12.6). Figure 13.5(b) shows late evening. End

Click for ballAndTorusReflected.cpp Program Windows Project

Experiment 13.6. Run ballAndTorusReflected.cpp, which builds onballAndTorusShadowed.cpp. Press space to start the ball traveling aroundthe torus and the up and down arrow keys to change its speed.

The reflected ball and torus are obtained by drawing them scaled by afactor of −1 in the y-direction, which creates their reflections in the xz-plane,and then blending the floor into the reflection. Figure 13.5(c) shows ascreenshot. End

Click for fieldAndSkyFogged.cpp Program Windows Project

Experiment 13.7. Run fieldAndSkyFogged.cpp, which is based on ourfavorite workhorse program fieldAndSky.cpp, adding to it a movable blackball and controllable fog. Figure 13.6 is a screenshot.

Press the up/down arrow keys to move the ball. When the programstarts there is no fog. We’ll describe the fog controls after we discuss theirimplementation in the following. End

Click for billboard.cpp Program Windows Project

Experiment 13.8. Run billboard.cpp, where an image of two trees istextured onto a rectangle. Press the up and down arrow keys to move theviewpoint and the space bar to turn billboarding on and off. See Figure 13.9for screenshots. End 93

Page 98: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 13

Special Visual

Techniques

Click for antiAliasing+multisampling.cpp Program Windows

Project

Experiment 13.9. Run antiAliasing+multisampling.cpp. Ignore themultisampling controls, as well as the blue-yellow rectangle, for now. Focuson the red line segment and the green point, which are both either antialiasedor not, ‘a’ or ‘A’ toggling between the two modes. The width of the line ischanged by pressing ‘l/L’, while the size of the point with ‘p/P’. The scenecan be turned by the ‘x’-‘Z’ keys and translated by pressing the arrow andpage up/down keys. A wire cube is drawn as frame of reference to view themotion.

Figure 13.11 shows screenshots of antialiasing both off and on. The effectof antialiasing is especially marked when the line is just shy of horizontal orvertical. End

Click for antiAliasing+multisampling.cpp Program Windows

Project

Experiment 13.10. Fire up again antiAliasing+multisampling.cpp.Multisampling is toggled on/off, independently of antialiasing, by pressing‘m’ or ‘M’.

Multisampling antialiases polygons particularly effectively and its effectin our program is best observed on the boundary of the blue-yellow rectangle,as well as the edge between its two colored halves, particularly, when theyare nearly horizontal or vertical.

When multisampling is enabled, lines and points are antialiased regardlessif GL POINT SMOOTH or GL LINE SMOOTH have been enabled, which you cansee as well. End

Click for pointSprite.cpp Program Windows Project

Experiment 13.11. Fire up pointSprite.cpp. The space bar togglesanimation on and off. The particle system of six sprites of fluctuating size,imprinted with the same star texture, spinning in a circle is simple-minded,though, hopefully, indicative of the possibilities. Figure 13.13 is a screenshot.

End

Click for sphereMapping.cpp Program Windows Project

Experiment 13.12. Run sphereMapping.cpp, which shows the scene ofa shuttle launch with a reflective rocket cone initially stationary in the sky infront of the rocket. Press the up and down arrow keys to move the cone. Asthe cone flies down, the reflection on its surface of the launch image changes.Figure 13.15 is a screenshot as it’s about to crash to the ground. End94

Page 99: Download - Computer Graphics Through OpenGL: From Theory to

Click for ballAndTorusStenciled.cpp Program Windows Project

Experiment 13.13. Run ballAndTorusStenciled.cpp, based on ball-

AndTorusReflected.cpp. The difference is that in the earlier program theentire checkered floor was reflective, while in the current one the red floor isnon-reflective except for a mirror-like disc lying on it. Pressing the arrowkeys moves the disc and pressing the space key starts and stops the ballmoving. As you can see in the screenshot of Figure 13.24, the ball and torusare reflected only in the disc and nowhere else. End

Click for imageManipulation.cpp Program Windows Project

Experiment 13.14. Run imageManipulation.cpp. An image of thenumeral 1 appears at the bottom left of the OpenGL window. Clicking themouse left button anywhere on the window will move the image to thatlocation, while you can, as well, drag the image with the left button pressed.Figure 13.25 is a screenshot of the initial configuration. End

Click for imagaManipulationPBO.cpp Program Windows Project

Experiment 13.15. Fire up imageManipulationPBO.cpp, which modifiesimageManipulation.cpp to store the pixel data in a PBO. Otherwise, thefunctionality of both programs is identical, the image of the numeral beingmoved by mouse clicks and drags. End

Click for bumpMapping.cpp Program Windows Project

Experiment 13.16. Run bumpMapping.cpp, where a plane is bumpmapped to make it appear corrugated. Press space to toggle betweenbump mapping turned on and off. Figure 13.29 shows screenshots. End

95

Page 100: Download - Computer Graphics Through OpenGL: From Theory to
Page 101: Download - Computer Graphics Through OpenGL: From Theory to

Part VII

Pixels, Pixels, Everywhere

97

Page 102: Download - Computer Graphics Through OpenGL: From Theory to
Page 103: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 14Raster Algorithms

Click for DDA.cpp Program Windows Project

Experiment 14.1. Run DDA.cpp, which is pretty much a word for wordimplementation of the DDA algorithm above. A point of note is the simula-tion of the raster by the OpenGL window: the statement gluOrtho2D(0.0,500.0, 0.0, 500.0) identifies “pixel-to-pixel” the viewing face with the500×500 OpenGL window (a “pixel” of the viewing face being a 1×1 squarewith corners at integer coordinates).

There’s no interaction and the endpoints of the line are fixed in the codeat (100, 100) and (300, 200). Figure 14.12 is a screenshot. End

99

Page 104: Download - Computer Graphics Through OpenGL: From Theory to
Page 105: Download - Computer Graphics Through OpenGL: From Theory to

Part VIII

Anatomy of Curves andSurfaces

101

Page 106: Download - Computer Graphics Through OpenGL: From Theory to
Page 107: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 15Bezier

Click for deCasteljau3.cpp Program Windows Project

Experiment 15.1. Run deCasteljau3.cpp, which shows an animation ofde Casteljau’s method for three control points. Press the left or right arrowkeys to decrease or increase the curve parameter u. The interpolating pointsa(u), b(u) and c(u) are colored red, green and blue, respectively. Figure 15.4is a screenshot. End

Click for bezierCurves.cpp Program Windows Project

Experiment 15.2. Run bezierCurves.cpp, which allows the user tochoose a Bezier curve of order 2-6 and move each control point.

You can choose an order in the first screen by pressing the up and downarrow keys. Select 3. Press enter to go to the next screen to find the controlpoints initially on a straight line. Press space to select a control point – theselected one is red – and then arrow keys to move it. Delete resets to thefirst screen. Figure 15.5 is a screenshot.

The polygonal line joining the control points, called the control polygonof the curve, is drawn in light gray. Evidently, the Bezier curve “mimics” itscontrol polygon, but smoothly, avoiding a corner. End

Click for bezierCurves.cpp Program Windows Project

Experiment 15.3. Run bezierCurves.cpp and choose order 4 to get afeel for cubic Bezier curves. Note again how the curve mimics its controlpolygon. End 103

Page 108: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 15

Bezier

Click for bezierCurves.cpp Program Windows Project

Experiment 15.4. Run bezierCurves.cpp and choose the higher orders.It’s straightforward to enhance the code for orders even greater than 6. End

Click for bezierCurveTangent.cpp Program Windows Project

Experiment 15.5. Run bezierCurveTangent.cpp which shows two cubicBezier curves. The second curve may be shaped by selecting a control pointwith the space bar and moving it with the arrow keys. See Figure 15.10.Visually verify Proposition 15.1(g). End

Click for sweepBezierSurface.cpp Program Windows Project

Experiment 15.6. Run sweepBezierSurface.cpp to see an animationof the procedure. Press the left/right (or up/down) arrow keys to move thesweeping curve and the space bar to toggle between the two possible sweepdirections. Figure 15.14 is a screenshot.

The 4 × 4 array of the Bezier surface’s control points (drawn as smallsquares) consists of a blue, red, green and yellow row of four control pointseach. The four fixed Bezier curves of order 4 are drawn blue, red, green andyellow, respectively (the curves are in 3-space, which is a bit hard to makeout because of the projection). The sweeping Bezier curve is black and its(moving) control points are drawn as larger squares. The currently sweptpart of the Bezier surface is the dark mesh. The current parameter value isshown at the top left. End

Click for bezierSurface.cpp Program Windows Project

Experiment 15.7. Run bezierSurface.cpp, which allows the user toshape a Bezier surface by selecting and moving control points. Press thespace and tab keys to select a control point. Use the left/right arrow keysto move the control point parallel to the x-axis, the up/down arrow keys tomove it parallel to the y-axis and the page up/down keys to move it parallelto the z-axis.

Press ‘x/X’, ‘y/Y’ and ‘z/Z’ to turn the viewpoint. Figure 15.15 is ascreenshot. End

104

Page 109: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 16B-Spline

Click for bSplines.cpp Program Windows Project

Experiment 16.1. Run bSplines.cpp, which shows the non-zero partsof the spline functions from first order to cubic over the uniformly spacedknot vector

[0, 1, 2, 3, 4, 5, 6, 7, 8]

Press the up/down arrow keys to choose the order. Figure 16.9 is a screenshotof the first order. The knot values can be changed as well, but there’s noneed to now. End

Click for bSplines.cpp Program Windows Project

Experiment 16.2. Run again bSplines.cpp and select the linear B-splines over the knot vector

[0, 1, 2, 3, 4, 5, 6, 7, 8]

Figure 16.13 is a screenshot. End

Click for bSplines.cpp Program Windows Project

Experiment 16.3. Run again bSplines.cpp and select the quadraticB-splines over the knot vector

[0, 1, 2, 3, 4, 5, 6, 7, 8]

Figure 16.18 is a screenshot. Note the joints indicated as black points. End 105

Page 110: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 16

B-Spline

Click for quadraticSplineCurve.cpp Program Windows Project

Experiment 16.4. Run quadraticSplineCurve.cpp, which shows thequadratic spline approximation of nine control points over a uniformlyspaced vector of 12 knots. Figure 16.21 is a screenshot.

The control points are green. Press the space bar to select a control point– the selected one turns red – and the arrow keys to move it. The knots arethe green points on the black bars at the bottom. At this stage there is noneed to change their values. The blue points are the joints of the curve, i.e.,images of the knots. Also drawn in light gray is the control polygon. End

Click for bSplines.cpp Program Windows Project

Experiment 16.5. Run bSplines.cpp and change the order to see asequence of cubic B-splines. End

Click for cubicSplineCurve1.cpp Program Windows Project

Experiment 16.6. Run cubicSplineCurve1.cpp, which shows the cubicspline approximation of nine control points over a uniformly-spaced vectorof 13 knots. The program is similar to quadraticSplineCurve.cpp. SeeFigure 16.23 for a screenshot.

The control points are green. Press the space bar to select a controlpoint – the selected one is colored red – then the arrow keys to move it. Theknots are the green points on the black bars at the bottom. The blue pointsare the joints of the curve. The control polygon is a light gray. End

Click for bSplines.cpp Program Windows Project

Experiment 16.7. Run again bSplines.cpp. Change the knot valuesby selecting one with the space bar and then pressing the left/right arrowkeys. Press delete to reset knot values. Note that the routine Bspline()

implements the CdM formula (and its convention for 0 denominators).

In particular, observe the quadratic and cubic spline functions. Notehow they lose their symmetry about a vertical axis through the center, andthat no longer are they translates of one another.

Play around with making knot values equal – we’ll soon be discussingthe utility of multiple knots.

Figures 16.27(a) and (b) are screenshots of the quadratic and cubicfunctions, respectively, both over the same non-uniform knot vector with atriple knot at the right end. End106

Page 111: Download - Computer Graphics Through OpenGL: From Theory to

Click for quadraticSplineCurve.cpp Program Windows Project

Experiment 16.8. Run again quadraticSplineCurve.cpp. Press ‘k’ toenter knots mode and alter knot values using the left/right arrow keys and‘c’ to return to control points mode. Press delete in either mode to reset.

Try to understand what happens if knots are repeated. Do you noticea loss of C1-continuity when knots in the interior of the knot vectorcoincide? What if knots at the ends coincide? Figure 16.28 is a screenshotof quadraticSplineCurve.cpp with a double knot at 5 and a triple at theend at 11. End

Click for cubicSplineCurve1.cpp Program Windows Project

Experiment 16.9. Run again cubicSplineCurve1.cpp. Press ‘k’ to enterknots mode and alter knot values using the left/right arrow keys and ‘c’ toreturn to control points mode. Press delete in either mode to reset. End

Click for quadraticSplineCurve.cpp Program Windows Project

Experiment 16.10. Use the programs quadraticSplineCurve.cpp andcubicSplineCurve1.cpp to make the quadratic and cubic B-spline approx-imations over the knot vector T = {0, 1, 2, 3, 3, 4, 5, 6, 7, . . .} of nine controlpoints placed as in Figure 16.31(a) (or (b)). See Figure 16.32(a) and (b) forscreenshots of the quadratic and cubic curves, respectively.

(a) (b)

Figure 16.1: Screenshots of (a) quadraticSplineCurve.cpp and(b) cubicSplineCurve1.cpp over the knot vector T = {0, 1, 2, 3, 3, 4, 5, 6, 7, . . .} andapproximating nine control points arranged in two horizontal rows.

The quadratic approximation loses C1-continuity precisely at the controlpoint P2, which it now interpolates as the curve point c(3). It’s still C0

everywhere. 107

Page 112: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 16

B-Spline

It’s not easy to discern visually, but the cubic spline drops from C2 toC1-continuous at c(3). End

Click for cubicSplineCurve1.cpp Program Windows Project

Experiment 16.11. Continuing with cubicSplineCurve1.cpp withcontrol points as in the preceding experiment, press delete to reset andthen make equal t4, t5 and t6, creating a triple knot. Figure 16.33 is ascreenshot of this configuration. Evidently, the control point P3 is nowinterpolated at the cost of a drop in continuity there to mere C0. Elsewhere,the curve is still C2. End

Click for quadraticSplineCurve.cpp Program Windows Project

Experiment 16.12. Make the first three and last three knots separatelyequal in quadraticSplineCurve.cpp (Figure 16.34(a)). Make the firstfour and last four knots separately equal in cubicSplineCurve1.cpp

(Figure 16.34(b)). The first and last control points are interpolated inboth. Do you notice any impairment in continuity? No! End

Click for quadraticSplineCurve.cpp Program Windows Project

Experiment 16.13. Change the last parameter of the statement

gluNurbsProperty(nurbsObject, GLU_SAMPLING_TOLERANCE, 10.0);

in the initialization routine of quadraticSplineCurve.cpp from 10.0 to100.0. The fall in resolution is noticeable. End

Click for cubicSplineCurve2.cpp Program Windows Project

Experiment 16.14. Run cubicSplineCurve2.cpp, which draws the cubicspline approximation of 30 movable control points, initially laid out on acircle, over a fixed standard knot vector. Press space and backspace to cyclethrough the control points and the arrow keys to move the selected controlpoint. The delete key resets the control points. Figure 16.36 is a screenshotof the initial configuration.

The number of control points being much larger than the order, the userhas good local control. End

Click for bicubicSplineSurface.cpp Program Windows Project108

Page 113: Download - Computer Graphics Through OpenGL: From Theory to

Experiment 16.15. Run bicubicSplineSurface.cpp, which draws aspline surface approximation to a 15 × 10 array of control points, eachmovable in 3-space. The spline is cubic in both parameter directions and astandard knot vector is specified in each as well.

Press the space, backspace, tab and enter keys to select a control point.Move the selected control point using the arrow and page up and down keys.The delete key resets the control points. Press ‘x/X’, ‘y/Y’ and ‘z/Z’ toturn the surface. Figure 16.38 is a screenshot. End

Click for bicubicSplineSurfaceLitTextured.cpp Program Windows

Project

Experiment 16.16. Run bicubicSplineSurfaceLitTextured.cpp, whichtextures the spline surface of bicubicSplineSurface.cpp with a red-whitechessboard texture. Figure 16.39 is a screenshot. The surface is illuminatedby a single positional light source whose location is indicated by a large blackpoint. User interaction remains as in bicubicSplineSurface.cpp. Notethat pressing the ‘x’-‘Z’ keys turns only the surface, not the light source.

The bicubic B-spline surface, as well as the fake bilinear one in texturespace, are created by the following statements in the drawing routine:

gluBeginSurface(nurbsObject);

gluNurbsSurface(nurbsObject, 19, uknots, 14, vknots,

30, 3, controlPoints[0][0], 4, 4, GL_MAP2_VERTEX_3);

gluNurbsSurface(nurbsObject, 4, uTextureknots, 4, vTextureknots,

4, 2, texturePoints[0][0], 2, 2, GL_MAP2_TEXTURE_COORD_2);

gluEndSurface(nurbsObject);

We’ll leave the reader to parse in particular the third statement and verifythat it creates a “pseudo-surface” – a 10× 10 rectangle – in texture spaceon the same parameter domain [0, 12]× [0, 7] as the real one. End

Click for trimmedBicubicBsplineSurface.cpp Program Windows

Project

Experiment 16.17. Run trimmedBicubicBsplineSurface.cpp, whichshows the surface of cubicBsplineSurface.cpp trimmed by multiple loops.The code is modified from bicubicBsplineSurface.cpp, functionalityremaining same. Figure 16.41(a) is a screenshot. End

109

Page 114: Download - Computer Graphics Through OpenGL: From Theory to
Page 115: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 17Hermite

Click for hermiteCubic.cpp Program Windows Project

Experiment 17.1. Run hermiteCubic.cpp, which implements Equa-tion (17.10) to draw a Hermite cubic on a plane. Press space to selecteither a control point or tangent vector and the arrow keys to change it.Figure 17.4 is a screenshot. The actual cubic is simple to draw, but as youcan see in the program we invested many lines of code to get the arrow headsright! End

111

Page 116: Download - Computer Graphics Through OpenGL: From Theory to
Page 117: Download - Computer Graphics Through OpenGL: From Theory to

Part IX

Well Projected

113

Page 118: Download - Computer Graphics Through OpenGL: From Theory to
Page 119: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 18Applications of Projective Spaces

Click for manipulateProjectionMatrix.cpp Program Windows

Project

Experiment 18.1. Run manipulateProjectionMatrix.cpp, a simplemodification of manipulateModelviewMatrix.cpp of Chapter 5. Figure 18.4is a screenshot, though the output to the OpenGL window is of littleinterest. Of interest, though, are the new statements in the resize()

routine that output the current projection matrix just before and after thecall glFrustum(-5.0, 5.0, -5.0, 5.0, 5.0, 100.0).

Compare the second matrix output to the command window withP (glFrustum(-5.0, 5.0, -5.0, 5.0, 5.0, 100.0)) computed with thehelp of Equation (18.4). End

Click for ballAndTorusShadowMapped.cpp Program Windows Project

Experiment 18.2. Before running ballAndTorusShadowMapped.cpp youmay want to run again ballAndTorusShadowed.cpp from Section 4.7.2,which implements a simple-minded blacken-and-flatten strategy, with helpof a scaling degenerate along the y-direction, to draw shadows on the floor.

The scenes of the two programs are almost identical, except, of course,that ballAndTorusShadowMapped.cpp shadow maps a local light source,whose position is indicated by a red sphere. Controls are identical too: pressspace to start the ball traveling around the torus and the up and down arrowkeys to change its speed. Figure 18.6 is a screenshot. End

Click for rationalBezierCurve1.cpp Program Windows Project 115

Page 120: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 18

Applications of

Projective Spaces

Experiment 18.3. Run rationalBezierCurve1.cpp, which draws thecubic rational Bezier curve specified by four control points on the plane atfixed locations, but with changeable weights.

The control points on the plane (light gray triangular mesh) are all red,except for the currently selected one, which is black. Press space to cyclethrough the control points. The control point weights are shown at theupper-left, that of the currently selected one being changed by pressing theup/down arrow keys. The rational Bezier curve on the plane is red as well.Figure 18.8 is a screenshot.

Drawn in green are all the lifted control points, except for that of thecurrently selected control point, which is black. The projective polynomialBezier curve approximating the lifted control points is green too. The liftedcontrol points are a larger size as well.

Note: The lifted control points and the projective Bezier curve are primitivesin P2, of course, but represented in R3 using their homogeneous coordinates.

Also drawn is a cone of several gray lines through the projective Beziercurve which intersects the plane in its projection, the rational Bezier curve.

Observe that increasing the weight of a control point pulls the (redrational Bezier) curve toward it, while reducing it has the opposite effect.Moreover, the end control points are always interpolated regardless ofassigned weights. It’s sometimes hard to discern the very gradual change inthe shape of the curve as one varies the weights. A trick is to press deletefor the curve to spring back to its original configuration, at which momentthe difference should be clear.

It seems, then, that the control point weights are an additional set of“dials” at the designer’s disposal for use to edit the curve.

The code of rationalBezierCurve1.cpp is instructive as well, as we’llsee in the next section on drawing. End

Click for rationalBezierCurve2.cpp Program Windows Project

Experiment 18.4. Run rationalBezierCurve2.cpp, which draws a redquadratic rational Bezier curve on the plane specified by the three controlpoints [1, 0]T , [1, 1]T and [0, 1]T . See Figure 18.9. Also drawn is the unitcircle centered at the origin. Press the up/down arrow keys to change theweight of the middle control point [1, 1]T . The weights of the two end controlpoints are fixed at 1.

Decrease the weight of the control point [1, 1]T from its initial value of1.5. It seems that at some value between 0.70 and 0.71 the curve lies exactlyalong a quarter of the circle (the screenshot of Figure 18.9 is at 1.13). Thisis no accident, as the following exercise shows. End116

Page 121: Download - Computer Graphics Through OpenGL: From Theory to

Click for rationalBezierCurve3.cpp Program Windows Project

Experiment 18.5. Run rationalBezierCurve3.cpp, which shows arational Bezier curve on the plane specified by six control points. SeeFigure 18.10 for a screenshot. A control point is selected by pressing thespace key, moved with the arrow keys and its weight changed by the pageup/down keys. Pressing delete resets. End

Click for turnFilm2.cpp Program Windows Project

Experiment 18.6. Run turnFilm2.cpp, which animates the snapshottransformation of a polynomial Bezier curve described above. Three controlpoints and their red dashed approximating polynomial Bezier curve areinitially drawn on the z = 1 plane. See Figure 18.12(a). The locations ofthe control points, and so of their approximating curve as well, are fixed inworld space. However, they will appear to move as the film rotates.

Initially, the film lies along the z = 1 plane. Pressing the right arrowkey rotates it toward the x = 1 plane, while pressing the left arrow keyrotates it back. The film itself, of course, is never seen. As the film changesposition, so do the control points and the red dashed curve, these beingthe projections (snapshot transformations, particularly) onto the currentfilm of the control points and their approximating curve (all fixed, as said,in world space). Also drawn on the film is a green dashed curve, which isthe polynomial Bezier curve approximating the current projections of thecontrol points.

Note: The control points and their approximating curve, all fixed on thez = 1 plane, and corresponding to the control points p0, p1 and p2 and thesolid red curve in Figure 18.11, are not drawn by the program – only theirsnapshot transformations on the turning film.

Initially, when the plane of the film coincides with that on which thecontrol points are drawn, viz. z = 1, the projection onto the film ofthe polynomial Bezier curve approximating the control points (the reddashed curve) coincides with the polynomial Bezier curve approximating theprojected control points (the green dashed curve). This is to be expectedbecause the control points coincide with their projections. However, as thefilm turns away from the z = 1 plane, the red and green dashed curves beginto separate. Their final configuration, when the film lies along x = 1, isshown in Figure 18.12(b).

There is more functionality to the program that we’ll discuss momentarily.End

Click for turnFilm2.cpp Program Windows Project 117

Page 122: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 18

Applications of

Projective Spaces

Experiment 18.7. Fire up turnFilm2.cpp once again. Pressing space atany time draws, instead of the green dashed curve, a blue dashed rationalBezier curve approximating the projected control points on the current planeof the film. The control point weights of the blue dashed curve are computedaccording to the strategy just described. Voila! The blue dashed rationalcurve and the red dashed projection are inseparable. End

Click for rationalBezierSurface.cpp Program Windows Project

Experiment 18.8. Run rationalBezierSurface.cpp, based on bezier-

Surface.cpp, which draws a rational Bezier surface with the functionalitythat the location and weight of each control point can be changed. Pressthe space and tab keys to select a control point. Use the arrow and pageup/down keys to translate the selected control point. Press ‘</>’ to changeits weight. Press delete to reset. The ‘x/X’, ‘y/Y’ and ‘z/Z’ keys turn theviewpoint. Figure 18.14 is a screenshot.

Mark the use of glMap2f(GL MAP2 VERTEX 4, . . .), as also of glEnable-(GL MAP2 VERTEX 4). The 2’s in the syntax are for a surface. End

118

Page 123: Download - Computer Graphics Through OpenGL: From Theory to

Part X

The Time is Pipe

119

Page 124: Download - Computer Graphics Through OpenGL: From Theory to
Page 125: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 19Fixed-Functionality Pipelines

Click for box.cpp modified Program Windows Project

Experiment 19.1. Replace the box glutWireCube(5.0) of box.cpp withthe line segment

glBegin(GL_LINES);

glVertex3f(1.0, 0.0, -10.0);

glVertex3f(1.0, 0.0, 0.0);

glEnd();

and delete the glTranslatef(0.0, 0.0, -15.0) statement. You see ashort segment, the clipped part of the defined line segment, whose firstendpoint [1 0 − 10]T is inside the viewing frustum defined by the program’sprojection statement glFrustum(-5.0, 5.0, -5.0, 5.0, 5.0, 100.0),while the second [1 0 0]T is outside (as is easily checked). Figure 19.2is a screenshot. End

Click for perspectiveCorrection.cpp Program Windows Project

Experiment 19.2. Run perspectiveCorrection.cpp. You see a thickstraight line segment which starts at a red vertex at its left and ends at agreen one at its right. Also seen is a big point just above the line, which canbe slid along it by pressing the left/right arrow keys. The point’s color canbe changed, as well, between red and green by pressing the up/down arrowkeys. Figure 19.4 is a screenshot.

The color-tuple of the segment’s left vertex, as you can verify in the code,is (1.0, 0.0, 0.0), a pure red, while that of the right is (0.0, 1.0, 0.0), a puregreen. As expected by interpolation, therefore, there is a color transitionfrom red at the left end of the segment to green at its right. 121

Page 126: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 19

Fixed-Functionality

Pipelines

The number at the topmost right of the display indicates the fraction ofthe way the big movable point is from the left vertex of the segment to theright. The number below it indicates the fraction of the “way” its color isfrom red to green – precisely, if the value is u then the color of the point is(1− u, u, 0).

Initially, the point is at the left and a pure red; in other words, it is 0distance from the left end, and its color 0 distance from red. Change bothvalues to 0.5 – the color of the point does not match that of the segmentbelow it any more. It seems, therefore, that the midpoint of the line is notcolored (0.5, 0.5, 0.0), which is the color of the point. Shouldn’t it be so,though, by linear interpolation, as it is half-way between two end verticescolored (1.0, 0.0, 0.0) and (0.0, 1.0, 0.0), respectively? End

The program sphereInBoxPOV.pov is in the folderExperimenterSource/Chapter19/SphereInBoxPOV.

Experiment 19.3. If you have successfully installed POV-Ray, then opensphereInBoxPOV.pov from that program; if not, use any editor.

If you have installed POV-Ray, then press the Run button at the top;otherwise, open the output image file sphereInBoxPOV.jpg in the samefolder as sphereInBoxPOV.pov. Figure 19.16(a) is a screenshot. Impressive,is it not, especially if you compare with the output in Figure 19.16(b) ofsphereInBox1.cpp? The inside of the box, with the interplay of light evidentin shadows and reflections, is far more realistic in the ray-traced picture.End

The program sphereInBoxPOV.pov is in the folderExperimenterSource/Chapter19/ExperimentRadiosity.

Experiment 19.4. Run again sphereInBoxPOV.pov. Then run againafter uncommenting the line

global_settings{radiosity{}}

at the top to enable radiosity computation with default settings. Thedifference is significant, is it not?

Figure 19.24(a) is the ray-traced output without radiosity, whileFigure 19.24(b) is the output with radiosity (both images are in the folderExperimenterSource/Chapter19/ExperimentRadiosity). There clearly ismuch more light going around inside the box in the latter rendering. End

122

Page 127: Download - Computer Graphics Through OpenGL: From Theory to

Part XI

Rendering Pipe Dreams

123

Page 128: Download - Computer Graphics Through OpenGL: From Theory to
Page 129: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 20OpenGL 4.3, Shaders and theProgrammable Pipeline: Liftoff

Click for squareShaderized.cpp Program Windows Project

Experiment 20.1. Fire up the application program squareShaderized.-

cpp, which comes with its two sidekick shaders, the imaginatively namedvertexShader.glsl and fragmentShader.glsl. Compiling and runningthe application program should automatically suck in the shaders providedthey are all in the same folder. Not only is the functionality ofsquareShaderized.cpp – drawing a black square over white background,see Figure 20.3 – exactly that of square.cpp, but, as we’ll see, so are itsinternals (modulo shaders). End

Click for ballAndTorusShaderized.cpp Program Windows Project

Experiment 20.2. Run ballAndTorusShaderized.cpp. The program’stwo shaders are vertexShader.glsl and fragmentShader.glsl. If youcare to run ballAndTorus.cpp again you see that the functionality ofballAndTorusShaderized.cpp is exactly same. Figure 20.6 is a screenshot.

End

Click for bumpMappingShaderized.cpp Program Windows Project

Experiment 20.3. Run bumpMappingShaderized.cpp. Interaction is thesame as bumpMapping.cpp: press space to toggle between bump mappingon and off. Figure 20.7(b) is a screenshot with bump mapping enabled,evidently identical to that of bumpMapping.cpp in Figure 20.7(a). End 125

Page 130: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 20

OpenGL 4.3, Shaders

and the

Programmable

Pipeline: Liftoff

Click for litCylinderShaderized.cpp Program Windows Project

Experiment 20.4. Run litCylinderShaderized.cpp. Interaction is thesame as litCylinder.cpp: press the ‘x’-‘Z’ keys to turn the cylinder. Asfar as lighting is concerned, the main twist from bumpMappingShaderized

is that now there is two-sided lighting, following litCylinder.cpp where itwas activated by the statement

glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

Material properties differ, as well, between the inside and outside of thecylinder. Figure 20.8 is a screenshot. End

Click for bumpMappingPerPixelLight.cpp Program Windows Project

Experiment 20.5. Run bumpMappingPerPixelLight.cpp. Again, pressspace to toggle between bump mapping on and off. Figure 20.7(c) is ascreenshot. The program, its associated C++ source and header files are allexactly same as for bumpMappingShaderized.cpp – the difference is only inthe shaders! End

Click for fieldAndSkyFilteredShaderized.cpp Program Windows

Project

Experiment 20.6. Run fieldAndSkyFilteredShaderized.cpp. As infieldAndSkyFiltered.cpp press the up and down arrow keys to move theviewpoint. However, unlike the earlier program, fieldAndSkyFiltered-

Shaderized.cpp implements (to keep it simple) only one fixed filter for thegrass texture and no options. Figure 20.9 is a screenshot. End

Click for texturedTorusShaderized.cpp Program Windows Project

Experiment 20.7. Run texturedTorusShaderized.cpp. As in textured-

Torus.cpp press ‘x’-‘Z’ to turn the torus.The point to note is how the associated source torus.cpp defines texture

coordinates for the torus following exactly texturedTorus.cpp. Beyondthat, the application program and shaders should be easily understood. SeeFigure 20.10 for a screenshot. End

Click for litTexturedCylinderShaderized.cpp Program Windows

Project126

Page 131: Download - Computer Graphics Through OpenGL: From Theory to

Experiment 20.8. Run litTexturedCylinderShaderized.cpp. As inlitTexturedCylinder.cpp press ‘x’-‘Z’ to turn the beer can. Figure 20.11is a screenshot. End

127

Page 132: Download - Computer Graphics Through OpenGL: From Theory to
Page 133: Download - Computer Graphics Through OpenGL: From Theory to

CHAPTER 21OpenGL 4.3, Shaders and theProgrammable Pipeline: EscapeVelocity

Click for helixListShaderizedInstancedVertAttrib.cpp Program Windows

Project

Experiment 21.1. Run helixListShaderizedInstancedVertAttrib.-

cpp. The output of six different helixes is exactly the same as that ofhelixList.cpp. See Figure 21.1. End

Click for helixListShaderizedShaderCounter.cpp Program Windows

Project

Experiment 21.2. Run helixListShaderizedShaderCounter.cpp. Theoutput, just like that of helixListShaderizedInstancedVertAttrib.cpp,is the same as that of helixList.cpp. See Figure 21.2. End

Click for ballAndTorusClipped.cpp Program Windows Project

Experiment 21.3. Run ballAndTorusClipped.cpp. The controls areexactly as for ballAndTorusShaderized.cpp: space to toggle animation onand off, up/down arrows to change its speed and ‘x’-‘Z’ to rotate the scene.

However, there is now, as will be evident as soon as the animation isstarted, a clipping plane slicing through the torus’s initial position. You cansee this from Figure 21.3. Let’s see how the clipping plane is set up. End 129

Page 134: Download - Computer Graphics Through OpenGL: From Theory to

Chapter 21

OpenGL 4.3, Shaders

and the

Programmable

Pipeline: Escape

Velocity

Click for ballAndTorusShaderSubroutines.cpp Program Windows

Project

Experiment 21.4. Run ballAndTorusShaderSubroutines.cpp. Thecontrols are exactly as for ballAndTorusShaderized.cpp: space to toggleanimation on and off, up/down arrows to change its speed, and ‘x’-‘Z’ torotate the scene. Figure 21.4 is a screenshot. End

Click for ballAndTorusPickingShaderized.cpp Program Windows

Project

Experiment 21.5. Run ballAndTorusPickingShaderized.cpp. Thecontrols are exactly as for ballAndTorusPicking.cpp: space to toggleanimation on and off, up/down arrows to change its speed, ‘x’-‘Z’ to rotatethe scene, and, most importantly, left mouse click to pick either ball or torus.See Figure 21.5 for a screenshot. End

Click for ballsAndTorusTransformFeedback.cpp Program Windows

Project

Experiment 21.6. Run ballsAndTorusTransformFeedback.cpp. Thecontrols are exactly as for ballAndTorusShaderized.cpp: space to toggleanimation on and off, up/down arrows to change its speed, and ‘x’-‘Z’ torotate the scene.

However, instead of one ball, now there are two, initially coincident, whichtravel in opposite directions around the torus. When the balls intersect theyare red, when they are close (closer than a particular threshold distance)they turn orange, and beyond that they are blue. Figure 21.6 is a screenshotwhen the balls are close. End

Click for fieldAndSkyTexturesBlendedShaderized.cpp Program Windows

Project

Experiment 21.7. Run fieldAndSkyTexturesBlendedShaderized.cpp.As in fieldAndSkyTexturesBlended.cpp press the arrow keys to move thesun, the transition between day and night happening from a blending of dayand night textures. See Figure 21.7 for a screenshot. End

Click for points.cpp Program Windows Project

Experiment 21.8. Run points.cpp. Drawn are three large points. Pressspace to cycle between four different point renderings and the up and down130

Page 135: Download - Computer Graphics Through OpenGL: From Theory to

arrow keys to move the points parallel to the z-axis. Figure 21.8 is ascreenshot of what is seen at first, particularly, three unedited points. End

Click for tessellatedCurve.cpp Program Windows Project

Experiment 21.9. Run tessellatedCurve.cpp. You see the three inputvertices and an initially 5-segment Bezier curve polyline. Press the up/downarrow keys to increase/decrease the number of segments. Figure 21.12 is ascreenshot with the initial five segments.

The Bezier curve is evidently a poor approximation to the circular arc(not drawn) through the three input vertices, the reason being, as we’ll seein the upcoming discussion, an intentionally simple-minded choice of thecontrol points; keep in mind, though, that the actual curve itself is of farless interest here than the programming steps to generate it.

The code is explained through the following sections. End

Click for tessellatedHemisphere.cpp Program Windows Project

Experiment 21.10. Run tessellatedHemisphere.cpp. You see atessellated hemisphere. Press ‘x’-‘Z’ to turn it, the up/down arrow keys toincrease/decrease the inner tessellation levels (both equal) and the right/leftarrow keys to increase/decrease the outer tessellation levels (all four equal).Figure 21.19 is a screenshot after raising both inner and outer tessellationlevels a fair amount.

We ask the reader to examine the program in the following exercise.End

Click for torusSilhouette.cpp Program Windows Project

Experiment 21.11. Run torusSilhouette.cpp. Press the space bar totoggle between the silhouette and mesh of a torus. Press ‘x’-‘Z’ to turn thetorus. Figure 21.23 is a screenshot of the torus in silhouette. We explainthe program below. End

131

Page 136: Download - Computer Graphics Through OpenGL: From Theory to
Page 137: Download - Computer Graphics Through OpenGL: From Theory to

APPENDIX AProjective Spaces andTransformations

Click for turnFilm1.cpp Program Windows Project

Experiment A.1. Run turnFilm1.cpp, which animates the setting of thepreceding exercise by means of a viewing transformation. Initially, the filmlies along the z = 1 plane. Pressing the right arrow key rotates it toward thex = 1 plane, while pressing the left one reverses the rotation. Figure A.11 isa screenshot midway. You cannot, of course, see the film, only the view ofthe lines as captured on it.

The reason that the lower part of the X-shaped image of the power linescannot be seen is that OpenGL film doesn’t capture rays hitting it frombehind, as the viewing plane is a clipping plane too. Moreover, if the linesseem to actually meet to make a V after the film turns a certain finiteamount, that’s because they are very long and your monitor has limitedresolution!

This program itself is simple with the one statement of interest beinggluLookAt(), which we ask the reader to examine next. End

133