Free JavaScript Editor Ajax Editor

↑

Main Page

## Resolving the n-t Coordinate SystemNow that we have the final collision response, we need to figure out how to get the initial values for (v To find n we want a vector that is unit length (length equal to 1.0) and along the line from the center of ball A(x Equation 8: Computation of n and t N = B – A = <x Normalizing N to find n, we get n = N/|N| = <n Now we need the tangential axis t which is perpendicular to n. We could find it again using vector geometry, but there's a trick we can use; if we rotate n 90 degrees clockwise, that's what we want. However, when a 2D vector <x,y> is rotated in a plane 90 degrees clockwise, the rotated vector is just t=<-y, x>=<t ## Figure 13.35. Rotating a vector 90 degrees to find its perpendicular.Now that we have both n and t and they are both unit vectors (since n was unit, t is unit also) we're ready to go. We want to resolve the initial velocities of each ball into terms of n and t for ball A and B, respectively: v This is nothing more than a dot product. To find (v (v Note the result is a scalar, as it should be. Computing the other initial velocities is the same as shown in Equation 9. Equation 9: Components of v (v Components of v (v Now we're ready to solve the problem completely. Here are the steps: -
Compute n and t (use equation 8). -
Resolve all the components of v _{ai}and v_{bi}into magnitudes along n and t (use equation 9). -
Plug values into final velocity shown in equation 7 and remember the tangential components of the final velocities are the same as the initial. -
The results to the problem are in terms of the coordinate axes n and t, so you must transform back into x,y.
I'll leave step 4 up to you. Now let's talk about tensors. Just kidding, just kidding. Let's finish this bad boy off. At this point we have the final velocities: Final velocity for Ball A in terms of n,t: (v Final velocity for Ball B in terms of n,t: (v Now, let's forget about collisions and think about vector geometry. Take a look at Figure 13.36; it illustrates the problem we have. ## Figure 13.36. Transforming a vector from basis to basis.Stated in plain Vulcan, we have a vector in one coordinate system n-t that we want to resolve into x,y. But how? Again, we are going to use dot products. Take a look at the vector (v For Ball A, v v Therefore writing with dot products, x For Ball B: v Therefore, x 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 ## Figure 13.37. The hyper-realistic collision response model. |

↓

Ajax Editor JavaScript Editor