Designing Collision Code. Need Help !

Started by
2 comments, last by Crazy Chicken 19 years, 4 months ago
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
Advertisement
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 objectsbool 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, GameObjects[j]))			{				GameObjects->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.
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]
____________________________"This just in, 9 out of 10 americans agree that 1 out of 10 americans will disagree with the other 9"- Colin Mochrie
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

This topic is closed to new replies.

Advertisement