static inline void hashHandle(cpSpaceHash *hash, cpHandle *hand, cpBB bb) { // Find the dimensions in cell coordinates. cpFloat dim = hash->celldim; int l = bb.l/dim; int r = bb.r/dim; int b = bb.b/dim; int t = bb.t/dim; int n = hash->numcells; for(int i=l; i<=r; i++){ for(int j=b; j<=t; j++){ int index = hash_func(i,j,n); cpSpaceHashBin *bin = hash->table[index]; // Don't add an object twice to the same cell. if(containsHandle(bin, hand)) continue; cpHandleRetain(hand); // Insert a new bin for the handle in this cell. cpSpaceHashBin *newBin = getEmptyBin(hash); newBin->handle = hand; newBin->next = bin; hash->table[index] = newBin; } } }
// Transformation function for the handleset. static void * handleSetTrans(void *obj, void *unused) { cpHandle *hand = cpHandleNew(obj); cpHandleRetain(hand); return hand; }
// Hashset iterator func used with cpSpaceHashQueryRehash(). static void handleQueryRehashHelper(void *elt, void *data) { cpHandle *hand = (cpHandle *)elt; // Unpack the user callback data. queryRehashPair *pair = (queryRehashPair *)data; cpSpaceHash *hash = pair->hash; cpSpaceHashQueryFunc func = pair->func; cpFloat dim = hash->celldim; int n = hash->numcells; void *obj = hand->obj; cpBB bb = hash->bbfunc(obj); int l = floor_int(bb.l/dim); int r = floor_int(bb.r/dim); int b = floor_int(bb.b/dim); int t = floor_int(bb.t/dim); cpSpaceHashBin **table = hash->table; for(int i=l; i<=r; i++){ for(int j=b; j<=t; j++){ // // exit the loops if the object has been deleted in func(). // if(!hand->obj) goto break_out; int idx = hash_func(i,j,n); cpSpaceHashBin *bin = table[idx]; if(containsHandle(bin, hand)) continue; cpHandleRetain(hand); // this MUST be done first in case the object is removed in func() query(hash, &bin, obj, func, pair->data); cpSpaceHashBin *newBin = getEmptyBin(hash); newBin->handle = hand; newBin->next = bin; table[idx] = newBin; } } // break_out: // Increment the stamp for each object we hash. hash->stamp++; }
static void * handleSetTrans(void *obj, cpSpaceHash *hash) { if(hash->pooledHandles->num == 0){ // handle pool is exhausted, make more int count = CP_BUFFER_BYTES/sizeof(cpHandle); cpAssertSoft(count, "Buffer size is too small."); cpHandle *buffer = (cpHandle *)cpcalloc(1, CP_BUFFER_BYTES); cpArrayPush(hash->allocatedBuffers, buffer); for(int i=0; i<count; i++) cpArrayPush(hash->pooledHandles, buffer + i); } cpHandle *hand = cpHandleInit((cpHandle *)cpArrayPop(hash->pooledHandles), obj); cpHandleRetain(hand); return hand; }
// Hashset iterator func used with cpSpaceHashQueryRehash(). static void handleQueryRehashHelper(void *elt, void *data) { cpHandle *hand = (cpHandle *)elt; // Unpack the user callback data. queryRehashPair *pair = (queryRehashPair *)data; cpSpaceHash *hash = pair->hash; cpSpaceHashQueryFunc func = pair->func; cpFloat dim = hash->celldim; int n = hash->numcells; void *obj = hand->obj; cpBB bb = hash->bbfunc(obj); int l = bb.l/dim; int r = bb.r/dim; int b = bb.b/dim; int t = bb.t/dim; for(int i=l; i<=r; i++){ for(int j=b; j<=t; j++){ int index = hash_func(i,j,n); cpSpaceHashBin *bin = hash->table[index]; if(containsHandle(bin, hand)) continue; query(hash, bin, obj, func, pair->data); cpHandleRetain(hand); cpSpaceHashBin *newBin = getEmptyBin(hash); newBin->handle = hand; newBin->next = bin; hash->table[index] = newBin; } } // Increment the stamp for each object we hash. hash->stamp++; }
// Hashset iterator func used with cpSpaceHashQueryRehash(). static void queryRehash_helper(cpHandle *hand, queryRehashContext *context) { cpSpaceHash *hash = context->hash; cpSpatialIndexQueryFunc func = context->func; void *data = context->data; cpFloat dim = hash->celldim; int n = hash->numcells; void *obj = hand->obj; cpBB bb = hash->spatialIndex.bbfunc(obj); int l = floor_int(bb.l/dim); int r = floor_int(bb.r/dim); int b = floor_int(bb.b/dim); int t = floor_int(bb.t/dim); cpSpaceHashBin **table = hash->table; for(int i=l; i<=r; i++){ for(int j=b; j<=t; j++){ int idx = hash_func(i,j,n); cpSpaceHashBin *bin = table[idx]; if(containsHandle(bin, hand)) continue; cpHandleRetain(hand); // this MUST be done first in case the object is removed in func() query_helper(hash, &bin, obj, func, data); cpSpaceHashBin *newBin = getEmptyBin(hash); newBin->handle = hand; newBin->next = bin; table[idx] = newBin; } } // Increment the stamp for each object hashed. hash->stamp++; }