# How do I stop sinking and sliding objects?

## Recommended Posts

Some objects don't penetrate the ground, some does. why? How can I fix that?


void Manifold::ApplyImpulse( float dt )
{

for(int i = 0; i < contact_count; ++i)
{
XMVECTOR p = XMVectorSet(contacts[i].x,contacts[i].y,contacts[i].z, 1.0f);

XMVECTOR padot = A->GetVelocityAtPoint(p);
XMVECTOR pbdot = B->GetVelocityAtPoint(p);

XMVECTOR n = normal;
XMVECTOR ra = (p - A->GetPosition());
XMVECTOR rb = (p - B->GetPosition());

float term1 =  A->GetMass()>0.0f ? (1.0f / A->GetMass()) : 0.0f;
float term2 =  B->GetMass()>0.0f ? (1.0f / B->GetMass()) : 0.0f;
float invdt = dt>0.0f ? (1/dt) : 0.0f;

// Add constraint error to the velocity constraint.
float C = min(0.0f, penetration + 0.015f);
float velocityBias = 0.0f;

velocityBias += -invdt * C *.1f;

// Compute normal mass.
XMVECTOR rnA = XMVector3Cross(ra, n);
XMVECTOR rnB = XMVector3Cross(rb, n);

float K = term1 + term2 + XMVector3Dot(rnA, XMVector4Transform(rnA, A->GetIInverse())).m128_f32[0] + XMVector3Dot(rnB, XMVector4Transform(rnB, B->GetIInverse())).m128_f32[0];
float invK = K > 0.0f ? 1.0f / K : 0.0f;

XMVECTOR dv = padot  - pbdot;
float Cdot = XMVector3Dot(dv, n).m128_f32[0];
//if (Cdot < -1.0f)
{
velocityBias += -e * Cdot;
}
float impulse = -invK * (Cdot - velocityBias);
XMVECTOR P = 1.17f*impulse * n;

/*
tangent[0] = XMVector3Orthogonal(n);
tangent[1] = XMVector3Cross(tangent[0], n);;

// Add friction constraints.
{
pbdot = B->GetVelocityAtPoint(p);

ra = (p - A->GetPosition());
rb = (p - B->GetPosition());

XMVECTOR rt1A = XMVector3Cross(ra, tangent[0]);
XMVECTOR rt1B = XMVector3Cross(rb, tangent[0]);

XMVECTOR rt2A = XMVector3Cross(ra, tangent[1]);
XMVECTOR rt2B = XMVector3Cross(rb, tangent[1]);

float K1 =	term1 + term2 + XMVector3Dot(rt1A, XMVector4Transform(rt1A, A->GetIInverse())).m128_f32[0] + XMVector3Dot(rt1B, XMVector4Transform(rt1B, B->GetIInverse())).m128_f32[0];
float K2 = 	term1 + term2 + XMVector3Dot(rt2A, XMVector4Transform(rt2A, A->GetIInverse())).m128_f32[0] + XMVector3Dot(rt2B, XMVector4Transform(rt2B, B->GetIInverse())).m128_f32[0];

tangentMasses[0] = K1 > 0.0f ? 1.0f / K1 : 0.0f;
tangentMasses[1] = K2 > 0.0f ? 1.0f / K2 : 0.0f;
}

// Solve tangent constraints.
for (int j = 0; j < 2; ++j)
{
float hi = sf * impulse;
float lo = -hi;

dv = padot  - pbdot;
Cdot = XMVector3Dot(tangent[j], dv).m128_f32[0];

float timpulse = -tangentMasses[j] * Cdot;

P = timpulse * tangent[j];

}*/

}
}

I had to multiply impulse by 1.17f to get bounciness. why?

I have attached two videos. with and without the tangent code (^^^^^ the code I have commented out)

with the tangent code all objects start to slide. why?

1st video >> with full apply impulse code

2nd video >> w/o tangent code

##### Share on other sites

Are you solving one contact point? By looking at your stuff I don't think so...

If that's the case, there are some bugs in your code, which is common for a newbie. Some fixes:

1. Your code is using the relative velocity at each iteration to compute the velocity bias. This is wrong. You should only use the initial relative velocity to compute the velocity bias.

