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.
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