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
@@ -32,7 +32,7 @@
32
32
  cpArray*
33
33
  cpArrayAlloc(void)
34
34
  {
35
- return (cpArray *)calloc(1, sizeof(cpArray));
35
+ return (cpArray *)cpcalloc(1, sizeof(cpArray));
36
36
  }
37
37
 
38
38
  cpArray*
@@ -42,7 +42,7 @@ cpArrayInit(cpArray *arr, int size)
42
42
 
43
43
  size = (size ? size : 4);
44
44
  arr->max = size;
45
- arr->arr = (void **)malloc(size*sizeof(void**));
45
+ arr->arr = (void **)cpmalloc(size*sizeof(void**));
46
46
 
47
47
  return arr;
48
48
  }
@@ -56,15 +56,16 @@ cpArrayNew(int size)
56
56
  void
57
57
  cpArrayDestroy(cpArray *arr)
58
58
  {
59
- free(arr->arr);
59
+ cpfree(arr->arr);
60
60
  }
61
61
 
62
62
  void
63
63
  cpArrayFree(cpArray *arr)
64
64
  {
65
- if(!arr) return;
66
- cpArrayDestroy(arr);
67
- free(arr);
65
+ if(arr){
66
+ cpArrayDestroy(arr);
67
+ cpfree(arr);
68
+ }
68
69
  }
69
70
 
70
71
  void
@@ -72,18 +73,31 @@ cpArrayPush(cpArray *arr, void *object)
72
73
  {
73
74
  if(arr->num == arr->max){
74
75
  arr->max *= 2;
75
- arr->arr = (void **)realloc(arr->arr, arr->max*sizeof(void**));
76
+ arr->arr = (void **)cprealloc(arr->arr, arr->max*sizeof(void**));
76
77
  }
77
78
 
78
79
  arr->arr[arr->num] = object;
79
80
  arr->num++;
80
81
  }
81
82
 
83
+ void *
84
+ cpArrayPop(cpArray *arr)
85
+ {
86
+ arr->num--;
87
+
88
+ void *value = arr->arr[arr->num];
89
+ arr->arr[arr->num] = NULL;
90
+
91
+ return value;
92
+ }
93
+
82
94
  void
83
- cpArrayDeleteIndex(cpArray *arr, int index)
95
+ cpArrayDeleteIndex(cpArray *arr, int idx)
84
96
  {
85
- int last = --arr->num;
86
- arr->arr[index] = arr->arr[last];
97
+ arr->num--;
98
+
99
+ arr->arr[idx] = arr->arr[arr->num];
100
+ arr->arr[arr->num] = NULL;
87
101
  }
88
102
 
89
103
  void
data/ext/chipmunk/cpBB.c CHANGED
@@ -20,6 +20,7 @@
20
20
  */
21
21
 
22
22
  #include <math.h>
23
+ #include <stdlib.h>
23
24
 
24
25
  #include "chipmunk.h"
25
26
 
@@ -34,12 +35,12 @@ cpBBClampVect(const cpBB bb, const cpVect v)
34
35
  cpVect
35
36
  cpBBWrapVect(const cpBB bb, const cpVect v)
