chipmunk 5.3.4.5 → 6.1.3.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/chipmunk/chipmunk.c +199 -28
- data/ext/chipmunk/chipmunk.h +123 -68
- data/ext/chipmunk/chipmunk_ffi.h +129 -11
- data/ext/chipmunk/chipmunk_private.h +232 -16
- data/ext/chipmunk/chipmunk_types.h +94 -30
- data/ext/chipmunk/chipmunk_unsafe.h +12 -3
- data/ext/chipmunk/constraints/cpConstraint.h +90 -34
- data/ext/chipmunk/{cpDampedRotarySpring.h → constraints/cpDampedRotarySpring.h} +18 -8
- data/ext/chipmunk/{cpDampedSpring.h → constraints/cpDampedSpring.h} +27 -16
- data/ext/chipmunk/constraints/cpGearJoint.h +17 -7
- data/ext/chipmunk/constraints/cpGrooveJoint.h +19 -10
- data/ext/chipmunk/constraints/cpPinJoint.h +17 -8
- data/ext/chipmunk/constraints/cpPivotJoint.h +18 -9
- data/ext/chipmunk/constraints/cpRatchetJoint.h +17 -8
- data/ext/chipmunk/constraints/cpRotaryLimitJoint.h +16 -7
- data/ext/chipmunk/{cpSimpleMotor.h → constraints/cpSimpleMotor.h} +15 -6
- data/ext/chipmunk/constraints/cpSlideJoint.h +18 -9
- data/ext/chipmunk/constraints/util.h +36 -44
- data/ext/chipmunk/cpArbiter.c +159 -94
- data/ext/chipmunk/cpArbiter.h +135 -129
- data/ext/chipmunk/cpArray.c +37 -56
- data/ext/chipmunk/cpBB.c +1 -12
- data/ext/chipmunk/cpBB.h +80 -18
- data/ext/chipmunk/cpBBTree.c +891 -0
- data/ext/chipmunk/cpBody.c +185 -47
- data/ext/chipmunk/cpBody.h +156 -124
- data/ext/chipmunk/cpCollision.c +126 -115
- data/ext/chipmunk/cpConstraint.c +10 -6
- data/ext/chipmunk/cpDampedRotarySpring.c +26 -17
- data/ext/chipmunk/cpDampedSpring.c +25 -18
- data/ext/chipmunk/cpGearJoint.c +23 -17
- data/ext/chipmunk/cpGrooveJoint.c +26 -22
- data/ext/chipmunk/cpHashSet.c +51 -51
- data/ext/chipmunk/cpPinJoint.c +26 -19
- data/ext/chipmunk/cpPivotJoint.c +23 -19
- data/ext/chipmunk/cpPolyShape.c +93 -69
- data/ext/chipmunk/cpPolyShape.h +33 -69
- data/ext/chipmunk/cpRatchetJoint.c +26 -21
- data/ext/chipmunk/cpRotaryLimitJoint.c +28 -22
- data/ext/chipmunk/cpShape.c +122 -133
- data/ext/chipmunk/cpShape.h +146 -95
- data/ext/chipmunk/cpSimpleMotor.c +24 -17
- data/ext/chipmunk/cpSlideJoint.c +28 -26
- data/ext/chipmunk/cpSpace.c +251 -196
- data/ext/chipmunk/cpSpace.h +173 -103
- data/ext/chipmunk/cpSpaceComponent.c +236 -159
- data/ext/chipmunk/cpSpaceHash.c +259 -159
- data/ext/chipmunk/cpSpaceQuery.c +127 -59
- data/ext/chipmunk/cpSpaceStep.c +235 -197
- data/ext/chipmunk/cpSpatialIndex.c +69 -0
- data/ext/chipmunk/cpSpatialIndex.h +227 -0
- data/ext/chipmunk/cpSweep1D.c +254 -0
- data/ext/chipmunk/cpVect.c +11 -26
- data/ext/chipmunk/cpVect.h +76 -71
- data/ext/chipmunk/extconf.rb +4 -31
- data/ext/chipmunk/prime.h +1 -1
- data/ext/chipmunk/rb_chipmunk.c +36 -45
- data/ext/chipmunk/rb_chipmunk.h +6 -3
- data/ext/chipmunk/rb_cpArbiter.c +2 -2
- data/ext/chipmunk/rb_cpBB.c +116 -35
- data/ext/chipmunk/rb_cpBody.c +5 -12
- data/ext/chipmunk/rb_cpConstraint.c +144 -9
- data/ext/chipmunk/rb_cpShape.c +69 -78
- data/ext/chipmunk/rb_cpSpace.c +81 -76
- metadata +61 -61
- data/LICENSE +0 -22
- data/README +0 -110
- data/Rakefile +0 -102
- data/ext/chipmunk/cpArray.h +0 -49
- data/ext/chipmunk/cpCollision.h +0 -28
- data/ext/chipmunk/cpHashSet.h +0 -82
- data/ext/chipmunk/cpSpaceHash.h +0 -110
- data/lib/chipmunk.rb +0 -194
data/ext/chipmunk/cpSpaceHash.c
CHANGED
@@ -19,12 +19,37 @@
|
|
19
19
|
* SOFTWARE.
|
20
20
|
*/
|
21
21
|
|
22
|
-
#include <math.h>
|
23
|
-
#include <stdlib.h>
|
24
|
-
|
25
22
|
#include "chipmunk_private.h"
|
26
23
|
#include "prime.h"
|
27
24
|
|
25
|
+
typedef struct cpSpaceHashBin cpSpaceHashBin;
|
26
|
+
typedef struct cpHandle cpHandle;
|
27
|
+
|
28
|
+
struct cpSpaceHash {
|
29
|
+
cpSpatialIndex spatialIndex;
|
30
|
+
|
31
|
+
int numcells;
|
32
|
+
cpFloat celldim;
|
33
|
+
|
34
|
+
cpSpaceHashBin **table;
|
35
|
+
cpHashSet *handleSet;
|
36
|
+
|
37
|
+
cpSpaceHashBin *pooledBins;
|
38
|
+
cpArray *pooledHandles;
|
39
|
+
cpArray *allocatedBuffers;
|
40
|
+
|
41
|
+
cpTimestamp stamp;
|
42
|
+
};
|
43
|
+
|
44
|
+
|
45
|
+
//MARK: Handle Functions
|
46
|
+
|
47
|
+
struct cpHandle {
|
48
|
+
void *obj;
|
49
|
+
int retain;
|
50
|
+
cpTimestamp stamp;
|
51
|
+
};
|
52
|
+
|
28
53
|
static cpHandle*
|
29
54
|
cpHandleInit(cpHandle *hand, void *obj)
|
30
55
|
{
|
@@ -44,69 +69,34 @@ cpHandleRelease(cpHandle *hand, cpArray *pooledHandles)
|
|
44
69
|
if(hand->retain == 0) cpArrayPush(pooledHandles, hand);
|
45
70
|
}
|
46
71
|
|
47
|
-
cpSpaceHash*
|
48
|
-
cpSpaceHashAlloc(void)
|
49
|
-
{
|
50
|
-
return (cpSpaceHash *)cpcalloc(1, sizeof(cpSpaceHash));
|
51
|
-
}
|
52
|
-
|
53
|
-
// Frees the old table, and allocate a new one.
|
54
|
-
static void
|
55
|
-
cpSpaceHashAllocTable(cpSpaceHash *hash, int numcells)
|
56
|
-
{
|
57
|
-
cpfree(hash->table);
|
58
|
-
|
59
|
-
hash->numcells = numcells;
|
60
|
-
hash->table = (cpSpaceHashBin **)cpcalloc(numcells, sizeof(cpSpaceHashBin *));
|
61
|
-
}
|
62
|
-
|
63
|
-
// Equality function for the handleset.
|
64
72
|
static int handleSetEql(void *obj, cpHandle *hand){return (obj == hand->obj);}
|
65
73
|
|
66
|
-
// Transformation function for the handleset.
|
67
74
|
static void *
|
68
75
|
handleSetTrans(void *obj, cpSpaceHash *hash)
|
69
76
|
{
|
70
77
|
if(hash->pooledHandles->num == 0){
|
71
78
|
// handle pool is exhausted, make more
|
72
79
|
int count = CP_BUFFER_BYTES/sizeof(cpHandle);
|
73
|
-
|
80
|
+
cpAssertHard(count, "Internal Error: Buffer size is too small.");
|
74
81
|
|
75
|
-
cpHandle *buffer = (cpHandle *)
|
82
|
+
cpHandle *buffer = (cpHandle *)cpcalloc(1, CP_BUFFER_BYTES);
|
76
83
|
cpArrayPush(hash->allocatedBuffers, buffer);
|
77
84
|
|
78
85
|
for(int i=0; i<count; i++) cpArrayPush(hash->pooledHandles, buffer + i);
|
79
86
|
}
|
80
87
|
|
81
|
-
cpHandle *hand = cpHandleInit((cpHandle *)
|
88
|
+
cpHandle *hand = cpHandleInit((cpHandle *)cpArrayPop(hash->pooledHandles), obj);
|
82
89
|
cpHandleRetain(hand);
|
83
90
|
|
84
91
|
return hand;
|
85
92
|
}
|
86
93
|
|
87
|
-
|
88
|
-
cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int numcells, cpSpaceHashBBFunc bbfunc)
|
89
|
-
{
|
90
|
-
cpSpaceHashAllocTable(hash, next_prime(numcells));
|
91
|
-
hash->celldim = celldim;
|
92
|
-
hash->bbfunc = bbfunc;
|
93
|
-
|
94
|
-
hash->handleSet = cpHashSetNew(0, (cpHashSetEqlFunc)handleSetEql, (cpHashSetTransFunc)handleSetTrans);
|
95
|
-
hash->pooledHandles = cpArrayNew(0);
|
96
|
-
|
97
|
-
hash->pooledBins = NULL;
|
98
|
-
hash->allocatedBuffers = cpArrayNew(0);
|
99
|
-
|
100
|
-
hash->stamp = 1;
|
101
|
-
|
102
|
-
return hash;
|
103
|
-
}
|
94
|
+
//MARK: Bin Functions
|
104
95
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
}
|
96
|
+
struct cpSpaceHashBin {
|
97
|
+
cpHandle *handle;
|
98
|
+
cpSpaceHashBin *next;
|
99
|
+
};
|
110
100
|
|
111
101
|
static inline void
|
112
102
|
recycleBin(cpSpaceHash *hash, cpSpaceHashBin *bin)
|
@@ -116,7 +106,7 @@ recycleBin(cpSpaceHash *hash, cpSpaceHashBin *bin)
|
|
116
106
|
}
|
117
107
|
|
118
108
|
static inline void
|
119
|
-
|
109
|
+
clearTableCell(cpSpaceHash *hash, int idx)
|
120
110
|
{
|
121
111
|
cpSpaceHashBin *bin = hash->table[idx];
|
122
112
|
while(bin){
|
@@ -131,50 +121,96 @@ clearHashCell(cpSpaceHash *hash, int idx)
|
|
131
121
|
hash->table[idx] = NULL;
|
132
122
|
}
|
133
123
|
|
134
|
-
// Clear all cells in the hashtable.
|
135
124
|
static void
|
136
|
-
|
125
|
+
clearTable(cpSpaceHash *hash)
|
137
126
|
{
|
138
|
-
for(int i=0; i<hash->numcells; i++)
|
139
|
-
clearHashCell(hash, i);
|
127
|
+
for(int i=0; i<hash->numcells; i++) clearTableCell(hash, i);
|
140
128
|
}
|
141
129
|
|
142
|
-
|
130
|
+
// Get a recycled or new bin.
|
131
|
+
static inline cpSpaceHashBin *
|
132
|
+
getEmptyBin(cpSpaceHash *hash)
|
133
|
+
{
|
134
|
+
cpSpaceHashBin *bin = hash->pooledBins;
|
135
|
+
|
136
|
+
if(bin){
|
137
|
+
hash->pooledBins = bin->next;
|
138
|
+
return bin;
|
139
|
+
} else {
|
140
|
+
// Pool is exhausted, make more
|
141
|
+
int count = CP_BUFFER_BYTES/sizeof(cpSpaceHashBin);
|
142
|
+
cpAssertHard(count, "Internal Error: Buffer size is too small.");
|
143
|
+
|
144
|
+
cpSpaceHashBin *buffer = (cpSpaceHashBin *)cpcalloc(1, CP_BUFFER_BYTES);
|
145
|
+
cpArrayPush(hash->allocatedBuffers, buffer);
|
146
|
+
|
147
|
+
// push all but the first one, return the first instead
|
148
|
+
for(int i=1; i<count; i++) recycleBin(hash, buffer + i);
|
149
|
+
return buffer;
|
150
|
+
}
|
151
|
+
}
|
143
152
|
|
144
|
-
|
145
|
-
|
153
|
+
//MARK: Memory Management Functions
|
154
|
+
|
155
|
+
cpSpaceHash *
|
156
|
+
cpSpaceHashAlloc(void)
|
146
157
|
{
|
147
|
-
|
158
|
+
return (cpSpaceHash *)cpcalloc(1, sizeof(cpSpaceHash));
|
159
|
+
}
|
160
|
+
|
161
|
+
// Frees the old table, and allocate a new one.
|
162
|
+
static void
|
163
|
+
cpSpaceHashAllocTable(cpSpaceHash *hash, int numcells)
|
164
|
+
{
|
165
|
+
cpfree(hash->table);
|
148
166
|
|
149
|
-
|
167
|
+
hash->numcells = numcells;
|
168
|
+
hash->table = (cpSpaceHashBin **)cpcalloc(numcells, sizeof(cpSpaceHashBin *));
|
169
|
+
}
|
170
|
+
|
171
|
+
static inline cpSpatialIndexClass *Klass();
|
172
|
+
|
173
|
+
cpSpatialIndex *
|
174
|
+
cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int numcells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
|
175
|
+
{
|
176
|
+
cpSpatialIndexInit((cpSpatialIndex *)hash, Klass(), bbfunc, staticIndex);
|
150
177
|
|
151
|
-
|
152
|
-
|
153
|
-
cpArrayFree(hash->pooledHandles);
|
178
|
+
cpSpaceHashAllocTable(hash, next_prime(numcells));
|
179
|
+
hash->celldim = celldim;
|
154
180
|
|
155
|
-
|
181
|
+
hash->handleSet = cpHashSetNew(0, (cpHashSetEqlFunc)handleSetEql);
|
182
|
+
|
183
|
+
hash->pooledHandles = cpArrayNew(0);
|
184
|
+
|
185
|
+
hash->pooledBins = NULL;
|
186
|
+
hash->allocatedBuffers = cpArrayNew(0);
|
187
|
+
|
188
|
+
hash->stamp = 1;
|
189
|
+
|
190
|
+
return (cpSpatialIndex *)hash;
|
156
191
|
}
|
157
192
|
|
158
|
-
|
159
|
-
|
193
|
+
cpSpatialIndex *
|
194
|
+
cpSpaceHashNew(cpFloat celldim, int cells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
|
160
195
|
{
|
161
|
-
|
162
|
-
cpSpaceHashDestroy(hash);
|
163
|
-
cpfree(hash);
|
164
|
-
}
|
196
|
+
return cpSpaceHashInit(cpSpaceHashAlloc(), celldim, cells, bbfunc, staticIndex);
|
165
197
|
}
|
166
198
|
|
167
|
-
void
|
168
|
-
|
199
|
+
static void
|
200
|
+
cpSpaceHashDestroy(cpSpaceHash *hash)
|
169
201
|
{
|
170
|
-
|
171
|
-
|
202
|
+
if(hash->table) clearTable(hash);
|
203
|
+
cpfree(hash->table);
|
172
204
|
|
173
|
-
hash->
|
174
|
-
|
205
|
+
cpHashSetFree(hash->handleSet);
|
206
|
+
|
207
|
+
cpArrayFreeEach(hash->allocatedBuffers, cpfree);
|
208
|
+
cpArrayFree(hash->allocatedBuffers);
|
209
|
+
cpArrayFree(hash->pooledHandles);
|
175
210
|
}
|
176
211
|
|
177
|
-
//
|
212
|
+
//MARK: Helper Functions
|
213
|
+
|
178
214
|
static inline cpBool
|
179
215
|
containsHandle(cpSpaceHashBin *bin, cpHandle *hand)
|
180
216
|
{
|
@@ -186,29 +222,6 @@ containsHandle(cpSpaceHashBin *bin, cpHandle *hand)
|
|
186
222
|
return cpFalse;
|
187
223
|
}
|
188
224
|
|
189
|
-
// Get a recycled or new bin.
|
190
|
-
static inline cpSpaceHashBin *
|
191
|
-
getEmptyBin(cpSpaceHash *hash)
|
192
|
-
{
|
193
|
-
cpSpaceHashBin *bin = hash->pooledBins;
|
194
|
-
|
195
|
-
if(bin){
|
196
|
-
hash->pooledBins = bin->next;
|
197
|
-
return bin;
|
198
|
-
} else {
|
199
|
-
// Pool is exhausted, make more
|
200
|
-
int count = CP_BUFFER_BYTES/sizeof(cpSpaceHashBin);
|
201
|
-
cpAssert(count, "Buffer size is too small.");
|
202
|
-
|
203
|
-
cpSpaceHashBin *buffer = (cpSpaceHashBin *)cpmalloc(CP_BUFFER_BYTES);
|
204
|
-
cpArrayPush(hash->allocatedBuffers, buffer);
|
205
|
-
|
206
|
-
// push all but the first one, return the first instead
|
207
|
-
for(int i=1; i<count; i++) recycleBin(hash, buffer + i);
|
208
|
-
return buffer;
|
209
|
-
}
|
210
|
-
}
|
211
|
-
|
212
225
|
// The hash function itself.
|
213
226
|
static inline cpHashValue
|
214
227
|
hash_func(cpHashValue x, cpHashValue y, cpHashValue n)
|
@@ -238,7 +251,7 @@ hashHandle(cpSpaceHash *hash, cpHandle *hand, cpBB bb)
|
|
238
251
|
int n = hash->numcells;
|
239
252
|
for(int i=l; i<=r; i++){
|
240
253
|
for(int j=b; j<=t; j++){
|
241
|
-
|
254
|
+
cpHashValue idx = hash_func(i,j,n);
|
242
255
|
cpSpaceHashBin *bin = hash->table[idx];
|
243
256
|
|
244
257
|
// Don't add an object twice to the same cell.
|
@@ -254,14 +267,16 @@ hashHandle(cpSpaceHash *hash, cpHandle *hand, cpBB bb)
|
|
254
267
|
}
|
255
268
|
}
|
256
269
|
|
257
|
-
|
258
|
-
|
270
|
+
//MARK: Basic Operations
|
271
|
+
|
272
|
+
static void
|
273
|
+
cpSpaceHashInsert(cpSpaceHash *hash, void *obj, cpHashValue hashid)
|
259
274
|
{
|
260
|
-
cpHandle *hand = (cpHandle *)cpHashSetInsert(hash->handleSet, hashid, obj, hash);
|
261
|
-
hashHandle(hash, hand, hash->bbfunc(obj));
|
275
|
+
cpHandle *hand = (cpHandle *)cpHashSetInsert(hash->handleSet, hashid, obj, hash, (cpHashSetTransFunc)handleSetTrans);
|
276
|
+
hashHandle(hash, hand, hash->spatialIndex.bbfunc(obj));
|
262
277
|
}
|
263
278
|
|
264
|
-
void
|
279
|
+
static void
|
265
280
|
cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, cpHashValue hashid)
|
266
281
|
{
|
267
282
|
cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet, hashid, obj);
|
@@ -270,20 +285,24 @@ cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, cpHashValue hashid)
|
|
270
285
|
hand->obj = NULL;
|
271
286
|
cpHandleRelease(hand, hash->pooledHandles);
|
272
287
|
|
273
|
-
cpSpaceHashInsert(hash, obj, hashid
|
288
|
+
cpSpaceHashInsert(hash, obj, hashid);
|
274
289
|
}
|
275
290
|
}
|
276
291
|
|
277
|
-
static void
|
292
|
+
static void
|
293
|
+
rehash_helper(cpHandle *hand, cpSpaceHash *hash)
|
294
|
+
{
|
295
|
+
hashHandle(hash, hand, hash->spatialIndex.bbfunc(hand->obj));
|
296
|
+
}
|
278
297
|
|
279
|
-
void
|
298
|
+
static void
|
280
299
|
cpSpaceHashRehash(cpSpaceHash *hash)
|
281
300
|
{
|
282
|
-
|
283
|
-
cpHashSetEach(hash->handleSet, (
|
301
|
+
clearTable(hash);
|
302
|
+
cpHashSetEach(hash->handleSet, (cpHashSetIteratorFunc)rehash_helper, hash);
|
284
303
|
}
|
285
304
|
|
286
|
-
void
|
305
|
+
static void
|
287
306
|
cpSpaceHashRemove(cpSpaceHash *hash, void *obj, cpHashValue hashid)
|
288
307
|
{
|
289
308
|
cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet, hashid, obj);
|
@@ -294,23 +313,22 @@ cpSpaceHashRemove(cpSpaceHash *hash, void *obj, cpHashValue hashid)
|
|
294
313
|
}
|
295
314
|
}
|
296
315
|
|
297
|
-
typedef struct
|
298
|
-
|
316
|
+
typedef struct eachContext {
|
317
|
+
cpSpatialIndexIteratorFunc func;
|
299
318
|
void *data;
|
300
|
-
}
|
319
|
+
} eachContext;
|
301
320
|
|
302
|
-
static void eachHelper(cpHandle *hand,
|
321
|
+
static void eachHelper(cpHandle *hand, eachContext *context){context->func(hand->obj, context->data);}
|
303
322
|
|
304
|
-
|
305
|
-
void
|
306
|
-
cpSpaceHashEach(cpSpaceHash *hash, cpSpaceHashIterator func, void *data)
|
323
|
+
static void
|
324
|
+
cpSpaceHashEach(cpSpaceHash *hash, cpSpatialIndexIteratorFunc func, void *data)
|
307
325
|
{
|
308
|
-
|
309
|
-
cpHashSetEach(hash->handleSet, (
|
326
|
+
eachContext context = {func, data};
|
327
|
+
cpHashSetEach(hash->handleSet, (cpHashSetIteratorFunc)eachHelper, &context);
|
310
328
|
}
|
311
329
|
|
312
|
-
static
|
313
|
-
|
330
|
+
static void
|
331
|
+
remove_orphaned_handles(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr)
|
314
332
|
{
|
315
333
|
cpSpaceHashBin *bin = *bin_ptr;
|
316
334
|
while(bin){
|
@@ -331,9 +349,10 @@ removeOrphanedHandles(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr)
|
|
331
349
|
}
|
332
350
|
}
|
333
351
|
|
334
|
-
//
|
352
|
+
//MARK: Query Functions
|
353
|
+
|
335
354
|
static inline void
|
336
|
-
|
355
|
+
query_helper(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr, void *obj, cpSpatialIndexQueryFunc func, void *data)
|
337
356
|
{
|
338
357
|
restart:
|
339
358
|
for(cpSpaceHashBin *bin = *bin_ptr; bin; bin = bin->next){
|
@@ -348,24 +367,14 @@ query(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr, void *obj, cpSpaceHashQueryFu
|
|
348
367
|
} else {
|
349
368
|
// The object for this handle has been removed
|
350
369
|
// cleanup this cell and restart the query
|
351
|
-
|
370
|
+
remove_orphaned_handles(hash, bin_ptr);
|
352
371
|
goto restart; // GCC not smart enough/able to tail call an inlined function.
|
353
372
|
}
|
354
373
|
}
|
355
374
|
}
|
356
375
|
|
357
|
-
void
|
358
|
-
|
359
|
-
{
|
360
|
-
cpFloat dim = hash->celldim;
|
361
|
-
int idx = hash_func(floor_int(point.x/dim), floor_int(point.y/dim), hash->numcells); // Fix by ShiftZ
|
362
|
-
|
363
|
-
query(hash, &hash->table[idx], &point, func, data);
|
364
|
-
hash->stamp++;
|
365
|
-
}
|
366
|
-
|
367
|
-
void
|
368
|
-
cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc func, void *data)
|
376
|
+
static void
|
377
|
+
cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
|
369
378
|
{
|
370
379
|
// Get the dimensions in cell coordinates.
|
371
380
|
cpFloat dim = hash->celldim;
|
@@ -380,7 +389,7 @@ cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc fun
|
|
380
389
|
// Iterate over the cells and query them.
|
381
390
|
for(int i=l; i<=r; i++){
|
382
391
|
for(int j=b; j<=t; j++){
|
383
|
-
|
392
|
+
query_helper(hash, &table[hash_func(i,j,n)], obj, func, data);
|
384
393
|
}
|
385
394
|
}
|
386
395
|
|
@@ -388,28 +397,25 @@ cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc fun
|
|
388
397
|
}
|
389
398
|
|
390
399
|
// Similar to struct eachPair above.
|
391
|
-
typedef struct
|
400
|
+
typedef struct queryRehashContext {
|
392
401
|
cpSpaceHash *hash;
|
393
|
-
|
402
|
+
cpSpatialIndexQueryFunc func;
|
394
403
|
void *data;
|
395
|
-
}
|
404
|
+
} queryRehashContext;
|
396
405
|
|
397
406
|
// Hashset iterator func used with cpSpaceHashQueryRehash().
|
398
407
|
static void
|
399
|
-
|
408
|
+
queryRehash_helper(cpHandle *hand, queryRehashContext *context)
|
400
409
|
{
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
queryRehashPair *pair = (queryRehashPair *)data;
|
405
|
-
cpSpaceHash *hash = pair->hash;
|
406
|
-
cpSpaceHashQueryFunc func = pair->func;
|
410
|
+
cpSpaceHash *hash = context->hash;
|
411
|
+
cpSpatialIndexQueryFunc func = context->func;
|
412
|
+
void *data = context->data;
|
407
413
|
|
408
414
|
cpFloat dim = hash->celldim;
|
409
415
|
int n = hash->numcells;
|
410
416
|
|
411
417
|
void *obj = hand->obj;
|
412
|
-
cpBB bb = hash->bbfunc(obj);
|
418
|
+
cpBB bb = hash->spatialIndex.bbfunc(obj);
|
413
419
|
|
414
420
|
int l = floor_int(bb.l/dim);
|
415
421
|
int r = floor_int(bb.r/dim);
|
@@ -420,13 +426,13 @@ handleQueryRehashHelper(void *elt, void *data)
|
|
420
426
|
|
421
427
|
for(int i=l; i<=r; i++){
|
422
428
|
for(int j=b; j<=t; j++){
|
423
|
-
|
429
|
+
cpHashValue idx = hash_func(i,j,n);
|
424
430
|
cpSpaceHashBin *bin = table[idx];
|
425
431
|
|
426
432
|
if(containsHandle(bin, hand)) continue;
|
427
433
|
|
428
434
|
cpHandleRetain(hand); // this MUST be done first in case the object is removed in func()
|
429
|
-
|
435
|
+
query_helper(hash, &bin, obj, func, data);
|
430
436
|
|
431
437
|
cpSpaceHashBin *newBin = getEmptyBin(hash);
|
432
438
|
newBin->handle = hand;
|
@@ -439,17 +445,19 @@ handleQueryRehashHelper(void *elt, void *data)
|
|
439
445
|
hash->stamp++;
|
440
446
|
}
|
441
447
|
|
442
|
-
void
|
443
|
-
|
448
|
+
static void
|
449
|
+
cpSpaceHashReindexQuery(cpSpaceHash *hash, cpSpatialIndexQueryFunc func, void *data)
|
444
450
|
{
|
445
|
-
|
451
|
+
clearTable(hash);
|
446
452
|
|
447
|
-
|
448
|
-
cpHashSetEach(hash->handleSet,
|
453
|
+
queryRehashContext context = {hash, func, data};
|
454
|
+
cpHashSetEach(hash->handleSet, (cpHashSetIteratorFunc)queryRehash_helper, &context);
|
455
|
+
|
456
|
+
cpSpatialIndexCollideStatic((cpSpatialIndex *)hash, hash->spatialIndex.staticIndex, func, data);
|
449
457
|
}
|
450
458
|
|
451
459
|
static inline cpFloat
|
452
|
-
|
460
|
+
segmentQuery_helper(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr, void *obj, cpSpatialIndexSegmentQueryFunc func, void *data)
|
453
461
|
{
|
454
462
|
cpFloat t = 1.0f;
|
455
463
|
|
@@ -467,7 +475,7 @@ segmentQuery(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr, void *obj, cpSpaceHash
|
|
467
475
|
} else {
|
468
476
|
// The object for this handle has been removed
|
469
477
|
// cleanup this cell and restart the query
|
470
|
-
|
478
|
+
remove_orphaned_handles(hash, bin_ptr);
|
471
479
|
goto restart; // GCC not smart enough/able to tail call an inlined function.
|
472
480
|
}
|
473
481
|
}
|
@@ -476,7 +484,8 @@ segmentQuery(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr, void *obj, cpSpaceHash
|
|
476
484
|
}
|
477
485
|
|
478
486
|
// modified from http://playtechs.blogspot.com/2007/03/raytracing-on-grid.html
|
479
|
-
|
487
|
+
static void
|
488
|
+
cpSpaceHashSegmentQuery(cpSpaceHash *hash, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data)
|
480
489
|
{
|
481
490
|
a = cpvmult(a, 1.0f/hash->celldim);
|
482
491
|
b = cpvmult(b, 1.0f/hash->celldim);
|
@@ -512,12 +521,12 @@ void cpSpaceHashSegmentQuery(cpSpaceHash *hash, void *obj, cpVect a, cpVect b, c
|
|
512
521
|
cpFloat next_h = (temp_h ? temp_h*dt_dx : dt_dx);
|
513
522
|
cpFloat next_v = (temp_v ? temp_v*dt_dy : dt_dy);
|
514
523
|
|
524
|
+
int n = hash->numcells;
|
515
525
|
cpSpaceHashBin **table = hash->table;
|
516
526
|
|
517
|
-
int n = hash->numcells;
|
518
527
|
while(t < t_exit){
|
519
|
-
|
520
|
-
t_exit = cpfmin(t_exit,
|
528
|
+
cpHashValue idx = hash_func(cell_x, cell_y, n);
|
529
|
+
t_exit = cpfmin(t_exit, segmentQuery_helper(hash, &table[idx], obj, func, data));
|
521
530
|
|
522
531
|
if (next_v < next_h){
|
523
532
|
cell_y += y_inc;
|
@@ -532,3 +541,94 @@ void cpSpaceHashSegmentQuery(cpSpaceHash *hash, void *obj, cpVect a, cpVect b, c
|
|
532
541
|
|
533
542
|
hash->stamp++;
|
534
543
|
}
|
544
|
+
|
545
|
+
//MARK: Misc
|
546
|
+
|
547
|
+
void
|
548
|
+
cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells)
|
549
|
+
{
|
550
|
+
if(hash->spatialIndex.klass != Klass()){
|
551
|
+
cpAssertWarn(cpFalse, "Ignoring cpSpaceHashResize() call to non-cpSpaceHash spatial index.");
|
552
|
+
return;
|
553
|
+
}
|
554
|
+
|
555
|
+
clearTable(hash);
|
556
|
+
|
557
|
+
hash->celldim = celldim;
|
558
|
+
cpSpaceHashAllocTable(hash, next_prime(numcells));
|
559
|
+
}
|
560
|
+
|
561
|
+
static int
|
562
|
+
cpSpaceHashCount(cpSpaceHash *hash)
|
563
|
+
{
|
564
|
+
return cpHashSetCount(hash->handleSet);
|
565
|
+
}
|
566
|
+
|
567
|
+
static int
|
568
|
+
cpSpaceHashContains(cpSpaceHash *hash, void *obj, cpHashValue hashid)
|
569
|
+
{
|
570
|
+
return cpHashSetFind(hash->handleSet, hashid, obj) != NULL;
|
571
|
+
}
|
572
|
+
|
573
|
+
static cpSpatialIndexClass klass = {
|
574
|
+
(cpSpatialIndexDestroyImpl)cpSpaceHashDestroy,
|
575
|
+
|
576
|
+
(cpSpatialIndexCountImpl)cpSpaceHashCount,
|
577
|
+
(cpSpatialIndexEachImpl)cpSpaceHashEach,
|
578
|
+
(cpSpatialIndexContainsImpl)cpSpaceHashContains,
|
579
|
+
|
580
|
+
(cpSpatialIndexInsertImpl)cpSpaceHashInsert,
|
581
|
+
(cpSpatialIndexRemoveImpl)cpSpaceHashRemove,
|
582
|
+
|
583
|
+
(cpSpatialIndexReindexImpl)cpSpaceHashRehash,
|
584
|
+
(cpSpatialIndexReindexObjectImpl)cpSpaceHashRehashObject,
|
585
|
+
(cpSpatialIndexReindexQueryImpl)cpSpaceHashReindexQuery,
|
586
|
+
|
587
|
+
(cpSpatialIndexQueryImpl)cpSpaceHashQuery,
|
588
|
+
(cpSpatialIndexSegmentQueryImpl)cpSpaceHashSegmentQuery,
|
589
|
+
};
|
590
|
+
|
591
|
+
static inline cpSpatialIndexClass *Klass(){return &klass;}
|
592
|
+
|
593
|
+
//MARK: Debug Drawing
|
594
|
+
|
595
|
+
//#define CP_BBTREE_DEBUG_DRAW
|
596
|
+
#ifdef CP_BBTREE_DEBUG_DRAW
|
597
|
+
#include "OpenGL/gl.h"
|
598
|
+
#include "OpenGL/glu.h"
|
599
|
+
#include <GLUT/glut.h>
|
600
|
+
|
601
|
+
void
|
602
|
+
cpSpaceHashRenderDebug(cpSpatialIndex *index)
|
603
|
+
{
|
604
|
+
if(index->klass != &klass){
|
605
|
+
cpAssertWarn(cpFalse, "Ignoring cpSpaceHashRenderDebug() call to non-spatial hash spatial index.");
|
606
|
+
return;
|
607
|
+
}
|
608
|
+
|
609
|
+
cpSpaceHash *hash = (cpSpaceHash *)index;
|
610
|
+
cpBB bb = cpBBNew(-320, -240, 320, 240);
|
611
|
+
|
612
|
+
cpFloat dim = hash->celldim;
|
613
|
+
int n = hash->numcells;
|
614
|
+
|
615
|
+
int l = (int)floor(bb.l/dim);
|
616
|
+
int r = (int)floor(bb.r/dim);
|
617
|
+
int b = (int)floor(bb.b/dim);
|
618
|
+
int t = (int)floor(bb.t/dim);
|
619
|
+
|
620
|
+
for(int i=l; i<=r; i++){
|
621
|
+
for(int j=b; j<=t; j++){
|
622
|
+
int cell_count = 0;
|
623
|
+
|
624
|
+
int index = hash_func(i,j,n);
|
625
|
+
for(cpSpaceHashBin *bin = hash->table[index]; bin; bin = bin->next)
|
626
|
+
cell_count++;
|
627
|
+
|
628
|
+
GLfloat v = 1.0f - (GLfloat)cell_count/10.0f;
|
629
|
+
glColor3f(v,v,v);
|
630
|
+
glRectf(i*dim, j*dim, (i + 1)*dim, (j + 1)*dim);
|
631
|
+
}
|
632
|
+
}
|
633
|
+
}
|
634
|
+
#endif
|