95.402 Winter ‘99 Assignment #2

Due: In 2 weeks Monday Oct 4, 1999 in assignment box or in demo lab.

To do this assignment, we will first need to extend the existing implementation so that the states of the keys are kept in the world (whether or not the shift key is down or not, for example, is currently kept track of in the person object; it should be in the world). We could have a boolean for every key and this would work fine and is particularly useful for special keys like SHIFT, CTL, and ALT which can play the role of modifiers. However, instead of keeping track of the arrow keys directly, it might be more useful to keep track of higher level information such as the following:

movingForward, movingBack, turningLeft, turningRight (NO MODIFIERS)

As part of this assignment, you need to extend the implemenation so as to also have states for

movingUp, movingDown, slidingLeft, slidingRight, (when CTL is down)

lookingUp, lookingDown twistingClockwise, twistingCounterClockwise (when ALT is down)

This is easy to do. If CTL is down, interpret up and down as moving UPWARD and DOWNWARD; if ALT is down, interpret up and down as looking UP and DOWN; otherwise, interpret up and down to mean moving FORWARD and BACKWARD. Similarly, for the ALT key. Use different keys if you wish but provide the functionality. On key up, simply turn off the booleans. When a person is told to tick (), it can look up at the status information in the world and decide what to do (there should only be one world in the game; so it can be global).

Here’s our real task, however. We would like to add 5 or more model objects (representing coins) to our world, each with different textures and each spinning in a different way. What is interesting about this task is that we will add a "cycle key; e.g., the character c" that will make a coin object become the camera. We should be able to cycle through each coin in sequence. Our world will have to be extended to additionally keep track of the list of model objects. Once a particular coin becomes the active camera, it will stop rotating. Instead, we should be able to "drive it" around. When we switch to a specific coin, it can be in any orientation. That’s why we will need the ability to perform key actions like looking up or twisting right. If we happen to be pointing straight down, for example, we will have to look up to re-orient ourselves with the ground. All coins used as cameras should be in God mode; i.e., you do not have to worry about collision detection because that’s too hard.

There are many ways of doing this. So let be give you a suggestion. You don’t need to do it "my" way if you have other ideas. I noticed that the Face object in the sample code was meant primarily for collision detection. Consequently, it lacks information needed for rendering; e.g., it lacks information like the texture coordinate and the normal for each point. So rather than do something that might break collision detection, let’s create a new replacement class for Face called TexturedFace (can you think of a better name?). You could just extend it and not bother with a new name. One more thing… Better fix the Texture class so that a texture handle is created for each new texture and so that it this handle can be selected before the texture is used for rendering. Currently, the bits for each texture are reset on every tick because there is really only one texture handle (the default texture handle 0). The bits need to be given to OpenGL just once at load time, NOT on each tick.

Create a (1) TexturedFace class along with a (2) GamePoint class and a (3) Transformation class.

A textured face object keeps track of a texture object and a list of game points; either an array or a linked list. A textured face object understands draw ().

A gamePoint objects is an extended point that contains 8 doubles (there is no intention to do point arithmetic, so you could just use a struct instead of a class if you wanted to):

x, y, z (normal coordinates),

nx, ny, nz (normals pointing out of the face that the point is part of),

tx, ty (texture coordinates)

A transformation object provides methods that make them easier to use. Currently, a transformation is represented very simply as a 16 element array of doubles. Because it’s not a class, you can’t say "rotate around vector V by angle X" or "translate by vector V" or even "moveForward" or "turnLeft". It would be a lot more understandable if you could do that. You might also want to create a special transformation class such as InvertibleTransformation that keeps track of two transformations: a normal transformation and its inverse. You’ll learn in class that a camera needs an inverse transformation but a non-camera needs a normal one.

Clearly, to create something that represents a coin, we will need more than one textured face. For example, if the coin is to be represented by an 8-sided n-gon with thickness, we will need 2 textured faces for the sides and 8 textured faces for the edges around the coin. Also, the sides might need a different texture than the edges. Make sure the origin of the coin is at its exact center. Also, set it up so that if it were to roll on the ground, it would roll around the x-axis; if you don’t do this, it will be more difficult to control it later.

We’ll also need to provide a (5) Model object that

    1. has 2 transformations (a normal one and it’s inverse) or one invertible transformation,
    2. a list of textured faces; e.g., representing a coin,
    3. a goal such as "rotating" which implies a vector around which the rotation will occur and the rotation angle to be used for each tick or "driven" which implies the model is being used as a camera.

The model class should contain a static method (anybody know what that is?), say called coin, or creating a coin given two texture objects; i.e., a method that creates an instance of Model with 10 textured faces containing the game points properly initialized to represent a coin.

With this design, we can create 5 coins by re-using the same game points for the texture faces but we need different textured faces if we are to have different textures. In order to have different sized coins and position them in different places, we simply manipulate the model’s transformations. So the model object must understand tick () and draw (). To tick, for example, it will either rotate or be driven as a camera. To draw, it will ask each textured faces to draw (provided it’s not currently a camera).

Alternative Design: Have a TexturedFace and an UntexturedFace class. Also have a TexturedModel which keeps a list of texture objects along with corresponding untextured faces. The UntextureModel would be the above which keeps a list of textured faces. The advantage of this design is that you would only need to create one list of untextured faces for the coins and 5 textured models.

Recommendations for the future:

  1. Add facilities so that the model objects can be read in and written out.
  2. Consider other model objects such as cars, ski boards, motorcycles. Maybe you can get some free models off the net. The challenge will be to format the data in such a way that you can read it in. Alternatively, you might be able to get away with creation methods like your coin method (though they are likely to be long).
  3. Consider moving the camera behind the object just a little so that you can see your coin move. Maybe you want to additionally add "wiggle" to your coin as you move ahead.
  4. Consider decomposing the code into two pieces: the "build-time" piece (e.g., this is the part that constructs a world, such as the terrain building code, and puts it into a file) and the "run-time" piece (this portion loads a world and runs it but CANNOT make a world). This might become a requirement by the third assignment.