9

This question has one major question, and one minor question. I believe I am right in either question from my research, but not both.

For my physics loop, the first thing I do is apply a gravitational force to my TotalForce for a rigid body object. I then check for collisions using my TotalForce and my Velocity. My TotalForce is reset to (0, 0, 0) after every physics loop, although I will keep my velocity.

I am familiar with doing a collision check between a moving sphere and a static plane when using only velocity. However, what if I have other forces besides velocity, such as gravity? I put the other forces into TotalForces (right now I only have gravity). To compensate for that, when I determine that the sphere is not currently overlapping the plane, I do

    Vector3 forces = (sphereTotalForces + sphereVelocity);
    Vector3 forcesDT = forces * fElapsedTime;
    float denom = Vec3Dot(&plane->GetNormal(), &forces);

However, this can be problematic for how I thought was suppose to be resting contact. I thought resting contact was computed by

denom * dist == 0.0f

Where dist is

float dist = Vec3Dot(&plane->GetNormal(), &spherePosition) - plane->d;

(For reference, the obvious denom * dist > 0.0f meaning the sphere is moving away from the plane)

However, this can never be true. Even when there appears to be "resting contact". This is due to my forces calculation above always having at least a .y of -9.8 (my gravity). When when moving towards a plane with a normal of (0, 1, 0) will produce a y of denom of -9.8.

My question is

1) Am I calculating resting contact correctly with how I mentioned with my first two code snippets?

If so,

2) How should my "other forces" such as gravity be used? Is my use of TotalForces incorrect?

For reference, my timestep is

  mAcceleration = mTotalForces / mMass;
  mVelocity += mAcceleration * fElapsedTime;
  Vector3 translation = (mVelocity * fElapsedTime);

EDIT

Since it appears that some suggested changes will change my collision code, here is how i detect my collision states

