Jump to content
  • Advertisement
Sign in to follow this  
VanKurt

RigidBodies: Almost got it!

This topic is 4809 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

Today was a really bad day. I tried to finish my rigid body simulator, which was almost done. But there was one bug I couldn't get rid of. I tried for hours without success...until I got so angry that I started to cry and kick things around my room ;-) So you guys are my last hope! The problem: There's two hovercraft (simple boxes) that can be accelerated and steered. They float around, rotate and do everything you'd expect of a hovercraft :-) The collision detection is also implemented (Thank's, Oliii!!!!): it decides if a collision has occured, calculates the point of collision (one global and two relative to both hovers) and finds the MTD / collisionNormal. So what's missing? Right! Collision response! I've implemented the following function (adapted from "Physics for game developers"):
// This function is called after the bodies collided
// (one vertex hit an edge of the other body)
// colNormal is a vector perpendicular to the edge
// b1 and b2 are the two involved bodies
void ApplyImpulse( CBody *b1, CBody *b2, CVector collisionNormal )
{
	// Calculate the relative velocity
	CVector relativeVelocity;
	CVector tempVec1, tempVec2;
	tempVec1 = b1->velocity + b1->velocityAngular ^ b1->colPoint;
	tempVec2 = b2->velocity + b2->velocityAngular ^ b2->colPoint;
	RotateVector( b1->orientation, tempVec1 );
	RotateVector( b2->orientation, tempVec2 );
	vRelativeVelocity = tempVec1 - tempVec2;

	// Now it's time for the impulse
	float impulse;

	impulse =	(-(1+fCr) * (vRelativeVelocity*vCollisionNormal)) /						
				( (1/b1->mass + 1/b2->mass) +
				(collisionNormal * ( ( (b1->colPoint ^ collisionNormal)/b1->inertia )^b1->colPoint) ) +
				(collisionNormal * ( ( (b2->colPoint ^ collisionNormal)/b2->inertia )^b2->colPoint) ));

	// Apply impulse to bodies (NOTE: angular effects are missing!)					
	b1->velocity += (impulse*vCollisionNormal) / b1->mass;
	b2->velocity -= (impulse*vCollisionNormal) / b2->mass;
}


it is called right after the collision detection stuff. The problem with this function is: it works only in some cases: one hover crashes into the other, they bounce off, rotate accordingly etc. But in other cases (e.g. when I crash into the craft from the other side) the forces are somehow reversed. So insted of bouncing off, they get pulled together, collide again, get pulled together again etc. -> the objects totally freak out! The same is true for rotation: sometimes they rotate in the reverse direction that I'd expect (causing them to get faster and faster...). What could cause this behavior? Is there a wrong sign (+/-) somewhere? Could it be that I calculate the collision-normal in a wrong way? Please tell me everything that comes to your mind! Thank's a lot for your help! (you may save me from commiting suicide ;-))

Share this post


Link to post
Share on other sites
Advertisement
why this?
RotateVector( b1->orientation, tempVec1 );
RotateVector( b2->orientation, tempVec2 );

I suppose r1 and r2 are relative to the centre of gravity of the object. Velocities should be world relative, so no need to rotate.

to make it simpler, you should have r1 and r2 in world coordinates.

this is what I have

n, normal, roughly points from B to A (roughly in the direction (b1->pos - b2->pos)).
r1, r2 are in world coordinates.

Vector r1 = b1->colPoint - b1->position;
Vector r2 = b2->colPoint - b2->position;
Vector v1 = b1->velocity + b1->angularvelocity ^ r1;
Vector v2 = b2->velocity + b2->angularvelocity ^ r2;
Vector v = v1 - v2;

float vn = v * n;
if (vn > 0.0f) return;

float numer = -(1 + cor) * (vn);
float m = b1->inverse_mass + b2->inverse_mass;
float i1 = (((r1 ^ n) * b1->inverseinertia) ^ r1) * n;
float i2 = (((r2 ^ n) * b2->inverseinertia) ^ r2) * n;
float denom = m + i1 + i2;

float j = numer / denom;

Vector jn = j * n;

