chipmunk 4.1.0 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|