energy absorbtion ...

Started by
7 comments, last by ekrax 19 years, 11 months ago
im currently programming a physics engine, and having a bit of trouble with some realism ... for the most part object collisions, gravity, and acceleration all work pretty good (havent added friction yet) ... let me begin on saying i only have grade 11 physics knowledge, so i might be missing something ... ok here''s the scenerio i have a ball that bounces on a flat frictionless surface with regular earth gravity 9.81 m/s^2 ... if i leave everything the way it is the ball bounces right back up to the same height it starts off, my obvious conclusion is that the surface must absorb some of the energy of the ball, and that the ball returns with less energy. i simply added an absorbtion variable to a class which describes all objects in my world. the equation works like this ... this is after a few "if''s" to find out if the object has made contact witht he surface, when it has ... obj1 is the moving object obj2 is the static object vy is the velocity on the y plane obj1.vy = (obj1.vy - obj2.absorbtion) * -1; if(obj1.vy > 0) obj1.vy = 0; so you can see i subtract the absorbtion value from the moving objects velocity and then invert it to send it back the other way.. the problem is the ball will be boucning and ones it reaches a certain height it just drops like a stone and doesnt bounce, even though it really should.. any suggestions?
Advertisement
It stops bouncing when obj2.absorbtion is less than obj1.vy

You should do obj1.vy = (obj1.vy / obj2.absorbtion) * -1;
where obj2.absorbtion is between 0 and 1

Edit: You should really use obj1.vy = (obj1.vy * obj1.restitution) * -1; but I was editing your own code

--------------------------------------
I am the master of stories.....
If only I could just write them down...

[edited by - Nathaniel Hammen on May 20, 2004 9:11:07 PM]
I am the master of ideas.....If only I could write them down...
ahh that would make much more sense!
by using this ...
obj1.vy = (obj1.vy * obj1.restitution) * -1;
if obj1.restitution was equal to say 0.80 that would mean it would keep 80% of it''s energy ... resulting in a smaller bounce correct?

