Featured Posts

8. Bump Mapping in GLSL8. Bump Mapping in GLSL Introduction Bump mapping is essential in todays computer games, and computer graphics in general. Would you like to know the best thing about it? It is extremely simple to implement. Bump mapping works...

Read more

Swiftless GLSL Shader DeveloperSwiftless GLSL Shader Developer Swiftless GLSL Shader Developer   Version 0.1a Currently Swiftless GLSL Shader Developer is in it's first public release, and is currently in alpha status, meaning it is not complete and may contain...

Read more

Wordpress Optimization Wordpress Website Optimizations Introduction Wordpress itself is a fairly wonderful tool. Since switching to it, I find it is a lot quicker to make changes to my website and it is also quicker to get...

Read more

36. OpenGL Framebuffers36. OpenGL Framebuffers Introduction Frame buffers are one of those mythical things that we have all heard of, but many beginner OpenGL developers avoid because there is not much information about them, and they can be confusing...

Read more

1. Terrain Class1. Terrain Class Terrain is one of those things that so far, hasn't been perfectly recreated in computer graphics. But it is almost there! Looking over a beautiful landscape can be one of the most amazing feelings in the...

Read more

  • Prev
  • Next

29. OpenGL Bounding Sphere Collision

Posted on : 25-03-2010 | By : Swiftless | In : OpenGL

Tags: , , , , ,

13

p>Every good game has some sort of collision detection. Without it you would
not even be able to tell if there was a wall in front of you. So here
I am going to show you how to use bounding spheres.

Bounding spheres are like a sphere that radiates from your chosen point
and radiates to the distance in which you set as the radius of your
sphere.

A bigger sphere has a bigger radius. Therefore, objects can’t come as
close as with a smaller sphere.

Now first, we need to set some variables to be able to hold our points
locations and the size of their radii.

This will hold the distance between our objects
GLfloat d;

This will hold the x,y and z positions for our first point
GLfloat p1x;
GLfloat p1y;
GLfloat p1z;

This will hold the size of the radii for the 2 points
point 1 has a radius of 1, and point 2 has a radius of 0, there point 2
will act just like a point, while point 1 will act like a sphere
const p1radius = 1;
const p2radius = 0;

This will hold the x,y and z poisitions for our second point
GLfloat p2x;
GLfloat p2y;
GLfloat p2z;

Now for the guts of this tutorial, working out the collision
void collision (void) {
Our distance is worked out with this simple little formula.
d = sqrt(((p1x – p2x) * (p1x – p2x)) + ((p1y – p2y) * (p1y – p2y)) + ((p1z – p2z) * (p1z – p2z)));
}

Technically you could write it as:
d = sqrt(((p1x – p2x)^2) + ((p1y – p2y)^2) + ((p1z – p2z)^2));
But it is just a matter of preference.

Now to draw the points.
void pointz (void) {
glPushMatrix();

If the distance between the 2 points, is less than that of there radii
combined, then there is a collision
if (d <= p2radius + p1radius)
{

Set the color of our first point to red
glColor3f(1, 0, 0);
}
else
{

If not, then set it to blue
glColor3f(0, 0, 1);
}

Begin drawing the point
glBegin(GL_POINTS);
Draw it at its x,y and z position
glVertex3f(p1x, p1y, p1z);
glEnd();
glPopMatrix();

glPushMatrix();
Set the color of our first point to green
glColor3f(0, 1, 0);
Begin drawing the point
glBegin(GL_POINTS);
Draw it at its x,y and z position
glVertex3f(p2x, p2y, p2z);
glEnd();
glPopMatrix();
}

