Sign in to follow this  

Designing Collision Code. Need Help !

This topic is 4794 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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
Sign in to follow this