• Advertisement
Sign in to follow this  

Stability problem

This topic is 4364 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I made a 2D physics app based on Oliver Renault’s tutorial, but the collision response isn’t working. If there are two or three objects on top of each other the program explodes. I’ve tried adding more damping, but then the objects don’t bounce off each other, and it still once in a while explodes. Any help appreciated! BTW - this is the method for collision response, I’ve tried to make it like Chris Hecker’s tutorials.
public static void Respond(
	Polygon a, Polygon b, float deltaTime, Vector2 cP, Vector2 mtdN, float aRatio, float bRatio)
{
	//------------------------------------------------------------------------------------------------------
	//Pre-computations
	//------------------------------------------------------------------------------------------------------
	float friction = (a.Material.Friction + b.Material.Friction) * 0.5F;
	float bounce = (a.Material.Bounce + b.Material.Bounce) * 0.5F;

	Vector2 aOB = cP - a.COM;
	Vector2 aOBNormal = new Vector2(-aOB.Y, aOB.X);
	Vector2 aOBn = Vector2.Normalize(aOB);
	Vector2 aOBnNormal = new Vector2(-aOBn.Y, aOBn.X);

	Vector2 bOB = cP - b.COM;
	Vector2 bOBNormal = new Vector2(-bOB.Y, bOB.X);
	Vector2 bOBn = Vector2.Normalize(bOB);
	Vector2 bOBnNormal = new Vector2(-bOBn.Y, bOBn.X);

	//Angular Velocity
	Vector2 aAV = aOBNormal * a.Rotation;
	Vector2 bAV = bOBNormal * b.Rotation;

	//Added Velocity
	Vector2 aAddV = aAV + a.Velocity;
	Vector2 bAddV = bAV + b.Velocity;

	//Linear Velocities
	Vector2 LV = -aAddV + bAddV;

	//------------------------------------------------------------------------------------------------------
	// Friction and bounce
	//------------------------------------------------------------------------------------------------------
	Vector2 mtdNNorm = new Vector2(-mtdN.Y, mtdN.X);

	Vector2 dFriction = Vector2.Dot(mtdNNorm, LV) * mtdNNorm;
	Vector2 dBounce = Vector2.Dot(mtdN, LV) * mtdN;
	LV = (dFriction * friction) + (dBounce * bounce);

	//------------------------------------------------------------------------------------------------------
	// Applied velocity
	//------------------------------------------------------------------------------------------------------
	//Applied Angular Velocities
	float aAVApply = Vector2.Dot(aOBnNormal, LV);
	float bAVApply = Vector2.Dot(bOBnNormal, -LV);

	//Applied Linear Velocity
	Vector2 aLVApply = Vector2.Dot(aOBn, LV) * aOBn;
	Vector2 bLVApply = Vector2.Dot(bOBn, -LV) * bOBn;

	//------------------------------------------------------------------------------------------------------
	// Apply forces
	//------------------------------------------------------------------------------------------------------
	//Apply Rotation
	a.AddForce(aAVApply * aRatio / a.MOE);
	b.AddForce(bAVApply * bRatio / b.MOE);

	//Apply linear velocity
	a.AddForce(aLVApply * aRatio);
	b.AddForce(bLVApply * bRatio);
}

Share this post


Link to post
Share on other sites
Advertisement
Phew! I think first off, you (and we) could probably benefit from some disambiguation. variable names such as mtdN (and others) are difficult to decipher.

After working my way through it, here is what I gathered. mtdN is the collisionNormal. AVApply and LVApply are actually angularAcceleration and linearAcceleration. cP is collisionPoint. .ratio and .MOE have something to do with mass.

If these assumptions are correct the only possible logic flaw I can see is this:
cP is in world space whereas .COM (center of mass, right?) is in body space. Without translating your COM from body space to world space your aOB (whatever that means) can be grossly out of whack, and there goes the whole routine.

edit: typo

Share this post


Link to post
Share on other sites
Whoops! Sorry about the naming. [grin] The ratios are how heavy one polygon is compared to the other polygon (out of 1). The MOE is the moment of inertia (the length between the COM and all the points, added together). The center of mass is actually in world space, it's a bit screwed up in that respect, but it works fine (you just change the COM along with everything else when you translate the points). Thanks for the reply!

Share this post


Link to post
Share on other sites
I made a mistake also, the linearAcceleration and angularAcceleration I spoke of are actually the linearForce and angularForce (or torque to be specific).

The use of a "ratio" may be a source of problem. The amount of acceleration of object A doesn't depend on it mass ratio to B. From Newton and Chris Hecker - F=ma... more usefully written: acceleration=force/mass. Take the linearForce, divide it by a.mass (or whatever) and that is the acceleration. add the acceleration to the velocity and there you go. Same thing for object B.