Now this is just to show you that it works, we are moving the points around
with the following keys.
void keyboard (unsigned char key, int x, int y) {
if (key==’q') {
p1z = p1z – 0.1;
}

if (key==’z') {
p1z = p1z + 0.1;
}

if (key==’w') {
p1y = p1y + 0.1;
}

if (key==’s') {
p1y = p1y – 0.1;
}

if (key==’a') {
p1x = p1x – 0.1;
}

if (key==’d') {
p1x = p1x + 0.1;
}

if (key==’i') {
p2y = p2y + 0.1;
}

if (key==’k') {
p2y = p2y – 0.1;
}

if (key==’j') {
p2x = p2x – 0.1;
}

if (key==’l') {
p2x = p2x + 0.1;
}

If you have any problems with this tutorial, please email me at swiftless@gmail.com

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
  #include <GL/gl.h>
#include <GL/glut.h>
#include <math.h>

GLfloat d;

GLfloat p1x;
GLfloat p1y;
GLfloat p1z;

const p1radius = 1;
const p2radius = 0;

GLfloat p2x;
GLfloat p2y;
GLfloat p2z;

void collision (void) {
d = sqrt(((p1x - p2x) * (p1x - p2x)) + ((p1y - p2y) * (p1y - p2y))
+ ((p1z - p2z) * (p1z - p2z)));
}

void pointz (void) {
glPushMatrix();
if (d <= p2radius + p1radius)
{
glColor3f(1, 0, 0);
}
else
{
glColor3f(0, 0, 1);
}
glBegin(GL_POINTS);
glVertex3f(p1x, p1y, p1z);
glEnd();
glPopMatrix();

glPushMatrix();
glColor3f(0, 1, 0);
glBegin(GL_POINTS);
glVertex3f(p2x, p2y, p2z);
glEnd();
glPopMatrix();
}

void display (void) {
    glClearColor (0.0,0.0,0.0,1.0);
    glClear (GL_COLOR_BUFFER_BIT);
    glLoadIdentity();  
    gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    glPointSize(5);
    collision();
    pointz();
    glutSwapBuffers();
}

void reshape (int w, int h) {
    glViewport (0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
    glMatrixMode (GL_MODELVIEW);
}

void keyboard (unsigned char key, int x, int y) {
if (key==‘q’) {
p1z = p1z - 0.1;
}

if (key==‘z’) {
p1z = p1z + 0.1;
}

if (key==‘w’) {
p1y = p1y + 0.1;
}

if (key==‘s’) {
p1y = p1y - 0.1;
}

if (key==‘a’) {
p1x = p1x - 0.1;
}

if (key==‘d’) {
p1x = p1x + 0.1;
}

if (key==‘i’) {
p2y = p2y + 0.1;
}

if (key==‘k’) {
p2y = p2y - 0.1;
}

if (key==‘j’) {
p2x = p2x - 0.1;
}

if (key==‘l’) {
p2x = p2x + 0.1;
}

if (key==27) { //27 is the ascii code for the ESC key
    exit (0); //end the program
}
}

int main (int argc, char **argv) {
    glutInit (&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE); //set up the double 
buffering

    glutInitWindowSize (500, 500);
    glutInitWindowPosition (100, 100);
    glutCreateWindow (“A basic OpenGL Window);
    glutDisplayFunc (display);
    glutIdleFunc (display);
    glutReshapeFunc (reshape);
    glutKeyboardFunc (keyboard);//the call for the keyboard 
function.

    glutMainLoop ();
    return 0;
}

VN:F [1.9.3_1094]
Please rate so I know where to improve the site. 1 means needs a lot of improvement, 10 means perfect. If you leave a low rating, please state why. I don't want people just coming to bash the site.
Rating: 9.3/10 (3 votes cast)
VN:F [1.9.3_1094]
Rating: +3 (from 3 votes)
29. OpenGL Bounding Sphere Collision, 9.3 out of 10 based on 3 ratings

Related posts:

  1. 31. OpenGL Sphere Creation
  2. 30. OpenGL Circle Drawing
  3. 6. OpenGL Cube (Version 2.0)
  4. 18. OpenGL Popping and Pushing Matrices
  5. 1. Maths Distance Formula

Comments (13)

Hi Philip, I hope I understood you good, but what you want to know, is how to know where you are looking at some point of the rendering? are you using glLookAt ? if yes, then from the 4th to the 6th value are the LookAt X,Y,Z respectively, if not, then you are using glRotatef -> in this case I don’t really know how to apply, I guess doing some Sin/Cos will be enough, they way to “shoot” in straight line, can be done by using some geometry -> something like Ray Tracing, the definition of a Ray is; r(t) = o + td, where “o” is the origin (your actual position) and t is the direction you are looking at, “d” is the direction vector (where you are looking at), and t is the scalar, t means how many times is multiplied the direction, for example your origin is 0,0,0 and d is 1,0,0, that means that you are looking at the x axis and the ray distance at x is 1, but if t is 2, then you are looking at x=2, if t<0 that means the point is behind the ray, "d" should be normalized, so "t" we can say is a distance unit, which shows how far is the point from the origin ;)
The easiest collision detection is doing ray-sphere and ray-triangle , I think ray-plane is easy too, but I have code it yet (in my life)

@Donald: sorry man, I have some troubles with my thesis, and I will need more time, before we can start the video-youtube-thing, I hope all is fine hehe! ;)

