In the second part of your engine assignment, you will implement camera profiles and a basic physics engine and associated interface operations. The interface operations will allow the player to select a direction and force with which to hit the ball. The physics engine will use these inputs, together with the layout of the minigolf hole, to animate the ball in a realistic manner.

Your game should support at least the following camera profiles and the ability of the player to switch between profiles at any time in the game.

1) Free look

2) Third-person attached to the ball

+ (Required) Camera moves with the ball

+ (Optional) Smooth camera movement

+ (Optional) Always keep Cup in sight

3) One camera profile of your choice

+ Top-down

+ First-person

+ Scripted along fixed path

In our simple environment, hitting the ball defines an initial ball direction* D *and ball velocity *v*. For a discrete unit of time, the ball moves in direction* D *a distance proportional to *v*. We use an approximation of rolling friction to slow the ball: each time the ball is moved, we decrease* v *by a constant rolling friction value *rf*. When* v*falls to zero, the ball stops.

Because tiles are not always flat, gravity may also affect the ball's trajectory. A sloped tile has a normalized rolling direction* R *that defines how objects roll down its surface. When the ball moves over a sloped tile, it is pulled in direction* R *by an amount proportional to *R*'s downward angle (*i.e.*, *R*'s *Y*-component). This pull will modify both* D *and *v*, since the ball will be travelling in a new direction, and with a new velocity.

As the ball moves, it will interact with different parts of the minigolf hole. For example:

- The ball can leave the current tile and enter a new tile.
- The ball can hit the edge of a tile.
- The ball can fall into the cup.

Each of these situations must produce appropriate modifications to* D *and *v*. To simplify processing, you should keep track of the tile *t* that contains the ball. This will limit intersection testing to *t*'s edges. It will also limit checking to see if the ball has fallen into the cup (this can only happen if t also contains the cup).

**Note:** We assume **the ball never leaves the surface of a tile** (*i.e.*, the ball never enters a "free-fall" state where it flys through the air). This assumption allows you to simplify the processing in your physics engine simple. This is one reason why we don't allow tiles that "wrap around" in the *Y*-direction (in fact, we don't expect tiles with a downward angle of 90Âº or greater, since it would look odd to have the ball rolling down the surface of an "upside down" tile).

We offer some suggestions below for how to compute the ball's direction as it moves from tile to tile. Most of the proposed solutions are based on coordinate axis changes, in part because this is a simple and intuitive way to explain how the ball's direction changes, and in part because manipulating coordinate axes is a fundamental operation in computer graphics. Note that these are only suggestions, and are not the only way to compute the appropriate direction vectors. You are free to implement whatever method you prefer. The only requirement is that you solution simulate ball movement in **exactly** the way we have defined in the assignment.

----------------------------------------------------------------

Figure 1: Methods for computing tile direction vectors: (a) a sloped tile with its normal *N* and the world up-direction *Up*, the *X*-axis selected perpendicular to the plane containing *N* and *Up*, and the*R *axis selected perpendicular to *N* and *X;* (b) a sloped tile with its normal *N*, the world-up direction*Up*, and the ball's *XZ*-direction *XZ-D*, with the *X*-axis selected perpendicular to the plane containing*Up* and *XZ-D*, and the true ball direction* D *selected perpendicular to *N* and *X*.

------------------------------------------------------------

To compute the rolling direction* R *for a sloped tile, recall that* R *lies in the plane formed by the tile's normal *N* and the world up-vector *Up*=(0,1,0). First, compute an *X*-axis perpendicular to *N* and*Up*.* R *is then defined as the normalized direction perpendicular to *N* and *X* (see also Fig. 1a).

When the ball enters a new tile, the *Y*-component of its direction* D *will change if the old and new tiles have different slopes. To compute the proper *D*, start with the ball's direction in the *XZ*-plane,*XZ-D*. Define the plane that holds the ball direction* D *by computing an *X*-axis perpendicular to *XZ-D*and the world up-vector *Up*=(0,1,0).* D *is the normalized direction perpendicular to *N* and *X* (see also Fig. 1b).

Whenever the ball strikes a tile edge that represents the edge of the minigolf hole layout (*i.e.*, a "hard" edge), it bounces back with an outgoing angle around the edge's normal equal to the incoming angle. The bounce direction* D *can initially be computed in the *XZ*-plane using simple vector arithmetic. Given an incoming direction *D_in*, the projection of -*D_in* onto the edge normal *N*produces a vector *W* in the direction *N*. The incoming angle between *D_in* and *N* can then be represented as a new vector -*H* = -*W* - *D_in*. Since incoming and outgoing angles are identical, this means the bounce direction* D *is:

