Please Help - Simple collision detection problem

Started by
29 comments, last by LostBoy 21 years, 6 months ago
I cannot find a specific example of what I need to do. I simply need to test to see if my sphere touches a line. All of the examples that I can find deal with spheres coliding with polygons or polygons with polygons. The reason that I need to do it with lines is because I have bound my area with lines. Thanks JC
Advertisement
I''m not 100% sure, but didn''t gametutorials (www.gametutorials.com) have a sphere-line collision example?

Hope this helps,
Crispy
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared
Horizontal/Verticle lines?

X + Radius <= Line X then they are touching. etc etc.

If the lines are on an angle... that gets complicated.
Hmm... Just thinking from the top of my head...
*head explodes*

Hm.... actually, you could convert the x&y values to polar, add at the angle that the line is at and then check it the same way, ya?

*hopes hes not wrong*
Once you have the equation of the line, you can compute the distance between any point and the line.
Get the distance between the line and the center of the sphere (the center being a point obviously), and if this distance is inferior than the radius of the sphere : collision happens.
Does anyone have any code examples ? What throws me for a loop is that I draw my sphere the way that NEHE does in one of his tuts, but then I see it being done differently in other tuts. Maybe there are different methods for different situations, but if possible I''m trying to stick to one way.

I don''t need to know the reactions that the ball would have if it did hit. I just need help with the ball touching the line which surounds my mini golf course. I can figure out the if statements.

Thanks guys

JC
By "line" you mean a "wall" in fact, isn''t it ?

How is represented your "line" in your code ? Is it a couple of 2D points ? Is it the equation ax+by+c=0 ? Is it something else ?
I think it goes something like this (might be wrong):

BOOL line_and_sphere(POINT p1, POINT p2, POINT sphere, float radius)
{
float v, d;
VECTOR EO, ray;

EO=make_vector(p1, sphere);
ray=make_vector(p1, p2);

v=dot(EO, ray);

if (v<0) return FALSE;
d=radius*radius-(dot(EO,EO)-v*v);

if (d<0)
return FALSE;
else
{
d=v-sqrt(d);
if (d>lenght(ray)) return FALSE;
}

return TRUE;
}
And if you have the Cartesian equation as ax+by+c=0, you can do :


  bool intersect_sphere_line(float center_x, float center_y, float radius, float a, float b, float c){  float sqr_norm = a*a+b*b; // compute (a²+b²)  if (sqr_norm==0) return c==0;  else  {    float dot_prod = a*center_x+b*center_y; // compute ax+by+c    float sqr_dot = dot_prod*dot_prod; // compute (ax+by+c)²    float sqr_dist = sqr_dot/sqr_norm; // compute distance²=(ax+by+c)²/(a²+b²)    float sqr_radius = radius*radius; // compute radius²    return sqr_radius < sqr_dist; // intersection happens if radius²<distance²  }}  
Here is what I have so far everyone. It's enough to draw my rectangle (with bitmap on to for course), draw 4 of my boundary lines, draw my sphere (ball), and a temporary means of setting my ball in motion. Note the "delay" variable. It is only so that the ball will not move until a second or so after everything appears. Maybe my code will make it more clear as to what I am trying to do. Also, if you provide code, please include how I would initialize any variables so that I don't get errors.
Please feel free to correct me if I have done anything unneccesarily or ineficiently. Also note my comments where there is a push or pop. Let me know if I am thinking the wrong way with those. When I see something like that, I am thinking assembley language and stack actions (from my days with ASM). If this code looks familiar it's because I adapted with NEHE's code.


int DrawGLScene(GLvoid) // Here's Where We Do
All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Clear Screen And Depth Buffer

glLoadIdentity();
// Reset The Current Modelview Matrix

glTranslatef(-3.0f,0.0f,-2.0f);
// Move Left 3 And Into The Screen 2

glTranslatef(3.0f,0.0f,0.0f);
// Move Right 3 Units

glEnable(GL_TEXTURE_2D);
// Enable Texture Mapping

glBindTexture(GL_TEXTURE_2D, texture[0]);
// Binds our BMP to next object

glPushMatrix();
// Save matrix position

glBegin(GL_QUADS);// Draw A Quad (our corse)
//Texture and quad coordinates

glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
// Top Left

glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
// Top Right

glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
// Bottom Right

glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
// Bottom Left

glEnd();// Done Drawing Quad

//glTranslatef(0.0f,0.0f,1.0f);
glDisable(GL_TEXTURE_2D);//disable last texture
glBegin(GL_LINES);
glColor3f(1.0f,0.0f,0.0f);

glVertex3f( -0.334f,-0.612f,.0f); // start of line 1
glVertex3f( -0.681f,-0.612f,.0f); // end of line.

glVertex3f( -0.681f,-0.612f,.0f); // start of line 2
glVertex3f( -0.681f,0.415f,.0f); // end of line.

glVertex3f( -0.6812f,0.415f,.0f); // start of line 3
glVertex3f( -0.332f,0.765f,.0f); // end of line.

glVertex3f( -0.332f,0.765f,.0f); // start of line 4
glVertex3f( 0.29f,0.765f,.0f); // end of line.

glEnd();

//glTranslatef(-1.0f,0.0f,0.0f);(not used)

glTranslatef(xtravel,ytravel,0.0f);
// Move to ball position

//glDisable(GL_TEXTURE_2D); (not used)

glColor3f(1.0f,0.0f,0.0f);
// Load red for our ball

gluSphere(quadratic,0.02f,32,32);
// Draw a sphere (our ball)

glColor3f(1.0f,1.0f,1.0f);// Reset color

delay=delay-5.0f;
if (delay<=0)
{
delay=0;//all of this is temporary,
just to set ball in motion

glPopMatrix(); // Get matrix position
ytravel=ytravel+decay;// increment ytravel
glPushMatrix(); // Save matrix position
decay=decay-.00001f; // Decrement decay
}

if (decay<=0) // Eventually stop/
decay=0; prevent going backwards

return TRUE; // Keep Going
}