if(fabs(dist) <= sphereRadius)
{ // There already is a collision }
else
{
    Vector3 forces = (sphereTotalForces + sphereVelocity);
    float denom = Vec3Dot(&plane->GetNormal(), &forces);

    // Resting contact
    if(dist == 0) { }
    // Sphere is moving away from plane
    else if(denom * dist > 0.0f) { }
    // There will eventually be a collision
    else
    {
        float fIntersectionTime = (sphereRadius - dist) / denom;
        float r;
        if(dist > 0.0f)
            r = sphereRadius;
        else
            r = -sphereRadius;

        Vector3 collisionPosition = spherePosition + fIntersectionTime * sphereVelocity - r * planeNormal;
    }
}
mmurphy
  • 1,327
  • 4
  • 15
  • 30
  • There are several elements of this question that are note worthy and after also looking a solution, it seems to be a complex issue with no a lot of resources. Hopefully a bounty could help out with this. – josephthomas May 03 '12 at 05:35
  • @mmurphy: what is the meaning of `sphereTotalForces + sphereVelocity`? Something missing in the expression? – user2k5 May 03 '12 at 05:59
  • sphereTotalForces is the `TotalForces` (`mTotalForces`) I described, and `sphereVelocity` is the same `mVelocity` mentioned below. `TotalForces` are external forces that are placed on to the current sphere (rigid body) during this time step where as `mVelocity` is the velocity over the life time. If this is the wrong way to handle this, I would be interested in an explanation of how to do so otherwise. – mmurphy May 03 '12 at 06:37
  • What does "resting contact" mean to you? Does it mean that the sphere is in contact with the plane and stationary? – Beta May 03 '12 at 16:06
  • "Resting contact" is the state in which the rigid body (my sphere) is touching another object (my plane) without penetration. Is there another definition for "resting contact"? – mmurphy May 04 '12 at 01:00
  • Yes, the definition could also require that the objects be stationary (and not, say, bouncing off one another). You're not going to be able to solve this problem (or understand any answer we give you) without learning some basic physics. We're willing to teach, but please don't make us repeat ourselves. – Beta May 04 '12 at 02:52
  • @Beta: I am sorry, I should have been more clear. I understand that "resting contact" means the object is "stationary". However, isn't that the same state the object is in where I would compute static friction. For example, when a ball is at (0, 1, 0) with a radius of 1 on a plane at (0, 0, 0) with the normal of (0, 1, ), it seems to be at "resting contact". At that point with a velocity of (2, 0, 0) the ball is not bouncing off the plane. At that point, it would seem appropriate to compute static friction, wouldn't it? – mmurphy May 04 '12 at 03:49
  • @Beta: I would be interested in your response. It appears the bounty on this question is running up soon, so I hope it gets awarded to someone. – mmurphy May 09 '12 at 06:47
  • You're still asking how to "calculate resting contact". I've studied physics to a pretty high level, and I don't know what you mean. Your geometry is similarly cryptic ("a plane at (0,0,0)"?). I could try to explain how to simulate elastic and inelastic collisions under gravity, but honestly I wouldn't know whether I was addressing your real question and I don't think my answer would do you any good. – Beta May 10 '12 at 04:29
  • @Beta: I suppose "resting contact" is more of a game physics term (where I see it mentioned often). What would you describe an object when it is laying on a plane (with no penetration), but there is still a velocity on the object? – mmurphy May 10 '12 at 04:34
  • I'd describe it as sliding or rolling, depending. Is that the kind of motion you're trying to simulate? A sphere travels through the air, strikes a surface, and then starts sliding (or rolling)? – Beta May 10 '12 at 04:51
  • I am trying to figure out the state of when I would calculate friction. The ball is rolling on a surface, but I am not sure of when I should calculate friction. – mmurphy May 10 '12 at 05:15
  • You're trying to simulate a ball rolling, without sliding, on a surface. And do you want a simulation dedicated to that, or do you want a simulation that can also handle e.g. the ball traveling through the air? – Beta May 10 '12 at 05:37
  • I can already simulate a ball traveling in the air and bouncing off of a surface. I am trying to simulate when a ball would slide on a surface. There is two parts to a ball moving on a surface (that I know of), it "rolling" and it "sliding". The rolling would of course cause the model to rotate, where the "sliding" would require me to apply a friction to the ball. – mmurphy May 10 '12 at 05:45
  • Think of it this way: If the plane is flat (horizontal). You split the force into a horizontal and vertical component. Vertical: the surface apply the same force upwards as the down force, thus resolting in the ball not moving up or down. Horizontal: The surface apply no force, so it is only external forces on the ball. That will result in the ball sliding. If the surface is at an angle, then you have to split the force components to the normal component, and parallel component. You set the normal component to 0, and keep the parallel component. – Gerhard Powell May 11 '12 at 14:50
  • -1 one for confusing a force and a velocity (or at least presenting code which suggests you do this). – Walter May 13 '12 at 17:10
  • @Walter: That was part of my question, I was confused about the part. – josephthomas May 15 '12 at 00:26

6 Answers6

1
  1. You should use if(fabs(dist) < 0.0001f) { /* collided */ } This is to acocunt for floating point accuracies. You most certainly would not get an exact 0.0f at most angles or contact.

  2. the value of dist if negative, is in fact the actual amount you need to shift the body back onto the surface of the plane in case it goes through the plane surface. sphere.position = sphere.position - plane.Normal * fabs(dist);

  3. Once you have moved it back to the surface, you can optionally make it bounce in the opposite direction about the plane normal; or just stay on the plane.

    parallel_vec = Vec3.dot(plane.normal, -sphere.velocity);

    perpendicular_vec = sphere.velocity - parallel_vec;

    bounce_velocity = parallel - perpendicular_vec;

  4. you cannot blindly do totalforce = external_force + velocity unless everything has unit mass.

EDIT:

  1. To fully define a plane in 3D space, you plane structure should store a plane normal vector and a point on the plane. http://en.wikipedia.org/wiki/Plane_(geometry) .

Vector3 planeToSphere = sphere.point - plane.point;

float dist = Vector3.dot(plane.normal, planeToSphere) - plane.radius;

if(dist < 0) { // collided. }

I suggest you study more Maths first if this is the part you do not know.

NB: Sorry, the formatting is messed up... I cannot mark it as code block.

EDIT 2: Based on my understanding on your code, either you are naming your variables badly or as I mentioned earlier, you need to revise your maths and physics theory. This line does not do anything useful.

float denom = Vec3Dot(&plane->GetNormal(), &forces);

A at any instance of time, a force on the sphere can be in any direction at all unrelated to the direction of travel. so denom essentially calculates the amount of force in the direction of the plane surface, but tells you nothing about whether the ball will hit the plane. e.g. gravity is downwards, but a ball can have upward velocity and hit a plane above. With that, you need to Vec3Dot(plane.normal, velocity) instead.

Alternatively, Mark Phariss and Gerhard Powell had already give you the physics equation for linear kinematics, you can use those to directly calculate future positions, velocity and time of impact.

e.g. s = 0.5 * (u + v) * t; gives the displacement after future time t. compare that displacement with distance from plane and you get whether the sphere will hit the plane. So again, I suggest you read up on http://en.wikipedia.org/wiki/Linear_motion and the easy stuff first then http://en.wikipedia.org/wiki/Kinematics .

Yet another method, if you expect or assume no other forces to act on the sphere, then you do a ray / plane collision test to find the time t at which it will hit the plane, in that case, read http://en.wikipedia.org/wiki/Line-plane_intersection .

Jake
  • 11,273
  • 21
  • 90
  • 147
  • My primary concern is dealing with calculating resting contact, am I do this correct? If not, how should I? Also, in `4` you metnined I can not do `totalforce = external_force + velocity`. How should I calculate my total force then? – mmurphy May 10 '12 at 00:34
  • I understand how to define a plane, however, knowing how to define a plane and determining if there is `resting contact` is two different things. – mmurphy May 10 '12 at 03:07
  • Based on your conversation with Beta in your OP comments, you seem to have misconceptions about maths and physics. You said "resting contact" is when the ball has velocity and is touching the plane. In code it would be `if(sphere.velocity.length() > 0 && dist < 0) { /* resting contact */ }` What is so difficult about this if you know how to calculate everything? I don't understand your issue. – Jake May 10 '12 at 12:10
  • For my "resting contact", this seems very close, and it seems it may work for just a ball sliding only. However, in my simulation, I was calculating `dist` differently, and with your changes, it seems it may have messed with my "future collision point" calculate. I was previously calculating the intersection time as `float fIntersectionTime = (sphere->GetRadius() - dist) / denom;` then finding the collision point with `Vector3 collision = spherePosition + fIntersectionTime * rigidBodySphere->GetVelocity() - r * plane->GetNormal()`, as mentioned in my post. How should this be modified? – mmurphy May 11 '12 at 02:49
  • Hi mmurphy, Please see my edit. Please also see the equations by Gerhard Powell and Mark Phariss. Those equations already give you the answer to predict collision. – Jake May 11 '12 at 04:01
  • Ah, I think the second edit cleared up a lot of misconceptions I was having. A large portion of my issues comes from having gravity be part of `TotalForces` and attempting to use that properly. It would appears that during my sphere and plane collision test, that `TotalForces` is irrelevant and I should only be using velocity, is this correct? – mmurphy May 11 '12 at 06:04
  • Yes, correct you should use the velocity since that will give the direction of travel. So at each step of simulation, `v = u + at` then use v in your dot product. Don't forget that gravity of 9.81 is NOT a force, it is acceleration in m/s^2 units and is irregardless of mass. – Jake May 11 '12 at 08:22
  • Since gravity is not a force, should it even be getting added to my "TotalForce", is my concept of that just plain wrong? Should I just add gravity to Acceleration if there is not "resting contact"? – mmurphy May 12 '12 at 18:10
  • The idea of using total forces is not wrong, but the way you have implemented is wrong as other have pointed out. Gravity is always added to the total acceleration of the sphere, even at resting contact. You may misunderstand that there is no gravity at resting contact due to your observation of Newton's 3rd law, http://en.wikipedia.org/wiki/Newton's_laws_of_motion. But if you faithfully add it in, it will give you automatic rolling and sliding. – Jake May 13 '12 at 06:45
  • 1
    Since this discussion is getting lengthy, if you think any of our answers helped, I suggest you mark it as answer and then open new question in maths/physics stackexchange specifically related to the problem you are trying to get right. The experts should be able to give you better insight. – Jake May 13 '12 at 06:50
0

There will always be -9.8y of gravity acting on the sphere. In the case of a suspended sphere this will result in downwards acceleration (net force is non-zero). In the case of the sphere resting on the plane this will result in the plane exerting a normal force on the sphere. If the plane was perfectly horizontal with the sphere at rest this normal force would be exactly +9.8y which would perfectly cancel the force of gravity. For a sphere at rest on a non-horizontal plane the normal force is 9.8y * cos(angle) (angle is between -90 and +90 degrees).

Things get more complicated when a moving sphere hits a plane as the normal force will depend on the velocity and the plane/sphere material properties. Depending what your application requirements are you could either ignore this or try some things with the normal forces and see how it works.

For your specific questions:

  1. I believe contact is more specifically just when dist == 0.0f, that is the sphere and plane are making contact. I assume your collision takes into account that the sphere may move past the plane in any physics time step.
  2. Right now you don't appear to have any normal forces being put on the sphere from the plane when they are making contact. I would do this by checking for contact (dist == 0.0f) and if true adding the normal force to the sphere. In the simple case of a falling sphere onto a near horizontal plane (angle between -90 and +90 degrees) it would just be sphereTotalForces += Vector3D(0, 9.8 * cos(angle), 0).

Edit:

From here your equation for dist to compute the distance from the edge of sphere to the plane may not be correct depending on the details of your problem and code (which isn't given). Assuming your plane goes through the origin the correct equation is:

dist = Vec3Dot(&spherePosition, &plane->GetNormal()) - sphereRadius;

This is the same as your equation if plane->d == sphereRadius. Note that if the plane is not at the origin then use:

D3DXVECTOR3 vecTemp(spherePosition - pointOnPlane);
dist = Vec3Dot(&vecTemp, &plane->GetNormal()) - sphereRadius;
uesp
  • 6,194
  • 20
  • 15
  • Wouldn't calculating `dist == 0.0f` give a false positive if their was still velocity/force and the sphere just happens to be at the surface? – mmurphy May 02 '12 at 00:32
  • When `dist == 0` you have to apply some sort of force on the sphere from the plane, the exact amount depends on how simple/complex you want your physics model to be. Take the simplest case of a sphere falling onto a horizontal plane. For a simple model with no bounce you just apply the opposite gravity force to the sphere causing it to 'stick' without bouncing. To make the sphere bounce you would have to apply an additional force based on the sphere's previous velocity. – uesp May 02 '12 at 02:02
  • I understand that I would need to do some sort of vector reflection, however, just checking `dist == 0.0f` seems as if it could give a false positive if there is a force already acting on the sphere. Is this true? – mmurphy May 02 '12 at 02:45
  • I guess I don't understand what you mean by "false positive". When `dist == 0` the sphere *is* touching the plane in which case there will be some form of normal force. This normal force is simply added to whatever other forces are acting on the sphere. – uesp May 02 '12 at 12:02
  • Shouldn't the check then be `dist == sphereRadius` for resting contact? For example, if the radius is 1 and the center point of the sphere is at (0, 1, 0) then for a plane at (0, 0, 0) with a normal of (0, 1, 0) it would seem resting contact would be when `dist == sphereRadius`. – mmurphy May 03 '12 at 01:50
  • I was assuming that `plane->d` was actually the same as the sphere radius otherwise the `dist` calculation wouldn't make any sense. If this is not the case then yes, you'll need to change the dist calculation to one that actually represents when the sphere is touching the plane (see additional edit). – uesp May 03 '12 at 11:39
  • If I were to do, then it would change the entirety of how I check my collision states. Particularly, how I find my collision point (or what I called "adjusted position"). I have modified my original code, how should my collision state detection be changed based upon your suggestions? – mmurphy May 04 '12 at 01:13
  • I would be interested in your opinion to my last question. It appears the bounty on this question is running up soon, so I hope it gets awarded to someone. – mmurphy May 09 '12 at 06:48
0

Answers to your physics problems:

f = mg + other_f; // m = mass, g = gravity (9.8)
a = f / m; // a = acceleration
v = u + at; // v = new speed, u = old speed, t = delta time
s = 0.5 * (u + v) *t;

When you have a collision, you change the both speeds to 0 (or v and u = -(u * 0.7) if you want it to bounce).

Because speed = 0, the ball is standing still.

If it is 2D or 3D, then you just change the speed in the direction of the normal of the surface to 0, and keep the parallel speed the same. That will result in the ball rolling on the surface.

You must move the ball to the surface if it cuts the surface. You can make collision distance to a small amount (for example 0.001) to make sure it stay still.

http://www.physicsforidiots.com/dynamics.html#vuat

Edit:

NeHe is an amazing source of game engine design: Here is a page on collision detection with very good descriptions: http://nehe.gamedev.net/tutorial/collision_detection/17005/

Edit 2: (From NeHe)

double DotProduct=direction.dot(plane._Normal); // Dot Product Between Plane Normal And Ray Direction
Dsc=(plane._Normal.dot(plane._Position-position))/DotProduct; // Find Distance To Collision Point
Tc= Dsc*T / Dst
Collision point= Start + Velocity*Tc
Gerhard Powell
  • 5,965
  • 5
  • 48
  • 59
  • My primary concern is with how to calculate resting contact. Am I do this correctly? If not, should do I when using forces other than velocity? – mmurphy May 10 '12 at 00:35
  • I don't agree with mixing forces and velocity. If you throw a ball up for example, then the force is down, but the velocity is upwards. You must think of force as something trying to change the velocity, instead of velocity itself. So forces is only gravity and something that pushes it. If you make velocity = 0, then it does not matter what forces you apply, it will stay still. – Gerhard Powell May 10 '12 at 14:58
0

The exact solution to this problem involves some pretty serious math. If you want an approximate solution I strongly recommend developing it in stages.

1) Make sure your sim works without gravity. The ball must travel through space and have inelastic (or partially elastic) collisions with angled frictionless surfaces.

2) Introduce gravity. This will change ballistic trajectories from straight lines to parabolae, and introduce sliding, but it won't have much effect on collisions.

3) Introduce static and kinetic friction (independently). These will change the dynamics of sliding. Don't worry about friction in collisions for now.

