chipmunk 4.1.0 → 5.2.0
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/LICENSE +20 -0
- data/README +60 -0
- data/Rakefile +47 -40
- data/ext/chipmunk/chipmunk.c +39 -3
- data/ext/chipmunk/cpArbiter.c +91 -80
- data/ext/chipmunk/cpArray.c +24 -10
- data/ext/chipmunk/cpBB.c +5 -4
- data/ext/chipmunk/cpBody.c +30 -22
- data/ext/chipmunk/cpCollision.c +54 -53
- data/ext/chipmunk/cpConstraint.c +54 -0
- data/ext/chipmunk/cpDampedRotarySpring.c +106 -0
- data/ext/chipmunk/cpDampedSpring.c +117 -0
- data/ext/chipmunk/cpGearJoint.c +114 -0
- data/ext/chipmunk/cpGrooveJoint.c +138 -0
- data/ext/chipmunk/cpHashSet.c +74 -40
- data/ext/chipmunk/cpPinJoint.c +117 -0
- data/ext/chipmunk/cpPivotJoint.c +114 -0
- data/ext/chipmunk/cpPolyShape.c +117 -15
- data/ext/chipmunk/cpRatchetJoint.c +128 -0
- data/ext/chipmunk/cpRotaryLimitJoint.c +122 -0
- data/ext/chipmunk/cpShape.c +174 -18
- data/ext/chipmunk/cpSimpleMotor.c +99 -0
- data/ext/chipmunk/cpSlideJoint.c +131 -0
- data/ext/chipmunk/cpSpace.c +584 -215
- data/ext/chipmunk/cpSpaceHash.c +191 -105
- data/ext/chipmunk/cpVect.c +18 -10
- data/ext/chipmunk/extconf.rb +34 -4
- data/ext/chipmunk/{chipmunk.h → include/chipmunk/chipmunk.h} +63 -6
- data/ext/chipmunk/include/chipmunk/chipmunk_ffi.h +42 -0
- data/ext/chipmunk/include/chipmunk/chipmunk_types.h +80 -0
- data/ext/chipmunk/include/chipmunk/chipmunk_unsafe.h +54 -0
- data/ext/chipmunk/include/chipmunk/constraints/cpConstraint.h +92 -0
- data/ext/chipmunk/include/chipmunk/constraints/cpDampedRotarySpring.h +46 -0
- data/ext/chipmunk/include/chipmunk/constraints/cpDampedSpring.h +53 -0
- data/ext/chipmunk/include/chipmunk/constraints/cpGearJoint.h +41 -0
- data/ext/chipmunk/include/chipmunk/constraints/cpGrooveJoint.h +44 -0
- data/ext/chipmunk/include/chipmunk/constraints/cpPinJoint.h +43 -0
- data/ext/chipmunk/include/chipmunk/constraints/cpPivotJoint.h +42 -0
- data/ext/chipmunk/include/chipmunk/constraints/cpRatchetJoint.h +40 -0
- data/ext/chipmunk/include/chipmunk/constraints/cpRotaryLimitJoint.h +39 -0
- data/ext/chipmunk/include/chipmunk/constraints/cpSimpleMotor.h +37 -0
- data/ext/chipmunk/include/chipmunk/constraints/cpSlideJoint.h +44 -0
- data/ext/chipmunk/include/chipmunk/constraints/util.h +116 -0
- data/ext/chipmunk/{cpArbiter.h → include/chipmunk/cpArbiter.h} +66 -15
- data/ext/chipmunk/{cpArray.h → include/chipmunk/cpArray.h} +2 -1
- data/ext/chipmunk/{cpBB.h → include/chipmunk/cpBB.h} +21 -0
- data/ext/chipmunk/{cpBody.h → include/chipmunk/cpBody.h} +37 -9
- data/ext/chipmunk/{cpCollision.h → include/chipmunk/cpCollision.h} +1 -1
- data/ext/chipmunk/{cpHashSet.h → include/chipmunk/cpHashSet.h} +12 -9
- data/ext/chipmunk/{cpPolyShape.h → include/chipmunk/cpPolyShape.h} +13 -2
- data/ext/chipmunk/{cpShape.h → include/chipmunk/cpShape.h} +51 -18
- data/ext/chipmunk/include/chipmunk/cpSpace.h +180 -0
- data/ext/chipmunk/{cpSpaceHash.h → include/chipmunk/cpSpaceHash.h} +18 -9
- data/ext/chipmunk/{cpVect.h → include/chipmunk/cpVect.h} +61 -10
- data/ext/chipmunk/prime.h +32 -32
- data/ext/chipmunk/rb_chipmunk.c +125 -109
- data/ext/chipmunk/rb_chipmunk.h +96 -77
- data/ext/chipmunk/rb_cpArbiter.c +225 -0
- data/ext/chipmunk/rb_cpBB.c +174 -154
- data/ext/chipmunk/rb_cpBody.c +347 -239
- data/ext/chipmunk/rb_cpConstraint.c +346 -0
- data/ext/chipmunk/rb_cpShape.c +455 -292
- data/ext/chipmunk/rb_cpSpace.c +544 -330
- data/ext/chipmunk/rb_cpVect.c +321 -250
- data/lib/chipmunk.rb +28 -15
- data/lib/chipmunk/version.rb +3 -0
- metadata +74 -34
- data/ext/chipmunk/cpJoint.c +0 -553
- data/ext/chipmunk/cpJoint.h +0 -122
- data/ext/chipmunk/cpSpace.h +0 -120
- data/ext/chipmunk/rb_cpJoint.c +0 -136
data/ext/chipmunk/cpSpaceHash.c
CHANGED
@@ -18,21 +18,14 @@
|
|
18
18
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
19
|
* SOFTWARE.
|
20
20
|
*/
|
21
|
-
|
21
|
+
|
22
|
+
#include <math.h>
|
22
23
|
#include <stdlib.h>
|
23
24
|
#include <stdio.h>
|
24
|
-
#include <math.h>
|
25
|
-
#include <assert.h>
|
26
25
|
|
27
26
|
#include "chipmunk.h"
|
28
27
|
#include "prime.h"
|
29
28
|
|
30
|
-
static cpHandle*
|
31
|
-
cpHandleAlloc(void)
|
32
|
-
{
|
33
|
-
return (cpHandle *)malloc(sizeof(cpHandle));
|
34
|
-
}
|
35
|
-
|
36
29
|
static cpHandle*
|
37
30
|
cpHandleInit(cpHandle *hand, void *obj)
|
38
31
|
{
|
@@ -43,12 +36,6 @@ cpHandleInit(cpHandle *hand, void *obj)
|
|
43
36
|
return hand;
|
44
37
|
}
|
45
38
|
|
46
|
-
static cpHandle*
|
47
|
-
cpHandleNew(void *obj)
|
48
|
-
{
|
49
|
-
return cpHandleInit(cpHandleAlloc(), obj);
|
50
|
-
}
|
51
|
-
|
52
39
|
static inline void
|
53
40
|
cpHandleRetain(cpHandle *hand)
|
54
41
|
{
|
@@ -56,34 +43,26 @@ cpHandleRetain(cpHandle *hand)
|
|
56
43
|
}
|
57
44
|
|
58
45
|
static inline void
|
59
|
-
|
60
|
-
{
|
61
|
-
free(hand);
|
62
|
-
}
|
63
|
-
|
64
|
-
static inline void
|
65
|
-
cpHandleRelease(cpHandle *hand)
|
46
|
+
cpHandleRelease(cpHandle *hand, cpArray *pooledHandles)
|
66
47
|
{
|
67
48
|
hand->retain--;
|
68
|
-
if(hand->retain == 0)
|
69
|
-
cpHandleFree(hand);
|
49
|
+
if(hand->retain == 0) cpArrayPush(pooledHandles, hand);
|
70
50
|
}
|
71
51
|
|
72
|
-
|
73
52
|
cpSpaceHash*
|
74
53
|
cpSpaceHashAlloc(void)
|
75
54
|
{
|
76
|
-
return (cpSpaceHash *)
|
55
|
+
return (cpSpaceHash *)cpcalloc(1, sizeof(cpSpaceHash));
|
77
56
|
}
|
78
57
|
|
79
58
|
// Frees the old table, and allocates a new one.
|
80
59
|
static void
|
81
60
|
cpSpaceHashAllocTable(cpSpaceHash *hash, int numcells)
|
82
61
|
{
|
83
|
-
|
62
|
+
cpfree(hash->table);
|
84
63
|
|
85
64
|
hash->numcells = numcells;
|
86
|
-
hash->table = (cpSpaceHashBin **)
|
65
|
+
hash->table = (cpSpaceHashBin **)cpcalloc(numcells, sizeof(cpSpaceHashBin *));
|
87
66
|
}
|
88
67
|
|
89
68
|
// Equality function for the handleset.
|
@@ -96,9 +75,20 @@ handleSetEql(void *obj, void *elt)
|
|
96
75
|
|
97
76
|
// Transformation function for the handleset.
|
98
77
|
static void *
|
99
|
-
handleSetTrans(void *obj,
|
78
|
+
handleSetTrans(void *obj, cpSpaceHash *hash)
|
100
79
|
{
|
101
|
-
|
80
|
+
if(hash->pooledHandles->num == 0){
|
81
|
+
// handle pool is exhausted, make more
|
82
|
+
int count = CP_BUFFER_BYTES/sizeof(cpHandle);
|
83
|
+
cpAssert(count, "Buffer size is too small.");
|
84
|
+
|
85
|
+
cpHandle *buffer = (cpHandle *)cpmalloc(CP_BUFFER_BYTES);
|
86
|
+
cpArrayPush(hash->allocatedBuffers, buffer);
|
87
|
+
|
88
|
+
for(int i=0; i<count; i++) cpArrayPush(hash->pooledHandles, buffer + i);
|
89
|
+
}
|
90
|
+
|
91
|
+
cpHandle *hand = cpHandleInit(cpArrayPop(hash->pooledHandles), obj);
|
102
92
|
cpHandleRetain(hand);
|
103
93
|
|
104
94
|
return hand;
|
@@ -111,8 +101,11 @@ cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int numcells, cpSpaceHashBBF
|
|
111
101
|
hash->celldim = celldim;
|
112
102
|
hash->bbfunc = bbfunc;
|
113
103
|
|
114
|
-
hash->
|
115
|
-
hash->
|
104
|
+
hash->handleSet = cpHashSetNew(0, handleSetEql, (cpHashSetTransFunc)handleSetTrans);
|
105
|
+
hash->pooledHandles = cpArrayNew(0);
|
106
|
+
|
107
|
+
hash->pooledBins = NULL;
|
108
|
+
hash->allocatedBuffers = cpArrayNew(0);
|
116
109
|
|
117
110
|
hash->stamp = 1;
|
118
111
|
|
@@ -126,22 +119,27 @@ cpSpaceHashNew(cpFloat celldim, int cells, cpSpaceHashBBFunc bbfunc)
|
|
126
119
|
}
|
127
120
|
|
128
121
|
static inline void
|
129
|
-
|
122
|
+
recycleBin(cpSpaceHash *hash, cpSpaceHashBin *bin)
|
130
123
|
{
|
131
|
-
|
124
|
+
bin->next = hash->pooledBins;
|
125
|
+
hash->pooledBins = bin;
|
126
|
+
}
|
127
|
+
|
128
|
+
static inline void
|
129
|
+
clearHashCell(cpSpaceHash *hash, int idx)
|
130
|
+
{
|
131
|
+
cpSpaceHashBin *bin = hash->table[idx];
|
132
132
|
while(bin){
|
133
133
|
cpSpaceHashBin *next = bin->next;
|
134
134
|
|
135
135
|
// Release the lock on the handle.
|
136
|
-
cpHandleRelease(bin->handle);
|
137
|
-
|
138
|
-
bin->next = hash->bins;
|
139
|
-
hash->bins = bin;
|
136
|
+
cpHandleRelease(bin->handle, hash->pooledHandles);
|
137
|
+
recycleBin(hash, bin);
|
140
138
|
|
141
139
|
bin = next;
|
142
140
|
}
|
143
141
|
|
144
|
-
hash->table[
|
142
|
+
hash->table[idx] = NULL;
|
145
143
|
}
|
146
144
|
|
147
145
|
// Clear all cells in the hashtable.
|
@@ -152,45 +150,29 @@ clearHash(cpSpaceHash *hash)
|
|
152
150
|
clearHashCell(hash, i);
|
153
151
|
}
|
154
152
|
|
155
|
-
|
156
|
-
static void
|
157
|
-
freeBins(cpSpaceHash *hash)
|
158
|
-
{
|
159
|
-
cpSpaceHashBin *bin = hash->bins;
|
160
|
-
while(bin){
|
161
|
-
cpSpaceHashBin *next = bin->next;
|
162
|
-
free(bin);
|
163
|
-
bin = next;
|
164
|
-
}
|
165
|
-
}
|
166
|
-
|
167
|
-
// Hashset iterator function to free the handles.
|
168
|
-
static void
|
169
|
-
handleFreeWrap(void *elt, void *unused)
|
170
|
-
{
|
171
|
-
cpHandle *hand = (cpHandle *)elt;
|
172
|
-
cpHandleFree(hand);
|
173
|
-
}
|
153
|
+
static void freeWrap(void *ptr, void *unused){cpfree(ptr);}
|
174
154
|
|
175
155
|
void
|
176
156
|
cpSpaceHashDestroy(cpSpaceHash *hash)
|
177
157
|
{
|
178
158
|
clearHash(hash);
|
179
|
-
freeBins(hash);
|
180
159
|
|
181
|
-
// Free the handles.
|
182
|
-
cpHashSetEach(hash->handleSet, &handleFreeWrap, NULL);
|
183
160
|
cpHashSetFree(hash->handleSet);
|
184
161
|
|
185
|
-
|
162
|
+
cpArrayEach(hash->allocatedBuffers, freeWrap, NULL);
|
163
|
+
cpArrayFree(hash->allocatedBuffers);
|
164
|
+
cpArrayFree(hash->pooledHandles);
|
165
|
+
|
166
|
+
cpfree(hash->table);
|
186
167
|
}
|
187
168
|
|
188
169
|
void
|
189
170
|
cpSpaceHashFree(cpSpaceHash *hash)
|
190
171
|
{
|
191
|
-
if(
|
192
|
-
|
193
|
-
|
172
|
+
if(hash){
|
173
|
+
cpSpaceHashDestroy(hash);
|
174
|
+
cpfree(hash);
|
175
|
+
}
|
194
176
|
}
|
195
177
|
|
196
178
|
void
|
@@ -219,20 +201,39 @@ containsHandle(cpSpaceHashBin *bin, cpHandle *hand)
|
|
219
201
|
static inline cpSpaceHashBin *
|
220
202
|
getEmptyBin(cpSpaceHash *hash)
|
221
203
|
{
|
222
|
-
cpSpaceHashBin *bin = hash->
|
204
|
+
cpSpaceHashBin *bin = hash->pooledBins;
|
223
205
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
206
|
+
if(bin){
|
207
|
+
hash->pooledBins = bin->next;
|
208
|
+
return bin;
|
209
|
+
} else {
|
210
|
+
// Pool is exhausted, make more
|
211
|
+
int count = CP_BUFFER_BYTES/sizeof(cpSpaceHashBin);
|
212
|
+
cpAssert(count, "Buffer size is too small.");
|
213
|
+
|
214
|
+
cpSpaceHashBin *buffer = (cpSpaceHashBin *)cpmalloc(CP_BUFFER_BYTES);
|
215
|
+
cpArrayPush(hash->allocatedBuffers, buffer);
|
216
|
+
|
217
|
+
// push all but the first one, return the first instead
|
218
|
+
for(int i=1; i<count; i++) recycleBin(hash, buffer + i);
|
219
|
+
return buffer;
|
220
|
+
}
|
229
221
|
}
|
230
222
|
|
231
223
|
// The hash function itself.
|
232
|
-
static inline
|
233
|
-
hash_func(
|
224
|
+
static inline cpHashValue
|
225
|
+
hash_func(cpHashValue x, cpHashValue y, cpHashValue n)
|
226
|
+
{
|
227
|
+
return (x*1640531513ul ^ y*2654435789ul) % n;
|
228
|
+
}
|
229
|
+
|
230
|
+
// Much faster than (int)floor(f)
|
231
|
+
// Profiling showed floor() to be a sizable performance hog
|
232
|
+
static inline int
|
233
|
+
floor_int(cpFloat f)
|
234
234
|
{
|
235
|
-
|
235
|
+
int i = (int)f;
|
236
|
+
return (f < 0.0f && f != i ? i - 1 : i);
|
236
237
|
}
|
237
238
|
|
238
239
|
static inline void
|
@@ -240,16 +241,16 @@ hashHandle(cpSpaceHash *hash, cpHandle *hand, cpBB bb)
|
|
240
241
|
{
|
241
242
|
// Find the dimensions in cell coordinates.
|
242
243
|
cpFloat dim = hash->celldim;
|
243
|
-
int l = bb.l/dim;
|
244
|
-
int r = bb.r/dim;
|
245
|
-
int b = bb.b/dim;
|
246
|
-
int t = bb.t/dim;
|
244
|
+
int l = floor_int(bb.l/dim); // Fix by ShiftZ
|
245
|
+
int r = floor_int(bb.r/dim);
|
246
|
+
int b = floor_int(bb.b/dim);
|
247
|
+
int t = floor_int(bb.t/dim);
|
247
248
|
|
248
249
|
int n = hash->numcells;
|
249
250
|
for(int i=l; i<=r; i++){
|
250
251
|
for(int j=b; j<=t; j++){
|
251
|
-
int
|
252
|
-
cpSpaceHashBin *bin = hash->table[
|
252
|
+
int idx = hash_func(i,j,n);
|
253
|
+
cpSpaceHashBin *bin = hash->table[idx];
|
253
254
|
|
254
255
|
// Don't add an object twice to the same cell.
|
255
256
|
if(containsHandle(bin, hand)) continue;
|
@@ -259,22 +260,22 @@ hashHandle(cpSpaceHash *hash, cpHandle *hand, cpBB bb)
|
|
259
260
|
cpSpaceHashBin *newBin = getEmptyBin(hash);
|
260
261
|
newBin->handle = hand;
|
261
262
|
newBin->next = bin;
|
262
|
-
hash->table[
|
263
|
+
hash->table[idx] = newBin;
|
263
264
|
}
|
264
265
|
}
|
265
266
|
}
|
266
267
|
|
267
268
|
void
|
268
|
-
cpSpaceHashInsert(cpSpaceHash *hash, void *obj,
|
269
|
+
cpSpaceHashInsert(cpSpaceHash *hash, void *obj, cpHashValue hashid, cpBB bb)
|
269
270
|
{
|
270
|
-
cpHandle *hand = (cpHandle *)cpHashSetInsert(hash->handleSet,
|
271
|
+
cpHandle *hand = (cpHandle *)cpHashSetInsert(hash->handleSet, hashid, obj, hash);
|
271
272
|
hashHandle(hash, hand, bb);
|
272
273
|
}
|
273
274
|
|
274
275
|
void
|
275
|
-
cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj,
|
276
|
+
cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, cpHashValue hashid)
|
276
277
|
{
|
277
|
-
cpHandle *hand = (cpHandle *)cpHashSetFind(hash->handleSet,
|
278
|
+
cpHandle *hand = (cpHandle *)cpHashSetFind(hash->handleSet, hashid, obj);
|
278
279
|
hashHandle(hash, hand, hash->bbfunc(obj));
|
279
280
|
}
|
280
281
|
|
@@ -298,13 +299,13 @@ cpSpaceHashRehash(cpSpaceHash *hash)
|
|
298
299
|
}
|
299
300
|
|
300
301
|
void
|
301
|
-
cpSpaceHashRemove(cpSpaceHash *hash, void *obj,
|
302
|
+
cpSpaceHashRemove(cpSpaceHash *hash, void *obj, cpHashValue hashid)
|
302
303
|
{
|
303
|
-
cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet,
|
304
|
+
cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet, hashid, obj);
|
304
305
|
|
305
306
|
if(hand){
|
306
307
|
hand->obj = NULL;
|
307
|
-
cpHandleRelease(hand);
|
308
|
+
cpHandleRelease(hand, hash->pooledHandles);
|
308
309
|
}
|
309
310
|
}
|
310
311
|
|
@@ -363,9 +364,9 @@ void
|
|
363
364
|
cpSpaceHashPointQuery(cpSpaceHash *hash, cpVect point, cpSpaceHashQueryFunc func, void *data)
|
364
365
|
{
|
365
366
|
cpFloat dim = hash->celldim;
|
366
|
-
int
|
367
|
+
int idx = hash_func(floor_int(point.x/dim), floor_int(point.y/dim), hash->numcells); // Fix by ShiftZ
|
367
368
|
|
368
|
-
query(hash, hash->table[
|
369
|
+
query(hash, hash->table[idx], &point, func, data);
|
369
370
|
|
370
371
|
// Increment the stamp.
|
371
372
|
// Only one cell is checked, but query() requires it anyway.
|
@@ -377,18 +378,18 @@ cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc fun
|
|
377
378
|
{
|
378
379
|
// Get the dimensions in cell coordinates.
|
379
380
|
cpFloat dim = hash->celldim;
|
380
|
-
int l = bb.l/dim;
|
381
|
-
int r = bb.r/dim;
|
382
|
-
int b = bb.b/dim;
|
383
|
-
int t = bb.t/dim;
|
381
|
+
int l = floor_int(bb.l/dim); // Fix by ShiftZ
|
382
|
+
int r = floor_int(bb.r/dim);
|
383
|
+
int b = floor_int(bb.b/dim);
|
384
|
+
int t = floor_int(bb.t/dim);
|
384
385
|
|
385
386
|
int n = hash->numcells;
|
386
387
|
|
387
388
|
// Iterate over the cells and query them.
|
388
389
|
for(int i=l; i<=r; i++){
|
389
390
|
for(int j=b; j<=t; j++){
|
390
|
-
int
|
391
|
-
query(hash, hash->table[
|
391
|
+
int idx = hash_func(i,j,n);
|
392
|
+
query(hash, hash->table[idx], obj, func, data);
|
392
393
|
}
|
393
394
|
}
|
394
395
|
|
@@ -420,27 +421,32 @@ handleQueryRehashHelper(void *elt, void *data)
|
|
420
421
|
void *obj = hand->obj;
|
421
422
|
cpBB bb = hash->bbfunc(obj);
|
422
423
|
|
423
|
-
int l = bb.l/dim;
|
424
|
-
int r = bb.r/dim;
|
425
|
-
int b = bb.b/dim;
|
426
|
-
int t = bb.t/dim;
|
424
|
+
int l = floor_int(bb.l/dim);
|
425
|
+
int r = floor_int(bb.r/dim);
|
426
|
+
int b = floor_int(bb.b/dim);
|
427
|
+
int t = floor_int(bb.t/dim);
|
427
428
|
|
428
429
|
for(int i=l; i<=r; i++){
|
429
430
|
for(int j=b; j<=t; j++){
|
430
|
-
|
431
|
-
|
431
|
+
// // exit the loops if the object has been deleted in func().
|
432
|
+
// if(!hand->obj) goto break_out;
|
433
|
+
|
434
|
+
int idx = hash_func(i,j,n);
|
435
|
+
cpSpaceHashBin *bin = hash->table[idx];
|
432
436
|
|
433
437
|
if(containsHandle(bin, hand)) continue;
|
438
|
+
|
439
|
+
cpHandleRetain(hand); // this MUST be done first in case the object is removed in func()
|
434
440
|
query(hash, bin, obj, func, pair->data);
|
435
441
|
|
436
|
-
cpHandleRetain(hand);
|
437
442
|
cpSpaceHashBin *newBin = getEmptyBin(hash);
|
438
443
|
newBin->handle = hand;
|
439
444
|
newBin->next = bin;
|
440
|
-
hash->table[
|
445
|
+
hash->table[idx] = newBin;
|
441
446
|
}
|
442
447
|
}
|
443
448
|
|
449
|
+
// break_out:
|
444
450
|
// Increment the stamp for each object we hash.
|
445
451
|
hash->stamp++;
|
446
452
|
}
|
@@ -449,7 +455,87 @@ void
|
|
449
455
|
cpSpaceHashQueryRehash(cpSpaceHash *hash, cpSpaceHashQueryFunc func, void *data)
|
450
456
|
{
|
451
457
|
clearHash(hash);
|
452
|
-
|
458
|
+
|
453
459
|
queryRehashPair pair = {hash, func, data};
|
454
460
|
cpHashSetEach(hash->handleSet, &handleQueryRehashHelper, &pair);
|
455
461
|
}
|
462
|
+
|
463
|
+
static inline cpFloat
|
464
|
+
segmentQuery(cpSpaceHash *hash, cpSpaceHashBin *bin, void *obj, cpSpaceHashSegmentQueryFunc func, void *data)
|
465
|
+
{
|
466
|
+
cpFloat t = 1.0f;
|
467
|
+
|
468
|
+
for(; bin; bin = bin->next){
|
469
|
+
cpHandle *hand = bin->handle;
|
470
|
+
void *other = hand->obj;
|
471
|
+
|
472
|
+
// Skip over certain conditions
|
473
|
+
if(
|
474
|
+
// Have we already tried this pair in this query?
|
475
|
+
hand->stamp == hash->stamp
|
476
|
+
// Has other been removed since the last rehash?
|
477
|
+
|| !other
|
478
|
+
) continue;
|
479
|
+
|
480
|
+
// Stamp that the handle was checked already against this object.
|
481
|
+
hand->stamp = hash->stamp;
|
482
|
+
|
483
|
+
t = cpfmin(t, func(obj, other, data));
|
484
|
+
}
|
485
|
+
|
486
|
+
return t;
|
487
|
+
}
|
488
|
+
|
489
|
+
// modified from http://playtechs.blogspot.com/2007/03/raytracing-on-grid.html
|
490
|
+
void cpSpaceHashSegmentQuery(cpSpaceHash *hash, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpaceHashSegmentQueryFunc func, void *data)
|
491
|
+
{
|
492
|
+
a = cpvmult(a, 1.0f/hash->celldim);
|
493
|
+
b = cpvmult(b, 1.0f/hash->celldim);
|
494
|
+
|
495
|
+
cpFloat dt_dx = 1.0f/cpfabs(b.x - a.x), dt_dy = 1.0f/cpfabs(b.y - a.y);
|
496
|
+
|
497
|
+
int cell_x = floor_int(a.x), cell_y = floor_int(a.y);
|
498
|
+
|
499
|
+
cpFloat t = 0;
|
500
|
+
|
501
|
+
int x_inc, y_inc;
|
502
|
+
cpFloat temp_v, temp_h;
|
503
|
+
|
504
|
+
if (b.x > a.x){
|
505
|
+
x_inc = 1;
|
506
|
+
temp_h = (cpffloor(a.x + 1.0f) - a.x);
|
507
|
+
} else {
|
508
|
+
x_inc = -1;
|
509
|
+
temp_h = (a.x - cpffloor(a.x));
|
510
|
+
}
|
511
|
+
|
512
|
+
if (b.y > a.y){
|
513
|
+
y_inc = 1;
|
514
|
+
temp_v = (cpffloor(a.y + 1.0f) - a.y);
|
515
|
+
} else {
|
516
|
+
y_inc = -1;
|
517
|
+
temp_v = (a.y - cpffloor(a.y));
|
518
|
+
}
|
519
|
+
|
520
|
+
// fix NANs in horizontal directions
|
521
|
+
cpFloat next_h = (temp_h ? temp_h*dt_dx : dt_dx);
|
522
|
+
cpFloat next_v = (temp_v ? temp_v*dt_dy : dt_dy);
|
523
|
+
|
524
|
+
int n = hash->numcells;
|
525
|
+
while(t < t_exit){
|
526
|
+
int idx = hash_func(cell_x, cell_y, n);
|
527
|
+
t_exit = cpfmin(t_exit, segmentQuery(hash, hash->table[idx], obj, func, data));
|
528
|
+
|
529
|
+
if (next_v < next_h){
|
530
|
+
cell_y += y_inc;
|
531
|
+
t = next_v;
|
532
|
+
next_v += dt_dy;
|
533
|
+
} else {
|
534
|
+
cell_x += x_inc;
|
535
|
+
t = next_h;
|
536
|
+
next_h += dt_dx;
|
537
|
+
}
|
538
|
+
}
|
539
|
+
|
540
|
+
hash->stamp++;
|
541
|
+
}
|