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.
Files changed (71) hide show
  1. data/LICENSE +20 -0
  2. data/README +60 -0
  3. data/Rakefile +47 -40
  4. data/ext/chipmunk/chipmunk.c +39 -3
  5. data/ext/chipmunk/cpArbiter.c +91 -80
  6. data/ext/chipmunk/cpArray.c +24 -10
  7. data/ext/chipmunk/cpBB.c +5 -4
  8. data/ext/chipmunk/cpBody.c +30 -22
  9. data/ext/chipmunk/cpCollision.c +54 -53
  10. data/ext/chipmunk/cpConstraint.c +54 -0
  11. data/ext/chipmunk/cpDampedRotarySpring.c +106 -0
  12. data/ext/chipmunk/cpDampedSpring.c +117 -0
  13. data/ext/chipmunk/cpGearJoint.c +114 -0
  14. data/ext/chipmunk/cpGrooveJoint.c +138 -0
  15. data/ext/chipmunk/cpHashSet.c +74 -40
  16. data/ext/chipmunk/cpPinJoint.c +117 -0
  17. data/ext/chipmunk/cpPivotJoint.c +114 -0
  18. data/ext/chipmunk/cpPolyShape.c +117 -15
  19. data/ext/chipmunk/cpRatchetJoint.c +128 -0
  20. data/ext/chipmunk/cpRotaryLimitJoint.c +122 -0
  21. data/ext/chipmunk/cpShape.c +174 -18
  22. data/ext/chipmunk/cpSimpleMotor.c +99 -0
  23. data/ext/chipmunk/cpSlideJoint.c +131 -0
  24. data/ext/chipmunk/cpSpace.c +584 -215
  25. data/ext/chipmunk/cpSpaceHash.c +191 -105
  26. data/ext/chipmunk/cpVect.c +18 -10
  27. data/ext/chipmunk/extconf.rb +34 -4
  28. data/ext/chipmunk/{chipmunk.h → include/chipmunk/chipmunk.h} +63 -6
  29. data/ext/chipmunk/include/chipmunk/chipmunk_ffi.h +42 -0
  30. data/ext/chipmunk/include/chipmunk/chipmunk_types.h +80 -0
  31. data/ext/chipmunk/include/chipmunk/chipmunk_unsafe.h +54 -0
  32. data/ext/chipmunk/include/chipmunk/constraints/cpConstraint.h +92 -0
  33. data/ext/chipmunk/include/chipmunk/constraints/cpDampedRotarySpring.h +46 -0
  34. data/ext/chipmunk/include/chipmunk/constraints/cpDampedSpring.h +53 -0
  35. data/ext/chipmunk/include/chipmunk/constraints/cpGearJoint.h +41 -0
  36. data/ext/chipmunk/include/chipmunk/constraints/cpGrooveJoint.h +44 -0
  37. data/ext/chipmunk/include/chipmunk/constraints/cpPinJoint.h +43 -0
  38. data/ext/chipmunk/include/chipmunk/constraints/cpPivotJoint.h +42 -0
  39. data/ext/chipmunk/include/chipmunk/constraints/cpRatchetJoint.h +40 -0
  40. data/ext/chipmunk/include/chipmunk/constraints/cpRotaryLimitJoint.h +39 -0
  41. data/ext/chipmunk/include/chipmunk/constraints/cpSimpleMotor.h +37 -0
  42. data/ext/chipmunk/include/chipmunk/constraints/cpSlideJoint.h +44 -0
  43. data/ext/chipmunk/include/chipmunk/constraints/util.h +116 -0
  44. data/ext/chipmunk/{cpArbiter.h → include/chipmunk/cpArbiter.h} +66 -15
  45. data/ext/chipmunk/{cpArray.h → include/chipmunk/cpArray.h} +2 -1
  46. data/ext/chipmunk/{cpBB.h → include/chipmunk/cpBB.h} +21 -0
  47. data/ext/chipmunk/{cpBody.h → include/chipmunk/cpBody.h} +37 -9
  48. data/ext/chipmunk/{cpCollision.h → include/chipmunk/cpCollision.h} +1 -1
  49. data/ext/chipmunk/{cpHashSet.h → include/chipmunk/cpHashSet.h} +12 -9
  50. data/ext/chipmunk/{cpPolyShape.h → include/chipmunk/cpPolyShape.h} +13 -2
  51. data/ext/chipmunk/{cpShape.h → include/chipmunk/cpShape.h} +51 -18
  52. data/ext/chipmunk/include/chipmunk/cpSpace.h +180 -0
  53. data/ext/chipmunk/{cpSpaceHash.h → include/chipmunk/cpSpaceHash.h} +18 -9
  54. data/ext/chipmunk/{cpVect.h → include/chipmunk/cpVect.h} +61 -10
  55. data/ext/chipmunk/prime.h +32 -32
  56. data/ext/chipmunk/rb_chipmunk.c +125 -109
  57. data/ext/chipmunk/rb_chipmunk.h +96 -77
  58. data/ext/chipmunk/rb_cpArbiter.c +225 -0
  59. data/ext/chipmunk/rb_cpBB.c +174 -154
  60. data/ext/chipmunk/rb_cpBody.c +347 -239
  61. data/ext/chipmunk/rb_cpConstraint.c +346 -0
  62. data/ext/chipmunk/rb_cpShape.c +455 -292
  63. data/ext/chipmunk/rb_cpSpace.c +544 -330
  64. data/ext/chipmunk/rb_cpVect.c +321 -250
  65. data/lib/chipmunk.rb +28 -15
  66. data/lib/chipmunk/version.rb +3 -0
  67. metadata +74 -34
  68. data/ext/chipmunk/cpJoint.c +0 -553
  69. data/ext/chipmunk/cpJoint.h +0 -122
  70. data/ext/chipmunk/cpSpace.h +0 -120
  71. data/ext/chipmunk/rb_cpJoint.c +0 -136
