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/cpArray.c
CHANGED
@@ -32,7 +32,7 @@
|
|
32
32
|
cpArray*
|
33
33
|
cpArrayAlloc(void)
|
34
34
|
{
|
35
|
-
return (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 **)
|
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
|
-
|
59
|
+
cpfree(arr->arr);
|
60
60
|
}
|
61
61
|
|
62
62
|
void
|
63
63
|
cpArrayFree(cpArray *arr)
|
64
64
|
{
|
65
|
-
if(
|
66
|
-
|
67
|
-
|
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 **)
|
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
|
95
|
+
cpArrayDeleteIndex(cpArray *arr, int idx)
|
84
96
|
{
|
85
|
-
|
86
|
-
|
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 =
|
38
|
-
cpFloat modx =
|
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 =
|
42
|
-
cpFloat mody =
|
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);
|
data/ext/chipmunk/cpBody.c
CHANGED
@@ -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 *)
|
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 =
|
38
|
-
body->position_func =
|
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)
|
72
|
-
|
75
|
+
if(body){
|
76
|
+
cpBodyDestroy(body);
|
77
|
+
cpfree(body);
|
78
|
+
}
|
73
79
|
}
|
74
80
|
|
75
81
|
void
|
76
|
-
cpBodySetMass(cpBody *body, cpFloat
|
82
|
+
cpBodySetMass(cpBody *body, cpFloat mass)
|
77
83
|
{
|
78
|
-
body->m =
|
79
|
-
body->m_inv = 1.0f/
|
84
|
+
body->m = mass;
|
85
|
+
body->m_inv = 1.0f/mass;
|
80
86
|
}
|
81
87
|
|
82
88
|
void
|
83
|
-
cpBodySetMoment(cpBody *body, cpFloat
|
89
|
+
cpBodySetMoment(cpBody *body, cpFloat moment)
|
84
90
|
{
|
85
|
-
body->i =
|
86
|
-
body->i_inv = 1.0f/
|
91
|
+
body->i = moment;
|
92
|
+
body->i_inv = 1.0f/moment;
|
87
93
|
}
|
88
94
|
|
89
95
|
void
|
90
|
-
cpBodySetAngle(cpBody *body, cpFloat
|
96
|
+
cpBodySetAngle(cpBody *body, cpFloat angle)
|
91
97
|
{
|
92
|
-
body->a = fmod(a, (cpFloat)M_PI*2.0f);
|
93
|
-
body->rot = cpvforangle(
|
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.
|
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
|
-
|
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
|
136
|
+
cpBodyApplyForce(cpBody *body, cpVect force, cpVect r)
|
129
137
|
{
|
130
|
-
body->f = cpvadd(body->f,
|
131
|
-
body->t += cpvcross(r,
|
138
|
+
body->f = cpvadd(body->f, force);
|
139
|
+
body->t += cpvcross(r, force);
|
132
140
|
}
|
133
141
|
|
134
142
|
void
|
135
|
-
|
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);
|
data/ext/chipmunk/cpCollision.c
CHANGED
@@ -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
|
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 =
|
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
|
-
|
51
|
-
cpvadd(p1, cpvmult(delta, 0.
|
52
|
-
cpvmult(delta, 1.
|
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
|
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
|
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 =
|
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
|
-
|
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
|
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
|
-
|
119
|
+
nextContactPoint(cpContact *arr, int *numPtr)
|
124
120
|
{
|
125
|
-
|
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
|
-
|
137
|
-
|
123
|
+
if(num <= CP_MAX_CONTACTS_PER_ARBITER)
|
124
|
+
(*numPtr) = num + 1;
|
138
125
|
|
139
|
-
return
|
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.
|
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.
|
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
|
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(
|
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(
|
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
|
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
|
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
|
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(
|
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
|
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(
|
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(
|
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, &
|
268
|
+
findPointsBehindSeg(arr, &num, seg, poly, minNorm, 1.0f);
|
284
269
|
else
|
285
|
-
findPointsBehindSeg(arr, &
|
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
|
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.
|
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
|
-
|
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 *)
|
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
|
384
|
+
cpCollideShapes(cpShape *a, cpShape *b, cpContact *arr)
|
384
385
|
{
|
385
386
|
// Their shape types must be in order.
|
386
|
-
|
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;
|