chipmunk 4.1.0 → 5.2.0

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