Sign in to follow this  
MrPickle

Circle at rest on a line

Recommended Posts

I have written the code below that works out if a circle is touching a line and if so it "bounces" the circle, it works fine except I'm having trouble removing a couple of bugs. When the circle is at rest, it slowly sinks through the line. I can prevent this by subtracting the "gravity" but this means the circle doesn't slide down the line, it just remains stationary. After some research I found that the velocity's y component was constantly fluctuating between ±2x10-8 before slowly increasing and hence sinking through the line. If the line has a very shallow gradient (about -70 < gradient < 70) the collision doesn't register. Every frame the gravity is added to the velocity.
Line l; /* this is just a struct holding two vectors and a function to work out the normal */
float length = velocity.length();

Vector3 n = l.normal(); /* the normal to the line */
Vector3 p = position - (n * radius); /* the closest point to the line on the circumference of the circle */

Vector3 line_dir = l.points[1] - l.points[0]; /* the direction of the line */

float tolerance = 1.0f * (floor(length) == 0 ? 1 : fabs(length));

/* First check if the line is horizontal or vertical to avoid divisions by 0 */
if(line_dir.x == 0) /* vertical line */
{
	float x = p.x, lx = l.points[0].x;
	if((lx > x && x + tolerance >= lx) || (lx < x && lx + tolerance >= x))
	{
		velocity = (velocity - (n * (2 * (dot_product(velocity, n))))) * elasticity;
		return true;
	}
	return false;
}
else if(line_dir.y == 0) /* horizontal line */
{
	float y = p.y, ly = l.points[0].y;
	if((ly > y && y + tolerance >= ly) || (ly < y && ly + tolerance >= y))
	{
		velocity = (velocity - (n * (2 * (dot_product(velocity, n))))) * elasticity;
		return true;
	}
	return false;
}
else
{
	float tx = (p.x - l.points[0].x) / line_dir.x;
	float ty = (p.y - l.points[0].y) / line_dir.y;
	tolerance /= 100;
	
	if((tx > ty && ty + tolerance >= tx) || (ty > tx && tx + tolerance >= ty))
	{
		velocity = (velocity - (n * (2 * (dot_product(velocity, n))))) * elasticity;
		return true;
	}
}

return false;






I have tried increasing and decreasing the tolerance but this didn't work. I don't know what else to try. Thanks (: [Edited by - MrPickle on April 26, 2010 12:34:10 PM]

Share this post


Link to post
Share on other sites
The easiest solution is to move your circle's position too. I.e., if the circle is slightly below the line, bounce it and set its height to the line's height plus the circle's radius.

In the event of a slant-y line, you can use the same process, except setting your circle's position differently. To the latter, my recommendation:
-Find a perpendicular line through the circle's center
-Find where the two lines meet (this is where your circle ought to touch the line). Call it "A".
-Find the normalized vector from A to your circle's center. Scale this vector by your circle's radius. Call this vector v.
-Set the circle's new position to be "A" + v.

-G

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this