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 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 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);
}
.....

Collision Detection

// BS - BoundingSphere class & Plane- Normal Plane class
bool SpherePlaneIntersection(BS *CricketBall, Plane *CricketGround, Contact *c)
{
c->a = rbBall;
c->b = rbGround;
{
return true;
}
else
return false;
return false;
}

.....

In the Rendering loop code

Contact CBwithCG;
if (SpherePlaneIntersection(cdBall, cdGround, &CBwithCG))
{
if (VerifyTypeOfColliding(&CBwithCG) == Resting)
{
}
else
if (VerifyTypeOfColliding(&CBwithCG) == Collide)
{
CollisionResponse(&CBwithCG, .5f);
}
}
else


Share on other sites

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 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;
}

{
v += Impulse*(1/Mass);
}

{
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 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 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.

Create an account

Register a new account

• What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 15
• 9
• 11
• 9
• 9
• Forum Statistics

• Total Topics
634134
• Total Posts
3015751
×