b1->velocity += jn;
b2->velocity -= jn;
b1->angularvelocity += r1 ^ jn;
b2->angularvelocity -= r2 ^ jn;

Share this post


Link to post
Share on other sites
HumHom...that sounds interesting! Don't got time right now but I'll check out your idea/code this afternoon :-)
Thank's a lot in advance (I've got a good feeling about this) :-D !!
<You're da man, oliii!>

Share this post


Link to post
Share on other sites
Demo download
(You can press SPACE to reset the object's positions!)

Here's a little demo of the project. The hovercraft can be controlled using WSAD and the arrows. Thank's to Oliii's help it's almost working now :-D

But one problem is still left: if you drive too fast the force applied to the hovercraft gets incredible high! => BANG! Everything explodes!
(You got to be realy careful and slow!)

What could cause this strange behavior? Should I simply scale the impulse down by a constant value? (that can't be a good idea!)

Thanks again for your help!!!

[Edited by - VanKurt on June 7, 2005 11:53:44 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by VanKurt

But one problem is still left: if you drive too fast the force applied to the hovercraft gets incredible high! => BANG! Everything explodes!
(You got to be realy careful and slow!) Demo

What could cause this strange behavior? Should I simply scale the impulse down by a constant value? (that can't be a good idea!)

Thanks again for your help!!!


Wow that's a strong collision. Post your impulse code (something like oliii posted). Are you sure your momenta of inertia are correct? For boxes it is MI = Mass * (Width^2 + Height^2) / 12.

Share this post


Link to post
Share on other sites
That shouldn't be the problem because the whole thing works fine without collisions (acceleration, rotation etc.). And when your're slow enough while colliding results seem to be OK, too...


Important for the demo:
You can press SPACE to reset the object's positions! :-)

[Edited by - VanKurt on June 7, 2005 11:58:40 AM]

Share this post


Link to post
Share on other sites
Looking good, almost there. [smile]

Yeah, it looks like your impulse code has a problem... are you sure your collision normal is normalized?

Share this post


Link to post
Share on other sites
Quote:
Looking good, almost there.
Thanks :-D
(hopefully I'll get there...I'd hate to have to give up at this point)

Quote:
are you sure your collision normal is normalized?

Yep, it is (but maybe it's direction is reversed???). I compared my code to oliii's and it seemed to be ok. I'm doing the same calculations but it still doesn't work...ARGH!!!
I also realized that the problem with forces acting in the wrong (inverse) direction is still there... (it only occures in certain situations, very strange...)
More ideas are welcome :-D

Share this post


Link to post
Share on other sites
Here, try it with my code :
p.N is the normal of the collision.


template < class Real >
void Impulse<Real>::process_collisioncontact( RigidBody<Real> & a,
RigidBody<Real>& b,
CollisionPoint<Real> p )
{

const Real e = 1.0;

Vector2<Real> rA = p.P - a.get_pos() ;
Vector2<Real> rB = p.P - b.get_pos() ;

Real kA = rA.perp().dot( p.N );
Real kB = rB.perp().dot( p.N );

Real uA = kA / a.get_inertiatensor() ;
Real uB = kB / b.get_inertiatensor() ;

Real f_numer = - ( 1 + e ) * ( p.N.dot( a.linear_velocity - b.linear_velocity ) + a.angular_velocity * kA - b.angular_velocity * kB );

Real f_denom = ( 1 / a.get_mass() ) + ( 1 / b.get_mass() ) + kA * uA + kB * uB ;

Real f = f_numer / f_denom ;

Vector2<Real> impulse = f * p.N ;

a.linear_momentum += impulse;
b.linear_momentum -= impulse;

a.angular_momentum += f * kA ;
b.angular_momentum -= f * kB ;

a.linear_velocity = a.linear_momentum / a.get_mass() ;
b.linear_velocity = b.linear_momentum / b.get_mass() ;

a.angular_velocity += f * uA;
b.angular_velocity += f * uB;

}




( it can be found in my physics engine project : http://inertia2d.sf.net )

Share this post


Link to post
Share on other sites
Woops, didn't see Oliii already posted something,sry :)

Try to look if the collision normal is always in the good direction .

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!