@@ -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
- cpHandleFree(cpHandle *hand)
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 *)calloc(1, sizeof(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
- free(hash->table);
62
+ cpfree(hash->table);
84
63
 
85
64
  hash->numcells = numcells;
86
- hash->table = (cpSpaceHashBin **)calloc(numcells, sizeof(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, void *unused)
78
+ handleSetTrans(void *obj, cpSpaceHash *hash)
100
79
  {
101
- cpHandle *hand = cpHandleNew(obj);
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->bins = NULL;
115
- hash->handleSet = cpHashSetNew(0, &handleSetEql, &handleSetTrans);
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
- clearHashCell(cpSpaceHash *hash, int index)
122
+ recycleBin(cpSpaceHash *hash, cpSpaceHashBin *bin)
130
123
  {
131
- cpSpaceHashBin *bin = hash->table[index];
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
- // Recycle the bin.
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[index] = NULL;
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
- // Free the recycled hash bins.
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
- free(hash->table);
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(!hash) return;
192
- cpSpaceHashDestroy(hash);
193
- free(hash);
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->bins;
204
+ cpSpaceHashBin *bin = hash->pooledBins;
223
205
 
224
- // Make a new one if necessary.
225
- if(bin == NULL) return (cpSpaceHashBin *)malloc(sizeof(cpSpaceHashBin));
226
-
227
- hash->bins = bin->next;
228
- return bin;
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 unsigned int
233
- hash_func(unsigned int x, unsigned int y, unsigned int n)
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
- return (x*2185031351ul ^ y*4232417593ul) % n;
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 index = hash_func(i,j,n);
252
- cpSpaceHashBin *bin = hash->table[index];
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[index] = newBin;
263
+ hash->table[idx] = newBin;
263
264
  }
264
265
  }
265
266
  }
266
267
 
267
268
  void
268
- cpSpaceHashInsert(cpSpaceHash *hash, void *obj, unsigned int id, cpBB bb)
269
+ cpSpaceHashInsert(cpSpaceHash *hash, void *obj, cpHashValue hashid, cpBB bb)
269
270
  {
270
- cpHandle *hand = (cpHandle *)cpHashSetInsert(hash->handleSet, id, obj, NULL);
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, unsigned int id)
276
+ cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, cpHashValue hashid)
276
277
  {
277
- cpHandle *hand = (cpHandle *)cpHashSetFind(hash->handleSet, id, obj);
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, unsigned int id)
302
+ cpSpaceHashRemove(cpSpaceHash *hash, void *obj, cpHashValue hashid)
302
303
  {
303
- cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet, id, obj);
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 index = hash_func((int)(point.x/dim), (int)(point.y/dim), hash->numcells);
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[index], &point, func, data);
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 index = hash_func(i,j,n);
391
- query(hash, hash->table[index], obj, func, data);
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
- int index = hash_func(i,j,n);
431
- cpSpaceHashBin *bin = hash->table[index];
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[index] = newBin;
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
+ }