thanks for your help!
just to elaborate, as was mentioned, this is called the 'coefficient of restitution', and it is a measure of how much kinetic energy is lost in a system of collisions. I say 'system of collisions' because typically it must be measured for very specific scenarios. In reality, you can just have a 'stiffness' variable which ranges between 0 and 1 for each object, and when 2 objects collide you can average their stiffness values together (this is what I do in my physics engine, it's sort of a hack, but it works very nicely).

In general, the object's velocity only changes in the direction normal to the collision. You probably knew this already, but it is crucial to break the object's velocity into components perpendicular and parallel to the normal of the collision. You then reverse the direction and multiply it by the coefficient of restitution for the collision.

Hope that helps.

EDIT:
for example, in your scenario, only the y value of the ball's velocity would be changed, because the ball fell on a flat surface. If the object was also moving in the X direction, that part of the velocity would just keep on going.

[edited by - shadow12345 on May 21, 2004 9:49:25 AM]
Why don't alcoholics make good calculus teachers?Because they don't know their limits!Oh come on, Newton wasn't THAT smart...
this sounds very similar to the coefficent of friction, ive added friction as well but i used a hack i guess you could say also, by adding the 2 ''mu'' values together and averaging, then dividing the velocity on the x plane by this... i get little difference when i use the proper way of

Ff = u * m * g
then converting the force in newtons into acceleration ...

however i havent added in friction on sloped planes yet, i know how to implement it though

another question though on restitution, when two objects collide and energy is converted and soforth is there any acceleration after the collision and does mass have anything to do with how the objects react after the collision?
the mass has absolutely everything to do with the acceleration and velocity after the impact. The way I've implemented it is that when two objects in the world collide, an impulse is produced. An impulse isn't really considered a force because it acts instantaneously (or over very short durations), but, well, it's a force

impulse = mass * changeinvelocity

NewVelocity = OldVelocity + changeinvelocity

or

NewVelocity = OldVelocity+ (ImpulseForce / mass)

A very crucial thing to remember is that your velocity is ONLY MODIFIED IN THE DIRECTION OF THE NORMAL. Subsequently, everything here can be expressed as scalars representing the magnitude of the velocity, in the direction of the normal. All 3D collisions are ultimately broken down into an impulse which acts along a single line.

the coefficient of restitution is the absolute value of the relative escape velocities. I don't really feel like explaining all of this, but I'll show you an implementation and some notes from Physics for Game Developers.

My implementation is here:
#include	"Physics.h"#include	"GAMEEXPORT.H"extern	GameExport	Export;extern	std::ofstream	trace;/*	Impulse	=	Mass(v+ - v_)	J	=	m(v+	-	v_)	v+	=	(J/m)	+	v_	1	=	-(v1+ - v2+) / (v1_ - v2_)		Positive J (impulse) acts on body 1	Negative J (impulse) acts on body 2	v1+	=	(J/m)	+	v1_	v2+	=	(-J/m)	+	v2_	Put these into the equation for coefficient of restitution (in this case	and in all cases, this will be 1, at least for now):	1	=	-(((J/m) + v1_) - (-J/m) + v2_)) / (v1_ - v2_))	1	=	-((J(1/m) + v1_) - J(-1/m) + v2_)) / (v1_ - v2_))*/void	Physics::ApplyImpulse(VWorldObject*a,VWorldObject*b){	if(a->mMass	<=	0	||	b->mMass <=	0)	{		return;	//can't deal with this other than returning	}	//this is just linear for right now, get the speeds in the direction of the collision normal	float	mag1,mag2;	//magnitude in direction of normal before the collision 	Vector3	*normal = &Export.mpBSP->mBSPColInfo.hitNormal;	mag1	=	DotProduct(&a->mVelocity.Dir,normal);	mag2	=	DotProduct(&b->mVelocity.Dir,normal);	//Now you know a calculation must be performed no matter what, and they all use this data	Vector3	normalpart1,normalpart2;	//actual normal vector components in direction of normal	Vector3	par1,par2;	//parallel vector components against plane	normalpart1	=	*normal * mag1;	normalpart2	=	*normal * mag2;	par1		=	a->mVelocity.Dir - normalpart1;	par2		=	b->mVelocity.Dir - normalpart2;		float	force;	//the impulse, baby (needs to be solved for unfortunately) 	float	relative = mag1-mag2;	//relative incoming velocity	float	imass1,imass2;		if(a->mMass)	{		imass1	=	1/a->mMass;	}		if(b->mMass)	{		imass2	=	1/b->mMass;	}	//restitution is 1 for right now, because the elasticity must be	//experimentally determined	//however, you can make a 'hack' my averaging two values of coefficient of restitution together	//it isn't physically accurate but works beautifully	float	averagerest = (a->mStiffness	+	b->mStiffness) * .5;	force	=	-(relative*averagerest)/(imass1+imass2);	float	newmag1,newmag2;	//new vector components in the direction of the normal 		//force acts positively on body 1, new velocity is:	//oldvel + (j/m)	newmag1	=	mag1	+	(force/a->mMass);	newmag2	=	mag2	+	(-force/b->mMass);	a->mVelocity.Dir	=	(*normal * newmag1) + par1;	b->mVelocity.Dir	=	(*normal * newmag2) + par2;}


I suppose if you wanted to know exactly what all of this means in exact detail, you could bug me on aim and i'll be glad to explain it to ya:
OpenGLProgrammer

Otherwise I don't know how much you want/need to know.

EDIT:
and, this is pretty difficult stuff to learn, I just learned it myself

[edited by - shadow12345 on May 21, 2004 8:17:08 PM]

[edited by - shadow12345 on May 22, 2004 1:10:29 AM]
Why don't alcoholics make good calculus teachers?Because they don't know their limits!Oh come on, Newton wasn't THAT smart...
ok i think i know what you mean, but i''ve just tried to implement it but for some reason i can''t get it to work ... this is what i''ve got ... (note: i did it in a lot of steps just so i woudn''t mix myself up)

float force1 = obj1.vx * obj1.mass;
float force2 = obj2.vx * obj2.mass;
float netForce = force1 + force2;
float deltaV = netForce / obj1.mass;
obj1.vx = (obj1.vx * ((obj1.restitution + obj2.restitution) / 2)) * deltaV;


[[ float deltaV = netForce / obj1.mass; ]] ??? which mass should i be dividing by?

[[ obj1.vx = (obj1.vx * ((obj1.restitution + obj2.restitution) / 2)) * deltaV; ]] ??? should i be multiplaying my deltaV or should i be adding it to the new velocity?

thanks for any help in advance ...
if you want to do it properly, it''s more complicated than that Especially when you do body vs. another body, not just body versus floor. You have to take into account the masses of the two objects, the relative velocity at the contact point, their restitution factors, combine all that together to generate an impulse.

Also, doing angular effects will add complications, especially in 3D. you have to learn about inertia, torques, ...

I suggest you have a read through Chris Hecker''s physics articles. You need to have a good understanding of physics (linear and angular momentums, forces, mass, acceleration, inertia, energy, work, velocity, ect... ).

for simplicity, look for the velocity reflection algorithm, which provides a simple physics model, for non-rotating objects (like FPS physics, in Quake clones, or 2D platform games).

Everything is better with Metal.

alright this is what i got now, seems to work pretty good (note: the calculation of restitution and friction is cheated, but works well. also the velocity of each object is done one at a time, so this code is only for one object ... also this is only on the x plane, the code however is the same on the y plane)

float deltaV = obj1.vx - obj2.vx;
float M1 = (-((obj1.restitution + obj2.restitution) / 2) * deltaV) * obj2.mass;
float M2 = (-((obj1.smoothness + obj2.smoothness) / 2) * deltaV) * obj2.mass;
obj1.vx += (M1 + M2) / (obj1.mass + obj2.mass);

just wondering if anyone can see if there is something that is terribly wrong in this method, however i''m not looking for exact precision.

This topic is closed to new replies.

Advertisement