 Allegro.cc Forums » Game Design & Concepts » [Math] Elasticity/Deflection

 This thread is locked; no one can reply to it.  [Math] Elasticity/Deflection
 ngiacomelli Member #5,114 October 2004 Quite a few questions here. I'm looking for a very simple way to demonstrate elasticity! Basically, I have a line with two points. I have a spherical object. I want to check the line for a collision with this spherical object. After that, I need a way to find the angle of deflection... and update the spherical objects speed/direction accordingly.{"name":"590377","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/7\/f7433584382862f02fff33c41ec27b86.png","w":339,"h":235,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/7\/f7433584382862f02fff33c41ec27b86"} DanielH Member #934 January 2001 You can use these 3d equations with 2D with some minor adjustments;Point1 = ( x1, y1, 0 );Point2 = ( x2, y2, 0 );Point3 = ( x2, y2, -5 );Dir = direction VectorspherePos = center spheresphereRadius = As it saysArbitraryPointOnLine = As it saysNormal to Line: ```normal = ( Point2 - Point3 ).crossProduct( Point2 - Point1 ); normal = normal / normal.length; // normalize ``` Distance to Line: (distance is signed, neg means other side ) ```distance = normal.dotProduct( spherePos - ArbitraryPointOnLine ); ``` To be a hit then distance is less than sphereRadius. ```if ( distance < sphereRadius ) { spherePos = spherePos + Dir + this->normal * 2.0 * ( sphereRadius - distance ); } ```
 Zaphos Member #1,468 August 2001 Quote: normal = ( Point2 - Point3 ).crossProduct( Point2 - Point1 ); For reference (since a cross product for 2D seems a bit silly), you can find the normal direction of a 2D line like this: Say your line is p1 to p2, and it's direction is d = (p2 - p1) = (dx, dy). Then the normal direction is just (-dy, dx). And the normalized normal, as in the 3D case, may be found by dividing the normal direction by its magnitude.Quote: Point3 = ( x2, y2, -5 ); There should be no need to keep around that Point3 variable, or use 3D math functions -- functions that only operate on 2D vectors will work just fine.Quote: distance = normal.dotProduct( spherePos - ArbitraryPointOnLine ); Note that to detect a hit on a line segment, which is what it looks like you might be talking about, you also would want to do another dot product to find how far along the line segment the circle lies, and you'd want to do two distance tests against the line segment's endpoints.Quote: After that, I need a way to find the angle of deflection... and update the spherical objects speed/direction accordingly. You probably don't want to use an angle of deflection, or a direction vector, or a speed value. Just track velocity. To adjust the velocity in response to a collision, do something like this:velocity += (1 + elasticity) * dotProduct(velocity, normal);Where elasticity is a value between 0 and 1 (inclusive).I'll note that I really have no idea what math you do or don't understand, so ... if anything doesn't make sense: sorry! Ask for clarifications as needed.Do you understand the dot product, and why it's useful here?
 ngiacomelli Member #5,114 October 2004 Quote: I'll note that I really have no idea what math you do or don't understand, so ... if anything doesn't make sense: sorry! Ask for clarifications as needed.Do you understand the dot product, and why it's useful here? I'm not so hot when it comes to number work. I understand that the dot product is the result of adding two vectors together. I'm not entirely sure why DanielH is using 3d equations, but I assume I can just remove the references to point3. I'm definately going to need my hand held for a little. I'm not even sure how I would go about writing the routines to calculate the dot product or cross product.I don't like to just copy and paste code. So if anyone's willing to (try) and explain this to me, that'd be wonderful.
 DanielH Member #934 January 2001 Quote: I'm not entirely sure why DanielH is using 3d equations That's all I've been working with for the past few weeks.
 Zaphos Member #1,468 August 2001 Quote: I understand that the dot product is the result of adding two vectors together. Okay, so for notation I'll refer to a vector as if it had this structure: struct vector { float x; float y; };The dot product is an operation that takes two vectors and returns a scalar (single number). It takes the components of the vectors, multiplies them together, then sums the results.In code, that's: ```float dot_product(vector a, vector b) { return a.x * b.x + a.y * b.y; } ``` Abstractly, the dot product is useful because of one interesting identity: dot_product(v, n) = length(v) * length(n) * cos(theta), where theta is the angle between vectors v and n.(wikipedia has a picture, to help visualize.)Computing the angle between two vectors, and their lengths, is relatively slow. The dot product is fast and easy. When we use the dot product, we're really using it as a short-cut to get at the length * cos(theta) value.In our case what we want is really the length(velocity) * cos(theta). We get this out of dot_product(velocity, normal) by ensuring the normal vector is 'normalized' -- has length(n) == 1.If you'll recall from trigonometry, the length(velocity) * cos(theta) gives the magnitude of velocity in the normal direction, ignoring magnitude of the velocity parallel to the wall.Now, think back to your collision example. Let's look at a picture:{"name":"590378","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/1\/717f363fba88a8270ff65394cac2c3a3.png","w":368,"h":187,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/1\/717f363fba88a8270ff65394cac2c3a3"} In this case, the black arrow represents our ball's velocity. This arrow can be broken down into the red arrow (velocity in to the wall) and the green arrow (velocity parallel to the wall).When you hit a wall, your motion parallel to the wall is unchanged. Your motion 'in to' the wall is either stopped (inelastic collision) or reversed (elastic collision). So we first want to isolate: how much of the motion is 'in to' the wall? As noted above, that's: dot_product(normal, velocity). Now, that's just a length, but we can make that a vector along the correct direction by simply scaling the normal: normal * dot_product(normal, velocity). This should give us a vector equivalent to the red vector*. Now, to change the black vector so it no longer has any motion 'in to' the wall, we can simply subtract the red vector from the black vector. To change the black vector so the ball bounces away from the wall, simply subtract the red vector an additional time.In code, that's:velocity += (1 + elasticity) * dot_product(velocity, normal) * normal;you may be concerned that the dot_product(normal, velocity) will be negative, if the normal and velocity are in opposite directions. This is true, but okay, because in this case the normal, when scaled by a negative, will reverse directions and again match the red vector as expected.Is this making sense?