4) Give the ball angular velocity and a moment of inertia. This is a big step. Make sure you can apply torques to it and get realistic angular accelerations. Note that realistic behavior of a spinning mass can be counter-intuitive.

5) Try sliding the ball along a level surface, under gravity. If you've done everything right, its angular velocity will gradually increase and its linear velocity gradually decrease, until it breaks into a roll. Experiment with giving the ball some initial spin ("draw", "follow" or "english").

6) Try the same, but on a sloped surface. This is a relatively small step.

If you get this far you'll have a pretty realistic sim. Don't try to skip any of the steps, you'll only give yourself headaches.

Beta
  • 96,650
  • 16
  • 149
  • 150
0

I suggest after that to take a look at erin cato articles (the author of Box2D) and Glenn fiedler articles as well. Gravity is a strong acceleration and results in strong forces. It is easy to have faulty simulations because of floating imprecisions, variable timesteps and euler integration, very quickly. The repositionning of the sphere at the plane surface in case it starts to burry itself passed the plane is mandatory, I noticed myself that it is better to do it only if velocity of the sphere is in opposition to the plane normal (this can be compared to face culling in 3D rendering: do not take into account backfaced planes).

also, most physics engine stops simulation on idle bodies, and most games never take gravity into account while moving, only when falling. They use "navigation meshes", and custom systems as long as they are sure the simulated objet is sticking to its "ground".