Figure 2: The bounce direction in the XZ-plane, showing the incoming direction D_in, the projection W of -D_in onto the edge normal N, and the vector -H = -W - D_in; given this arrangement, the bounce direction D is computed as D = W + H = W + ( W + D_in ). |

---------------------------------------------

Once the bounce direction in the *XZ*-plane is known, the ball direction algorithm (described above) can be used to find the complete *(X,Y,Z)* ball direction.

In order to start the physics engine, an initial ball direction* D *and ball velocity* v *must be provided. This is done through a set of interface operators that allow a player to choose where to shoot the ball, and how hard to hit it.

You must first provide an input method to allow a player to select* D *(the ball's direction of motion), together with an associated output method that displays* D *(*e.g.*, left and right allow keys to select a direction in a 360Â° circle around the current ball position, with an arrow shown centered about the ball that represents *D*'s value).

Once a player selects *D*, he or she needs a way to hit the ball. This will also include an input method to choose the strength of the stroke, and an output method that shows how hard the ball will be hit if the current input is accepted (*e.g.*, pressing and holding down the spacebar to initiate and increment the stroke's strength, and a graphical "power bar" that shows the strength; the current strength is accepted and the ball is hit when the spacebar is released).

When the ball is struck, the stroke's strength must be converted to an initial velocity *v*.* D *and* v *are sent to the physics engine, which is used to animate the ball as it rolls within the minigolf hole. This continues until the ball comes to rest (at which point a new* D *and* v *must be selected), or until the ball falls into the cup.

After the ball is struck, it moves step-by-step around the minigolf hole based on its current* D *and *v*. In order to simplify controlling this movement, and to guarantee consistent motion across different hardware platforms, each ball motion step is tied to an underlying clock tick that occurs at a constant rate as the program runs. Every time the clock ticks, a check should be made to see if a ball is currently in motion. If it is, it should be moved one step forward from its current position. The minigolf hole is then redrawn to show the ball as it "moves."

The speed of your ball motion will depend on how much time passes between each clock tick. Both GLUT and tcl/tk have a timer routine that can be used to invoke a user-defined function every t milliseconds (*e.g.*, glutTimerFunc() in GLUT). We have set *t*=50 in our program, that is, the clock ticks every 50 milliseconds. A smaller *t*would produce faster motion (assuming your machine can complete the required processing before the next clock tick occurs); a larger *t* would produce slower motion.

The main goal of the player is to hit the ball into the cup in as few strokes as possible. Determining when the ball falls into the cup is simplified by tracking the tile t that contains the ball. Intersection with the cup can only occur when the ball and the cup both occupy the same tile.

Two key issues must be considered when an intersection test is performed:

- Is the ball close enough to the center of the cup to fall into the cup?
- Is the ball travelling slowly enough to fall into the cup?

The ball needs to be within a certain distance from the center of the cup in order to fall in. On a typical minigolf course the diameter of the cup is two to three times the diameter of the ball (*i.e.*, the center of the ball needs to pass within one to one and a half ball diameters from the center of the cup to fall in).

Even if the ball passes close enough to the cup, it won't fall in if it's moving too quickly. The cutoff velocity is related to the distance between the center of the ball and the center of the cup. The smaller the distance (*i.e.*, the closer the ball passes to the center of the cup), the faster it can be travelling and still fall into the cup.

If the ball is close enough to the cup, but is moving too quickly, it will not simply "pass over" the cup and continue in the same direction *D*. On a real minigolf course the ball will "lip out", following the curve of the cup and exiting with a new direction. Some form of lip-out must be implemented in your assignment. A simple solution is to choose a random change to *D*. A more sophisticated solution will ensure the angular difference between the old and new directions: (1) pulls the ball towards the center of the cup (*i.e.*, the lip-out direction follows the curve of the cup), and (2) has a magnitude relative to the velocity of the ball, since a smaller velocity normally produces a larger lip-out angle.

In the complete minigolf game, when the ball falls into the cup the player moves to the next minigolf hole (or finishes his or her game if this is the last minigolf hole on the course). For this assignment, you can simply stop the ball (*i.e.* set *v*=0) and return the player to the interactive shot selection loop.

You should submit one copy of code per team on Moodle when submission system opens up. We will run your program in the lab for grading and give you feedback on your code after looking at your submission.

Things you need to submit:

1) Code (well-written and documented)

2) Development Log: This is a file that you will submit along with your submission and will contain the following sections:

+ Key things you added or changed to your code from Lab #1

+ Refactoring of code from Lab #1

+ Any additional documentation/commenting/cleanup from code in Lab #1

+ References you used to learn about camera/physics/ball movement etc. in addition to links discussed in class