Here are links for the lessons for geometry (Lesson 6) and Lighting (Lesson 7).
Download the Chapter 6 Example Folder
Download the Chapter 7 Example Folder
This week, we will shift from the first phase in which we were trying to get a basic capability going, to the definition of a major project. The rest of the course will be driven (in many cases) by the need to learn essential information in pursuit of the project.
Before we do that, though, we need to clean up some leftover business from last week.
The two books we have recommended for study of OpenGL, do not do an adequate job of describing the ordering of matrix transformations. Specifically, we have discussed the idea that there are two complementary views of what a model-view transformation is:
Let's talk about each of these in turn.
Transforming data in a fixed system (METHOD 1). If we have a point P=(10,5) in a 2d space named W ("World coordinates."), and we apply a scaling matrix S(0.5, 0.5) to it, we would wind up with a point P'=(5,2.5). In the fixed-coordinate way of thinking, we have just "shrunk" the object of which P is a part, moving all its vertices (and thus edges and other composite features) closer to the origin. All the numbers are still in W.
In this view, the object "moves" with respect to the
fixed world coordinate system W, and the camera (viewer) stays
put. The objective results of such a transformation are that P'
has different numeric values than P.
Changing the coordinate system (METHOD 2). Consider again the point P=(10,5) in world coordinate system W. Now draw a second coordinate system V with marks twice as far apart, but the axes of V are exactly on top of those of W.
You can see that the point P (in W) now has a different description
(set of numbers) B = (5, 2.5) when measured with the V system.
We didn't really "move" the point this time, but we
re-measured it. (According to Method 2, objects at the origin
of V never move or rotate with respect to V; but V itself moves
with respect to W.)
The significance of the different views. The sequence of matrix operations that one invokes, by adding matrices to the stack in OpenGL, was discussed in class last week. If for instance we wish to construct a model of the planet Earth, rotating around the Sun (once per minute), we'd like to be able to do the following things (speaking in "Method 1" language:)
To accomplish this, according to the description we gave in class last week, we would do the following operations IN THIS ORDER (assume your code executes the loop once per second)
Rotate by an additional 6 degrees CCW on Y, via
newAngle += 6;
glLoadIdentity();
glRotatef(newAngle, 0.0f, 1.0f, 0.0f);
glTranslatef(93.0f, 0.0f, 0.0f);
auxSolidSphere(3.0f); // Draw a world at that point
Now, this would be interpreted under METHOD 1 as follows: reading the matrix operations backward, we see that we translate, then rotate, so the planet would go around nicely. After newAngle makes it up to 90 degrees, for instance, the center of the sphere would land at (0.0, 0.0, -93.0) - that is, on the minus-Z axis.
Interpreting via Method 2, on the other hand, we discover that we want to read the matrix transformations FORWARD, as follows.
Under this interpretation, the numbers you wind up with after the transformation are harder to think through, so for purposes of hand-simulating examples, we're better off with Method 1.
This project may be performed either by individuals, or by teams of up to 3 people. As you will see, it leads directly to Project 3. We describe the project in steps.
0. The Viewing Context. Use your Lab1 as a starting point, so you already have your viewing parameters set up. Just modify it incrementally to build this project. I assume that you are using a viewing frustum that has around a 60 degree field of view centered around the negative Z axis, with near clipping around - 1 and far clipping around -400. You can set that view up with
gluPerspective(60.0f, 1.5, 1.0, 400.0);
- which are, respectively, the field of view, aspect ratio, near and far clipping planes.
1.Making a Block. Imagine a procedure called MakeBox with twelve arguments: sx, sy, sz specify the size of the solid cube to be made. rx, ry, rz specify the rotations, if any, about the three axes. tx, ty, tz specify where the center of the cube should be translated to, and r,g,b specify a color. Now MakeBox is actually rather easy to construct; it looks something like this:
glLoadIdentity();
glColor3f(r,g,b);
gltranslatef(tx,ty,tz);
glRotatef(rx, 1.0, 0.0, 0.0);
glRotatef(ry,0.0, 1.0, 0.0);
glRotatef(rz, 0.0, 0.0, 1.0);
glScalef(sx, sy, sz);
auxSolidCube(1.0);
2. A Data Structure for a Block. Now get slightly more sophisticated, by defining a new structure called a Box, with twelve data members:
struct BLOCK
{
glfloat sx, sy, sz, rx, ry, rz, tx, ty , tz, r, g, b;
}
and a corresponding procedure MakeBlock which, given a structure Block1 of type BLOCK, draws it:
MakeBlock(Block1);
3. The Castle Editor, conceptually. Now, here's the project. Your program is a Castle Editor. It will allow you to construct an arbitrary pile of blocks, like a child's castle. The controls are mostly in the EDIT menu, and are mostly used via keystroke equivalents. (I don't know which if any of these keystrokes are forbidden to app programs by Windows conventions; you guys alert me please.)
It may be the case that you have to make all these keystrokes to be CTRL keys, or (less desirable) function keys. But if anyone knows how to get directly at keystrokes, please tell us all!
At any given time, one block is the Active Block and receives all commands. It can be identified (when multiple blocks are on the screen) by simply moving it. Any command, when executed, causes a redrawing of the screen. Here are the commands
NEW BLOCK - create a new block of size 10 x 10 x 10 units, located fairly close to the viewer (e. g. at -50 on the Z axis.) Preferred keystroke is ctrl-N.
MOVING THE BLOCK: the right and left arrow keys move the block by 5 units in the x and -x directions. The up and down arrow keys move the block by the same distance in the y directions. If shift-arrow keys are detectable, use shift-up and shift-down arrows to move in the Z direction. If not, assign some other logical keys in the right hand, like semicolon (;) for increasing Z and slash (/) for decreasing Z.
SIZING THE BLOCK: the x, y and z keys increase the block's size by 25% positively in the specified dimensions. (If the block is rotated, it will be resized along the axes that were originally parallel to the stated dimensions.) . To scale in the opposite direction (shrinking the block by 20%), use uppercase X, Y and Z. << Why up 25, down 20? Think about it.>>
ROTATING THE BLOCK should be possible, though rarer than basic movement and sizing. So you can use function keys for this control; for instance, F1, F2 for rotation around x by 30 degrees per stroke; F3, F4 for rotation around y and F5, F6 for rotation around Z.
SELECTING ANOTHER BLOCK: The blocks are numbered 1..n. When you choose the menu item for selecting another block, you are presented with a window in a dialog box into which you can type an integer. If no block exists for which you typed the integer, produce an error message. If you selected an existing block, that block jumps up and down on the screen three times, to help you identify it.
SETTING THE COLOR OF THE BLOCK. There are six pre-set colors named in a menu called COLOR. Choosing a new color changes the color of the current block.
4. Priorities. You will have a month to build this code, and for an 'A', I expect all the above functionalities. You should build it in a particular order, so as to have working code as soon as possible. I recommend that you begin with one pre-built block, and work on moving and sizing the block. Then add a second pre-built block and work on selecting the active block via menu. Then add in the other capabilities.
5. Goodies. To extend Lab 2 in directions which will contribute to Lab 3, you might think about the following functionalities:
a) A capability to save the castle to disk and reload it.
b) A capability to memorize a sequence of changes to the blocks, and replay them.
c) A capability to group two or more blocks into a rigid structure, and move or resize or recolor them all at once.
I'll be describing Lab 3 verbally, and working on the specifications interactively with the class for the next few days. In fact, we're going to "co-design" it, in a workshop format.