chipmunk 5.3.4.5 → 6.1.3.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. data/ext/chipmunk/chipmunk.c +199 -28
  2. data/ext/chipmunk/chipmunk.h +123 -68
  3. data/ext/chipmunk/chipmunk_ffi.h +129 -11
  4. data/ext/chipmunk/chipmunk_private.h +232 -16
  5. data/ext/chipmunk/chipmunk_types.h +94 -30
  6. data/ext/chipmunk/chipmunk_unsafe.h +12 -3
  7. data/ext/chipmunk/constraints/cpConstraint.h +90 -34
  8. data/ext/chipmunk/{cpDampedRotarySpring.h → constraints/cpDampedRotarySpring.h} +18 -8
  9. data/ext/chipmunk/{cpDampedSpring.h → constraints/cpDampedSpring.h} +27 -16
  10. data/ext/chipmunk/constraints/cpGearJoint.h +17 -7
  11. data/ext/chipmunk/constraints/cpGrooveJoint.h +19 -10
  12. data/ext/chipmunk/constraints/cpPinJoint.h +17 -8
  13. data/ext/chipmunk/constraints/cpPivotJoint.h +18 -9
  14. data/ext/chipmunk/constraints/cpRatchetJoint.h +17 -8
  15. data/ext/chipmunk/constraints/cpRotaryLimitJoint.h +16 -7
  16. data/ext/chipmunk/{cpSimpleMotor.h → constraints/cpSimpleMotor.h} +15 -6
  17. data/ext/chipmunk/constraints/cpSlideJoint.h +18 -9
  18. data/ext/chipmunk/constraints/util.h +36 -44
  19. data/ext/chipmunk/cpArbiter.c +159 -94
  20. data/ext/chipmunk/cpArbiter.h +135 -129
  21. data/ext/chipmunk/cpArray.c +37 -56
  22. data/ext/chipmunk/cpBB.c +1 -12
  23. data/ext/chipmunk/cpBB.h +80 -18
  24. data/ext/chipmunk/cpBBTree.c +891 -0
  25. data/ext/chipmunk/cpBody.c +185 -47
  26. data/ext/chipmunk/cpBody.h +156 -124
  27. data/ext/chipmunk/cpCollision.c +126 -115
  28. data/ext/chipmunk/cpConstraint.c +10 -6
  29. data/ext/chipmunk/cpDampedRotarySpring.c +26 -17
  30. data/ext/chipmunk/cpDampedSpring.c +25 -18
  31. data/ext/chipmunk/cpGearJoint.c +23 -17
  32. data/ext/chipmunk/cpGrooveJoint.c +26 -22
  33. data/ext/chipmunk/cpHashSet.c +51 -51
  34. data/ext/chipmunk/cpPinJoint.c +26 -19
  35. data/ext/chipmunk/cpPivotJoint.c +23 -19
  36. data/ext/chipmunk/cpPolyShape.c +93 -69
  37. data/ext/chipmunk/cpPolyShape.h +33 -69
  38. data/ext/chipmunk/cpRatchetJoint.c +26 -21
  39. data/ext/chipmunk/cpRotaryLimitJoint.c +28 -22
  40. data/ext/chipmunk/cpShape.c +122 -133
  41. data/ext/chipmunk/cpShape.h +146 -95
  42. data/ext/chipmunk/cpSimpleMotor.c +24 -17
  43. data/ext/chipmunk/cpSlideJoint.c +28 -26
  44. data/ext/chipmunk/cpSpace.c +251 -196
  45. data/ext/chipmunk/cpSpace.h +173 -103
  46. data/ext/chipmunk/cpSpaceComponent.c +236 -159
  47. data/ext/chipmunk/cpSpaceHash.c +259 -159
  48. data/ext/chipmunk/cpSpaceQuery.c +127 -59
  49. data/ext/chipmunk/cpSpaceStep.c +235 -197
  50. data/ext/chipmunk/cpSpatialIndex.c +69 -0
  51. data/ext/chipmunk/cpSpatialIndex.h +227 -0
  52. data/ext/chipmunk/cpSweep1D.c +254 -0
  53. data/ext/chipmunk/cpVect.c +11 -26
  54. data/ext/chipmunk/cpVect.h +76 -71
  55. data/ext/chipmunk/extconf.rb +4 -31
  56. data/ext/chipmunk/prime.h +1 -1
  57. data/ext/chipmunk/rb_chipmunk.c +36 -45
  58. data/ext/chipmunk/rb_chipmunk.h +6 -3
  59. data/ext/chipmunk/rb_cpArbiter.c +2 -2
  60. data/ext/chipmunk/rb_cpBB.c +116 -35
  61. data/ext/chipmunk/rb_cpBody.c +5 -12
  62. data/ext/chipmunk/rb_cpConstraint.c +144 -9
  63. data/ext/chipmunk/rb_cpShape.c +69 -78
  64. data/ext/chipmunk/rb_cpSpace.c +81 -76
  65. metadata +61 -61
  66. data/LICENSE +0 -22
  67. data/README +0 -110
  68. data/Rakefile +0 -102
  69. data/ext/chipmunk/cpArray.h +0 -49
  70. data/ext/chipmunk/cpCollision.h +0 -28
  71. data/ext/chipmunk/cpHashSet.h +0 -82
  72. data/ext/chipmunk/cpSpaceHash.h +0 -110
  73. data/lib/chipmunk.rb +0 -194
