Tricks of the Windows Game Programming Gurus:Playing God: Basic Physics Modeling

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

#### Computing the Collision Response with Planes of Any Orientation

Using rectangles as bounding collision volumes works okay if you write pong games, but this is the 21st century, baby, and we need just a little bit more! What we need to do is derive the reflection equations for a vector reflecting off a flat plane. This is shown in part A of Figure 13.24 in 2D (the 3D case is the same). To solve the problem first we have to make an assumption about what will happen when an object that’s very small and perfectly elastic hits a wall. I think we can already come to the conclusion that it will bounce off the wall at the same angle it arrived at. Therefore, the angle of reflection (the angle of departure by the object after the collision) equals the angle of incidence (the incoming angle before the collision) relative to the normal, or perpendicular to the wall. Now, let’s see the math…

Figure 13.24 The vector reflection problem illustrated.

Solving the problem requires nothing more than a vector geometry construction, but it’s not totally trivial.

Part B of Figure 13.24 depicts the problem. Note that there isn’t an x,y axis. It’s unnecessary since we’re using vectors and I want the problem to be totally general.

The problem can be stated like this:

Given the initial vector direction I and the normal to the plane N`'`, find F.

Before we get crazy, let’s talk about the normal vector. The normal vector N`'` is just the normalized version of P, but what is P? N is just the perpendicular to the plane or line that the ball is hitting that we want the ball to bounce off of. We can determine P in a number of ways; we might have pre-computed it and stored it in a data structure or we can figure it out on-the-fly.

There are a number of ways to do this depending on the representation of the “wall.” If the wall is a plane in 3D then we can extract P based on the point-normal form of a plane:

    nx(x – x0) + ny(y – y0) + nz(z – zo) = 0

The normal vector is just P=<nx, ny, nz>. To make sure the normal is normalized or a unit vector then you divide each element by the total length—remember?

    N' = <nx, ny, nz >/|P|

Where |P| is the length and is computed like this:

    |P| = sqrt(nx2 + ny2 + nz2)

In general, the length of a vector is the square root of the sum of squares of its components.

On the other hand if your collision line is a line in 2D or a segment then you can compute the normal or perpendicular by finding any vector that is perpendicular to the line. Thus if the line is in the form of 2 endpoints in 2D as shown in Figure 13.25 like this:

Figure 13.25 Computing the perpendicular to a line.

Given: p1(x1,y1), p2(x2,y2)

The vector from p1 to p2 (remember endpoint minus initial) is

    V12 = <x2 – x1, y2 – y1> = <vx, vy>

The perpendicular can be found with this trick:

    P12 = <nx, ny> = <-vy, vx>

This trick is based on the definition of dot product, which states that a vector dotted with its normal equals 0, thus:

    V12 . N12 = 0

    <vx, vy> . <nx, ny> = 0

or

    vx*nx + vy*ny = 0

And what makes this true is nx = -vy, ny = vx:

    vx*(-vy) + vy*(vx) = -vx*vy+vx*vy = 0

Nice, huh?

All right, so you know how to get the normal vector and of course you need to normalize it and make sure it has length 1.0, so N`'`, = P/|P| which is equal to:

    N' = <-vy, vx>/sqrt((-vy)2 + vx2)

Now back to the derivation… At this point we have the normal vector N`'`, which shouldn’t be confused with N in the figure since N is along N`'`, but not related to the length of P in any way. N is the projection of I along N`'`. Okay, that sounds like voodoo—and it is. A projection is like a shadow. If I were to shine light from the left side of the figure in the left to right direction then N would be the shadow or projection that I casts on the N`'` axis. This projection is the N we need. Once we have N then we can find F with a little vector geometry. First, here’s N:

    N = (-I . N')*N'

This states that N (which is the vector projection of I on N`'`) is equal to the dot product of –I and N`'` and then multiplied by the vector N`'`. Let’s take this apart in two chunks. First the term (-I . N`’`) is just a scalar length like 5; it’s not a vector. This is a handy thing about dot products: If you want to find the shadow of one vector (projection) then you can dot it with the unit version of the vector in question, thus you can resolve the components of a vector into any direction you want. Basically, you can ask, “What’s R in the V`'` direction?” Where V`'` is normalized. Therefore, the first part (-I . N`'`) gives you a number (the –1 is just to flip the direction of I). But, you need a vector N, so all you do is multiply the number by the unit vector N`’` (vector multiplication) and, whammo, you have N.

Once you have N it’s all bedrock, baby, just do some vector geometry and you can find F:

    L = N + I

and

    F = N + L

substituting L into F,

    F = N + (N + I)

Therefore,

    F = 2*N + I

Burn that last line into your skull. It could be the difference between Burger King and DreamWorks Interactive—right, Rich?

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.