This section of the archives stores flipcode's complete Developer Toolbox collection,
featuring a variety of mini-articles and source code contributions from our readers.

Plug n' Play Collision Detection For Spheres
Submitted by

This is "theoretically" a plug and play collision detection routine that
anyone can include in their programs. Practically, it's plug and play if
you're using DirectX8 and Microsoft Visual Studio, since that's what I used.

However, it should be fairly easy to go through and change any D3DXVECTOR3
typedefs to your own desired format.

The class is very simple to use. Simply declare a CCollide object wherever
you want. You could declare a global one, but since it keeps a permanent
record of the last "safe" position, it is recommended that you encapsulate
this class in whatever class you are using.

This class is neither optimized nor perfect, and is intended to be used as a
gateway for people who just want to get something up and running, with the
intention of coming back to it later. I welcome any recommended changes or
advice. The class is based on Telemacho's collision detection routines, and
he deserves full credit for it. I only encapsulated it so a person can
essentially plug it in and use it. I also made a few small changes to
correct some errors of missed collisions, on the advice of BigB on this very
message board.

Just include Collide.cpp and Collide.h in your project, and you should be
ready to go.

To define:

CCollide TheCollision;

To use:

D3DXVECTOR3 initialposition; // Start position of the object you want to
move
D3DXVECTOR3 movementvector; // Direction and speed to move it in
D3DXVECTOR3 finalposition; // Final position where object "should" be
float radiusofsphere; // Radius of the bounding sphere for the object
finalposition=TheCollision.Move(initialposition,movementvector,radiusofsphere)

Finalposition will be filled with the correct position of the object, taking
all collisions and sliding into consideration.
Some limitations:
There are two variables called EPSILON and SECONDARYEPSILON, which define
the shortest possible length of the movement vector. The smaller these
variables are, the less exact your collision detection. The larger they
are, the more exact the detection, but the larger your smallest movement can
be. They are defined as .5 intitially, but can be set by calling
TheCollision.Tweak(EPSILON,SECONDARYEPSILON).
Also, note that whether a triangle is clockwise or counterclockwise makes a
difference. Every triangle has a front and a back to this routine, so if
you have a triangle that is behaving badly for collision, try reversing its
rotation and it should work fine.
I didn't implement any triangle sort routine. This class is designed for
the person who just wants to send it a pre-sorted list of triangles-- you
have to do your BSP trees or cubic volumes or whatever yourself. The
LPTRIANGLE *triangles member of the class should point to your triangle
list, but I recommend that you re-write this part of the handler to suit
your needs. Do a search for "// NOTE: Put your triangle handler here." in
Collide.cpp and insert your preferred format to cycle through your
triangles.
Well, that's all. Hopefully this helps some new people (like myself!) who
found that the collision routines on the net are either over-featured or
under-documented, and a real pain to put into your own code. Plug it in,
use it, write your game, and tweak the routine when you have time. That's
what I'm doing.
Changes and improvements welcome!
John Raptis

if (collision.foundCollision==FALSE) {
// if no collision move very close to the desired destination.
float l=lengthOfVector(velocity);
D3DXVECTOR3 V=velocity;
SetVectorLength(V,l-EPSILON);
collision.lastSafePosition = position;
return position + V;
}
else {
if (collision.stuck) {
// Okay, sometimes we end up inside our sphere, and we're stuck.
// That's because this collision detection is designed to be in full
// 3D, and in a normal stuck situation, we would not have this problem
// because it would be a backface.
// We can probably get stuck in any wedge... but the dangerous one is
// when we are stuck in the ground.
return collision.lastSafePosition;
}
D3DXVECTOR3 newSourcePoint;
if (collision.nearestDistance>=EPSILON) {
D3DXVECTOR3 V=velocity;
SetVectorLength(V,(float)collision.nearestDistance-SECONDARYEPSILON);
newSourcePoint=collision.sourcePoint+V;
}
else {
newSourcePoint = collision.sourcePoint;
}