Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Collision detection in 3d

This thread is locked; no one can reply to it. rss feed Print
Collision detection in 3d
Jeremias Raziel
Member #581
August 2000

At first, i'd like to say that my internet was down for seven days and then i reinstalled windoze me and lost all my passwords. Good that i remembered the one of my email account.
Also I'd like to announce, that there is a new release of my engine, Total Control ( prgames.cjb.net ), v0.2, which supports textoutput, dynamic display lists, up to 8 lights (OpenGL's maximum -:)), fog and all the basic things like textoutput and texturing.
Now my problem is, i'd like to make a little game to demonstrate the power of a c++ allegro+alleggl+opengl 3dengine, and i haven't 3d collision detection got to work. And because of the complexity i want my game to have (so the fun is bigger), i'd like to make polygon perfect collision detection(I'm only using triangles). This would be the same as pixel perfect collision detection in 2d.
I also would be very happy if someone at least could give me CODE (please, no PSEUDO-CODE, i've already found enough of this) for sphere, cylinder or box collision detection. Thanks much.
And matthew: Why is it so hard to get a forgotten password back? I had to ask someone to post something, before i found out that i'm stupid and only had to search my e-mailbox.
Thanks for ANY help in ANY way.
Ps. Polygon Revolution Games is also searching for programmers who know about c++.
Thanks in advance.
Ls

lwithers
Member #630
September 2000

Well, for a sphere, you can simply check how close the centres of the two spheres are. If this is less than the sum of their radii, then they are overlapping.
Code:
typedef struct point {
int x, y, z;
}point;
typedef struct sphere {
point c;
int radius;
}sphere;
int spheres_overlapping(sphere* a, sphere* b)
{
int pyth = 0, radsum = 0;
pyth = (a->c.x - b->c.x) * (a->c.x - b->c.x) + (a->c.y - b->c.y) * (a->c.y + b->c.y) + (a->c.z - b->c.z) * (a->c.z - b->c.z);
radsum = a->radius * a->radius + b->radius * b->radius;
return (pyth < radsum);
}
This function returns non-zero if the two spheres are overlapping. It simply uses 3D pythagoras to determine the distance of the two spheres (actually the square of the distance, since square root is expensive), and compares it with the sum of the radii (again, the square of the sum of the radii, since an integer multiplication is much quicker than a square root).
Presumably you will need to use floating point code, but you can just substitute `int' with `float'.
For cylinder detection, assuming the cylinders are all facing vertically up (which is probably what you want for bounding box collisions -- anyway, it is too difficult otherwise!):
typedef struct cylinder {
point c;
int radius;
int bottom, top;
}cylinder;
int cylinders_overlapping(cylinder* a, cylinder* b)
{
int pyth = 0, radsum = 0;
if(a->bottom > b->top

lwithers
Member #630
September 2000

aargh! there is a length limit on posts...
typedef struct cylinder {
point c;
int radius;
int bottom, top;
}cylinder;
int cylinders_overlapping(cylinder* a, cylinder* b)
{
int pyth = 0, radsum = 0;
if(a->bottom > b->top

lwithers
Member #630
September 2000

Or is it a bug in the UBB? You will have to replace `OR' with the symbol for logical OR, below.
typedef struct cylinder {
point c;
int radius;
int bottom, top;
}cylinder;
int cylinders_overlapping(cylinder* a, cylinder* b)
{
int pyth = 0, radsum = 0;
if(a->bottom > b->top OR b->bottom > a->top) return 0;
pyth = (a->c.x - b->c.x) * (a->c.x - b->c.x) + (a->c.y - b->c.y) * (a->c.y + b->c.y);
radsum = a->radius * a->radius + b->radius * b->radius;
return (pyth < radsum);
}
This time, we check that the two cylinders overlap in height (which I assume to be `z'); if they don't, then we return 0, and if they do, this simply becomes the problem of two circles overlapping. I use a 2d version of the problem above.
The code for two boxes overlapping is a little more complicated, but only because you have to explicitly check several conditions. All you have to do is check if any vertex of box A lies inside box B. If this is true, then you can assume the boxes overlap:
typedef struct box {
point corner;
int w, d, h; /* x, y, z dimensions */
}box;
int point_is_in_box(box* b, point p)
{
if(p->x < b->x OR p->x >= (b->x + b->w) OR p->y < b->y OR p->y >= (b->y + b->d) OR p->z < b->z OR p->z >= (b->z + b->h)) return 0;
return 1;
}
int boxes_overlap(box* a, box* b)
{
int i = 0;
point vtx[8];
for(i = 0; i < 8; i++) {
vtx[i] = b->corner;
if(i & 1) vtx[i].x += b->w;
if(i > 3) vtx[i].y += b->h;
if(i > 1 && i < 6) vtx[i].z += b->d;
}
return (point_is_in_box(a, vtx[0]) OR point_is_in_box(a, vtx[1]) OR point_is_in_box(a, vtx[2]) OR point_is_in_box(a, vtx[3]) OR point_is_in_box(a, vtx[4]) OR point_is_in_box(a, vtx[5]) OR point_is_in_box(a, vtx[6]) OR point_is_in_box(a, vtx[7]));
}
Actually, this doesn't check the case where box a lies entirely inside box b, but I'm sure you can add a simple check for that (you don't need to run the box check both ways; just write a quick check).
Anyway, I hope this helps you. I haven't tested it, so there may be bugs.

Bob
Free Market Evangelist
September 2000
avatar

WARNING: PSEUDO-CODE!
I use Axis-aligned bouding boxes...you find what's the smallest box that can go around your object. It usually gives a better
approximation.
vector AABB[2];
for (i = 0; i < numverts; i++) {
if (vert[i].x < aabb[0].x)
aabb[0].x = vert[i].x;
if (vert[i].x > aabb[1].x)
aabb[1].x = vert[i].x;
/* etc */
}

Then you just transform the box with the whatever rotation you orient the object with, and get the object's world-AABB.
apply_quat(object->orientation, object->AABB[0], object->world_aabb[0]);
Then just check for collision of all world-AABBs the same way you check for counding box collision in 2D...but with the z coordinate.
Note that you have to transform all 8 points (well, 4 at least and you can extrapolate the rest).
This has the disadvantage of not using GL for the transforms, but in any case, you can't if you wanna do collision or physics (glFeedBack is just too slow and eats up lots of AGP bandwidth).

--
- Bob
[ -- All my signature links are 404 -- ]

Daniel_C_McKinnon
Member #685
October 2000

Damnit! I Pseudo-code is thashiat! I would much rather see an algorithm in pseudo-code, it's much easier to implement than trying to descipher normal code (unless it is commented on every line or so)

But that's just my opinion, and I'm sure my random babbling didn't help.

Toidi_G
Member #848
December 2000

I guess I should point out that I am developing 3D engine a bit like yours. It is in C++ so the source might be helpful to you. It can load Quake BSP files which makes collision detection amazingly easy. If you would like to get the source code for it I can email it to you. It would be a stripped down version though as I don't want to release the full source code until the engine is complete in a few weeks.
My E-Mail address is Toidi_G@zfree.co.nz
PS. I would like to help develop your engine as well. We could even combine the two of them I guess.

Go to: