Sign in to follow this  
Crazy Chicken

Designing Collision Code. Need Help !

Recommended Posts

Hi, I am currently working on my first 3D demo. I have just been able get some simple collsion detection working using bounding Spheres and AABBs. But this is only half of the problem.... I am trying to make the code as object oriented as possible. But I don't know how to organize my collision code so that objects can check for collisons against other objects in a effcient and clear manner. Do I create a collision class and what functions would it perform? Is there a design pattern fequently used that could help me? Any ideas will be appreciated. Thanks, Lukas

Share this post


Link to post
Share on other sites
Hi,

The impression I have is that there is no simple way to implement collision detection - it's a horrible topic that no-one ever seems keen to discuss! That being said...

This is how I did my first collision detection code, using only spheres and 'notimplemented' which I used for things that couldn't collide, for example - bear in mind that I'm an amateur at this, and there are probably much better ways of doing it! This code uses a pattern called 'double dispatch'. Single dispatch is used with polymorphism - when you have f(base*) and the function calls the appropriate function for derived class from base. Double dispatch is used when you have f(base*, base*), where the 2 variables are both derived classes, and may not be the same. Unfortunately, C++ doesn't natively implement this - hence the rather ugly re-direction code that goes into the virtual classes.


class boundSphere;
class boundNotImplemented;


class boundType
{
public:
boundType(void) {};
~boundType(void) {};

virtual bool hasHit(const boundType& bt, const cVector3 loc1, const cVector3 loc2) const = 0;
virtual bool hasHit(const boundSphere& bt, const cVector3 loc1, const cVector3 loc2) const = 0;
virtual bool hasHit(const boundNotImplemented& bt, const cVector3 loc1, const cVector3 loc2) const = 0;

};


class boundSphere : public boundType
{
public:
boundSphere(float x) {radius = x;}
~boundSphere() {};

bool hasHit(const boundType& bt, const cVector3 loc1, const cVector3 loc2) const;
bool hasHit(const boundSphere& bt, const cVector3 loc1, const cVector3 loc2) const;
bool hasHit(const boundNotImplemented& bt, const cVector3 loc1, const cVector3 loc2) const;

float radius;
};


class boundNotImplemented : public boundType
{
public:
boundNotImplemented() {}
~boundNotImplemented() {}

bool hasHit(const boundType& bt, const cVector3 loc1, const cVector3 loc2) const;
bool hasHit(const boundSphere& bt, const cVector3 loc1, const cVector3 loc2) const;
bool hasHit(const boundNotImplemented& bt, const cVector3 loc1, const cVector3 loc2) const;


};



and some example of the .cpp code:


// loc1 and loc2 are the center co-ordinates of the colliding objects
bool boundSphere::hasHit(const boundType& bt, const cVector3 loc1, const cVector3 loc2) const
{
return(bt.hasHit(*this, loc1, loc2));
}


bool boundSphere::hasHit(const boundSphere& bt, const cVector3 loc1, const cVector3 loc2) const
{
if( ( (loc1.x - loc2.x) * (loc1.x - loc2.x) )
+ ( (loc1.z - loc2.z) * (loc1.z - loc2.z) )
< ( (this->radius + bt.radius) * (this->radius + bt.radius) )
)
return true;
return false;

}


bool boundSphere::hasHit(const boundNotImplemented& bt, const cVector3 loc1, const cVector3 loc2) const
{
return false;
}




Then in the object manager (again, bearing in mind this is code I wrote very early on, is horridly inefficient, and and violates every coding standard in the book - but it works, which is what I was looking for at the time!)


void cObjectManager::RunCollisionDetection()
{
for(int i = 0; i < GameObjects.size(); i++)
{
for(int j = 1; j < i; j++)
{
if(hasHit(GameObjects[i], GameObjects[j]))
{
GameObjects[i]->beenHit();
GameObjects[j]->beenHit();
}
}
}
}


bool cObjectManager::hasHit(cGameObject* ob1, cGameObject* ob2)
{
return(ob1->myBound->hasHit(*(ob2->myBound), ob1->location, ob2->location));
}



And objects have a 'boundType* myBound' data member.

Phew!

If I were going to do it now, I'd probably stick to the double dispatch method - despite the ugly code, it makes calling it a piece of cake, and you only need to write the code for a limited number of boundType objects - once you've done it, you're unlikely to add much more. I'd probably make the collision objects have a std::vector<float> of parameters, instead of just a 'radius' that's specific to one, and then something completely different that's specific to others. I'd also have gameObjects have a std::vector<boundType*> data member. This would make implementing multiple collision areas on an object a breeze. Finally, I'd tie the ugly objectManager::Collide code into a scene manager to cut down the number of collision tests.

Undoubtedly someone is now looking at this code and going 'Urgh!!', but hey - it worked for me!

All the best,
Jim.

Share this post


Link to post
Share on other sites
well i havnt done a collison response in 3d (ok so i dont even program in 3d yet) but from an oop point of view i think most people lump their collision code in with thier physics manager
just a thought [smile]

Share this post


Link to post
Share on other sites
Thankx for your reply JimPrice. It has definetly opened my eyes :). I have done a lot of reading on the double dispatch pattern and there is a lot of interesting discussions identical to my problem out there.

Cheers again,
Lukas

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this