I don't know of a flawless physics simulator out there, there will always be an integration explosion, a missed collision (look for "sweeped collision").... it takes a lot of empirical fine-tweaking.

Also I suggest you look for "impulses" which is a method to avoid to tweak manually the velocity when encountering a collision.

Also take a look to "what every computer scientist should know about floating points"

good luck, you entered a mine field, randomly un-understandable, finger biting area of numerical computer science :)

-1

For higher fidelity (wouldn't solve your main problem), I'd change your timestep to

mAcceleration = mTotalForces / mMass;
Vector3 translation = (mVelocity * fElapsedTime) + 0.5 * mAcceleration * pow(fElapsedTime, 2);
mVelocity += mAcceleration * fElapsedTime;

You mentioned that the sphere was a rigid body; are you also modeling the plane as rigid? If so, you'd have an infinite point force at the moment of contact & perfectly elastic collision without some explicit dissipation of momentum.

Force & velocity cannot be summed (incompatible units); if you're just trying to model the kinematics, you can disregard mass and work with acceleration & velocity only.

Assuming the sphere is simply dropped onto a horizontal plane with a perfectly inelastic collision (no bounce), you could do [N.B., I don't really know C syntax, so this'll be Pythonic]

mAcceleration = if isContacting then (0, 0, 0) else (0, -9.8, 0)

If you add some elasticity (say half momentum conserved) to the collision, it'd be more like

mAcceleration = (0, -9.8, 0) + if isContacting then (0, 4.9, 0)
Ghillie Dhu
  • 213
  • 2
  • 10
  • What do you mean by "higher fidelity"? What advantage is does this technique give? Also, what is this technique called? – mmurphy May 04 '12 at 01:15
  • Higher fidelity as in the discretization would more closely match the continuous motion; it's essentially using the trapezoidal method instead of the rectangle method to approximate the curve. ref: [kinematics of constant acceleration](https://en.wikipedia.org/wiki/Kinematics#Kinematics_of_constant_acceleration) – Ghillie Dhu May 04 '12 at 05:06