VA:F [1.9.3_1094]
Rating: 5.0/5 (1 vote cast)
VA:F [1.9.3_1094]
Rating: +1 (from 1 vote)

Hi Donald

How do you determine which direction is away from the camera or which way it is looking

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Hi Phillip,

That sounds like a great start, a sphere-plane intersection would work, but you only really need a ray-plane intersection for this. The ray being a vector that shoots from the camera, in the direction the camera is facing.

You’re plane should not need bounds, as it should only be generated as soon as you hit the sphere, and should only last for as long as it takes to calculate the next position to move to.

Cheers,
Swiftless

VN:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Hello

I have managed to do a sphere(camera) plane(wall) test, but the trouble is the plane is infinate, it detects when i hit the wall and when i try to go around it. How can i set bounds to the plane (wall) without making the wall axis alligned.

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Hi Phillip,

For this kind of interaction, you are going to have to do a bit more maths. Given we know the centre of the sphere, the size of the radius, and the point on the surface where the collision occurs, you are going to have to calculate the surface normal for this point on the sphere.

Using the surface normal, you can calculate the angle between the direction your object is moving, and the surface normal of the sphere, and with that angle you can then determine if you want to stop or ‘slide’ to another position.

Cheers,
Swiftless

VN:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Using the bounding sphere equation, when i detect the collsion i set the camera position to the last position but all this does is bounce off the object and is very jerky. How can i hit the object and slide around or stop dead if your square to the object.

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Ooops, rewrote it wrong was supposed to be:

distance = sqrt(((heroX – Object[i].Xpos) * (heroX – Object[i].Xpos)) + ((heroY – Object[i].Ypos) * (heroY – Object[i].Ypos))
+ ((heroZ – Object[i].Zpos) * (heroZ – Object[i].Zpos)));

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Thanks,
I was trying to pass object details into the array and then push the array values into the equation.

distance = sqrt(((hero – Object[i].Xpos) * (hero – Object[i].Xpos)) + ((hero – Object[i].Ypos) * (hero – Object[i].Ypos))
+ ((hero – Object[i].Zpos) * (hero – Object[i].Zpos)));

It didn’t seem to work. I will try the true/false boolean, hopefully i will make this work one way or another.

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Hi,
I was wondering, how would you go about adapting bounding sphere collision system for multiple objects. Cant wrap my head around it, how to keep track of multiple objects without hardcoding them all in.
Any ideas?

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Hi E_Nuclear,

I have had this question asked to me before via email, and this is the response I gave:

To have it go over a group of objects, try something like this:

// First change the collision method to return true or false, and to accept 3 parameters, the two objects, and the radius of the bounding sphere
bool collision (object a, object b, float radius) {
float d = sqrt(((a.x – b.x) * (a.x – b.x)) + ((a.y – b.y) * (a.y – b.y)) + ((a.z – b.z) * (a.z – b.z)));

if (d <= radius) {
return true;
}

return false;
}

// And then, you will need to call it (probably in a loop is easiest)
for (int i = 0; i < objects; i++) {
for (int j = 0; j < objects; j++) {
if (collision(object[i], object[j], 5.0f)) {
// Do collision code
}
}
}

This assumes you have one list of objects, each with an x, y and z position. And it also assumes that you want to check if any object has collided with any other object.

Hope this helps,
Swiftless

VN:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Hi once again,

Isn’t that bothers me, but is actually a number 2 (Two) in E2A instead of Z :P It really wouldn’t bother me at all just because Eza sounds like a girl’s name :P and beside that, if you want I can make the vids for you :) if you have a logo and so on, it can be like a cooler vid, I’m a lil’ into postproduction so if you would like just let me know, you got my mail, so just write to me ;)

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Hi D,

I got an idea, what about if you do like a video (recording) of how the code looks in action? you know it doesn’t have to be in your site the flash file (uploading it at youtube, for bandwidth consume avoidance of course :) )

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: +1 (from 1 vote)

Hi E2A (Sorry),

Believe it or not, I was thinking of video versions of the tutorials just last night.

I’m going to see if I have time for this after I finish rewriting most of the tutorials, but I can definitely fit in videos of the end result of the code.

Thanks for the suggestion,
Swiftless

VN:F [1.9.3_1094]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.3_1094]
Rating: +1 (from 1 vote)

Write a comment

Improve the web with Nofollow Reciprocity.