# Collision detection method is correct but object shakes when resolution takes place?

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

## Recommended Posts

Hello folks, I have the following algorithm that works out how far an object is from a line segment whilst keeping the object inside a certain radius at all times. The problem is that when I am resolving the position of the object it will visibly shake. This occurs when it is at the outmost limit of the allowed distance from the closest point on the segement (i.e. > radius). What have I done wrong here?
            // Set projected position to current object position
Vector3 position_Projected = debug_Polygon[0].Position;

// Get key presses this frame
if (InputState.Global.IsKeyDown(Keys.Left))
{
position_Projected = debug_Polygon[0].Position + new Vector3(-0.005f, 0, 0);
}
if (InputState.Global.IsKeyDown(Keys.Right))
{
position_Projected = debug_Polygon[0].Position + new Vector3(0.005f, 0, 0);
}
if (InputState.Global.IsKeyDown(Keys.Down))
{
position_Projected = debug_Polygon[0].Position + new Vector3(0, -0.005f, 0);
}
if (InputState.Global.IsKeyDown(Keys.Up))
{
position_Projected = debug_Polygon[0].Position + new Vector3(0, 0.005f, 0);
}

// Find the distance between the object and the nearest point on the segment
float distance = debug_Segment.SquareDistanceToPoint(position_Projected);

// If the object is outside the radius
if (distance > 2.0f)
{
// Calculate penetration depth
distance -= 2.0f;

// Compute the closest point on the segement to the projected position
Vector3 center_Segment = debug_Segment.ClosestPtPointSegment(position_Projected);

// Calculate the normal based on the closest point on segment to object's position
Vector3 normal = center_Segment - position_Projected;
normal.Normalize();

// Distance can also be found with normal (when it isn't normalized)
//Console.WriteLine("Distance " + normal.LengthSquared());

position_Projected += normal * (distance /* - radius_BoundingSphere */ - GameConstants.EPSILON);
}

// Update object's position with final projected position (doesn't change if key isn't pressed)
debug_Polygon[0].Position = position_Projected;


Thank you.

##### Share on other sites
It happens because of the Epsilon. In this case you should be able to remove it, if you only want to stay within a sphere. It's only necessary when you want the player to be able to be on both sides of a surface, to make sure he doesn't accidentally go through it. Staying within a sphere should be achievable by just setting distance to the radius whenever it's larger, and moving that distance in the direction of the endpoint.

##### Share on other sites
Quote:
 Original post by Erik RufeltIt happens because of the Epsilon.

I have tried removing the epsilon before and it still does exactly the same thing. Any other thoughts?

##### Share on other sites
What kind of numbers for the distance and position vector do you get when the shaking occurs?

##### Share on other sites
Distance (penetration depth): 0.009919167
Object position: {X:-1.412716 Y:0 Z:0}
Projected position: {X:-1.407797 Y:0 Z:0}

Distance (penetration depth): 0.01014829
Object position: {X:-1.412797 Y:0 Z:0}
Projected position: {X:-1.407649 Y:0 Z:0}

Distance (penetration depth): 0.006502628
Object position: {X:-1.411511 Y:0 Z:0}
Projected position: {X:-1.410008 Y:0 Z:0}

EDIT:

Theses are some distances from the segment to the new projected point, shouldn't they be dead on 2?

1.997116
1.979426
1.986003
1.999779

##### Share on other sites
Quote:
 shouldn't they be dead on 2?

I don't see why they should. The line
if( distance > 2 ) distance -= 2;

could result in any value of distance, depending on the initial value.

If you want to keep the object inside the radius "at all times," why not:
position_Projected = normal * (radius-epsilon);

Also, you use "SquareDistanceToPoint." Is "distance" the actual penetration depth or the square of the penetration depth?

##### Share on other sites
"distance" is actually the square distance from object position to segment, does that mess up my calculations?

If I have the following:

position_Projected += normal * (float)Math.Sqrt(distance);

then the shaking is worse.

Quote:

This makes the object wrap around the circle (warp from one side to opposite side)?!

##### Share on other sites
position_Projected = center_Segment - normal*(radius-epsilon);

EDIT: which, actually, is what Erik suggested. Since your test is distance > 2 rather than distance => 2, you can leave the epsilon out (as Erik said).
EDIT2: By the way, are you using a radius of sqrt(2)?

##### Share on other sites

            // Find the distance between the object and the nearest point on the segment            float distance = debug_Segment.SquareDistanceToPoint(position_Projected);            float radius = 2.0f;            float radius_Squared = radius * radius;            // If the object is outside the radius (> instead of >= means I don't have to use an Epsilon)            if (distance > radius_Squared)            {                                // Compute the closest point on the segement to the projected position                Vector3 center_Segment = debug_Segment.ClosestPtPointSegment(position_Projected);                // Calculate the normal based on the closest point on segment to object's position                Vector3 normal = center_Segment - position_Projected;                normal.Normalize();                // Distance can also be found with normal (when it isn't normalized)                //Console.WriteLine("Distance " + normal.LengthSquared());                position_Projected = center_Segment - normal * radius;            }

If this is what Erik was getting at then apologies to Erik for me being a bit slow on the uptake.

The line:

position_Projected = center_Segment - normal * radius;

is much simpler than my:

projectedPosition -= normal * (distance - radius - GameConstants.EPSILON);

option.

However, if I were to make the point a bounding sphere, how would I take into account the extra radius of the sphere?

Thank you.

EDIT: Misspelled Erik's name!

[Edited by - Spa8nky on October 15, 2009 6:17:47 PM]

##### Share on other sites
Quote:
 if I were to make the point a bounding sphere..

If you mean to keep a bounding sphere inside the radius as you did a point, and assuming position_Projected is the center of that sphere (similar to your existing code):

float distance = debug_Segment.SquareDistanceToPoint(position_Projected);
// account for distance from pos_projected to outer edge of sphere
distance = temp*temp;

and..

// if needs to be repositioned, keep the position + sphere_rad inside radius

However, if you were avoiding the sqrt() for efficiency (which was a good idea), you would have to use a sqrt() anyway now. So you could change your code:

1. 1
2. 2
Rutin
19
3. 3
4. 4
5. 5

• 14
• 12
• 9
• 12
• 37
• ### Forum Statistics

• Total Topics
631426
• Total Posts
3000019
×