36
37
  {
37
- cpFloat ix = fabsf(bb.r - bb.l);
38
- cpFloat modx = fmodf(v.x - bb.l, ix);
38
+ cpFloat ix = cpfabs(bb.r - bb.l);
39
+ cpFloat modx = cpfmod(v.x - bb.l, ix);
39
40
  cpFloat x = (modx > 0.0f) ? modx : modx + ix;
40
41
 
41
- cpFloat iy = fabsf(bb.t - bb.b);
42
- cpFloat mody = fmodf(v.y - bb.b, iy);
42
+ cpFloat iy = cpfabs(bb.t - bb.b);
43
+ cpFloat mody = cpfmod(v.y - bb.b, iy);
43
44
  cpFloat y = (mody > 0.0f) ? mody : mody + iy;
44
45
 
45
46
  return cpv(x + bb.l, y + bb.b);
@@ -20,7 +20,6 @@
20
20
  */
21
21
 
22
22
  #include <stdlib.h>
23
- #include <math.h>
24
23
  #include <float.h>
25
24
 
26
25
  #include "chipmunk.h"
@@ -28,14 +27,17 @@
28
27
  cpBody*
29
28
  cpBodyAlloc(void)
30
29
  {
31
- return (cpBody *)malloc(sizeof(cpBody));
30
+ return (cpBody *)cpmalloc(sizeof(cpBody));
32
31
  }
33
32
 
33
+ cpBodyVelocityFunc cpBodyUpdateVelocityDefault = cpBodyUpdateVelocity;
34
+ cpBodyPositionFunc cpBodyUpdatePositionDefault = cpBodyUpdatePosition;
35
+
34
36
  cpBody*
35
37
  cpBodyInit(cpBody *body, cpFloat m, cpFloat i)
36
38
  {
37
- body->velocity_func = cpBodyUpdateVelocity;
38
- body->position_func = cpBodyUpdatePosition;
39
+ body->velocity_func = cpBodyUpdateVelocityDefault;
40
+ body->position_func = cpBodyUpdatePositionDefault;
39
41
 
40
42
  cpBodySetMass(body, m);
41
43
  cpBodySetMoment(body, i);
@@ -52,6 +54,8 @@ cpBodyInit(cpBody *body, cpFloat m, cpFloat i)
52
54
  body->w_bias = 0.0f;
53
55
 
54
56
  body->data = NULL;
57
+ body->v_limit = (cpFloat)INFINITY;
58
+ body->w_limit = (cpFloat)INFINITY;
55
59
  // body->active = 1;
56
60
 
57
61
  return body;
@@ -68,43 +72,47 @@ void cpBodyDestroy(cpBody *body){}
68
72
  void
69
73
  cpBodyFree(cpBody *body)
70
74
  {
71
- if(body) cpBodyDestroy(body);
72
- free(body);
75
+ if(body){
76
+ cpBodyDestroy(body);
77
+ cpfree(body);
78
+ }
73
79
  }
74
80
 
75
81
  void
76
- cpBodySetMass(cpBody *body, cpFloat m)
82
+ cpBodySetMass(cpBody *body, cpFloat mass)
77
83
  {
78
- body->m = m;
79
- body->m_inv = 1.0f/m;
84
+ body->m = mass;
85
+ body->m_inv = 1.0f/mass;
80
86
  }
81
87
 
82
88
  void
83
- cpBodySetMoment(cpBody *body, cpFloat i)
89
+ cpBodySetMoment(cpBody *body, cpFloat moment)
84
90
  {
85
- body->i = i;
86
- body->i_inv = 1.0f/i;
91
+ body->i = moment;
92
+ body->i_inv = 1.0f/moment;
87
93
  }
88
94
 
89
95
  void
90
- cpBodySetAngle(cpBody *body, cpFloat a)
96
+ cpBodySetAngle(cpBody *body, cpFloat angle)
91
97
  {
92
- body->a = fmod(a, (cpFloat)M_PI*2.0f);
93
- body->rot = cpvforangle(a);
98
+ body->a = angle;//fmod(a, (cpFloat)M_PI*2.0f);
99
+ body->rot = cpvforangle(angle);
94
100
  }
95
101
 
96
102
  void
97
103
  cpBodySlew(cpBody *body, cpVect pos, cpFloat dt)
98
104
  {
99
105
  cpVect delta = cpvsub(pos, body->p);
100
- body->v = cpvmult(delta, 1.0/dt);
106
+ body->v = cpvmult(delta, 1.0f/dt);
101
107
  }
102
108
 
103
109
  void
104
110
  cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
105
111
  {
106
- body->v = cpvadd(cpvmult(body->v, damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), dt));
107
- body->w = body->w*damping + body->t*body->i_inv*dt;
112
+ body->v = cpvclamp(cpvadd(cpvmult(body->v, damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), dt)), body->v_limit);
113
+
114
+ cpFloat w_limit = body->w_limit;
115
+ body->w = cpfclamp(body->w*damping + body->t*body->i_inv*dt, -w_limit, w_limit);
108
116
  }
