1 #include "ContactCache.h" 2 3 ContactCache *currentContactCache = 0; 4 5 inline void ContactCacheStarted_CB(btPersistentManifold* const &manifold) { 6 currentContactCache->contactStarted(manifold); 7 } 8 inline void ContactCacheEnded_CB(btPersistentManifold* const &manifold) { 9 currentContactCache->contactEnded(manifold); 10 } 11 12 struct ContactPair { 13 const btCollisionObject *object0; 14 const btCollisionObject *object1; 15 float time; 16 17 ContactPair() : object0(0), object1(0), time(0) {} 18 19 ContactPair(const ContactPair &rhs) : object0(rhs.object0), object1(rhs.object1), time(rhs.time) {} 20 21 ContactPair(const btCollisionObject* const &object0, const btCollisionObject* const &object1, const float &time) : object0(object0), object1(object1), time(time) {} 22 23 ContactPair &operator=(const ContactPair &rhs) { 24 object0 = rhs.object0; 25 object1 = rhs.object1; 26 time = rhs.time; 27 return *this; 28 } 29 30 inline bool operator==(const ContactPair &rhs) const { 31 return ((rhs.object0 == object0) && (rhs.object1 == object1)) || ((rhs.object0 == object1) && (rhs.object1 == object0)); 32 } 33 34 inline bool operator<(const ContactPair &rhs) const { 35 if (*this == rhs) 36 return false; 37 return object0 < rhs.object0; 38 } 39 40 inline bool equals(const btCollisionObject* const &obj0, const btCollisionObject* const &obj1) const { 41 return ((obj0 == object0) && (obj1 == object1)) || ((obj0 == object1) && (obj1 == object0)); 42 } 43 }; 44 45 ContactCache::ContactCache(bool dummy) 46 : events(0), cacheTime(0.2f), filter(true) {} 47 48 ContactCache::~ContactCache() { 49 disable(); 50 } 51 52 void ContactCache::setEvents(const int &events) { 53 this->events = events; 54 } 55 56 void ContactCache::enable() { 57 currentContactCache = this; 58 gContactStartedCallback = ContactCacheStarted_CB; 59 gContactEndedCallback = ContactCacheEnded_CB; 60 } 61 62 void ContactCache::disable() { 63 if (currentContactCache == this) { 64 currentContactCache = 0; 65 if (gContactStartedCallback == ContactCacheStarted_CB) 66 gContactStartedCallback = 0; 67 if (gContactEndedCallback == ContactCacheEnded_CB) 68 gContactEndedCallback = 0; 69 } 70 } 71 72 bool ContactCache::isEnabled() { 73 return (currentContactCache == this) && (gContactStartedCallback == ContactCacheStarted_CB) && (gContactEndedCallback == ContactCacheEnded_CB); 74 } 75 76 void ContactCache::clear() { 77 cache.clear(); 78 } 79 80 void ContactCache::update(float delta) { 81 for (int i = cache.size() - 1; i >= 0; --i) { 82 ContactPair &pair = cache.at(i); 83 if ((pair.time -= delta) < 0) { 84 const btCollisionObject* const &object0 = pair.object0; 85 const btCollisionObject* const &object1 = pair.object1; 86 const bool match0 = gdxCheckFilter(object0, object1); 87 const bool match1 = gdxCheckFilter(object1, object0); 88 if (!filter || match0 || match1) 89 onContactEnded(object0, match0, object1, match1); 90 cache.swap(i, cache.size()-1); 91 cache.pop_back(); 92 } 93 } 94 } 95 96 int ContactCache::indexOf(const btCollisionObject* const &obj0, const btCollisionObject* const &obj1) { 97 for (int i = cache.size() - 1; i >= 0; --i) { 98 ContactPair &pair = cache.at(i); 99 if (pair.equals(obj0, obj1)) 100 return i; 101 } 102 return -1; 103 } 104 105 void ContactCache::contactStarted(btPersistentManifold* manifold) { 106 const bool match0 = gdxCheckFilter(manifold->getBody0(), manifold->getBody1()); 107 const bool match1 = gdxCheckFilter(manifold->getBody1(), manifold->getBody0()); 108 if (filter && !match0 && !match1) 109 return; 110 const int idx = indexOf(manifold->getBody0(), manifold->getBody1()); 111 if (idx >= 0) { 112 cache.swap(idx, cache.size()-1); 113 cache.pop_back(); 114 } 115 else 116 onContactStarted(manifold, match0, match1); 117 } 118 119 void ContactCache::contactEnded(btPersistentManifold* manifold) { 120 const bool match0 = gdxCheckFilter(manifold->getBody0(), manifold->getBody1()); 121 const bool match1 = gdxCheckFilter(manifold->getBody1(), manifold->getBody0()); 122 if (filter && !match0 && !match1) 123 return; 124 const int idx = indexOf(manifold->getBody0(), manifold->getBody1()); 125 if (idx >= 0) 126 cache[idx].time = cacheTime; 127 else 128 cache.push_back(ContactPair(manifold->getBody0(), manifold->getBody1(), cacheTime)); 129 } 130