Archived

This topic is now archived and is closed to further replies.

ZiM

Collision response problem again

Recommended Posts

I'm trying to implement collision handling system similar to one described in paper "Real-Time Collision Detection and Response with AABB" by Fabio Policarpo and Alan Watt, which utilizes Leafy BSP tree and AABBs. Right now I'm simply using rays for collision detection. The problem is that my collision loop is extremely unstable, ie. it ends up in infinite loop every now and then even with polygons with axis-aligned normals. Here's is the main collision response loop I'm using, it is similar to one given in the paper:
TraceResult tr;
Vector		dir, r, b, t;
float		len, len_left, normfact;

while(true)
{
	dir = p1 - p0;
	len = dir.Length();

        // If len gets very small the stop the recursion

	if(len < 0.0001)
	{
		gConsole.Printf("ResolveCollisions: len < 0.0001 !!\n");
		break;
	}

	dir.Normalize();
	TraceLine(p0, p1, false, mo, &tr);
	
	if(tr.fraction >= 1.0) // No collisions

		break;

	// Move p0 near the collision point

	p0 = p0 + dir * (len * tr.fraction);

	// Compute reflection vector

	r = dir + tr.plane.normal * (-2.0 * Vector::DotProduct(tr.plane.normal, dir));

	normfact = Vector::DotProduct(tr.plane.normal, r);
	len_left = (p1 - p0).Length();

        // Binormal and tangent vectors to the collision plane

	b = tr.plane.normal * (normfact * len_left);
	t = r * len_left - b;
        // Move the destination point to front of the plane

	p1 = p0 + b*0.05 + t*0.95;
}
return p1;

When a collision is detected, the start point (p0) is moved near the point of collision, destination position (p1) is moved to front of the collision plane. The distance between these points is now remainder of the length we haven't travelled yet because of the collision. Next iteration begins. [edited by - ZiM on October 15, 2003 5:04:27 PM]

Share this post


Link to post
Share on other sites
that should really be in the physics section

I''m not sure I understand this part correctly,

normfact = Vector::DotProduct(tr.plane.normal, r);
len_left = (p1 - p0).Length();
// Binormal and tangent vectors to the collision plane b = tr.plane.normal * (normfact * len_left);

t = r * len_left - b;
// Move the destination point to front of the plane p1 = p0 + b*0.05 + t*0.95;




... So I would have a collision loop like this.



Vector dir = p1 - p0;

if(Vector::DotProduct(dir, dir) < 1e-8)
{
gConsole.Printf("static particle. \n");
return p0;
}

while(true)
{
TraceResult tr;
TraceLine(p0, p1, false, mo, &tr);

// Move p0 near the collision point

p0 = p0 + (p1 - p0) * tr.fraction;

if(tr.fraction == 1.0f) // No collisions

{
gConsole.Printf("No more collisions\n");
break;
}

dir = (p1 - p0);
dir -= 2.0f * tr.plane.normal * (Vector::DotProduct(tr.plane.normal, dir));
p1 = p0 + dir;
}
return p0;



I assume the TraceResult can never return a result outside the range [0.0f, 1.0f].

These kind of loops are very sensitive to thresholds. mayle you want to do

p0 = p0 + (p1 - p0) * (tr.fraction - 0.00001f);

instead of

p0 = p0 + (p1 - p0) * (tr.fraction);

Share this post


Link to post
Share on other sites
OK, I got it now, a simple friction and elasticity




Vector dir = p1 - p0;

if(Vector::DotProduct(dir, dir) < 1e-8)
{
gConsole.Printf("static particle. \n");
return p0;
}

while(true)
{
TraceResult tr;
TraceLine(p0, p1, false, mo, &tr);

// Move p0 near the collision point

p0 = p0 + (p1 - p0) * tr.fraction;

if(tr.fraction == 1.0f) // No collisions

{
gConsole.Printf("No more collisions\n");
return p0;
}

dir = (p1 - p0);
dir_n = tr.plane.normal * (Vector::DotProduct(tr.plane.normal, dir));
dir_t = dir - dir_n;
dir = dir_t * (1.0f - friction) - dir_n * elasticity;

if(Vector::DotProduct(dir, dir) < 1e-8)
{
gConsole.Printf("no more collisions. \n");
return p0;
}
p1 = p0 + dir;
}
return p0;

Share this post


Link to post
Share on other sites
Yes, that's true. Your code looks more clean too I'll give it a try, thanks!

[edited by - ZiM on October 16, 2003 5:11:58 AM]

Share this post


Link to post
Share on other sites