// 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;
Collision detection method is correct but object shakes when resolution takes place?
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?
Thank you.
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.
Quote:Original post by Erik Rufelt
It happens because of the Epsilon.
I have tried removing the epsilon before and it still does exactly the same thing. Any other thoughts?
What kind of numbers for the distance and position vector do you get when the shaking occurs?
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
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
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?
"distance" is actually the square distance from object position to segment, does that mess up my calculations?
If I have the following:
then the shaking is worse.
This makes the object wrap around the circle (warp from one side to opposite side)?!
If I have the following:
position_Projected += normal * (float)Math.Sqrt(distance);
then the shaking is worse.
Quote:
position_Projected = normal * (radius-epsilon);
This makes the object wrap around the circle (warp from one side to opposite side)?!
Oops! How about:
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)?
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)?
Using your method and hopefully answering your edit questions I get the following working code:
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]
// 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]
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
float temp = sqrt(distance)+sphere_radius;
distance = temp*temp;
and..
// if needs to be repositioned, keep the position + sphere_rad inside radius
position_Projected = center_Segment - normal * (radius-sphere_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:
distance = sqrt(SquareDistance()) + sphere_radius;
if(distance > radius) ..
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement