Collision response - solver, penetration recovery

Please don't post Bullet support questions here, use the above forums instead.
Dirk Gregorius
Posts: 861
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA

Re: Collision response - solver, penetration recovery

Post by Dirk Gregorius »

Hmm, against how many side planes are you clipping? It should be four not two.
Pipirongu
Posts: 10
Joined: Fri Dec 04, 2015 2:48 am

Re: Collision response - solver, penetration recovery

Post by Pipirongu »

Dirk Gregorius wrote:Hmm, against how many side planes are you clipping? It should be four not two.
Yes, it's against four.
Should I clip the incident face vertices first, and then use the resulting points from the first clipping in the second clipping?

Code: Select all

	std::vector<Contact> contacts;
	this->ClipFaceToSidePlane(incident_face, -1 * normal1, neg_offset1, contacts);
	this->ClipFaceToSidePlane(incident_face, normal1, pos_offset1, contacts);
	this->ClipFaceToSidePlane(incident_face, -1 * normal2, neg_offset2, contacts);
	this->ClipFaceToSidePlane(incident_face, normal2, pos_offset2, contacts);

Code: Select all

void RenderScene::ClipFaceToSidePlane(const Vector3* face, const Vector3& normal, float plane_offset, std::vector<Contact> &contacts)
{
	Vector3 Vertex1 = face[3]; //start edge forms from endvertex->startvertex
	float Distance1 = Vector3::Dot(Vertex1, normal) - plane_offset;

	for (int i = 0; i < 4; i++)
	{
		Vector3 Vertex2 = face[i];
		float Distance2 = Vector3::Dot(Vertex2, normal) - plane_offset;

		if (Distance1 <= 0.0f && Distance2 <= 0.0f)
		{
			// Both vertices are behind the plane - keep vertex2
			Contact contact1;
			contact1.position = Vertex2;
			contacts.push_back(contact1);
		}
		else if (Distance1 <= 0.0f && Distance2 > 0.0f)
		{
			// Vertex1 is behind the plane, vertex2 is in front -> intersection point
			float Fraction = Distance1 / (Distance1 - Distance2);
			Vector3 Position = Vertex1 + Fraction * (Vertex2 - Vertex1);

			// Keep intersection point
			Contact contact1;
			contact1.position = Position;
			contacts.push_back(contact1);
		}
		else if (Distance2 <= 0.0f && Distance1 > 0)
		{
			// Vertex2 is behind the plane, vertex1 is in front -> intersection point
			float Fraction = Distance1 / (Distance1 - Distance2);
			Vector3 Position = Vertex1 + Fraction * (Vertex2 - Vertex1);

			// Keep intersection point 
			Contact contact1;
			contact1.position = Position;
			contacts.push_back(contact1);

			// And also keep vertex2
			Contact contact2;
			contact2.position = Vertex2;
			contacts.push_back(contact2);
		}

		// Keep vertex2 as starting vertex for next edge
		Vertex1 = Vertex2;
		Distance1 = Distance2;
	}
}
Pipirongu
Posts: 10
Joined: Fri Dec 04, 2015 2:48 am

Re: Collision response - solver, penetration recovery

Post by Pipirongu »

Okay, so it looks pretty good now. I first clip the incident face vertices and then use the result from the first clipping in the second clipping. I do the same for the other side planes. This also makes sense to me. A point might be behind a sideplane but still needs to be tested on the others. Reminds me of broadphase collision test with sort and sweep.

I still can't stack cubes though. They are stacked for awhile before they slide off. When they start to slide off, I get 5-6 contact points.

This is my solver and I use baumgarte otherwise they will sink into the ground. I'm not sure how iterations(accumulating impulses) work so I have to research more there.
Is warmstart something I should look into as well?

Second picture is when the cubes are sliding off.

Code: Select all

void RenderScene::ProcessContact(Contact* contact, float& Pn, Vector3&vel1, Vector3& ang_vel1, Vector3&vel2, Vector3& ang_vel2)
{
	const float k_allowedPenetration = 0.01f;
	float BAUMGARTE = 0.2f;
	//BAUMGARTE
	float bias = -BAUMGARTE * 1.f/this->physics_timestep * std::min(0.0f, -contact->penetration + k_allowedPenetration);

	RigidBody* ent1 = contact->one;
	RigidBody* ent2 = contact->two;

	const float e = std::min(ent1->restitution, ent2->restitution);
	Vector3 contactPoint = contact->position;
	Vector3 contactNormal = contact->normal;

	Vector3 rA = contactPoint - ent1->position;
	Vector3 rB = contactPoint - ent2->position;
	Vector3 kA = Vector3::Cross(rA, contactNormal);
	Vector3 kB = Vector3::Cross(rB, contactNormal);

	Vector3 uA = ent1->inverse_inertia_tensor_world_space*kA;
	Vector3 uB = ent2->inverse_inertia_tensor_world_space*kB;

	float normalMass = ent1->inverse_mass + ent2->inverse_mass;

	if (!ent1->is_kinematic){
		normalMass += Vector3::Dot(kA, uA);
	}
	if (!ent2->is_kinematic){
		normalMass += Vector3::Dot(kB, uB);
	}

	// Relative velocity at contact
	Vector3 relativeVel = (ent2->velocity + Vector3::Cross(ent2->angular_velocity, rB)) - (ent1->velocity + Vector3::Cross(ent1->angular_velocity, rA));
	float numer = -(1 + e)*Vector3::Dot(relativeVel, contactNormal) + bias;
	float f = numer / normalMass;

	float Pn0 = contact->accumulated_impulse;
	contact->accumulated_impulse = std::fmax(Pn0 + f, 0.0f);
	f = contact->accumulated_impulse - Pn0;

	Vector3 impulse = f*contactNormal;


	contact->one->velocity -= impulse*ent1->inverse_mass;
	contact->two->velocity += impulse*ent2->inverse_mass;
	contact->one->angular_velocity -= f*uA;
	contact->two->angular_velocity += f*uB;
}
Image

Image
Dirk Gregorius
Posts: 861
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA

Re: Collision response - solver, penetration recovery

Post by Dirk Gregorius »

Yes, you clip the clipped polygon with the next planes.

I am not sure about the last picture. Looks wrong to me, but again it is difficult to tell. Try a 45 degrees rotated box and if you get 8 vertices.
Pipirongu
Posts: 10
Joined: Fri Dec 04, 2015 2:48 am

Re: Collision response - solver, penetration recovery

Post by Pipirongu »

Dirk Gregorius wrote:Yes, you clip the clipped polygon with the next planes.

I am not sure about the last picture. Looks wrong to me, but again it is difficult to tell. Try a 45 degrees rotated box and if you get 8 vertices.
Yep, I get 8 vertices.

Image

Image
Dirk Gregorius
Posts: 861
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA

Re: Collision response - solver, penetration recovery

Post by Dirk Gregorius »

Looks good! I would add friction next. :)
Pipirongu
Posts: 10
Joined: Fri Dec 04, 2015 2:48 am

Re: Collision response - solver, penetration recovery

Post by Pipirongu »

Dirk Gregorius wrote:Looks good! I would add friction next. :)
I'll take a look at iterations(accumulating impulses), warmstart and friction.
I can let go of the clipping part for now. Using the clipped polygon for the next clipping make sense to me, thanks Dirk.
Post Reply