1 #include "ContactCache.h"
2
3 ContactCache *currentContactCache = 0;
4
ContactCacheStarted_CB(btPersistentManifold * const & manifold)5 inline void ContactCacheStarted_CB(btPersistentManifold* const &manifold) {
6 currentContactCache->contactStarted(manifold);
7 }
ContactCacheEnded_CB(btPersistentManifold * const & manifold)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
ContactPairContactPair17 ContactPair() : object0(0), object1(0), time(0) {}
18
ContactPairContactPair19 ContactPair(const ContactPair &rhs) : object0(rhs.object0), object1(rhs.object1), time(rhs.time) {}
20
ContactPairContactPair21 ContactPair(const btCollisionObject* const &object0, const btCollisionObject* const &object1, const float &time) : object0(object0), object1(object1), time(time) {}
22
operator =ContactPair23 ContactPair &operator=(const ContactPair &rhs) {
24 object0 = rhs.object0;
25 object1 = rhs.object1;
26 time = rhs.time;
27 return *this;
28 }
29
operator ==ContactPair30 inline bool operator==(const ContactPair &rhs) const {
31 return ((rhs.object0 == object0) && (rhs.object1 == object1)) || ((rhs.object0 == object1) && (rhs.object1 == object0));
32 }
33
operator <ContactPair34 inline bool operator<(const ContactPair &rhs) const {
35 if (*this == rhs)
36 return false;
37 return object0 < rhs.object0;
38 }
39
equalsContactPair40 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
ContactCache(bool dummy)45 ContactCache::ContactCache(bool dummy)
46 : events(0), cacheTime(0.2f), filter(true) {}
47
~ContactCache()48 ContactCache::~ContactCache() {
49 disable();
50 }
51
setEvents(const int & events)52 void ContactCache::setEvents(const int &events) {
53 this->events = events;
54 }
55
enable()56 void ContactCache::enable() {
57 currentContactCache = this;
58 gContactStartedCallback = ContactCacheStarted_CB;
59 gContactEndedCallback = ContactCacheEnded_CB;
60 }
61
disable()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
isEnabled()72 bool ContactCache::isEnabled() {
73 return (currentContactCache == this) && (gContactStartedCallback == ContactCacheStarted_CB) && (gContactEndedCallback == ContactCacheEnded_CB);
74 }
75
clear()76 void ContactCache::clear() {
77 cache.clear();
78 }
79
update(float delta)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
indexOf(const btCollisionObject * const & obj0,const btCollisionObject * const & obj1)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
contactStarted(btPersistentManifold * manifold)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
contactEnded(btPersistentManifold * manifold)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