energy absorbtion ...
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?
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]
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]
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!
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]
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]
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?
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:
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]
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]
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 ...
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).
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).
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.
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
Popular Topics
Advertisement