chipmunk 5.3.4.0-x86-mingw32 → 5.3.4.2-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/README +33 -13
- data/Rakefile +20 -7
- data/ext/chipmunk/extconf.rb +55 -12
- data/ext/chipmunk/rb_chipmunk.c +92 -98
- data/ext/chipmunk/rb_chipmunk.h +44 -34
- data/ext/chipmunk/rb_cpArbiter.c +135 -98
- data/ext/chipmunk/rb_cpBB.c +84 -101
- data/ext/chipmunk/rb_cpBody.c +219 -241
- data/ext/chipmunk/rb_cpConstraint.c +173 -185
- data/ext/chipmunk/rb_cpShape.c +347 -251
- data/ext/chipmunk/rb_cpSpace.c +376 -408
- data/ext/chipmunk/rb_cpVect.c +132 -170
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/chipmunk.h +163 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/chipmunk_ffi.h +59 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/chipmunk_private.h +49 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/chipmunk_types.h +151 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/chipmunk_unsafe.h +54 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/constraints/cpConstraint.h +105 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/constraints/cpDampedRotarySpring.h +46 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/constraints/cpDampedSpring.h +53 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/constraints/cpGearJoint.h +41 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/constraints/cpGrooveJoint.h +48 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/constraints/cpPinJoint.h +43 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/constraints/cpPivotJoint.h +42 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/constraints/cpRatchetJoint.h +40 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/constraints/cpRotaryLimitJoint.h +39 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/constraints/cpSimpleMotor.h +37 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/constraints/cpSlideJoint.h +44 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/constraints/util.h +134 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/cpArbiter.h +188 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/cpArray.h +49 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/cpBB.h +74 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/cpBody.h +219 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/cpCollision.h +28 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/cpHashSet.h +82 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/cpPolyShape.h +103 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/cpShape.h +177 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/cpSpace.h +206 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/cpSpaceHash.h +110 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/include/chipmunk/cpVect.h +207 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/chipmunk.c +151 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/constraints/cpConstraint.c +54 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/constraints/cpDampedRotarySpring.c +105 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/constraints/cpDampedSpring.c +115 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/constraints/cpGearJoint.c +113 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/constraints/cpGrooveJoint.c +161 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/constraints/cpPinJoint.c +116 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/constraints/cpPivotJoint.c +114 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/constraints/cpRatchetJoint.c +126 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/constraints/cpRotaryLimitJoint.c +120 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/constraints/cpSimpleMotor.c +97 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/constraints/cpSlideJoint.c +129 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/cpArbiter.c +280 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/cpArray.c +143 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/cpBB.c +47 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/cpBody.c +192 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/cpCollision.c +411 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/cpHashSet.c +253 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/cpPolyShape.c +240 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/cpShape.c +405 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/cpSpace.c +499 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/cpSpaceComponent.c +279 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/cpSpaceHash.c +534 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/cpSpaceQuery.c +246 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/cpSpaceStep.c +398 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/cpVect.c +71 -0
- data/ext/chipmunk/vendor/chipmunk-5.3.4/src/prime.h +68 -0
- data/lib/1.9/chipmunk.so +0 -0
- data/lib/chipmunk.rb +19 -8
- metadata +84 -42
- data/lib/1.8/chipmunk.so +0 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
/* Copyright (c) 2007 Scott Lembcke
|
2
|
+
*
|
3
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
* of this software and associated documentation files (the "Software"), to deal
|
5
|
+
* in the Software without restriction, including without limitation the rights
|
6
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
* copies of the Software, and to permit persons to whom the Software is
|
8
|
+
* furnished to do so, subject to the following conditions:
|
9
|
+
*
|
10
|
+
* The above copyright notice and this permission notice shall be included in
|
11
|
+
* all copies or substantial portions of the Software.
|
12
|
+
*
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
* SOFTWARE.
|
20
|
+
*/
|
21
|
+
|
22
|
+
#include <math.h>
|
23
|
+
#include <stdlib.h>
|
24
|
+
|
25
|
+
#include "chipmunk.h"
|
26
|
+
|
27
|
+
cpVect
|
28
|
+
cpBBClampVect(const cpBB bb, const cpVect v)
|
29
|
+
{
|
30
|
+
cpFloat x = cpfmin(cpfmax(bb.l, v.x), bb.r);
|
31
|
+
cpFloat y = cpfmin(cpfmax(bb.b, v.y), bb.t);
|
32
|
+
return cpv(x, y);
|
33
|
+
}
|
34
|
+
|
35
|
+
cpVect
|
36
|
+
cpBBWrapVect(const cpBB bb, const cpVect v)
|
37
|
+
{
|
38
|
+
cpFloat ix = cpfabs(bb.r - bb.l);
|
39
|
+
cpFloat modx = cpfmod(v.x - bb.l, ix);
|
40
|
+
cpFloat x = (modx > 0.0f) ? modx : modx + ix;
|
41
|
+
|
42
|
+
cpFloat iy = cpfabs(bb.t - bb.b);
|
43
|
+
cpFloat mody = cpfmod(v.y - bb.b, iy);
|
44
|
+
cpFloat y = (mody > 0.0f) ? mody : mody + iy;
|
45
|
+
|
46
|
+
return cpv(x + bb.l, y + bb.b);
|
47
|
+
}
|
@@ -0,0 +1,192 @@
|
|
1
|
+
/* Copyright (c) 2007 Scott Lembcke
|
2
|
+
*
|
3
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
* of this software and associated documentation files (the "Software"), to deal
|
5
|
+
* in the Software without restriction, including without limitation the rights
|
6
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
* copies of the Software, and to permit persons to whom the Software is
|
8
|
+
* furnished to do so, subject to the following conditions:
|
9
|
+
*
|
10
|
+
* The above copyright notice and this permission notice shall be included in
|
11
|
+
* all copies or substantial portions of the Software.
|
12
|
+
*
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
* SOFTWARE.
|
20
|
+
*/
|
21
|
+
|
22
|
+
#include <stdlib.h>
|
23
|
+
#include <float.h>
|
24
|
+
#include <stdarg.h>
|
25
|
+
|
26
|
+
#include "chipmunk_private.h"
|
27
|
+
|
28
|
+
// initialized in cpInitChipmunk()
|
29
|
+
cpBody cpStaticBodySingleton;
|
30
|
+
|
31
|
+
cpBody*
|
32
|
+
cpBodyAlloc(void)
|
33
|
+
{
|
34
|
+
return (cpBody *)cpmalloc(sizeof(cpBody));
|
35
|
+
}
|
36
|
+
|
37
|
+
cpBodyVelocityFunc cpBodyUpdateVelocityDefault = cpBodyUpdateVelocity;
|
38
|
+
cpBodyPositionFunc cpBodyUpdatePositionDefault = cpBodyUpdatePosition;
|
39
|
+
|
40
|
+
cpBody*
|
41
|
+
cpBodyInit(cpBody *body, cpFloat m, cpFloat i)
|
42
|
+
{
|
43
|
+
body->velocity_func = cpBodyUpdateVelocityDefault;
|
44
|
+
body->position_func = cpBodyUpdatePositionDefault;
|
45
|
+
|
46
|
+
cpBodySetMass(body, m);
|
47
|
+
cpBodySetMoment(body, i);
|
48
|
+
|
49
|
+
body->p = cpvzero;
|
50
|
+
body->v = cpvzero;
|
51
|
+
body->f = cpvzero;
|
52
|
+
|
53
|
+
cpBodySetAngle(body, 0.0f);
|
54
|
+
body->w = 0.0f;
|
55
|
+
body->t = 0.0f;
|
56
|
+
|
57
|
+
body->v_bias = cpvzero;
|
58
|
+
body->w_bias = 0.0f;
|
59
|
+
|
60
|
+
body->data = NULL;
|
61
|
+
body->v_limit = (cpFloat)INFINITY;
|
62
|
+
body->w_limit = (cpFloat)INFINITY;
|
63
|
+
|
64
|
+
body->space = NULL;
|
65
|
+
body->shapesList = NULL;
|
66
|
+
|
67
|
+
cpComponentNode node = {NULL, NULL, 0, 0.0f};
|
68
|
+
body->node = node;
|
69
|
+
|
70
|
+
return body;
|
71
|
+
}
|
72
|
+
|
73
|
+
cpBody*
|
74
|
+
cpBodyNew(cpFloat m, cpFloat i)
|
75
|
+
{
|
76
|
+
return cpBodyInit(cpBodyAlloc(), m, i);
|
77
|
+
}
|
78
|
+
|
79
|
+
cpBody *
|
80
|
+
cpBodyInitStatic(cpBody *body)
|
81
|
+
{
|
82
|
+
cpBodyInit(body, (cpFloat)INFINITY, (cpFloat)INFINITY);
|
83
|
+
body->node.idleTime = (cpFloat)INFINITY;
|
84
|
+
|
85
|
+
return body;
|
86
|
+
}
|
87
|
+
|
88
|
+
cpBody *
|
89
|
+
cpBodyNewStatic()
|
90
|
+
{
|
91
|
+
return cpBodyInitStatic(cpBodyAlloc());
|
92
|
+
}
|
93
|
+
|
94
|
+
void cpBodyDestroy(cpBody *body){}
|
95
|
+
|
96
|
+
void
|
97
|
+
cpBodyFree(cpBody *body)
|
98
|
+
{
|
99
|
+
if(body){
|
100
|
+
cpBodyDestroy(body);
|
101
|
+
cpfree(body);
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
void
|
106
|
+
cpBodySetMass(cpBody *body, cpFloat mass)
|
107
|
+
{
|
108
|
+
body->m = mass;
|
109
|
+
body->m_inv = 1.0f/mass;
|
110
|
+
}
|
111
|
+
|
112
|
+
void
|
113
|
+
cpBodySetMoment(cpBody *body, cpFloat moment)
|
114
|
+
{
|
115
|
+
body->i = moment;
|
116
|
+
body->i_inv = 1.0f/moment;
|
117
|
+
}
|
118
|
+
|
119
|
+
void
|
120
|
+
cpBodySetAngle(cpBody *body, cpFloat angle)
|
121
|
+
{
|
122
|
+
body->a = angle;//fmod(a, (cpFloat)M_PI*2.0f);
|
123
|
+
body->rot = cpvforangle(angle);
|
124
|
+
}
|
125
|
+
|
126
|
+
void
|
127
|
+
cpBodySlew(cpBody *body, cpVect pos, cpFloat dt)
|
128
|
+
{
|
129
|
+
cpVect delta = cpvsub(pos, body->p);
|
130
|
+
body->v = cpvmult(delta, 1.0f/dt);
|
131
|
+
}
|
132
|
+
|
133
|
+
void
|
134
|
+
cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
|
135
|
+
{
|
136
|
+
body->v = cpvclamp(cpvadd(cpvmult(body->v, damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), dt)), body->v_limit);
|
137
|
+
|
138
|
+
cpFloat w_limit = body->w_limit;
|
139
|
+
body->w = cpfclamp(body->w*damping + body->t*body->i_inv*dt, -w_limit, w_limit);
|
140
|
+
}
|
141
|
+
|
142
|
+
void
|
143
|
+
cpBodyUpdatePosition(cpBody *body, cpFloat dt)
|
144
|
+
{
|
145
|
+
body->p = cpvadd(body->p, cpvmult(cpvadd(body->v, body->v_bias), dt));
|
146
|
+
cpBodySetAngle(body, body->a + (body->w + body->w_bias)*dt);
|
147
|
+
|
148
|
+
body->v_bias = cpvzero;
|
149
|
+
body->w_bias = 0.0f;
|
150
|
+
}
|
151
|
+
|
152
|
+
void
|
153
|
+
cpBodyResetForces(cpBody *body)
|
154
|
+
{
|
155
|
+
body->f = cpvzero;
|
156
|
+
body->t = 0.0f;
|
157
|
+
}
|
158
|
+
|
159
|
+
void
|
160
|
+
cpBodyApplyForce(cpBody *body, cpVect force, cpVect r)
|
161
|
+
{
|
162
|
+
body->f = cpvadd(body->f, force);
|
163
|
+
body->t += cpvcross(r, force);
|
164
|
+
}
|
165
|
+
|
166
|
+
void
|
167
|
+
cpApplyDampedSpring(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat rlen, cpFloat k, cpFloat dmp, cpFloat dt)
|
168
|
+
{
|
169
|
+
// Calculate the world space anchor coordinates.
|
170
|
+
cpVect r1 = cpvrotate(anchr1, a->rot);
|
171
|
+
cpVect r2 = cpvrotate(anchr2, b->rot);
|
172
|
+
|
173
|
+
cpVect delta = cpvsub(cpvadd(b->p, r2), cpvadd(a->p, r1));
|
174
|
+
cpFloat dist = cpvlength(delta);
|
175
|
+
cpVect n = dist ? cpvmult(delta, 1.0f/dist) : cpvzero;
|
176
|
+
|
177
|
+
cpFloat f_spring = (dist - rlen)*k;
|
178
|
+
|
179
|
+
// Calculate the world relative velocities of the anchor points.
|
180
|
+
cpVect v1 = cpvadd(a->v, cpvmult(cpvperp(r1), a->w));
|
181
|
+
cpVect v2 = cpvadd(b->v, cpvmult(cpvperp(r2), b->w));
|
182
|
+
|
183
|
+
// Calculate the damping force.
|
184
|
+
// This really should be in the impulse solver and can produce problems when using large damping values.
|
185
|
+
cpFloat vrn = cpvdot(cpvsub(v2, v1), n);
|
186
|
+
cpFloat f_damp = vrn*cpfmin(dmp, 1.0f/(dt*(a->m_inv + b->m_inv)));
|
187
|
+
|
188
|
+
// Apply!
|
189
|
+
cpVect f = cpvmult(n, f_spring + f_damp);
|
190
|
+
cpBodyApplyForce(a, f, r1);
|
191
|
+
cpBodyApplyForce(b, cpvneg(f), r2);
|
192
|
+
}
|
@@ -0,0 +1,411 @@
|
|
1
|
+
/* Copyright (c) 2007 Scott Lembcke
|
2
|
+
*
|
3
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
* of this software and associated documentation files (the "Software"), to deal
|
5
|
+
* in the Software without restriction, including without limitation the rights
|
6
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
* copies of the Software, and to permit persons to whom the Software is
|
8
|
+
* furnished to do so, subject to the following conditions:
|
9
|
+
*
|
10
|
+
* The above copyright notice and this permission notice shall be included in
|
11
|
+
* all copies or substantial portions of the Software.
|
12
|
+
*
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
* SOFTWARE.
|
20
|
+
*/
|
21
|
+
|
22
|
+
#include <stdlib.h>
|
23
|
+
#include <math.h>
|
24
|
+
//#include <stdio.h>
|
25
|
+
|
26
|
+
#include "chipmunk_private.h"
|
27
|
+
|
28
|
+
typedef int (*collisionFunc)(const cpShape *, const cpShape *, cpContact *);
|
29
|
+
|
30
|
+
// Add contact points for circle to circle collisions.
|
31
|
+
// Used by several collision tests.
|
32
|
+
static int
|
33
|
+
circle2circleQuery(const cpVect p1, const cpVect p2, const cpFloat r1, const cpFloat r2, cpContact *con)
|
34
|
+
{
|
35
|
+
cpFloat mindist = r1 + r2;
|
36
|
+
cpVect delta = cpvsub(p2, p1);
|
37
|
+
cpFloat distsq = cpvlengthsq(delta);
|
38
|
+
if(distsq >= mindist*mindist) return 0;
|
39
|
+
|
40
|
+
cpFloat dist = cpfsqrt(distsq);
|
41
|
+
|
42
|
+
// Allocate and initialize the contact.
|
43
|
+
cpContactInit(
|
44
|
+
con,
|
45
|
+
cpvadd(p1, cpvmult(delta, 0.5f + (r1 - 0.5f*mindist)/(dist ? dist : INFINITY))),
|
46
|
+
(dist ? cpvmult(delta, 1.0f/dist) : cpv(1.0f, 0.0f)),
|
47
|
+
dist - mindist,
|
48
|
+
0
|
49
|
+
);
|
50
|
+
|
51
|
+
return 1;
|
52
|
+
}
|
53
|
+
|
54
|
+
// Collide circle shapes.
|
55
|
+
static int
|
56
|
+
circle2circle(const cpShape *shape1, const cpShape *shape2, cpContact *arr)
|
57
|
+
{
|
58
|
+
cpCircleShape *circ1 = (cpCircleShape *)shape1;
|
59
|
+
cpCircleShape *circ2 = (cpCircleShape *)shape2;
|
60
|
+
|
61
|
+
return circle2circleQuery(circ1->tc, circ2->tc, circ1->r, circ2->r, arr);
|
62
|
+
}
|
63
|
+
|
64
|
+
// Collide circles to segment shapes.
|
65
|
+
static int
|
66
|
+
circle2segment(const cpShape *circleShape, const cpShape *segmentShape, cpContact *con)
|
67
|
+
{
|
68
|
+
cpCircleShape *circ = (cpCircleShape *)circleShape;
|
69
|
+
cpSegmentShape *seg = (cpSegmentShape *)segmentShape;
|
70
|
+
|
71
|
+
// Radius sum
|
72
|
+
cpFloat rsum = circ->r + seg->r;
|
73
|
+
|
74
|
+
// Calculate normal distance from segment.
|
75
|
+
cpFloat dn = cpvdot(seg->tn, circ->tc) - cpvdot(seg->ta, seg->tn);
|
76
|
+
cpFloat dist = cpfabs(dn) - rsum;
|
77
|
+
if(dist > 0.0f) return 0;
|
78
|
+
|
79
|
+
// Calculate tangential distance along segment.
|
80
|
+
cpFloat dt = -cpvcross(seg->tn, circ->tc);
|
81
|
+
cpFloat dtMin = -cpvcross(seg->tn, seg->ta);
|
82
|
+
cpFloat dtMax = -cpvcross(seg->tn, seg->tb);
|
83
|
+
|
84
|
+
// Decision tree to decide which feature of the segment to collide with.
|
85
|
+
if(dt < dtMin){
|
86
|
+
if(dt < (dtMin - rsum)){
|
87
|
+
return 0;
|
88
|
+
} else {
|
89
|
+
return circle2circleQuery(circ->tc, seg->ta, circ->r, seg->r, con);
|
90
|
+
}
|
91
|
+
} else {
|
92
|
+
if(dt < dtMax){
|
93
|
+
cpVect n = (dn < 0.0f) ? seg->tn : cpvneg(seg->tn);
|
94
|
+
cpContactInit(
|
95
|
+
con,
|
96
|
+
cpvadd(circ->tc, cpvmult(n, circ->r + dist*0.5f)),
|
97
|
+
n,
|
98
|
+
dist,
|
99
|
+
0
|
100
|
+
);
|
101
|
+
return 1;
|
102
|
+
} else {
|
103
|
+
if(dt < (dtMax + rsum)) {
|
104
|
+
return circle2circleQuery(circ->tc, seg->tb, circ->r, seg->r, con);
|
105
|
+
} else {
|
106
|
+
return 0;
|
107
|
+
}
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
return 1;
|
112
|
+
}
|
113
|
+
|
114
|
+
// Helper function for working with contact buffers
|
115
|
+
// This used to malloc/realloc memory on the fly but was repurposed.
|
116
|
+
static cpContact *
|
117
|
+
nextContactPoint(cpContact *arr, int *numPtr)
|
118
|
+
{
|
119
|
+
int index = *numPtr;
|
120
|
+
|
121
|
+
if(index < CP_MAX_CONTACTS_PER_ARBITER){
|
122
|
+
(*numPtr) = index + 1;
|
123
|
+
return &arr[index];
|
124
|
+
} else {
|
125
|
+
return &arr[CP_MAX_CONTACTS_PER_ARBITER - 1];
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
// Find the minimum separating axis for the give poly and axis list.
|
130
|
+
static inline int
|
131
|
+
findMSA(const cpPolyShape *poly, const cpPolyShapeAxis *axes, const int num, cpFloat *min_out)
|
132
|
+
{
|
133
|
+
int min_index = 0;
|
134
|
+
cpFloat min = cpPolyShapeValueOnAxis(poly, axes->n, axes->d);
|
135
|
+
if(min > 0.0f) return -1;
|
136
|
+
|
137
|
+
for(int i=1; i<num; i++){
|
138
|
+
cpFloat dist = cpPolyShapeValueOnAxis(poly, axes[i].n, axes[i].d);
|
139
|
+
if(dist > 0.0f) {
|
140
|
+
return -1;
|
141
|
+
} else if(dist > min){
|
142
|
+
min = dist;
|
143
|
+
min_index = i;
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
(*min_out) = min;
|
148
|
+
return min_index;
|
149
|
+
}
|
150
|
+
|
151
|
+
// Add contacts for probably penetrating vertexes.
|
152
|
+
// This handles the degenerate case where an overlap was detected, but no vertexes fall inside
|
153
|
+
// the opposing polygon. (like a star of david)
|
154
|
+
static inline int
|
155
|
+
findVertsFallback(cpContact *arr, const cpPolyShape *poly1, const cpPolyShape *poly2, const cpVect n, const cpFloat dist)
|
156
|
+
{
|
157
|
+
int num = 0;
|
158
|
+
|
159
|
+
for(int i=0; i<poly1->numVerts; i++){
|
160
|
+
cpVect v = poly1->tVerts[i];
|
161
|
+
if(cpPolyShapeContainsVertPartial(poly2, v, cpvneg(n)))
|
162
|
+
cpContactInit(nextContactPoint(arr, &num), v, n, dist, CP_HASH_PAIR(poly1->shape.hashid, i));
|
163
|
+
}
|
164
|
+
|
165
|
+
for(int i=0; i<poly2->numVerts; i++){
|
166
|
+
cpVect v = poly2->tVerts[i];
|
167
|
+
if(cpPolyShapeContainsVertPartial(poly1, v, n))
|
168
|
+
cpContactInit(nextContactPoint(arr, &num), v, n, dist, CP_HASH_PAIR(poly2->shape.hashid, i));
|
169
|
+
}
|
170
|
+
|
171
|
+
return num;
|
172
|
+
}
|
173
|
+
|
174
|
+
// Add contacts for penetrating vertexes.
|
175
|
+
static inline int
|
176
|
+
findVerts(cpContact *arr, const cpPolyShape *poly1, const cpPolyShape *poly2, const cpVect n, const cpFloat dist)
|
177
|
+
{
|
178
|
+
int num = 0;
|
179
|
+
|
180
|
+
for(int i=0; i<poly1->numVerts; i++){
|
181
|
+
cpVect v = poly1->tVerts[i];
|
182
|
+
if(cpPolyShapeContainsVert(poly2, v))
|
183
|
+
cpContactInit(nextContactPoint(arr, &num), v, n, dist, CP_HASH_PAIR(poly1->shape.hashid, i));
|
184
|
+
}
|
185
|
+
|
186
|
+
for(int i=0; i<poly2->numVerts; i++){
|
187
|
+
cpVect v = poly2->tVerts[i];
|
188
|
+
if(cpPolyShapeContainsVert(poly1, v))
|
189
|
+
cpContactInit(nextContactPoint(arr, &num), v, n, dist, CP_HASH_PAIR(poly2->shape.hashid, i));
|
190
|
+
}
|
191
|
+
|
192
|
+
return (num ? num : findVertsFallback(arr, poly1, poly2, n, dist));
|
193
|
+
}
|
194
|
+
|
195
|
+
// Collide poly shapes together.
|
196
|
+
static int
|
197
|
+
poly2poly(const cpShape *shape1, const cpShape *shape2, cpContact *arr)
|
198
|
+
{
|
199
|
+
cpPolyShape *poly1 = (cpPolyShape *)shape1;
|
200
|
+
cpPolyShape *poly2 = (cpPolyShape *)shape2;
|
201
|
+
|
202
|
+
cpFloat min1;
|
203
|
+
int mini1 = findMSA(poly2, poly1->tAxes, poly1->numVerts, &min1);
|
204
|
+
if(mini1 == -1) return 0;
|
205
|
+
|
206
|
+
cpFloat min2;
|
207
|
+
int mini2 = findMSA(poly1, poly2->tAxes, poly2->numVerts, &min2);
|
208
|
+
if(mini2 == -1) return 0;
|
209
|
+
|
210
|
+
// There is overlap, find the penetrating verts
|
211
|
+
if(min1 > min2)
|
212
|
+
return findVerts(arr, poly1, poly2, poly1->tAxes[mini1].n, min1);
|
213
|
+
else
|
214
|
+
return findVerts(arr, poly1, poly2, cpvneg(poly2->tAxes[mini2].n), min2);
|
215
|
+
}
|
216
|
+
|
217
|
+
// Like cpPolyValueOnAxis(), but for segments.
|
218
|
+
static inline cpFloat
|
219
|
+
segValueOnAxis(const cpSegmentShape *seg, const cpVect n, const cpFloat d)
|
220
|
+
{
|
221
|
+
cpFloat a = cpvdot(n, seg->ta) - seg->r;
|
222
|
+
cpFloat b = cpvdot(n, seg->tb) - seg->r;
|
223
|
+
return cpfmin(a, b) - d;
|
224
|
+
}
|
225
|
+
|
226
|
+
// Identify vertexes that have penetrated the segment.
|
227
|
+
static inline void
|
228
|
+
findPointsBehindSeg(cpContact *arr, int *num, const cpSegmentShape *seg, const cpPolyShape *poly, const cpFloat pDist, const cpFloat coef)
|
229
|
+
{
|
230
|
+
cpFloat dta = cpvcross(seg->tn, seg->ta);
|
231
|
+
cpFloat dtb = cpvcross(seg->tn, seg->tb);
|
232
|
+
cpVect n = cpvmult(seg->tn, coef);
|
233
|
+
|
234
|
+
for(int i=0; i<poly->numVerts; i++){
|
235
|
+
cpVect v = poly->tVerts[i];
|
236
|
+
if(cpvdot(v, n) < cpvdot(seg->tn, seg->ta)*coef + seg->r){
|
237
|
+
cpFloat dt = cpvcross(seg->tn, v);
|
238
|
+
if(dta >= dt && dt >= dtb){
|
239
|
+
cpContactInit(nextContactPoint(arr, num), v, n, pDist, CP_HASH_PAIR(poly->shape.hashid, i));
|
240
|
+
}
|
241
|
+
}
|
242
|
+
}
|
243
|
+
}
|
244
|
+
|
245
|
+
// This one is complicated and gross. Just don't go there...
|
246
|
+
// TODO: Comment me!
|
247
|
+
static int
|
248
|
+
seg2poly(const cpShape *shape1, const cpShape *shape2, cpContact *arr)
|
249
|
+
{
|
250
|
+
cpSegmentShape *seg = (cpSegmentShape *)shape1;
|
251
|
+
cpPolyShape *poly = (cpPolyShape *)shape2;
|
252
|
+
cpPolyShapeAxis *axes = poly->tAxes;
|
253
|
+
|
254
|
+
cpFloat segD = cpvdot(seg->tn, seg->ta);
|
255
|
+
cpFloat minNorm = cpPolyShapeValueOnAxis(poly, seg->tn, segD) - seg->r;
|
256
|
+
cpFloat minNeg = cpPolyShapeValueOnAxis(poly, cpvneg(seg->tn), -segD) - seg->r;
|
257
|
+
if(minNeg > 0.0f || minNorm > 0.0f) return 0;
|
258
|
+
|
259
|
+
int mini = 0;
|
260
|
+
cpFloat poly_min = segValueOnAxis(seg, axes->n, axes->d);
|
261
|
+
if(poly_min > 0.0f) return 0;
|
262
|
+
for(int i=0; i<poly->numVerts; i++){
|
263
|
+
cpFloat dist = segValueOnAxis(seg, axes[i].n, axes[i].d);
|
264
|
+
if(dist > 0.0f){
|
265
|
+
return 0;
|
266
|
+
} else if(dist > poly_min){
|
267
|
+
poly_min = dist;
|
268
|
+
mini = i;
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
int num = 0;
|
273
|
+
|
274
|
+
cpVect poly_n = cpvneg(axes[mini].n);
|
275
|
+
|
276
|
+
cpVect va = cpvadd(seg->ta, cpvmult(poly_n, seg->r));
|
277
|
+
cpVect vb = cpvadd(seg->tb, cpvmult(poly_n, seg->r));
|
278
|
+
if(cpPolyShapeContainsVert(poly, va))
|
279
|
+
cpContactInit(nextContactPoint(arr, &num), va, poly_n, poly_min, CP_HASH_PAIR(seg->shape.hashid, 0));
|
280
|
+
if(cpPolyShapeContainsVert(poly, vb))
|
281
|
+
cpContactInit(nextContactPoint(arr, &num), vb, poly_n, poly_min, CP_HASH_PAIR(seg->shape.hashid, 1));
|
282
|
+
|
283
|
+
// Floating point precision problems here.
|
284
|
+
// This will have to do for now.
|
285
|
+
poly_min -= cp_collision_slop;
|
286
|
+
if(minNorm >= poly_min || minNeg >= poly_min) {
|
287
|
+
if(minNorm > minNeg)
|
288
|
+
findPointsBehindSeg(arr, &num, seg, poly, minNorm, 1.0f);
|
289
|
+
else
|
290
|
+
findPointsBehindSeg(arr, &num, seg, poly, minNeg, -1.0f);
|
291
|
+
}
|
292
|
+
|
293
|
+
// If no other collision points are found, try colliding endpoints.
|
294
|
+
if(num == 0){
|
295
|
+
cpVect poly_a = poly->tVerts[mini];
|
296
|
+
cpVect poly_b = poly->tVerts[(mini + 1)%poly->numVerts];
|
297
|
+
|
298
|
+
if(circle2circleQuery(seg->ta, poly_a, seg->r, 0.0f, arr))
|
299
|
+
return 1;
|
300
|
+
|
301
|
+
if(circle2circleQuery(seg->tb, poly_a, seg->r, 0.0f, arr))
|
302
|
+
return 1;
|
303
|
+
|
304
|
+
if(circle2circleQuery(seg->ta, poly_b, seg->r, 0.0f, arr))
|
305
|
+
return 1;
|
306
|
+
|
307
|
+
if(circle2circleQuery(seg->tb, poly_b, seg->r, 0.0f, arr))
|
308
|
+
return 1;
|
309
|
+
}
|
310
|
+
|
311
|
+
return num;
|
312
|
+
}
|
313
|
+
|
314
|
+
// This one is less gross, but still gross.
|
315
|
+
// TODO: Comment me!
|
316
|
+
static int
|
317
|
+
circle2poly(const cpShape *shape1, const cpShape *shape2, cpContact *con)
|
318
|
+
{
|
319
|
+
cpCircleShape *circ = (cpCircleShape *)shape1;
|
320
|
+
cpPolyShape *poly = (cpPolyShape *)shape2;
|
321
|
+
cpPolyShapeAxis *axes = poly->tAxes;
|
322
|
+
|
323
|
+
int mini = 0;
|
324
|
+
cpFloat min = cpvdot(axes->n, circ->tc) - axes->d - circ->r;
|
325
|
+
for(int i=0; i<poly->numVerts; i++){
|
326
|
+
cpFloat dist = cpvdot(axes[i].n, circ->tc) - axes[i].d - circ->r;
|
327
|
+
if(dist > 0.0f){
|
328
|
+
return 0;
|
329
|
+
} else if(dist > min) {
|
330
|
+
min = dist;
|
331
|
+
mini = i;
|
332
|
+
}
|
333
|
+
}
|
334
|
+
|
335
|
+
cpVect n = axes[mini].n;
|
336
|
+
cpVect a = poly->tVerts[mini];
|
337
|
+
cpVect b = poly->tVerts[(mini + 1)%poly->numVerts];
|
338
|
+
cpFloat dta = cpvcross(n, a);
|
339
|
+
cpFloat dtb = cpvcross(n, b);
|
340
|
+
cpFloat dt = cpvcross(n, circ->tc);
|
341
|
+
|
342
|
+
if(dt < dtb){
|
343
|
+
return circle2circleQuery(circ->tc, b, circ->r, 0.0f, con);
|
344
|
+
} else if(dt < dta) {
|
345
|
+
cpContactInit(
|
346
|
+
con,
|
347
|
+
cpvsub(circ->tc, cpvmult(n, circ->r + min/2.0f)),
|
348
|
+
cpvneg(n),
|
349
|
+
min,
|
350
|
+
0
|
351
|
+
);
|
352
|
+
|
353
|
+
return 1;
|
354
|
+
} else {
|
355
|
+
return circle2circleQuery(circ->tc, a, circ->r, 0.0f, con);
|
356
|
+
}
|
357
|
+
}
|
358
|
+
|
359
|
+
//static const collisionFunc builtinCollisionFuncs[9] = {
|
360
|
+
// circle2circle,
|
361
|
+
// NULL,
|
362
|
+
// NULL,
|
363
|
+
// circle2segment,
|
364
|
+
// NULL,
|
365
|
+
// NULL,
|
366
|
+
// circle2poly,
|
367
|
+
// seg2poly,
|
368
|
+
// poly2poly,
|
369
|
+
//};
|
370
|
+
//static const collisionFunc *colfuncs = builtinCollisionFuncs;
|
371
|
+
|
372
|
+
static collisionFunc *colfuncs = NULL;
|
373
|
+
|
374
|
+
static void
|
375
|
+
addColFunc(const cpShapeType a, const cpShapeType b, const collisionFunc func)
|
376
|
+
{
|
377
|
+
colfuncs[a + b*CP_NUM_SHAPES] = func;
|
378
|
+
}
|
379
|
+
|
380
|
+
#ifdef __cplusplus
|
381
|
+
extern "C" {
|
382
|
+
#endif
|
383
|
+
void cpInitCollisionFuncs(void);
|
384
|
+
|
385
|
+
// Initializes the array of collision functions.
|
386
|
+
// Called by cpInitChipmunk().
|
387
|
+
void
|
388
|
+
cpInitCollisionFuncs(void)
|
389
|
+
{
|
390
|
+
if(!colfuncs)
|
391
|
+
colfuncs = (collisionFunc *)cpcalloc(CP_NUM_SHAPES*CP_NUM_SHAPES, sizeof(collisionFunc));
|
392
|
+
|
393
|
+
addColFunc(CP_CIRCLE_SHAPE, CP_CIRCLE_SHAPE, circle2circle);
|
394
|
+
addColFunc(CP_CIRCLE_SHAPE, CP_SEGMENT_SHAPE, circle2segment);
|
395
|
+
addColFunc(CP_SEGMENT_SHAPE, CP_POLY_SHAPE, seg2poly);
|
396
|
+
addColFunc(CP_CIRCLE_SHAPE, CP_POLY_SHAPE, circle2poly);
|
397
|
+
addColFunc(CP_POLY_SHAPE, CP_POLY_SHAPE, poly2poly);
|
398
|
+
}
|
399
|
+
#ifdef __cplusplus
|
400
|
+
}
|
401
|
+
#endif
|
402
|
+
|
403
|
+
int
|
404
|
+
cpCollideShapes(const cpShape *a, const cpShape *b, cpContact *arr)
|
405
|
+
{
|
406
|
+
// Their shape types must be in order.
|
407
|
+
cpAssert(a->klass->type <= b->klass->type, "Collision shapes passed to cpCollideShapes() are not sorted.");
|
408
|
+
|
409
|
+
collisionFunc cfunc = colfuncs[a->klass->type + b->klass->type*CP_NUM_SHAPES];
|
410
|
+
return (cfunc) ? cfunc(a, b, arr) : 0;
|
411
|
+
}
|