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