ngiacomelli
Member #5,114
October 2004

I wrote the following code:

 1 typedef struct Point2d { 2 3 float x, y; 4 5 } Point2d; 6 7 float dotProduct( Point2d p1, Point2d p2 ) 8 { 9 return sqrt( p1.x * p2.x + p1.y * p2.y ); 10 } 11 12 13 int main(void) { 14 15 float len1, len2, mag; 16 Point2d p1, p2, delta, normal; 17 18 p1.x = 100; p1.y = 100; 19 p2.x = 200; p2.y = 200; 20 21 len1 = dotProduct( p1, p1 ); 22 len2 = dotProduct( p1, p2 ); 23 24 delta.x = p2.x - p1.x; 25 delta.y = p2.y - p1.y; 26 27 mag = dotProduct( delta, delta ); 28 29 printf("l1: %f | l2: %f | l3: %f", len1, len2, mag); 30 31 return 0; 32 33 }

And got these results:

```l1: 141.421356 | l2: 200.000000 | l3: 141.421356
```

Am I on the right track, here?

EDIT: Just saw the new post, reading!

 Zaphos Member #1,468 August 2001 Quote: return sqrt( p1.x * p2.x + p1.y * p2.y ); That's not a dot product. That's the square root of a dot product.Quote: len2 = dotProduct( p1, p2 ); I'm not sure why you think that's len2. Did you mean dotProduct( p2, p2 )?Quote: Am I on the right track, here? Well, I have no idea what you're trying to do, here. The dot product can give the squared magnitude of a vector, if you take the dot product of a vector and itself, because then the cos is equal to 1. But that's not really how you're going to be using the dot product for collision detection and response.edit: Oh ... was that code in response to DanielH's now-mysteriously-absent post?
 ngiacomelli Member #5,114 October 2004 I was just converting DanielH's equations to code, initially. I'll have to read through your post. I'm terrible when it comes to math. This will take me a while.
 DanielH Member #934 January 2001 I goofed and erased my goof. I was hoping it wasn't viewed before I erased it.
 Go to: Allegro Development Installation, Setup & Configuration Allegro.cc Comments Off-Topic Ordeals The Depot Game Design & Concepts Programming Questions Recent Threads