2. Your code is multiplying the impulse vector by some scalar. This is called relaxation. This is not necessary. You're already adding the restitution to the velocity constraint if it falls bellow a threshold (-1). So no need to scale it up.

3. Your code is not warm starting the solver (applying the cached impulses)

4. You code is not accumulating the impulses. Neither it is clamping the new accumulated impulses.

Then there can be a sign problem. If the contact normal always point from body A to body B (which is a good idea) then the velocity constraint is as such:

float32 Cdot = b3Dot(vB - vA, m_normal);

float32 impulse = -m_invK * (Cdot + m_velocityBias);

b3Vec3 PA = -impulse * m_normal;

b3Vec3 PB = -PA;

// Apply impulses to bodies

Your code should look something along these lines (pseudo):

void Contact::InitializeVelocityConstraints()
{
// Evaluate C
// Compute velocity bias
// Compute effective mass
}

void Contact::WarmStart()
{
// Apply accumulated impulses
}

void Contact::SolveVelocityConstraints()
{
// Compute Cdot
// Compute impulse
// Accumulate and clamp impulses
// Apply impulses
}

Then a simple simulation loop could be something like this:

GenerateContacts();

IntegrateVelocities();

for each contact c
c->InitializeVelocityConstraints();
c->WarmStart();

for each iteration
for each contact c
c->SolveVelocityConstraints();

IntegratePositions();

If you do the math you will realize that initializing and solving contact velocity constraints this way is equivalent to formulating a linear system (actually an LCP) and iteratively solving it using Projected Gauss Seidel.

As I said in an earlier post, you should port exactly the solver code that is in whatever reliable engine using sequential impulses. I recommend Bounce Lite's because that is the solver you're trying to implement. Don't play around with alternatives. Unless you're solving a sphere on a plane, which is what I recoomended earlier. In this case you need only one impulse to bring the relative velocity at the contact point to a target value and don't need impulse caching at all.

##### Share on other sites

I'm solving multiple contacts(4) at once. Your post is really helpful. Thank you sir. I'm still following randy's impulse engine. 'cos it's easy.

##### Share on other sites

I changed from impulse engine to box2d lite. still I'm dealing with weird motions.

Arbiter.cpp

Arbiter.h

World.cpp

World.h

##### Share on other sites

As I told you before. Debug it!

##### Share on other sites

Tangential (unintentional) question: who is seeing the videos? Not showing up for me. (Chrome)

Edited by Mosker

##### Share on other sites

Don't expect us to debug the code for you.

The best we can do is sharing information and some code.

Debug draw everything you can!

This can be done by defining a simple global draw interface variable that you can call anywhere in your library.

Draw the boxes
Draw the SAT features
Draw the Sutherland Hodgman Clipping polygon
Draw the contact points, normals, and tangents

Make a testbed. Each test draws something different.

The videos above are not showing up for me too. Put them on YT and share as a private link!

##### Share on other sites

I'm sorry for the videos. I'm sorry @Irlan Robson@Dirk Gregorius. Here's the latest video. Pls I'm just asking you to look at my code(below arbiter.cpp/h above world.cpp/h) and tell me what's wrong. As far as I know, friction is at work, since ball deviates.

Edited by isu diss

##### Share on other sites

Arbiter.h

Fine AFAIK

Arbiter.cpp

Collision detection and contact creation code difficult to read due to DXMATH and likely bugged.

Suggestion is to do spheres on a plane.

Line 379:

// accumulate Impulses
XMVECTOR P = c->Pn * n + c->Pt * tangent[1];

Should be

// apply impulses
XMVECTOR P = c->Pn * n + c->Pt1 * tangent[0] + C->Pt2 * tangent[1];

There should be two impulses per contact point. One for each tangential direction (simply).

World.h

Fine AFAIK

World.cpp

Seems good

The videos are still not showing up. Your posts are becoming a great mess. Use YouTube!

##### Share on other sites

Thank you sir @Irlan Robsonfor looking at my code. download the video and play if you don't mind.

## 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

• ### Game Developer Survey

We are looking for qualified game developers to participate in a 10-minute online survey. Qualified participants will be offered a \$15 incentive for your time and insights. Click here to start!

• 12
• 14
• 10
• 33
• 23