Home Collision Detection Collision Boxes
Collision Boxes

There are lots of way to do collision testing in your program...some more efficient then others. It all depends what types of object you want to test and how precise you want your calculations to be. Obviously the most efficient ones are the hardest to implement and not always too fast. Depends on what kind of an object you have you might want to use more then one algorithm.

 

I'm going to present you the most basic type of collision detection: The bounding Box technique. It's pretty simple...all you have to do is approximate an object with a box. This method is rather inaccurate so using it to test character collisions with bullets is not a very good idea. Perhaps if you split your character into several boxes but still....

Bounding Box Collision Detection

A box ca be defined by two points: two opposite corners. You think about it all that needs to be done is go through each vertex in your model and find the minimum and maximum for x, y and z. We are not interested in the min and max point of your sphere but the minimum and maxim x, y and z value. The two points that define you box are (xmin,ymin,zmin) and (xmax,ymax,zmax).

struct Vector3
{

float x;
float y;
float z;

};
struct BoundingBox
{

Vector3 max;
Vector3 min;

};

The algorithm is as follows:

for each object obj in the scene

begin
create new box
for each point(x,y,z) belonging to obj
begin
if (box->min.x>x) box->min.x = x;
if (box->min.y>y) box->min.y = y;
if (box->min.z>z) box->min.z = z;

if (box->max.x<x) box->max.x = x;
if (box->max.y<y) box->max.y = y;
if (box->max.z<z) box->max.z = z;
end
add the box to a list/array
end

Creating the box means creating a new structure and initializing it to some values we could use in min and max determining: chose a very large value for min and very small for max (small as in -1000000 not 0 :))

If you have a box and a point you could easily determine whenever the point is in the box (or will be in the next move) with a simple IF:

bool Collision(BoundingBox *b, GLfloat x, GLfloat y, GLfloat z)
{

return x <= b->max.x && x >= b->min.x &&
y <= b->max.y && y >= b->min.y &&
z <= b->max.z && z >= b->min.z ;

}

Being inside a box means your x coord is between xmin and xmax, your y is between ymin and ymax and your z between zmin and zmax

In your game loop you could test your current position against all boxes in your array/list and do some generic function to tell you if there is a collision or not:

bool CollisionTest(float x, float y, float z)
{

bool rez = false;
for (int i=0; i<number_of_boxes;i++)
rez = rez || Collision(boxes[i],x,y,z);
return rez;

}

Finally you might want to display the boxes for debugging purposes to see if they are constructed right and why they aren't approximating your object correctly (and you are getting invisible walls):

void drawbox(BoundingBox *b)
{

glColor3f(1,1,1);
glBegin (GL_LINE_LOOP);
glVertex3f(b->max.x,b->max.y,b->min.z); // 0
glVertex3f(b->min.x,b->max.y,b->min.z); // 1
glVertex3f(b->min.x,b->min.y,b->min.z); // 2
glVertex3f(b->max.x,b->min.y,b->min.z); // 3
glEnd();

glBegin (GL_LINE_LOOP);
glVertex3f(b->max.x,b->min.y,b->max.z); // 4
glVertex3f(b->max.x,b->max.y,b->max.z); // 5
glVertex3f(b->min.x,b->max.y,b->max.z); // 6
glVertex3f(b->min.x,b->min.y,b->max.z); // 7
glEnd();

glBegin (GL_LINE_LOOP);
glVertex3f(b->max.x,b->max.y,b->min.z); // 0
glVertex3f(b->max.x,b->max.y,b->max.z); // 5
glVertex3f(b->min.x,b->max.y,b->max.z); // 6
glVertex3f(b->min.x,b->max.y,b->min.z); // 1
glEnd();

glBegin (GL_LINE_LOOP);
glVertex3f(b->max.x,b->min.y,b->max.z); // 4
glVertex3f(b->min.x,b->min.y,b->max.z); // 7
glVertex3f(b->min.x,b->min.y,b->min.z); // 2
glVertex3f(b->max.x,b->min.y,b->min.z); // 3

glEnd();

}

 

In the next section I will give you the code I use to create collision boxes using the model structure from GLM.

If you don't use GLM and have your own geometry structure you are probably not interested in this but it might give you some ideas:

BoundingBox *boxes[60];

int boxindex = 0;

// If we want to calculate min and max values we should first initialize them with something we consider extreme and not like to occur
void initbox(BoundingBox *b)
{

b->min.x = 100000;
b->min.y = 100000;
b->min.z = 100000;

b->max.x = -100000;
b->max.y = -100000;
b->max.z = -100000;

}

// A GLMmodel has a chained list of groups, each group representing an object.
// Each object has a name (the name you gave it in 3D Studio Max or Gmax).
// Let's you have 10 walls in your scene a few other objects as well and you want to
// create collision boxes just for the walls and you do not want to make a collision box
// for one of your objects. You could name all your walls
// like this: Wall1, Wall2, ..., Wall10. If you wanted to add collision boxes just to them
// you could go through all objects in the scene and if their name contains "Wall" add them. There is a C function to help you
// with this one: strstr
// Basicly this function does just that: if you want to add boxes for the walls you would call it like this: DefineCollisionBoxes(model,"Wall");

void DefineCollisionBoxes(GLMmodel *model, char *part_of_the_name)
{

    GLMgroup *group = model->groups;
    while(group)
    {       
        if (strstr(group->name,part_of_the_name))   
            AddCollisionBox(model,group);       
        group = group->next;
    }

}

void AddCollisionBox(GLMmodel *model, GLMgroup * object)
{

    boxes[boxindex] = CreateCollisionBox(model,object);   
    boxindex++;       

}

 

BoundingBox *CreateCollisionBox(GLMmodel *model, GLMgroup * object)
{

BoundingBox *box = (BoundingBox*)malloc(sizeof(BoundingBox));
initbox(box);

// GLM doesn't store each vertex together with the object that owns it. It doesn't have that notion. In GLM object don't have vertex, they have triangles. And each triangle is actually an index in the triangle list of the object.

for(int i = 0; i < object->numtriangles; i++)
{
// for each vertex of the triangle pmodel1->triangles[object->triangles[i]]
// calculate min and max
for (int j=0;j<3;j++)
{
GLuint index = model->triangles[object->triangles[i]].vindices[j];
GLfloat x = model->vertices[index*3 + 0];
GLfloat y = model->vertices[index*3 + 1];
GLfloat z = model->vertices[index*3 + 2];

if (box->min.x>x) box->min.x = x;
if (box->min.y>y) box->min.y = y;
if (box->min.z>z) box->min.z = z;

if (box->max.x<x) box->max.x = x;
if (box->max.y<y) box->max.y = y;
if (box->max.z<z) box->max.z = z;
}
}
return box;

}

 
Copyright © 2010 Tudor Carean. All Rights Reserved.