@@ -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
- cpAssert(count, "Buffer size is too small.");
80
+ cpAssertHard(count, "Internal Error: Buffer size is too small.");
74
81
 
75
- cpHandle *buffer = (cpHandle *)cpmalloc(CP_BUFFER_BYTES);
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 *) cpArrayPop(hash->pooledHandles), obj);
88
+ cpHandle *hand = cpHandleInit((cpHandle *)cpArrayPop(hash->pooledHandles), obj);
82
89
  cpHandleRetain(hand);
83
90
 
84
91
  return hand;
85
92
  }
86
93
 
87
- cpSpaceHash*
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
- cpSpaceHash*
106
- cpSpaceHashNew(cpFloat celldim, int cells, cpSpaceHashBBFunc bbfunc)
107
- {
108
- return cpSpaceHashInit(cpSpaceHashAlloc(), celldim, cells, bbfunc);
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
- clearHashCell(cpSpaceHash *hash, int idx)
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
- clearHash(cpSpaceHash *hash)
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
- static void freeWrap(void *ptr, void *unused){cpfree(ptr);}
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
- void
145
- cpSpaceHashDestroy(cpSpaceHash *hash)
153
+ //MARK: Memory Management Functions
154
+
155
+ cpSpaceHash *
156
+ cpSpaceHashAlloc(void)
146
157
  {
147
- clearHash(hash);
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
- cpHashSetFree(hash->handleSet);
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
- cpArrayEach(hash->allocatedBuffers, freeWrap, NULL);
152
- cpArrayFree(hash->allocatedBuffers);
153
- cpArrayFree(hash->pooledHandles);
178
+ cpSpaceHashAllocTable(hash, next_prime(numcells));
179
+ hash->celldim = celldim;
154
180
 
155
- cpfree(hash->table);
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
- void
159
- cpSpaceHashFree(cpSpaceHash *hash)
193
+ cpSpatialIndex *
194
+ cpSpaceHashNew(cpFloat celldim, int cells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
160
195
  {
161
- if(hash){
162
- cpSpaceHashDestroy(hash);
163
- cpfree(hash);
164
- }
196
+ return cpSpaceHashInit(cpSpaceHashAlloc(), celldim, cells, bbfunc, staticIndex);
165
197
  }
166
198
 
167
- void
168
- cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells)
199
+ static void
200
+ cpSpaceHashDestroy(cpSpaceHash *hash)
169
201
  {
170
- // Clear the hash to release the old handle locks.
171
- clearHash(hash);
202
+ if(hash->table) clearTable(hash);
203
+ cpfree(hash->table);
172
204
 
173
- hash->celldim = celldim;
174
- cpSpaceHashAllocTable(hash, next_prime(numcells));
205
+ cpHashSetFree(hash->handleSet);
206
+
207
+ cpArrayFreeEach(hash->allocatedBuffers, cpfree);
208
+ cpArrayFree(hash->allocatedBuffers);
209
+ cpArrayFree(hash->pooledHandles);
175
210
  }
176
211
 
177
- // Return true if the chain contains the handle.
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
- int idx = hash_func(i,j,n);
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
- void
258
- cpSpaceHashInsert(cpSpaceHash *hash, void *obj, cpHashValue hashid, cpBB _deprecated_unused)
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, cpBBNew(0.0f, 0.0f, 0.0f, 0.0f));
288
+ cpSpaceHashInsert(hash, obj, hashid);
274
289
  }
