Designing Collision Code. Need Help !
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
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.
and some example of the .cpp code:
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!)
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.
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]
just a thought [smile]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement