Advertisement Jump to content
isu diss

3D Rigidbody Dynamics - Collision Response Problem

Recommended Posts

This post is about continuation of https://www.gamedev.net/forums/topic/699032-3d-rigidbody-simulation/. I have setup the Collision Detection and Collision Response for the cricket ball. But the ball doesn't bounce off the ground. After a bit of debugging, I've found that the impulse, generated when the ball bounces off the ground is very small. What should I do to make this right(right impulse)?

Rigidbody.cpp

XMVECTOR RigidBody::GetVelocityAtPoint(XMVECTOR p)
{
	return (v + XMVector3Cross(Omega, (p - x)));
}

XMMATRIX RigidBody::GetIInverse()
{
	return IInverse;
}
......

CollisionResponse.cpp

enum CollidingType
{
	None = -1,
	MoveAway = 0,
	Resting = 1,
	Collide = 2
};

struct Contact
{
	RigidBody	*a, *b;
	XMVECTOR	p, n;
};

CollidingType VerifyTypeOfColliding(Contact *c)
{
	XMVECTOR padot = c->a->GetVelocityAtPoint(c->p);
	XMVECTOR pbdot = c->b->GetVelocityAtPoint(c->p);
	XMVECTOR vrel = XMVector3Dot(c->n, (padot - pbdot));

	if (vrel.m128_f32[0] > 0)
		return MoveAway;
	else
	if (vrel.m128_f32[0] == 0)
		return Resting;
	else
	if (vrel.m128_f32[0] < 0)
		return Collide;
	return None;
}

void CollisionResponse(Contact *c, float epsilon)
{
	XMVECTOR padot = c->a->GetVelocityAtPoint(c->p);
	XMVECTOR pbdot = c->b->GetVelocityAtPoint(c->p);
	XMVECTOR n = c->n;
	XMVECTOR ra = (c->p - c->a->GetPosition());
	XMVECTOR rb = (c->p - c->b->GetPosition());
	XMVECTOR vrel = XMVector3Dot(c->n, (padot - pbdot));
	float numerator = (-(1 + epsilon)*vrel.m128_f32[0]);
	float term1 = (1 / c->a->GetMass());
	float term2 = (1 / c->b->GetMass());
	XMVECTOR term3 = XMVector3Dot(c->n, XMVector3Cross(XMVector4Transform(XMVector3Cross(ra, n), c->a->GetIInverse()), ra));
	XMVECTOR term4 = XMVector3Dot(c->n, XMVector3Cross(XMVector4Transform(XMVector3Cross(rb, n), c->b->GetIInverse()), rb));
	float j = (numerator / (term1 + term2 + term3.m128_f32[0] + term4.m128_f32[0]));
	XMVECTOR f = (j*n);
	c->a->AddForce(f);
	c->b->AddForce(-f);
	c->a->AddTorque(XMVector3Cross(ra, f));
	c->b->AddTorque(-XMVector3Cross(rb, f));
}
.....
      
Collision Detection
      
// BS - BoundingSphere class & Plane- Normal Plane class
bool SpherePlaneIntersection(BS *CricketBall, Plane *CricketGround, Contact *c)
{
	float dist = XMVector3Dot(XMLoadFloat3(&CricketBall->GetCenter()), XMLoadFloat3(&CricketGround->GetNormal())).m128_f32[0] - CricketGround->GetOffset();
	c->a = rbBall;
	c->b = rbGround;
	if ((dist) <= CricketBall->GetRadius())
	{
		c->n =  XMLoadFloat3(&CricketGround->GetNormal());
		c->p = XMLoadFloat3(&CricketBall->GetCenter()) - dist * XMLoadFloat3(&CricketGround->GetNormal());
		return true;
	}
	else
		return false;
	return false;
}     
   
  .....
      
    In the Rendering loop code 
      
	Contact CBwithCG;
	if (SpherePlaneIntersection(cdBall, cdGround, &CBwithCG))
	{
		if (VerifyTypeOfColliding(&CBwithCG) == Resting)
		{
			rbBall->AddForce(XMVectorSet(0, CB_Mass*g, 0, 0));
		}
		else
		if (VerifyTypeOfColliding(&CBwithCG) == Collide)
		{
			CollisionResponse(&CBwithCG, .5f);
		}
	}
	else
		rbBall->AddForce(XMVectorSet(0, -CB_Mass*g, 0, 0));     
      

 

Share this post


Link to post
Share on other sites
Advertisement

Hi isu_diss,

Your impulse computation looks correct to me, but I am suspicious of the way you are applying it. The equations you are using compute an impulse, which is a change in momentum.

Momentum = mass * velocity. To apply impulse, you do: newVelocity = velocity + impulse * inverseMass

You are using functions labeled AddForce and AddTorque. If you are actually adding force, you would be modifying acceleration instead of velocity. This is not correct when using an impulse to resolve collision. I am not sure if you mixed up terminology and correctly implemented the impulse application, or are accidentally using it like a force.

If you are using it like a force (modifying acceleration), try using it like I described above, and hopefully it will resolve your issue. This would definitely result in impulses having less impact than expected.

Max

Share this post


Link to post
Share on other sites

Here's the code of rigidbody.cpp I added a function addimpulse as you told me. when I multiplied f in the collisionresponse function by 1000. suddenly the ball started to bounce off the ground.

void RigidBody::AddForce(XMVECTOR Force)
{
	F_Total += Force;
}

void RigidBody::AddImpulse(XMVECTOR Impulse)
{
	v += Impulse*(1/Mass);
}

void RigidBody::AddTorque(XMVECTOR Torque)
{
	Tau_Total += Torque;
}

void RigidBody::Update(float h)
{
	x += h*v;
	v += h*(F_Total/Mass);
	XMVECTOR Omegaq = XMQuaternionMultiply(q, XMVectorSet(Omega.m128_f32[0], Omega.m128_f32[1], Omega.m128_f32[2], 0));
	q += 0.5f*h*Omegaq;
	L += h*Tau_Total;
	q = XMQuaternionNormalize(q);
	R = XMMatrixRotationQuaternion(q);
	IInverse = XMMatrixMultiply(XMMatrixTranspose(R), IBodyInverse);
	IInverse = XMMatrixMultiply(IInverse, R);
	Omega = XMVector4Transform(L, IInverse);
	F_Total = XMVectorSet(0, 0, 0, 0);
	Tau_Total = XMVectorSet(0, 0, 0, 0);
}

Is it because I consider one collision point?

Edited by isu diss

Share this post


Link to post
Share on other sites

I'm going to make a small off topic recommendation to you @isu diss, stop using single letter variables and non-descriptive variables.  What is F_Total?  What is R, h, L, etc.  And what is IInverse?  You seem to have a very inconsistent naming convention also.  You stand a strong chance of hating yourself down the road when you return to this code in a few months.  Name your variables so they make sense, F_Total (making a guess here) becomes Total_Force (reads better).  Auto complete exists, it's typically pretty efficient too.

Share this post


Link to post
Share on other sites

Thank you very much for your suggestion @maxwhitehead. I fixed the problem, Now it's working as I expected. There was a problem with the way I handle rigid bodies, I was considering the ground as a rigid body with large mass. That way, term4 of collision response goes to a large value, making the impulse so small.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

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

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!