PS hey vincoof, would you be so kind as to tell me how you got your code in your reply to look like real code ? This reply box is really pissing me off. I can't simply cut and paste my code, I have to screw with it alot just to make it readable.

Thanls all !


[edited by - LostBoy on September 30, 2002 4:00:50 PM]
After reading this, I''ve got a few comments to make. And to be honest, only one is critical. The others are *just* optimizations.



First the worst : pushing and popping the matrix.
Everytime you call glPushMatrix, you''re supposed to call a corresponding glPopMatrix sooner or later. In fact, you''re not obliged to do so (not like you''re obliged to call the corresponding glEnd for every glBegin) but it''s a mistake not to call it because you screw up the stack levels.

In your sample code, you''re calling either glPushMatrix once, either glPushmatrix twice and glPopMatrix once... that means that you''re always calling glPushMatrix one more time than glPopMatrix, resulting in a stack overflow after a few iterations !

You''re right about the fact that the matrix behaves like a stack, so I don''t know why you made that mistake.

Though in this case OpenGL won''t crash. Your matrix will not be pushed when the stack overflow happens (that is, glPushMatrix has no effect when the matrix stack is full) but obviously you should not play with such dangerous tricks.



Secondly, there are a few hints
You can replace this piece of code :
  glTranslatef(-3.0f,0.0f,-2.0f);// Move Left 3 And Into The Screen 2glTranslatef(3.0f,0.0f,0.0f);// Move Right 3 Units  

with that :
  glTranslatef(0.0f,0.0f,-2.0f);// Move 2 Units Into The Screen  

I don''t feel like I should give explanations because I think it''s obvious, but feel free to ask if it''s not obvious for you.


Because all your lines are connected, you can use a better primitive than GL_LINES, which is called GL_LINE_STRIP.
Replace :
  glBegin(GL_LINES);glColor3f(1.0f,0.0f,0.0f);glVertex3f( -0.334f,-0.612f,.0f); // start of line 1glVertex3f( -0.681f,-0.612f,.0f); // end of line.glVertex3f( -0.681f,-0.612f,.0f); // start of line 2glVertex3f( -0.681f,0.415f,.0f); // end of line.glVertex3f( -0.6812f,0.415f,.0f); // start of line 3glVertex3f( -0.332f,0.765f,.0f); // end of line.glVertex3f( -0.332f,0.765f,.0f); // start of line 4glVertex3f( 0.29f,0.765f,.0f); // end of line.glEnd();  

with :
  glBegin(GL_LINE_STRIP);glColor3f(1.0f,0.0f,0.0f);glVertex3f( -0.334f,-0.612f,.0f); // corner 1glVertex3f( -0.681f,-0.612f,.0f); // corner 2glVertex3f( -0.681f,0.415f,.0f); // corner 3glVertex3f( -0.332f,0.765f,.0f); // corner 4glVertex3f( 0.29f,0.765f,.0f); // final corner.glEnd();  

This line strip connects the corner 1 with corner 2, corner 2 with corner 3, corner 3 with corner 4, and corner 4 with the final corner.
The primitive GL_LINE_STRIP is better than GL_LINES because you call glVertex less often. In other words, you send less data through the pipeline (if you know what the pipeline is in OpenGL).


And finally, I''m not sure why you call glPopMatrix and glPushMatrix there :
  glPopMatrix(); // Get matrix positionytravel=ytravel+decay;// increment ytravelglPushMatrix(); // Save matrix position  

It''s like you want to want to restore the matrix as it was before, and then immediately save it again. It''s a nice trick... apart the fact that saving the matrix is useless since you''re not performing anymore matrix operations after that !



Formating posts on gamedev forums
To post source-like formated text, you have to use the [source] and [/source] tags before and after your source code, respectively. If you look at the FAQ you will find useful information for posting in gamedev forums.



Final note
Since your lines are axis-aligned, you can use very fast collision detection like Datalor presented. It''s more simple, it''s faster and uses less memory ! What do you want on top of that ? Oh yes, I admit it''s less flexible. Do you plan on using non axis-aligned borders ?

This topic is closed to new replies.

Advertisement