   Quick question about design of a geom module.
  Hello,I have a quick question about designing a geom module.Ok, so I am designing a geom module for shapes such as Frustum, sphere, AABB, OBB, Plane, Ray etc.  The shapes need to be tested for collision states such as intersecting, positive halfspace etc. relative to each other. In my game engine I would like to have a method of my entity class (used for basically all objects or entities in the game) called GetBoundingGeom.  That method would return the pointer to its bounding geom.  Then, arbitrary geoms could be tested for intersection without having to query for their types.So, my preliminary design has a base class called BaseGeom with a single pure virtual method called GetShape.  All geoms derive from that.  Then ... in my geom collision library I have a single function called GetCollisionState which takes two arbitrary BaseGeom class pointers, queries for their shape, and dynamic_casts them to the appropriate shape.  Then collision is then tested appropriately and the collision state is returned.In pseudo-code it looks like this:// Geoms.henum Shape{   FRUSTUM,   OBB,   ABB   // etc for all shapes};class BaseGeom{public:virtual Shape GetShape()const = 0;};The geom classes now look like this:// Frustum.hclass Frustum : public BaseGeom{private:// datapublic:// constructors, methods etc.Shape GetShape()const{return FRUSTUM;}}Now, the geom collision module looks like this:// GeomCollision.henum CollisionState{   E_DISJOINT,   E_INTERSECTING   // etc. for all possible states};// implemented in .cpp but prototype in .hCollisionState GetCollisionState(BaseGeom* geom1, BaseGeom* geom2){   Shape shape1 = geom1->GetShape();   Shape shape2 = geom2->GetShape();   if(FRUSTUM == shape1)   {  Frustum* frustum = dynamic_cast<Frustum*>(geom1);  if(SPHERE == shape2)  {  Sphere* sphere = dynamic_cast<Sphere*>(geom2);  // Implemented in collision state implementation namespace  // with one version per shape pair  return GeomCollisionImpl::GetCollisionState(frustum, sphere);  }   }   // never reached but ...   return E_DISJOINT;}So, my questions are ... 1) Is this an appropriate design for such a module?2) Is the virtual overhead of having ALL shapes derive virtually worth the benefits of having a GetBoundingGeom method now available so that all entities can simply return their shape no matter what it is?3) Any tips/ideas/suggestions?Thank you for your help.Jeremy[/source]   
Quote:Is the virtual overhead of having ALL shapes derive virtually worth the benefits of having a GetBoundingGeom method now available so that all entities can simply return their shape no matter what it is?It's not about "worth". It's about the fact that it's your absolute and unchangeable requirement due to:Quote:am designing a geom module for shapes such as Frustum, sphere, AABB, OBB, Plane, Ray etc. The shapes need to be tested for collision states such as intersecting, positive halfspace etc. relative to each other.The only choice you have is whether you use language polymorphism, or instead use switch statement for dispatch.A better question is: do I really need to compare all those to each other in this way.For example, is frustrum test really so generic that it needs to be handled at this level? Or will it only be used to test the camera.Sphere, AABB and OBB? Would perhaps just one do?Do all of these really need to be mashed together, or could some be part of quick broad-phase test, while ray/triangle are part of accurate detection?But, if that is the design requirement, then double dispatch is how it has to be done, and implementation, maintenance and runtime overhead is simple fact of life.   ;  Thank you, I appreciate your help.  The design seems solid from my perspective but I am still a bit new to some design patterns and thus still debating optimal design patterns before implementing anything.  I would love to hear optional design patterns for this task or any other suggestions/tips involving this before implementing anything.Thanks again.Jeremy   ;Quote:Original post by grill8The design seems solid from my perspective but I am still a bit new to some design patterns and thus still debating optimal design patterns before implementing anything.  I would love to hear optional design patterns for this task or any other suggestions/tips involving this before implementing anything.These aren't design patterns. At best, they are language idioms.Also - if you don't have experience, try it. Too many people today are obsessed with design patterns, instead of just getting the thing to run as simply as possible, and realizing they don't really need anything more. As said, it's not about whether double dispatch is the solution, but whether such all-to-all tests are even needed - just imagine how much coding it will require to support detection and response calculation - it's n^2, so right now you'll need 36 different specializations. And 49 if you add another bounding volume. And multiply that by number of different tests you wish to perform (intersection, halfspace, response, ...). Just these 3 will require 108 different functions.IMHO, I'd avoid such elaborate tests. Pick one, such as sphere or AABB for broad phase, and use triangle/ray test for accurate detection. Frustrum can probably be applied to broad-phase directly to AABB.   ;  Thank you all, that is very helpful.I will consider the necessity of everything in my design.I am starting to agree that simplicity is an often underrated aspect of creating robust solutions.Thank you for your help.Jeremy   