275
290
  }
276
291
 
277
- static void handleRehashHelper(cpHandle *hand, cpSpaceHash *hash){hashHandle(hash, hand, hash->bbfunc(hand->obj));}
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
- clearHash(hash);
283
- cpHashSetEach(hash->handleSet, (cpHashSetIterFunc)handleRehashHelper, hash);
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 eachPair {
298
- cpSpaceHashIterator func;
316
+ typedef struct eachContext {
317
+ cpSpatialIndexIteratorFunc func;
299
318
  void *data;
300
- } eachPair;
319
+ } eachContext;
301
320
 
302
- static void eachHelper(cpHandle *hand, eachPair *pair){pair->func(hand->obj, pair->data);}
321
+ static void eachHelper(cpHandle *hand, eachContext *context){context->func(hand->obj, context->data);}
303
322
 
304
- // Iterate over the objects in the spatial hash.
305
- void
306
- cpSpaceHashEach(cpSpaceHash *hash, cpSpaceHashIterator func, void *data)
323
+ static void
324
+ cpSpaceHashEach(cpSpaceHash *hash, cpSpatialIndexIteratorFunc func, void *data)
307
325
  {
308
- eachPair pair = {func, data};
309
- cpHashSetEach(hash->handleSet, (cpHashSetIterFunc)eachHelper, &pair);
326
+ eachContext context = {func, data};
327
+ cpHashSetEach(hash->handleSet, (cpHashSetIteratorFunc)eachHelper, &context);
310
328
  }
311
329
 
312
- static inline void
313
- removeOrphanedHandles(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr)
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
- // Calls the callback function for the objects in a given chain.
352
+ //MARK: Query Functions
353
+
335
354
  static inline void
336
- query(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr, void *obj, cpSpaceHashQueryFunc func, void *data)
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
- removeOrphanedHandles(hash, bin_ptr);
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
- cpSpaceHashPointQuery(cpSpaceHash *hash, cpVect point, cpSpaceHashQueryFunc func, void *data)
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
- query(hash, &table[hash_func(i,j,n)], obj, func, data);
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 queryRehashPair {
400
+ typedef struct queryRehashContext {
392
401
  cpSpaceHash *hash;
393
- cpSpaceHashQueryFunc func;
402
+ cpSpatialIndexQueryFunc func;
394
403
  void *data;
395
- } queryRehashPair;
404
+ } queryRehashContext;
396
405
 
397
406
  // Hashset iterator func used with cpSpaceHashQueryRehash().
398
407
  static void
399
- handleQueryRehashHelper(void *elt, void *data)
408
+ queryRehash_helper(cpHandle *hand, queryRehashContext *context)
400
409
  {
401
- cpHandle *hand = (cpHandle *)elt;
402
-
403
- // Unpack the user callback data.
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
- int idx = hash_func(i,j,n);
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
- query(hash, &bin, obj, func, pair->data);
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
- cpSpaceHashQueryRehash(cpSpaceHash *hash, cpSpaceHashQueryFunc func, void *data)
448
+ static void
449
+ cpSpaceHashReindexQuery(cpSpaceHash *hash, cpSpatialIndexQueryFunc func, void *data)
444
450
  {
445
- clearHash(hash);
451
+ clearTable(hash);
446
452
 
447
- queryRehashPair pair = {hash, func, data};
448
- cpHashSetEach(hash->handleSet, &handleQueryRehashHelper, &pair);
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
- segmentQuery(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr, void *obj, cpSpaceHashSegmentQueryFunc func, void *data)
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
- removeOrphanedHandles(hash, bin_ptr);
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
- void cpSpaceHashSegmentQuery(cpSpaceHash *hash, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpaceHashSegmentQueryFunc func, void *data)
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
- int idx = hash_func(cell_x, cell_y, n);
520
- t_exit = cpfmin(t_exit, segmentQuery(hash, &table[idx], obj, func, data));
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