Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

id_table.h

Go to the documentation of this file.
00001 #ifndef _ID_TABLE_H_
00002 #define _ID_TABLE_H_
00003 #include "key_mutable_set.h"
00004 #include "ext_stl.h"
00005 #include "collidable.h"
00006 
00008 const int fudgeFactor = 1;
00009 
00011 template<class T>
00012 class IdTable {
00013 private:
00014     class CollideKeyLess {
00015     public:
00016         bool operator() (const KeyMutableShell<T> &a, const KeyMutableShell<T> &b) const {
00017             return (a->getCollideKey()<b->getCollideKey());
00018         }
00019     };
00020     class MeshIdLess {
00021     public:
00022         bool operator() (const MutableShell<T> &a, const MutableShell<T> &b) const {
00023             if (a->model==b->model) {
00024                 return (a->getId()<b->getId());
00025             } else {
00026                 return (a->model<b->model);
00027             }
00028         }
00029     };
00031     typedef MutableSet <T, MeshIdLess> MeshMapClass;
00032     typedef KeyMutableSet <typename T::CollideKey, T, CollideKeyLess> CollideMapClass;
00033     typedef Hashtable <int, T *, 65535 > IdMap;
00034     std::vector<int> deleteQueue;
00035 private:
00036     MeshMapClass meshMap;
00037     IdMap idMap;
00038     CollideMapClass collideMap;
00039 
00040     inline void incrementAndCheck (typename CollideMapClass::iterator &iter) {
00041         iter=collideMap.changeKey(iter,(*iter)->recalculateCollideKey());
00042     }
00043 protected:
00045     bool del (int id) {
00046         using std::vector;
00047         T *spec=idMap.Get(id);
00048         if (!spec) {
00049             return false;
00050         }
00051         idMap.Delete(id);
00052         {
00053             typename CollideMapClass::iterator iter=collidemap.find(spec->getCollideKey());
00054             while (iter!=collidemap.end()) {
00055                 if (spec==(*iter).second) {
00056                     collidemap.erase(iter);
00057                 }
00058                 iter++;
00059             }
00060         }
00061         typename MeshMapClass::iterator iter=meshmap.find(spec);
00062         if (&(*iter)==spec) {
00063             meshmap.erase(iter);
00064             break;
00065         }
00066         return true;
00067     }   
00068 public:
00069     void eraseAll () {
00070         meshMap.clear();
00071 //      idMap=IdMap(); //Does not work :-(
00072         collideMap.clear();
00073         deleteQueue.clear();
00074     }
00076     int add (const T &s) {
00077         static int numgen=0;
00078         typename MeshMapClass::iterator iter= meshMap.insert(s);
00079         T *collidableToInsert=&(*iter).get();
00080         collideMap.insert(collidableToInsert);
00081         collidableToInsert->setId(numgen++);
00082         idMap.Put(collidableToInsert->getId(),collidableToInsert);
00083         return collidableToInsert->getId();
00084     }
00086     void kill(int id) {
00087         deleteQueue.push_back (id);
00088     }
00090     T * getById (int id) {
00091         typename IdMap::iterator iter = idMap.find(id);
00092         if (iter!=iter.end()) {
00093             return (*iter).second;
00094         } else {
00095             return NULL;
00096         }
00097     }
00098     
00099     // Returns an iterator to the CollideKeyMap perhaps? FIXME
00100     //iterator radius (const CollideKey &, T */*updates said T*/);
00101 
00103     void updateDeleteList() {
00104         while (!deleteQueue.empty()){
00105             Del (deleteQueue.back());
00106             deleteQueue.pop_back();
00107         }
00108     }
00110     void draw ();
00112     void update ();
00114     template <class Coll> void collideWithOther(Coll *coll, int surface, double minRadius, double maxRadius) {
00115         typename CollideMapClass::iterator othiter;
00116         typename T::CollideKey collideKey (surface,minRadius);
00117         othiter=this->collideMap.lower_bound(collideKey);
00118         while (othiter!=this->collideMap.end()&&(*othiter)->getCollideKey().radius<=maxRadius) {
00119             (*othiter)->collide(coll);
00120             ++othiter;
00121         }
00122     }
00124     void collideWithBolts() {
00125         //lower_bound!!!
00126         IdTable<Bolt> *btable=&world->surfaces[0]->boltField;//Just in case.
00127         typename CollideMapClass::iterator thisiter=collideMap.begin();
00128         for (;
00129                 thisiter!=collideMap.end();
00130                 ++thisiter) {
00131             const typename T::CollideKey &collideKey = ((*thisiter)->getCollideKey());
00132             int surface=collideKey.surface;
00133             btable=&world->surfaces[surface]->boltField;
00134             T * c = (*thisiter);
00135             float cRadius=c->getRadius();
00136             btable->collideWithOther(c,surface,collideKey.radius-fudgeFactor-cRadius,collideKey.radius+fudgeFactor+cRadius);
00137         }
00138     }
00139     void fixCollideOrder() {
00140         for (typename CollideMapClass::iterator thisiter=collideMap.begin();
00141                 thisiter!=collideMap.end();
00142                 incrementAndCheck(thisiter)) {}
00143     }
00145     void collideWithSame() {
00146         for (typename CollideMapClass::iterator thisiter=collideMap.begin();
00147                 thisiter!=collideMap.end();
00148                 ++thisiter) {
00149             const typename T::CollideKey &collideKey = ((*thisiter)->getCollideKey());
00150             for (typename CollideMapClass::iterator backward=thisiter;;) {
00151                 if (backward==collideMap.begin())
00152                     break;
00153                 --backward;
00154                 const typename T::CollideKey &backCollideKey = ((*backward)->getCollideKey());
00155                 if ((backCollideKey.radius<(collideKey.radius-fudgeFactor-(2 * (*thisiter)->getRadius())))||(backCollideKey.surface!=collideKey.surface)) {
00156                     break;
00157                 }
00158                 (*thisiter)->collide(*backward);
00159             }
00160             bool reachedthisiter=false;
00161             typename CollideMapClass::iterator otheriter=thisiter;
00162             ++otheriter;
00163             for (;otheriter!=collideMap.end();++otheriter) {
00164                 const typename T::CollideKey &forwardCollideKey = ((*otheriter)->getCollideKey());
00165                 if (forwardCollideKey.radius>(collideKey.radius+fudgeFactor+(2 * (*thisiter )->getRadius()))||forwardCollideKey.surface!=collideKey.surface) {
00166                     break;
00167                 }
00168                 (*thisiter)->collide(*otheriter);
00169             }
00170         }
00171     }
00172 };
00173 #endif

Generated on Mon Jul 7 21:13:44 2003 for Ethereal by doxygen1.2.15