When you use the moment of inertia scalar (MOE) that is already (supposed to be) taking into acount the mass of the object. it would simply be angularAcceleration=angularForce/a.MOE. no additional ratio or mass needs to be accounted for. Unfortunately, a polygon's moment of inertia can't actually be computed by just adding the square of vertex distance from the COM. As an example, imagine this: An equilateral triangle (all sides are same length, all angles are same measure) with the COM right in the middle (of course). As it stands, using the distance of each point squared will work for moment of inertia... but what if you took one edge of the trangle and divided in half and put a point there. It is the same shape, but with an additional point. This would change your MOE. When Chris Hecker talks about the summation it is with a set of points uniformly (and infinitely) distributed across the whole object... which your polygon vertices are certainly not. Unfortunately calculating an accurate version is a bit more complicated. Integraion Over Area!?! eek. If you are working with 3D polyhedron, look for Polyhedral Mass Properties by David Eberly... for 2D dunno.

Another problem... I noticed that you use the same member function "AddForce" to apply angular and linear force. This is actually a couple of problems balled into one. The force you are applying to the object is scaled by ratio and MOE. the force itself is not effected at all by mass. If the function is truly "adding force" as its name implies, it should itself be dividing the force by the objects mass to get acceleration... ie - a.AddForce(aLVApply). Perhaps the function should be renamed to AddAcceleration(). because you have already done the work of dividing the force by the mass.

Lastly, (perhaps most importantly) AddForce, or even AddAcceleration won't work quite as expected. Position, Velocity, and Acceleration are functions of time. Using this code, you have told your simulator to apply a force (or acceleration) to an object... but for how long (time)? if the next step of your simulation is one second from the step your calculating now, you will have been applying that force for a whole second, which will send your objects rocketing away from eachother. What you need for simulation is (to start off with) Newton’s Law of Restitution for Instantaneous Collisions with No Friction. Which is explained in Chris Heckers work. Since the code you have now shows that you mean to use friction, you shouldn't have much difficulty finding a model that also does this. (Hopefully)

Hope I've helped... Sometimes when I read what I've typed, I start to drift off myself! :-) I am also working on a 3D rigid body simulator + much much more...
http://www.codersoft.net/Pegason/Simulation%20Systems%20and%20Goals.txt

Edit: One more thing, linear acceleration does need to be multiplied by the dot product of the application point to COM vector and the force vector. Any force applied to any point on the body is added directly to the total linear force (without any scaling)... to see why, check out "Physically Based Modeling by David Baraff" section 5.5 Force vs. Torque puzzle. If you haven't already read this, it may help.

Share this post


Link to post
Share on other sites
I'm using the ratio out of one, because, say both of the objects had a mass of 100,000. If you divide the total force by 100,000 it would hardly affect each of the objects and they would pass through each other. Maybe I'm understanding this wrong or something... (btw - I'm using inverse masses)

In my simulation, the moment of inertia is incorrect. Most of the objects I have are Squares and hexagons and stuff, but I have noticed that on objects other than those, it doesn't work. I was thinking of weighting each of the points with the length of the surrounding lines (I'm using SAT, so there's only convex polygons). Also, is there any way to make concave polygons with SAT? I was thinking of piecing a concave polygon together with a bunch of convex ones.

The AddForce (now Add Acceleration[smile]) just applies a force to a temporary vector, then applies it every time I move the polygon (every tick). Once it's added, it clears the temp vector and starts over again. Is this what could be screwing it up?

I was looking at my code for finding a contact point. It usually finds the right one, but in special cases, (two flat edges, two pointy edges) it won't work.

The physics app your making sounds great! Thanks!

Share this post


Link to post
Share on other sites
You are correct, diving the force by 100,000 would result in very little acceleration (which is the natural case). That is why Newton’s Law of Restitution for Instantaneous Collisions with No Friction (in Chris Hecker's work) is so important. It creates change in velocity without having to apply a force over time, and does so in a way that compensates for massive objects.

I don't know anything about SAT.

As for a temporary vector for the application of force, the method you are using should work. But still, only collisions of deformable bodies are calculated with application of forces, otherwise your bodies will interpenetrate, leading to a stack of applied forces as each frame calculates an additional force for every one of those frames.

For your collision problems, it's probably better to start a new thread.

Share this post


Link to post
Share on other sites
Hmmm.... I don't under stand Newton’s Law of Restitution for Instantaneous Collisions with No Friction. Guess I'll have to read Chris Hecker's articles again [dead]. SAT is seperating axis therom (Google!). This is the tutorial I'm using

http://uk.geocities.com/olivier_rebellion/Polycolly.zip

I'll try rewriting parts of the code, that always works. [grin] Thanks for you help!

[Edited by - FreeDebreuil on May 10, 2006 7:12:36 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement