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

Send the balls off with the above velocities and you’re done! Wow, that was a whopper, huh? Now, since I think that the code is a lot easier to understand than the math, I have listed the collision algorithm here from an upcoming demo:

    void Collision_Response(void)

    {

    // this function does all the “real” physics to determine if there has

    // been a collision between any ball and any other ball; if there is a

    // collision, the function uses the mass of each ball along with the

    // initial velocities to compute the resulting velocities

    // from the book we know that in general

    // va2 = (e+1)*mb*vb1+va1(ma - e*mb)/(ma+mb)

    // vb2 = (e+1)*ma*va1+vb1(ma - e*mb)/(ma+mb)

    // and the objects will have direction vectors co-linear to the normal

    // of the point of collision, but since we are using spheres here as the

    // objects, we know that the normal to the point of collision is just

    // the vector from the centers of each object, thus the resulting

    // velocity vector of each ball will be along this normal vector direction

    // step 1: test each object against each other object and test for a

    // collision; there are better ways to do this other than a double nested

    // loop, but since there are a small number of objects this is fine;

    // also we want to somewhat model if two or more balls hit simultaneously

    for (int ball_a = 0; ball_a < NUM_BALLS; ball_a++)

         {

         for (int ball_b = ball_a+1; ball_b < NUM_BALLS; ball_b++)

             {

             if (ball_a == ball_b)

                continue;

             // compute the normal vector from a->b

             float nabx = (balls[ball_b].varsF[INDEX_X] –

                          balls[ball_a].varsF[INDEX_X]);

             float naby = (balls[ball_b].varsF[INDEX_Y] –

                          balls[ball_a].varsF[INDEX_Y]);

             float length = sqrt(nabx*nabx + naby*naby);

             // is there a collision?

             if (length <= 2.0*(BALL_RADIUS*.75))

                {

                // the balls have made contact, compute response

                // compute the response coordinate system axes

                // normalize normal vector

                nabx/=length;

                naby/=length;

                // compute the tangential vector perpendicular to normal,

                // simply rotate vector 90

                float tabx =  -naby;

                float taby =  nabx;

                // draw collision

                DDraw_Lock_Primary_Surface();

                // blue is normal

                Draw_Clip_Line(balls[ball_a].varsF[INDEX_X]+0.5,

                   balls[ball_a].varsF[INDEX_Y]+0.5,

                   balls[ball_a].varsF[INDEX_X]+20*nabx+0.5,

                   balls[ball_a].varsF[INDEX_Y]+20*naby+0.5,

                   252, primary_buffer, primary_lpitch);

                // yellow is tangential

                Draw_Clip_Line(balls[ball_a].varsF[INDEX_X]+0.5,

                   balls[ball_a].varsF[INDEX_Y]+0.5,

                   balls[ball_a].varsF[INDEX_X]+20*tabx+0.5,

                   balls[ball_a].varsF[INDEX_Y]+20*taby+0.5,

                   251, primary_buffer, primary_lpitch);

                 DDraw_Unlock_Primary_Surface();

                // tangential is also normalized since

                // it’s just a rotated normal vector

                // step 2: compute all the initial velocities

                // notation ball: (a,b) initial: i, final: f,

                // n: normal direction, t: tangential direction

                float vait = DOT_PRODUCT(balls[ball_a].varsF[INDEX_XV],

                                         balls[ball_a].varsF[INDEX_YV],

                                         tabx, taby);

                float vain = DOT_PRODUCT(balls[ball_a].varsF[INDEX_XV],

                                         balls[ball_a].varsF[INDEX_YV],

                                         nabx, naby);

                float vbit = DOT_PRODUCT(balls[ball_b].varsF[INDEX_XV],

                                         balls[ball_b].varsF[INDEX_YV],

                                         tabx, taby);

                float vbin = DOT_PRODUCT(balls[ball_b].varsF[INDEX_XV],

                                         balls[ball_b].varsF[INDEX_YV],

                                         nabx, naby);

                // now we have all the initial velocities

                // in terms of the n and t axes

                // step 3: compute final velocities after

                // collision, from book we have

                // note: all this code can be optimized, but I want you

    // to see what’s happening :)

                float ma = balls[ball_a].varsF[INDEX_MASS];

                float mb = balls[ball_b].varsF[INDEX_MASS];

                float vafn = (mb*vbin*(cof_E+1) + vain*(ma - cof_E*mb))

                              / (ma + mb);

                float vbfn = (ma*vain*(cof_E+1) - vbin*(ma - cof_E*mb))

                             / (ma + mb);

                // now luckily the tangential components

                // are the same before and after, so

                float vaft = vait;

                float vbft = vbit;

                // and that’s that baby!

                // the velocity vectors are:

                // object a (vafn, vaft)

                // object b (vbfn, vbft)

                // the only problem is that we are in the wrong coordinate

                // system! we need to             // translate back to the

                   original x,y

                // coordinate system; basically we need to

                // compute the sum of the x components relative to

                // the n,t axes and the sum of

                // the y components relative to the n,t axis,

                // since n,t may both have x,y

                // components in the original x,y coordinate system

                float xfa = vafn*nabx + vaft*tabx;

                float yfa = vafn*naby + vaft*taby;

                float xfb = vbfn*nabx + vbft*tabx;

                float yfb = vbfn*naby + vbft*taby;

                // store results

                balls[ball_a].varsF[INDEX_XV] = xfa;

                balls[ball_a].varsF[INDEX_YV] = yfa;

                balls[ball_b].varsF[INDEX_XV] = xfb;

                balls[ball_b].varsF[INDEX_YV] = yfb;

                // update position

               balls[ball_a].varsF[INDEX_X]+=

                        balls[ball_a].varsF[INDEX_XV];

                balls[ball_a].varsF[INDEX_Y]+=

                        balls[ball_a].varsF[INDEX_YV];

                balls[ball_b].varsF[INDEX_X]+=

                        balls[ball_b].varsF[INDEX_XV];

                balls[ball_b].varsF[INDEX_Y]+=

                        balls[ball_b].varsF[INDEX_YV];

                } // end if

             } // end for ball2

        } // end for ball1

    } // end Collision_Response

The code follows the algorithm almost identically. However, the code is from a demo that simulates a pool table system, so added loops test all collision pairs. Once inside the loop the code follows the math. To see the algorithm in action check out `DEMO13_8.CPP|EXE`. A screen shot from it is shown in Figure 13.37. The demo starts up with a number of randomly moving balls and then the physics takes over. At the bottom of the screen the total kinetic energy is displayed. Try changing the coefficient of restitution with the right and left arrows keys and watch what happens. For values less than 1, the system loses energy, for values equal to 1, the system maintains energy, and for values greater than 1, the system gains energy—I wish my bank account did that!

Figure 13.37 The hyper-realistic collision response model.

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.