Trouble with circle collision detection

… well, moreso I don’t know where to go with my code for now.

I’m currently taking an introduction to CG and have an assignment that involves a polygon corral (5 sided) in which a ball bounces. After much effort, I finally got it to work correctly and smoothly (figured out an error with how I used Double Buffering), but now I must manipulate my code so that it inclides 3 interior sphere (well, for my purposes, circles) obstacles upon which the ball must bounce upon. I understand the concept and believed that I had it implemented correctly, but the code does not work as intended, merely passes through the obstacles while continuing to correctly ricochet off the polygon’s inner walls.

Here is the main cpp code. It calls an external class Tigger that does the calculations for dot product, normal, unit normal, etc. as needed by the problem.

/*
Written and designed by Me
This is the OpenGL implementation of the
ball bounce program. 

*/

#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>

#include <math.h>
#include <stdlib.h>
#include <iostream.h>
#include "Tigger.h"



void display(void) {

	float A[2] = { 2.0, 7.0};//point A on boundary of ball
	float B[2] = {12.0, 1.0};//point B on boundary of ball
	float C[2] = {23.0,11.0};//point C on boundary of ball
	float D[2] = { 9.0,20.0};//point D on boundary of ball
	float E[2] = { 1.0,20.0};//point E on boundary of ball

	// Radii of Circle obstacles
	float Radius[3]={ 2.0,  2.5, 2.5 };

	// X Coordinates of Circle obstacles
	float CenterX[3]={ 12.0, 15.0, 5.0 };

	// Y Coordinates of Circle obstacles
	float CenterY[3]={ 5.0, 12.5, 17.5 };


	// Radius of Ball
	float radius=0.125;

	// Coordinates of center of ball
	float center[2] = { 8.0, 11.0 };

	// Velocity vector
	float velocity[2] = { 6.0, 5.0 };

	// Clear the entire display
    glClear( GL_COLOR_BUFFER_BIT );

	

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	float T=0.001;

	while ( T < 100 )
	{
		//Set initial time 

		//Setup distance array for Circle obstacle collision
		float distance[3], x,y;

		// Erase the ball by drawing the surface again
		
		glColor3f( 20.0, 20.0, 20.0 );
		glBegin(GL_POLYGON);
		glVertex3f( 2.0, 7.0, 0.0);
		glVertex3f(12.0, 1.0, 0.0);
		glVertex3f(23.0,11.0, 0.0);
		glVertex3f( 9.0,20.0, 0.0);
		glVertex3f( 1.0,20.0, 0.0);
		glEnd();
		glFlush();

		// Draw the ball (red)
		glColor3f( 1.0, 0.0, 0.0 );
		glPushMatrix();
		glTranslatef(center[0], center[1], 0.0);
		glutSolidSphere( radius, 25, 25);
		glPopMatrix();

		// Make sure the ball has been displayed
		glFlush();

		// Circle Obstacle 1
		glColor3f( 0.0, 2.0, 0.0 );
		glPushMatrix();
		glTranslatef( CenterX[0], CenterY[0], 1.0 );
		glutSolidSphere( Radius[0], 25, 25);
		glPopMatrix();
		glFlush();

		// Circle Obstacle 2
		glColor3f( 0.0, 2.0, 0.0 );
		glPushMatrix();
		glTranslatef( CenterX[1], CenterY[1], 2.0 );
		glutSolidSphere( Radius[1], 25, 25);
		glPopMatrix();
		glFlush();

		// Circle Obstacle 3
		glColor3f( 0.0, 2.0, 0.0 );
		glPushMatrix();
		glTranslatef( CenterX[2], CenterY[2], 2.0 );
		glutSolidSphere( Radius[2], 25, 25);
		glPopMatrix();
		glFlush();
	    


		// Slow the simulation down
		//Sleep( 0.00003 );
		
		// Set up Ball object through external class Tigger
		// This does computations for new CENTER and VELOCITY
		Tigger Ball(center,velocity);


		// Find current distance from each Circle obstacle
		for (int i=0; i<3; i++) {
			x = (CenterX[i]-center[0]);
			y = (CenterY[i]-center[1]);
			distance[i] = sqrt( (x*x) + (y*y) );
		}

		//What happens when an obstacle impact occurs
		if (distance[0]==Radius[0]){
			Ball.normC(CenterX[0],CenterY[0]);

			// Calculate Bounce Velocity
			velocity[0]=Ball.newVx();
			velocity[1]=Ball.newVy();

			// Calculate Bounce center
			center[0]=Ball.newCx();
			center[1]=Ball.newCy();
		}

		else if (distance[1]==Radius[1]){
			Ball.normC(CenterX[1],CenterY[1]);

			// Calculate Bounce Velocity
			velocity[0]=Ball.newVx();
			velocity[1]=Ball.newVy();

			// Calculate Bounce center
			center[0]=Ball.newCx();
			center[1]=Ball.newCy();
		}

		else if (distance[2]==Radius[2]){
			Ball.normC(CenterX[2],CenterY[2]);

			// Calculate Bounce Velocity
			velocity[0]=Ball.newVx();
			velocity[1]=Ball.newVy();

			// Calculate Bounce center
			center[0]=Ball.newCx();
			center[1]=Ball.newCy();
		}

		

		// What happens when a perimeter impact occurs
		else if (T==Ball.Time(A,B,C,D,E))
		{
			// Calculate Bounce Velocity
			velocity[0]=Ball.newVx();
			velocity[1]=Ball.newVy();

			// Calculate Bounce center
			center[0]=Ball.newCx();
			center[1]=Ball.newCy();
			
			T=0.001;
		}
		else
		{
			// Calculate the new center
			center[0] += (velocity[0]*(T));
			center[1] += (velocity[1]*(T));
		}
		
		glutSwapBuffers();
	}
	
}

