chipmunk 5.3.4.0-x86-mingw32 → 5.3.4.2-x86-mingw32
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/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
|
+
}
|