Intersecting a plane, precision problems

This topic is 4836 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

This has really got me stuck. This is for moving sphere collision response, and the problem happens when the sphere is moving almost parallel with the triangle's plane (brushing against it). This is how I determine where the sphere will intersect the triangle plane:
FLOAT plane_dot = DOT( TriangleNormal, MovingDirection );
// plane_dot is now -0.000017070566

// Only concerned if moving toward triangle facing
if( plane_dot is > 0.0f )
return NoCollsion;

// do something else if moving completely parallel with plane
if( plane_dot > -0.000001f )

// Get the distance from sphere start point to triangle plane (it's negative)
FLOAT dist_to_plane = DOT( TriangleNormal, VertexA - SphereStart );

// Add radius (really subtracting radius, since distance is neg)
dist_to_plane += SphereRadius; // in the situation I'm testing, dist_to_plane is now -0.0000038146973

// Convert this to the distance on the sphere moving line where it intersects the plane
FLOAT dist_on_sphere_line = dist_to_plane / plane_dot;

// dist_on_sphere_line is now 0.22346635, which is too high


Just a tiny bit of precision error before the dist_to_plane / plane_dot will cause massive differences in the final distance, because the numbers are so tiny. If I move the sphere from the sphere start point through the movement direction multiplied by dist_on_sphere_line, it is inside of the triangle plane. This is really bad. How low of a number (on plane_dot) should I consider parallel? If I use too high of a number, assuming the movement is exactly parallel may allow the sphere to move inside of the triangle, especially moving over a large distance on the plane of the triangle. Does anyone know of a better way to do this? Perhaps another way to compute the intersect point if plane_dot is so close to zero? Or just another way entirely? That final divide by the tiny numbers is what is screwing me, but I don't know another way to do this. Thanks for any help [smile] [Edited by - Jiia on November 24, 2004 6:33:29 PM]

Share on other sites
You have a precision problem. Single precision floats have only about 7 digits of precision. So when operating in the range of [-1,1], almost all of the bits in a number as small as 0.000001 are going to be garbage.

You have several choices (some better than others):
1. Use double precision.
2. Use a much larger cutoff value.
3. Reorder calculations to avoid multiplyig or dividing by the difference of two nearly-identical numbers.
4. Rather than determining where/when the intersection will happen, check each frame to see if the intersection happens in that frame.

Try a cutoff value of .001 instead. That will give you many more bits to work with and the sphere's direction is still very close to parallel at that value.

[Edited by - JohnBolton on November 25, 2004 2:36:07 AM]

Share on other sites
if you have a known timestep, you can use that as the basis for the comparison, instead of solving for t explicitly.

t = some_constant / DOT( TriangleNormal, MovingDirection );
if (t > dt)...

you could say:
if (dt * DOT( TriangleNormal, MovingDirection ) > some_constant)
...

this works for things like collision detection, but not for ray tracers.

Share on other sites
Well, I am only checking every frame. But if the framerate is low, time between frames is high. And the distance of movement increases.

lonesock: I need the distance to the plane in the movement direction. Is there a way to get it another way?

I ended up using a cutoff of -0.0001. I then pull the intersect point back by about 0.005, which so far has eliminated the problems.

I appreciate the help [smile]