void
main(int argc, char **argv) {

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(100,100);
	glutInitWindowSize(600,600);
	glutCreateWindow("Sphere In Irregular Pentagon");
	glClearColor( 20.0, 0.0, 0.0, 0.0 );
	glOrtho(0,25,0,25,-1,1);
	glutDisplayFunc(display);
	glutMainLoop();
}

If it helps, I’ll describe what I tried to do. My problem is set up that I start with a Ball of given center and velocity vector enclosed within the pentagon. What I did to get it to bounce is set up a while loop of infinity (while (1) ), in which the scene iterates by .001 seconds. I find the minimum time the ball will take to hit a surface (thus, the smallest non negatively timed surface collision) and have it reflect off that surface, else just increment the center by velocity times time ( C += V*T ).

For circle detection, established that for a collision to occur, the ball must be Radius distance from the center of the obstacle, and say that if at the given time in the loop that distance equals the radius of the obstacle, reflect, with the normal being the line from the center of the obstacle through the point of contact on the circumference. I am assuming that the way I impliment my code prevents me from being able to use the distance as a proof when the time is the variable, but if I prove according to Time, I would have 2 uknowns: Time and the position of the Hit, and I can’t seem to work with that right now.

Also, can someone help me use my code successfully using an glutIdleFunc() rather than the while loop?

Thanks alot in advance.

From a quick glance at your code, the problem is that your collision test only triggers when the spheres exactly touch, but ignores any overlapping.

You’re working with discrete time increments, so while in one frame the moving sphere doesn’t touch any object yet, in the next frame it might already be nearer to one of the obstacle spheres than it is allowed to.

Your test should probably look more like

  if (distance[0] < radius[0]) { ... } ...

Thanks, that helped a little, in terms of the logic behind the problem. However, the results are similar to implementing it without the case of if the object already penetrates the obstacles (I had assumed before, since the ball was moving in increments of time, that there would be a distance of hit where the distance and radius were equal and therefore caught the problem of it penetrating before). What occurs now is the same error I had once had when I initially tackled this assignment, where the ball somehow escaped from the pentagon it was bouncing in, and instead bounced along the extended lines of the pentagon (my setup for time in the Tigger class uses a minimum time of impact of the object with all of the lines involved in the perimeter it bounces within, and found that float numbers were cumbersome and thus created a function that rounded to the nearest thousandth rather than the float’s hundred thousandth) outside of the pentagon itself.

Is there a better way to test collision, one that would involve the time rather than distance, since I test for time in the polygon/ball collision?