Collision response with a particle and the ground.

Started by
7 comments, last by Skelit 14 years, 7 months ago
I'm making a physics engine based off of the one from the nehe tutorials, and I'm trying to get a particle to stop when it hits the ground, instead of falling through it. I found this site: http://www.essentialmath.com/tutorial.htm Which has this explaination about it all: http://www.essentialmath.com/CollisionResponse.pps And I understand it all, but when I code it, my particle just continues to fall through the ground. It slows down when it hits it, but it just keeps going. Here is what I have:
if ( pos.y < 200){ // 200 is an arbitrary point for the ground. 

  Vector3D v = vel;

  Vector3D n(0, m*gravity, 0);
  float impulse = -(1+0.5); //0.5 is the coefficient of restitution
  impulse *= v.dot(n);
  impulse /= n.dot(n)*(1/m);

  n *= impulse/m;
  vel = v + n;
}

/*
the Vector3D class is the same as the tutorial gives you, except i added a dot function to use for the dot product of two vectors. heres the code for that:
 */

float dot(Vector3D d) {
  return x*d.x + y*d.y + z*d.z;
}


Could someone help me figure out what I'm doing wrong?
Advertisement
"n" usually denotes normal, but you seem to have it represent acceleration. I don't know if that's necessarily your problem, but it seems odd to me.
[size=2]Darwinbots - [size=2]Artificial life simulation
I think you just miss :
y = 200.0f;

and / or that test :
if(v.dot(n) < 0.0f) return false;

so you your particle don't get stuck when it's exiting the collision plane.

I'd try this.

// 200 is an arbitrary point for the ground. if ( pos.y < 200.0f){   pos.y = 200.0f; // put particle on collision plane   // arbitrary normal of collision.  Vector3D n(0, m*gravity, 0);  float vn = vel.dot(n);  float nn = n.dot(n);  // particle not exiting the plane  if(vn > 0.0f) ///// or should it be (vn < 0.0f?!?). try either  {    // 0.5 is the coefficient of restitution.    // impulse magnitude (scaled by the inverse length of normal).    float impulse = -(1.0f + 0.5f) * vn / (nn * 1/m);     // impulse vector.    Vector j = impulse * n;    // apply impulse    vel += (j / m);  }}

Everything is better with Metal.

Quote:Original post by oliii
I think you just miss :
y = 200.0f;

and / or that test :
if(v.dot(n) < 0.0f) return false;

so you your particle don't get stuck when it's exiting the collision plane.

I'd try this.

// 200 is an arbitrary point for the ground. if ( pos.y < 200.0f){   pos.y = 200.0f; // put particle on collision plane   // arbitrary normal of collision.  Vector3D n(0, m*gravity, 0);  float vn = vel.dot(n);  float nn = n.dot(n);  // particle not exiting the plane  if(vn > 0.0f) ///// or should it be (vn < 0.0f?!?). try either  {    // 0.5 is the coefficient of restitution.    // impulse magnitude (scaled by the inverse length of normal).    float impulse = -(1.0f + 0.5f) * vn / (nn * 1/m);     // impulse vector.    Vector j = impulse * n;    // apply impulse    vel += (j / m);  }}


Ah, thank you! I just did that and now it works perfectly! I did have to change it to if ( vn < 0.0f ) though. Thank you so much for your help, it's so cool seeing my little dot bounce realisticly when it touches the ground! :D

Quote:Original post by Numsgil
"n" usually denotes normal, but you seem to have it represent acceleration. I don't know if that's necessarily your problem, but it seems odd to me.


When on object is just sitting on the ground and is at rest, isn't the normal mass*gravity? I thought it'd be the same for when a falling object collides with the ground. Since it's working right now though, I guess that normal does work.
In general, A collision normal doesn't have anything to do with which way the gravity is, or how strong it is. It just so happens that your hard-coded collision plane is aligned with your gravity and will be always point in the direction of (0, 1, 0).

If you collide with an inclined plane, the normal would be different (perpendicular to the plane), and your particle will 'deflect' and bounce around.

If your normal changes, your collision test (y < 200.0f) will not be valid anymore.

say you have a inclined plane with normal (0.1f, 1.0f, 0.1f), and an origin Vector(2.0f, -2.0f, -1.0f) (the origin is basically any point that would be on the plane).

your test would become.

//------------------------------------------// n : plane normal// o : an arbitrary point on the plane.//------------------------------------------float n2 = n.dot(n);// distance of particle from plane (scaled by the plane normal length).float dist = (pos - o).dot(n);// particle under the planeif(dist < 0.0f){  // move particle on surface of plane.  pos -= n * (dist / n2);  // impact speed  float vn = vel.dot(n);  // particle is entering the plane.  if(vn < 0.0f)  {     ////// ect.......     ////// .......     ////// ..     vel += (j / m);  }}

Everything is better with Metal.

Quote:Original post by oliii
In general, A collision normal doesn't have anything to do with which way the gravity is, or how strong it is. It just so happens that your hard-coded collision plane is aligned with your gravity and will be always point in the direction of (0, 1, 0).

If you collide with an inclined plane, the normal would be different (perpendicular to the plane), and your particle will 'deflect' and bounce around.

If your normal changes, your collision test (y < 200.0f) will not be valid anymore.


Yeah, my normal with the ground was just for testing to get started. :)

How could a find a normal for any surface that I come in contact with though? You don't just decide one for each plane, do you? Surely there has to be a way to calculate it for any plane at any angle, but how?
It doesn't matter what angle the particle hits the plane at; the normal is uniquely determined from the surface being hit. In the case you're hitting a line segment, the normal is perpindicular to that. Let r = p1 - p0, where p1 and p0 are points on your line segment. Then let n = (-ry, rx). Often times if you're careful with the math you don't have to normalize it, though since you're pretty new to the math I'd recommend normalizing it just as a sanity check.
[size=2]Darwinbots - [size=2]Artificial life simulation
Well, probably the most convenient way to describe a plane would be just with a point on the plane and its normal vector (as oliii showed); using angles would be much more cumbersome in this case.

For a surface such as a triangle where you know the vertices, you can calculate the normal by taking the cross product of the vectors representing two of its sides. For example, for a triangle with vertices A, B, C, you can calculate the normal by taking the cross product of the vector from A to B and the vector from B to C (and usually normalizing the result). Of course, the direction of the normal depends on the direction of the vectors and the order of the cross product operation.
Ah okay, i understand it now. Thank you guys!

This topic is closed to new replies.

Advertisement