Home | History | Annotate | Download | only in collision
      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