109
117
 
110
118
  void
@@ -125,14 +133,14 @@ cpBodyResetForces(cpBody *body)
125
133
  }
126
134
 
127
135
  void
128
- cpBodyApplyForce(cpBody *body, cpVect f, cpVect r)
136
+ cpBodyApplyForce(cpBody *body, cpVect force, cpVect r)
129
137
  {
130
- body->f = cpvadd(body->f, f);
131
- body->t += cpvcross(r, f);
138
+ body->f = cpvadd(body->f, force);
139
+ body->t += cpvcross(r, force);
132
140
  }
133
141
 
134
142
  void
135
- cpDampedSpring(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat rlen, cpFloat k, cpFloat dmp, cpFloat dt)
143
+ cpApplyDampedSpring(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat rlen, cpFloat k, cpFloat dmp, cpFloat dt)
136
144
  {
137
145
  // Calculate the world space anchor coordinates.
138
146
  cpVect r1 = cpvrotate(anchr1, a->rot);
@@ -22,34 +22,30 @@
22
22
  #include <stdlib.h>
23
23
  #include <math.h>
24
24
  #include <stdio.h>
25
- #include <assert.h>
26
25
 
27
26
  #include "chipmunk.h"
28
27
 
29
- typedef int (*collisionFunc)(cpShape*, cpShape*, cpContact**);
30
-
31
- static collisionFunc *colfuncs = NULL;
28
+ typedef int (*collisionFunc)(cpShape *, cpShape *, cpContact *);
32
29
 
33
30
  // Add contact points for circle to circle collisions.
34
31
  // Used by several collision tests.
35
32
  static int
36
- circle2circleQuery(cpVect p1, cpVect p2, cpFloat r1, cpFloat r2, cpContact **con)
33
+ circle2circleQuery(cpVect p1, cpVect p2, cpFloat r1, cpFloat r2, cpContact *con)
37
34
  {
38
35
  cpFloat mindist = r1 + r2;
39
36
  cpVect delta = cpvsub(p2, p1);
40
37
  cpFloat distsq = cpvlengthsq(delta);
41
38
  if(distsq >= mindist*mindist) return 0;
42
39
 
43
- cpFloat dist = sqrtf(distsq);
40
+ cpFloat dist = cpfsqrt(distsq);
44
41
  // To avoid singularities, do nothing in the case of dist = 0.
45
42
  cpFloat non_zero_dist = (dist ? dist : INFINITY);
46
43
 
47
44
  // Allocate and initialize the contact.
48
- (*con) = (cpContact *)malloc(sizeof(cpContact));
49
45
  cpContactInit(
50
- (*con),
51
- cpvadd(p1, cpvmult(delta, 0.5 + (r1 - 0.5*mindist)/non_zero_dist)),
52
- cpvmult(delta, 1.0/non_zero_dist),
46
+ con,
47
+ cpvadd(p1, cpvmult(delta, 0.5f + (r1 - 0.5f*mindist)/non_zero_dist)),
48
+ cpvmult(delta, 1.0f/non_zero_dist),
53
49
  dist - mindist,
54
50
  0
55
51
  );
@@ -59,7 +55,7 @@ circle2circleQuery(cpVect p1, cpVect p2, cpFloat r1, cpFloat r2, cpContact **con
59
55
 
60
56
  // Collide circle shapes.
61
57
  static int
62
- circle2circle(cpShape *shape1, cpShape *shape2, cpContact **arr)
58
+ circle2circle(cpShape *shape1, cpShape *shape2, cpContact *arr)
63
59
  {
64
60
  cpCircleShape *circ1 = (cpCircleShape *)shape1;
65
61
  cpCircleShape *circ2 = (cpCircleShape *)shape2;
@@ -69,7 +65,7 @@ circle2circle(cpShape *shape1, cpShape *shape2, cpContact **arr)
69
65
 
70
66
  // Collide circles to segment shapes.
71
67
  static int
72
- circle2segment(cpShape *circleShape, cpShape *segmentShape, cpContact **con)
68
+ circle2segment(cpShape *circleShape, cpShape *segmentShape, cpContact *con)
73
69
  {
74
70
  cpCircleShape *circ = (cpCircleShape *)circleShape;
75
71
  cpSegmentShape *seg = (cpSegmentShape *)segmentShape;
@@ -79,7 +75,7 @@ circle2segment(cpShape *circleShape, cpShape *segmentShape, cpContact **con)
79
75
 
80
76
  // Calculate normal distance from segment.
81
77
  cpFloat dn = cpvdot(seg->tn, circ->tc) - cpvdot(seg->ta, seg->tn);
82
- cpFloat dist = fabs(dn) - rsum;
78
+ cpFloat dist = cpfabs(dn) - rsum;
83
79
  if(dist > 0.0f) return 0;
84
80
 
85
81
  // Calculate tangential distance along segment.
@@ -97,9 +93,8 @@ circle2segment(cpShape *circleShape, cpShape *segmentShape, cpContact **con)
97
93
  } else {
98
94
  if(dt < dtMax){
99
95
  cpVect n = (dn < 0.0f) ? seg->tn : cpvneg(seg->tn);
100
- (*con) = (cpContact *)malloc(sizeof(cpContact));
101
96
  cpContactInit(
102
- (*con),
97
+ con,
103
98
  cpvadd(circ->tc, cpvmult(n, circ->r + dist*0.5f)),
104
99
  n,
105
100
  dist,
@@ -118,25 +113,17 @@ circle2segment(cpShape *circleShape, cpShape *segmentShape, cpContact **con)
118
113
  return 1;
119
114
  }
120
115
 
121
- // Helper function for allocating contact point lists.
116
+ // Helper function for working with contact buffers
117
+ // This used to malloc/realloc memory on the fly but was repurposed.
122
118
  static cpContact *
123
- addContactPoint(cpContact **arr, int *max, int *num)
119
+ nextContactPoint(cpContact *arr, int *numPtr)
124
120
  {
125
- if(*arr == NULL){
126
- // Allocate the array if it hasn't been done.
127
- (*max) = 2;
128
- (*num) = 0;
129
- (*arr) = (cpContact *)malloc((*max)*sizeof(cpContact));
130
- } else if(*num == *max){
131
- // Extend it if necessary.
132
- (*max) *= 2;
133
- (*arr) = (cpContact *)realloc(*arr, (*max)*sizeof(cpContact));
134
- }
121
+ int num = *numPtr;
135
122
 
136
- cpContact *con = &(*arr)[*num];
137
- (*num)++;
123
+ if(num <= CP_MAX_CONTACTS_PER_ARBITER)
124
+ (*numPtr) = num + 1;
138
125
 
139
- return con;
126
+ return &arr[num];
140
127
  }
141
128
 
142
129
  // Find the minimum separating axis for the give poly and axis list.
@@ -145,11 +132,11 @@ findMSA(cpPolyShape *poly, cpPolyShapeAxis *axes, int num, cpFloat *min_out)
145
132
  {
146
133
  int min_index = 0;
147
134
  cpFloat min = cpPolyShapeValueOnAxis(poly, axes->n, axes->d);
148
- if(min > 0.0) return -1;
135
+ if(min > 0.0f) return -1;
149
136
 
150
137
  for(int i=1; i<num; i++){
151
138
  cpFloat dist = cpPolyShapeValueOnAxis(poly, axes[i].n, axes[i].d);
152
- if(dist > 0.0) {
139
+ if(dist > 0.0f) {
153
140
  return -1;
154
141
  } else if(dist > min){
155
142
  min = dist;
@@ -163,21 +150,20 @@ findMSA(cpPolyShape *poly, cpPolyShapeAxis *axes, int num, cpFloat *min_out)
163
150
 
164
151
  // Add contacts for penetrating vertexes.
165
152
  static inline int
166
- findVerts(cpContact **arr, cpPolyShape *poly1, cpPolyShape *poly2, cpVect n, cpFloat dist)
153
+ findVerts(cpContact *arr, cpPolyShape *poly1, cpPolyShape *poly2, cpVect n, cpFloat dist)
167
154
  {
168
- int max = 0;
169
155
  int num = 0;
170
156
 
171
157
  for(int i=0; i<poly1->numVerts; i++){
172
158
  cpVect v = poly1->tVerts[i];
173
159
  if(cpPolyShapeContainsVertPartial(poly2, v, cpvneg(n)))
174
- cpContactInit(addContactPoint(arr, &max, &num), v, n, dist, CP_HASH_PAIR(poly1, i));
160
+ cpContactInit(nextContactPoint(arr, &num), v, n, dist, CP_HASH_PAIR(poly1->shape.hashid, i));
175
161
  }
176
162
 
177
163
  for(int i=0; i<poly2->numVerts; i++){
178
164
  cpVect v = poly2->tVerts[i];
179
165
  if(cpPolyShapeContainsVertPartial(poly1, v, n))
180
- cpContactInit(addContactPoint(arr, &max, &num), v, n, dist, CP_HASH_PAIR(poly2, i));
166
+ cpContactInit(nextContactPoint(arr, &num), v, n, dist, CP_HASH_PAIR(poly2->shape.hashid, i));
181
167
  }
182
168
 
183
169
  // if(!num)
@@ -188,7 +174,7 @@ findVerts(cpContact **arr, cpPolyShape *poly1, cpPolyShape *poly2, cpVect n, cpF
188
174
 
189
175
  // Collide poly shapes together.
190
176
  static int
191
- poly2poly(cpShape *shape1, cpShape *shape2, cpContact **arr)
177
+ poly2poly(cpShape *shape1, cpShape *shape2, cpContact *arr)
192
178
  {
193
179
  cpPolyShape *poly1 = (cpPolyShape *)shape1;
194
180
  cpPolyShape *poly2 = (cpPolyShape *)shape2;
@@ -209,7 +195,7 @@ poly2poly(cpShape *shape1, cpShape *shape2, cpContact **arr)
209
195
  }
210
196
 
211
197
  // Like cpPolyValueOnAxis(), but for segments.
212
- static inline float
198
+ static inline cpFloat
213
199
  segValueOnAxis(cpSegmentShape *seg, cpVect n, cpFloat d)
214
200
  {
215
201
  cpFloat a = cpvdot(n, seg->ta) - seg->r;
@@ -219,7 +205,7 @@ segValueOnAxis(cpSegmentShape *seg, cpVect n, cpFloat d)
219
205
 
220
206
  // Identify vertexes that have penetrated the segment.
221
207
  static inline void
222
- findPointsBehindSeg(cpContact **arr, int *max, int *num, cpSegmentShape *seg, cpPolyShape *poly, cpFloat pDist, cpFloat coef)
208
+ findPointsBehindSeg(cpContact *arr, int *num, cpSegmentShape *seg, cpPolyShape *poly, cpFloat pDist, cpFloat coef)
223
209
  {
224
210
  cpFloat dta = cpvcross(seg->tn, seg->ta);
225
211
  cpFloat dtb = cpvcross(seg->tn, seg->tb);
@@ -230,7 +216,7 @@ findPointsBehindSeg(cpContact **arr, int *max, int *num, cpSegmentShape *seg, cp
230
216
  if(cpvdot(v, n) < cpvdot(seg->tn, seg->ta)*coef + seg->r){
231
217
  cpFloat dt = cpvcross(seg->tn, v);
232
218
  if(dta >= dt && dt >= dtb){
233
- cpContactInit(addContactPoint(arr, max, num), v, n, pDist, CP_HASH_PAIR(poly, i));
219
+ cpContactInit(nextContactPoint(arr, num), v, n, pDist, CP_HASH_PAIR(poly->shape.hashid, i));
234
220
  }
235
221
  }
236
222
  }
@@ -239,7 +225,7 @@ findPointsBehindSeg(cpContact **arr, int *max, int *num, cpSegmentShape *seg, cp
239
225
  // This one is complicated and gross. Just don't go there...
240
226
  // TODO: Comment me!
241
227
  static int
242
- seg2poly(cpShape *shape1, cpShape *shape2, cpContact **arr)
228
+ seg2poly(cpShape *shape1, cpShape *shape2, cpContact *arr)
243
229
  {
244
230
  cpSegmentShape *seg = (cpSegmentShape *)shape1;
245
231
  cpPolyShape *poly = (cpPolyShape *)shape2;
@@ -263,7 +249,6 @@ seg2poly(cpShape *shape1, cpShape *shape2, cpContact **arr)
263
249
  }
264
250
  }
265
251
 
266
- int max = 0;
267
252
  int num = 0;
268
253
 
269
254
  cpVect poly_n = cpvneg(axes[mini].n);
@@ -271,18 +256,18 @@ seg2poly(cpShape *shape1, cpShape *shape2, cpContact **arr)
271
256
  cpVect va = cpvadd(seg->ta, cpvmult(poly_n, seg->r));
272
257
  cpVect vb = cpvadd(seg->tb, cpvmult(poly_n, seg->r));
273
258
  if(cpPolyShapeContainsVert(poly, va))
274
- cpContactInit(addContactPoint(arr, &max, &num), va, poly_n, poly_min, CP_HASH_PAIR(seg, 0));
259
+ cpContactInit(nextContactPoint(arr, &num), va, poly_n, poly_min, CP_HASH_PAIR(seg->shape.hashid, 0));
275
260
  if(cpPolyShapeContainsVert(poly, vb))
276
- cpContactInit(addContactPoint(arr, &max, &num), vb, poly_n, poly_min, CP_HASH_PAIR(seg, 1));
261
+ cpContactInit(nextContactPoint(arr, &num), vb, poly_n, poly_min, CP_HASH_PAIR(seg->shape.hashid, 1));
277
262
 
278
263
  // Floating point precision problems here.
279
264
  // This will have to do for now.
280
265
  poly_min -= cp_collision_slop;
281
266
  if(minNorm >= poly_min || minNeg >= poly_min) {
282
267
  if(minNorm > minNeg)
283
- findPointsBehindSeg(arr, &max, &num, seg, poly, minNorm, 1.0f);
268
+ findPointsBehindSeg(arr, &num, seg, poly, minNorm, 1.0f);
284
269
  else
285
- findPointsBehindSeg(arr, &max, &num, seg, poly, minNeg, -1.0f);
270
+ findPointsBehindSeg(arr, &num, seg, poly, minNeg, -1.0f);
286
271
  }
287
272
 
288
273
  // If no other collision points are found, try colliding endpoints.
@@ -309,7 +294,7 @@ seg2poly(cpShape *shape1, cpShape *shape2, cpContact **arr)
309
294
  // This one is less gross, but still gross.
310
295
  // TODO: Comment me!
311
296
  static int
312
- circle2poly(cpShape *shape1, cpShape *shape2, cpContact **con)
297
+ circle2poly(cpShape *shape1, cpShape *shape2, cpContact *con)
313
298
  {
314
299
  cpCircleShape *circ = (cpCircleShape *)shape1;
315
300
  cpPolyShape *poly = (cpPolyShape *)shape2;
@@ -319,7 +304,7 @@ circle2poly(cpShape *shape1, cpShape *shape2, cpContact **con)
319
304
  cpFloat min = cpvdot(axes->n, circ->tc) - axes->d - circ->r;
320
305
  for(int i=0; i<poly->numVerts; i++){
321
306
  cpFloat dist = cpvdot(axes[i].n, circ->tc) - axes[i].d - circ->r;
322
- if(dist > 0.0){
307
+ if(dist > 0.0f){
323
308
  return 0;
324
309
  } else if(dist > min) {
325
310
  min = dist;
@@ -337,9 +322,8 @@ circle2poly(cpShape *shape1, cpShape *shape2, cpContact **con)
337
322
  if(dt < dtb){
338
323
  return circle2circleQuery(circ->tc, b, circ->r, 0.0f, con);
339
324
  } else if(dt < dta) {
340
- (*con) = (cpContact *)malloc(sizeof(cpContact));
341
325
  cpContactInit(
342
- (*con),
326
+ con,
343
327
  cpvsub(circ->tc, cpvmult(n, circ->r + min/2.0f)),
344
328
  cpvneg(n),
345
329
  min,
@@ -352,6 +336,21 @@ circle2poly(cpShape *shape1, cpShape *shape2, cpContact **con)
352
336
  }
353
337
  }
354
338
 
339
+ //static const collisionFunc builtinCollisionFuncs[9] = {
340
+ // circle2circle,
341
+ // NULL,
342
+ // NULL,
343
+ // circle2segment,
344
+ // NULL,
345
+ // NULL,
346
+ // circle2poly,
347
+ // seg2poly,
348
+ // poly2poly,
349
+ //};
350
+ //static const collisionFunc *colfuncs = builtinCollisionFuncs;
351
+
352
+ static collisionFunc *colfuncs = NULL;
353
+
355
354
  static void
356
355
  addColFunc(cpShapeType a, cpShapeType b, collisionFunc func)
357
356
  {
@@ -361,13 +360,15 @@ addColFunc(cpShapeType a, cpShapeType b, collisionFunc func)
361
360
  #ifdef __cplusplus
362
361
  extern "C" {
363
362
  #endif
363
+ void cpInitCollisionFuncs(void);
364
+
364
365
  // Initializes the array of collision functions.
365
366
  // Called by cpInitChipmunk().
366
367
  void
367
368
  cpInitCollisionFuncs(void)
368
369
  {
369
370
  if(!colfuncs)
370
- colfuncs = (collisionFunc *)calloc(CP_NUM_SHAPES*CP_NUM_SHAPES, sizeof(collisionFunc));
371
+ colfuncs = (collisionFunc *)cpcalloc(CP_NUM_SHAPES*CP_NUM_SHAPES, sizeof(collisionFunc));
371
372
 
372
373
  addColFunc(CP_CIRCLE_SHAPE, CP_CIRCLE_SHAPE, circle2circle);
373
374
  addColFunc(CP_CIRCLE_SHAPE, CP_SEGMENT_SHAPE, circle2segment);
@@ -380,10 +381,10 @@ extern "C" {
380
381
  #endif
381
382
 
382
383
  int
383
- cpCollideShapes(cpShape *a, cpShape *b, cpContact **arr)
384
+ cpCollideShapes(cpShape *a, cpShape *b, cpContact *arr)
384
385
  {
385
386
  // Their shape types must be in order.
386
- assert(a->klass->type <= b->klass->type);
387
+ cpAssert(a->klass->type <= b->klass->type, "Collision shapes passed to cpCollideShapes() are not sorted.");
387
388
 
388
389
  collisionFunc cfunc = colfuncs[a->klass->type + b->klass->type*CP_NUM_SHAPES];
389
390
  return (cfunc) ? cfunc(a, b, arr) : 0;