chipmunk 4.1.0-x86-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,132 @@
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
+ struct cpBody;
23
+ typedef void (*cpBodyVelocityFunc)(struct cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);
24
+ typedef void (*cpBodyPositionFunc)(struct cpBody *body, cpFloat dt);
25
+
26
+
27
+ typedef struct cpBody{
28
+ // *** Integration Functions.
29
+
30
+ // Function that is called to integrate the body's velocity. (Defaults to cpBodyUpdateVelocity)
31
+ cpBodyVelocityFunc velocity_func;
32
+
33
+ // Function that is called to integrate the body's position. (Defaults to cpBodyUpdatePosition)
34
+ cpBodyPositionFunc position_func;
35
+
36
+ // *** Mass Properties
37
+
38
+ // Mass and it's inverse.
39
+ // Always use cpBodySetMass() whenever changing the mass as these values must agree.
40
+ cpFloat m, m_inv;
41
+
42
+ // Moment of inertia and it's inverse.
43
+ // Always use cpBodySetMass() whenever changing the mass as these values must agree.
44
+ cpFloat i, i_inv;
45
+
46
+ // *** Positional Properties
47
+
48
+ // Linear components of motion (position, velocity, and force)
49
+ cpVect p, v, f;
50
+
51
+ // Angular components of motion (angle, angular velocity, and torque)
52
+ // Always use cpBodySetAngle() to set the angle of the body as a and rot must agree.
53
+ cpFloat a, w, t;
54
+
55
+ // Cached unit length vector representing the angle of the body.
56
+ // Used for fast vector rotation using cpvrotate().
57
+ cpVect rot;
58
+
59
+ // *** User Definable Fields
60
+
61
+ // User defined data pointer.
62
+ void *data;
63
+
64
+ // *** Internally Used Fields
65
+
66
+ // Velocity bias values used when solving penetrations and correcting joints.
67
+ cpVect v_bias;
68
+ cpFloat w_bias;
69
+
70
+ // int active;
71
+ } cpBody;
72
+
73
+ // Basic allocation/destruction functions
74
+ cpBody *cpBodyAlloc(void);
75
+ cpBody *cpBodyInit(cpBody *body, cpFloat m, cpFloat i);
76
+ cpBody *cpBodyNew(cpFloat m, cpFloat i);
77
+
78
+ void cpBodyDestroy(cpBody *body);
79
+ void cpBodyFree(cpBody *body);
80
+
81
+ // Setters for some of the special properties (mandatory!)
82
+ void cpBodySetMass(cpBody *body, cpFloat m);
83
+ void cpBodySetMoment(cpBody *body, cpFloat i);
84
+ void cpBodySetAngle(cpBody *body, cpFloat a);
85
+
86
+ // Modify the velocity of the body so that it will move to the specified absolute coordinates in the next timestep.
87
+ // Intended for objects that are moved manually with a custom velocity integration function.
88
+ void cpBodySlew(cpBody *body, cpVect pos, cpFloat dt);
89
+
90
+ // Default Integration functions.
91
+ void cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);
92
+ void cpBodyUpdatePosition(cpBody *body, cpFloat dt);
93
+
94
+ // Convert body local to world coordinates
95
+ static inline cpVect
96
+ cpBodyLocal2World(cpBody *body, cpVect v)
97
+ {
98
+ return cpvadd(body->p, cpvrotate(v, body->rot));
99
+ }
100
+
101
+ // Convert world to body local coordinates
102
+ static inline cpVect
103
+ cpBodyWorld2Local(cpBody *body, cpVect v)
104
+ {
105
+ return cpvunrotate(cpvsub(v, body->p), body->rot);
106
+ }
107
+
108
+ // Apply an impulse (in world coordinates) to the body.
109
+ static inline void
110
+ cpBodyApplyImpulse(cpBody *body, cpVect j, cpVect r)
111
+ {
112
+ body->v = cpvadd(body->v, cpvmult(j, body->m_inv));
113
+ body->w += body->i_inv*cpvcross(r, j);
114
+ }
115
+
116
+ // Not intended for external use. Used by cpArbiter.c and cpJoint.c.
117
+ static inline void
118
+ cpBodyApplyBiasImpulse(cpBody *body, cpVect j, cpVect r)
119
+ {
120
+ body->v_bias = cpvadd(body->v_bias, cpvmult(j, body->m_inv));
121
+ body->w_bias += body->i_inv*cpvcross(r, j);
122
+ }
123
+
124
+ // Zero the forces on a body.
125
+ void cpBodyResetForces(cpBody *body);
126
+ // Apply a force (in world coordinates) to a body.
127
+ void cpBodyApplyForce(cpBody *body, cpVect f, cpVect r);
128
+
129
+ // Apply a damped spring force between two bodies.
130
+ void cpDampedSpring(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat rlen, cpFloat k, cpFloat dmp, cpFloat dt);
131
+
132
+ //int cpBodyMarkLowEnergy(cpBody *body, cpFloat dvsq, int max);
@@ -0,0 +1,390 @@
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
+ #include <assert.h>
26
+
27
+ #include "chipmunk.h"
28
+
29
+ typedef int (*collisionFunc)(cpShape*, cpShape*, cpContact**);
30
+
31
+ static collisionFunc *colfuncs = NULL;
32
+
33
+ // Add contact points for circle to circle collisions.
34
+ // Used by several collision tests.
35
+ static int
36
+ circle2circleQuery(cpVect p1, cpVect p2, cpFloat r1, cpFloat r2, cpContact **con)
37
+ {
38
+ cpFloat mindist = r1 + r2;
39
+ cpVect delta = cpvsub(p2, p1);
40
+ cpFloat distsq = cpvlengthsq(delta);
41
+ if(distsq >= mindist*mindist) return 0;
42
+
43
+ cpFloat dist = sqrtf(distsq);
44
+ // To avoid singularities, do nothing in the case of dist = 0.
45
+ cpFloat non_zero_dist = (dist ? dist : INFINITY);
46
+
47
+ // Allocate and initialize the contact.
48
+ (*con) = (cpContact *)malloc(sizeof(cpContact));
49
+ 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),
53
+ dist - mindist,
54
+ 0
55
+ );
56
+
57
+ return 1;
58
+ }
59
+
60
+ // Collide circle shapes.
61
+ static int
62
+ circle2circle(cpShape *shape1, cpShape *shape2, cpContact **arr)
63
+ {
64
+ cpCircleShape *circ1 = (cpCircleShape *)shape1;
65
+ cpCircleShape *circ2 = (cpCircleShape *)shape2;
66
+
67
+ return circle2circleQuery(circ1->tc, circ2->tc, circ1->r, circ2->r, arr);
68
+ }
69
+
70
+ // Collide circles to segment shapes.
71
+ static int
72
+ circle2segment(cpShape *circleShape, cpShape *segmentShape, cpContact **con)
73
+ {
74
+ cpCircleShape *circ = (cpCircleShape *)circleShape;
75
+ cpSegmentShape *seg = (cpSegmentShape *)segmentShape;
76
+
77
+ // Radius sum
78
+ cpFloat rsum = circ->r + seg->r;
79
+
80
+ // Calculate normal distance from segment.
81
+ cpFloat dn = cpvdot(seg->tn, circ->tc) - cpvdot(seg->ta, seg->tn);
82
+ cpFloat dist = fabs(dn) - rsum;
83
+ if(dist > 0.0f) return 0;
84
+
85
+ // Calculate tangential distance along segment.
86
+ cpFloat dt = -cpvcross(seg->tn, circ->tc);
87
+ cpFloat dtMin = -cpvcross(seg->tn, seg->ta);
88
+ cpFloat dtMax = -cpvcross(seg->tn, seg->tb);
89
+
90
+ // Decision tree to decide which feature of the segment to collide with.
91
+ if(dt < dtMin){
92
+ if(dt < (dtMin - rsum)){
93
+ return 0;
94
+ } else {
95
+ return circle2circleQuery(circ->tc, seg->ta, circ->r, seg->r, con);
96
+ }
97
+ } else {
98
+ if(dt < dtMax){
99
+ cpVect n = (dn < 0.0f) ? seg->tn : cpvneg(seg->tn);
100
+ (*con) = (cpContact *)malloc(sizeof(cpContact));
101
+ cpContactInit(
102
+ (*con),
103
+ cpvadd(circ->tc, cpvmult(n, circ->r + dist*0.5f)),
104
+ n,
105
+ dist,
106
+ 0
107
+ );
108
+ return 1;
109
+ } else {
110
+ if(dt < (dtMax + rsum)) {
111
+ return circle2circleQuery(circ->tc, seg->tb, circ->r, seg->r, con);
112
+ } else {
113
+ return 0;
114
+ }
115
+ }
116
+ }
117
+
118
+ return 1;
119
+ }
120
+
121
+ // Helper function for allocating contact point lists.
122
+ static cpContact *
123
+ addContactPoint(cpContact **arr, int *max, int *num)
124
+ {
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
+ }
135
+
136
+ cpContact *con = &(*arr)[*num];
137
+ (*num)++;
138
+
139
+ return con;
140
+ }
141
+
142
+ // Find the minimum separating axis for the give poly and axis list.
143
+ static inline int
144
+ findMSA(cpPolyShape *poly, cpPolyShapeAxis *axes, int num, cpFloat *min_out)
145
+ {
146
+ int min_index = 0;
147
+ cpFloat min = cpPolyShapeValueOnAxis(poly, axes->n, axes->d);
148
+ if(min > 0.0) return -1;
149
+
150
+ for(int i=1; i<num; i++){
151
+ cpFloat dist = cpPolyShapeValueOnAxis(poly, axes[i].n, axes[i].d);
152
+ if(dist > 0.0) {
153
+ return -1;
154
+ } else if(dist > min){
155
+ min = dist;
156
+ min_index = i;
157
+ }
158
+ }
159
+
160
+ (*min_out) = min;
161
+ return min_index;
162
+ }
163
+
164
+ // Add contacts for penetrating vertexes.
165
+ static inline int
166
+ findVerts(cpContact **arr, cpPolyShape *poly1, cpPolyShape *poly2, cpVect n, cpFloat dist)
167
+ {
168
+ int max = 0;
169
+ int num = 0;
170
+
171
+ for(int i=0; i<poly1->numVerts; i++){
172
+ cpVect v = poly1->tVerts[i];
173
+ if(cpPolyShapeContainsVertPartial(poly2, v, cpvneg(n)))
174
+ cpContactInit(addContactPoint(arr, &max, &num), v, n, dist, CP_HASH_PAIR(poly1, i));
175
+ }
176
+
177
+ for(int i=0; i<poly2->numVerts; i++){
178
+ cpVect v = poly2->tVerts[i];
179
+ if(cpPolyShapeContainsVertPartial(poly1, v, n))
180
+ cpContactInit(addContactPoint(arr, &max, &num), v, n, dist, CP_HASH_PAIR(poly2, i));
181
+ }
182
+
183
+ // if(!num)
184
+ // addContactPoint(arr, &size, &num, cpContactNew(shape1->body->p, n, dist, 0));
185
+
186
+ return num;
187
+ }
188
+
189
+ // Collide poly shapes together.
190
+ static int
191
+ poly2poly(cpShape *shape1, cpShape *shape2, cpContact **arr)
192
+ {
193
+ cpPolyShape *poly1 = (cpPolyShape *)shape1;
194
+ cpPolyShape *poly2 = (cpPolyShape *)shape2;
195
+
196
+ cpFloat min1;
197
+ int mini1 = findMSA(poly2, poly1->tAxes, poly1->numVerts, &min1);
198
+ if(mini1 == -1) return 0;
199
+
200
+ cpFloat min2;
201
+ int mini2 = findMSA(poly1, poly2->tAxes, poly2->numVerts, &min2);
202
+ if(mini2 == -1) return 0;
203
+
204
+ // There is overlap, find the penetrating verts
205
+ if(min1 > min2)
206
+ return findVerts(arr, poly1, poly2, poly1->tAxes[mini1].n, min1);
207
+ else
208
+ return findVerts(arr, poly1, poly2, cpvneg(poly2->tAxes[mini2].n), min2);
209
+ }
210
+
211
+ // Like cpPolyValueOnAxis(), but for segments.
212
+ static inline float
213
+ segValueOnAxis(cpSegmentShape *seg, cpVect n, cpFloat d)
214
+ {
215
+ cpFloat a = cpvdot(n, seg->ta) - seg->r;
216
+ cpFloat b = cpvdot(n, seg->tb) - seg->r;
217
+ return cpfmin(a, b) - d;
218
+ }
219
+
220
+ // Identify vertexes that have penetrated the segment.
221
+ static inline void
222
+ findPointsBehindSeg(cpContact **arr, int *max, int *num, cpSegmentShape *seg, cpPolyShape *poly, cpFloat pDist, cpFloat coef)
223
+ {
224
+ cpFloat dta = cpvcross(seg->tn, seg->ta);
225
+ cpFloat dtb = cpvcross(seg->tn, seg->tb);
226
+ cpVect n = cpvmult(seg->tn, coef);
227
+
228
+ for(int i=0; i<poly->numVerts; i++){
229
+ cpVect v = poly->tVerts[i];
230
+ if(cpvdot(v, n) < cpvdot(seg->tn, seg->ta)*coef + seg->r){
231
+ cpFloat dt = cpvcross(seg->tn, v);
232
+ if(dta >= dt && dt >= dtb){
233
+ cpContactInit(addContactPoint(arr, max, num), v, n, pDist, CP_HASH_PAIR(poly, i));
234
+ }
235
+ }
236
+ }
237
+ }
238
+
239
+ // This one is complicated and gross. Just don't go there...
240
+ // TODO: Comment me!
241
+ static int
242
+ seg2poly(cpShape *shape1, cpShape *shape2, cpContact **arr)
243
+ {
244
+ cpSegmentShape *seg = (cpSegmentShape *)shape1;
245
+ cpPolyShape *poly = (cpPolyShape *)shape2;
246
+ cpPolyShapeAxis *axes = poly->tAxes;
247
+
248
+ cpFloat segD = cpvdot(seg->tn, seg->ta);
249
+ cpFloat minNorm = cpPolyShapeValueOnAxis(poly, seg->tn, segD) - seg->r;
250
+ cpFloat minNeg = cpPolyShapeValueOnAxis(poly, cpvneg(seg->tn), -segD) - seg->r;
251
+ if(minNeg > 0.0f || minNorm > 0.0f) return 0;
252
+
253
+ int mini = 0;
254
+ cpFloat poly_min = segValueOnAxis(seg, axes->n, axes->d);
255
+ if(poly_min > 0.0f) return 0;
256
+ for(int i=0; i<poly->numVerts; i++){
257
+ cpFloat dist = segValueOnAxis(seg, axes[i].n, axes[i].d);
258
+ if(dist > 0.0f){
259
+ return 0;
260
+ } else if(dist > poly_min){
261
+ poly_min = dist;
262
+ mini = i;
263
+ }
264
+ }
265
+
266
+ int max = 0;
267
+ int num = 0;
268
+
269
+ cpVect poly_n = cpvneg(axes[mini].n);
270
+
271
+ cpVect va = cpvadd(seg->ta, cpvmult(poly_n, seg->r));
272
+ cpVect vb = cpvadd(seg->tb, cpvmult(poly_n, seg->r));
273
+ if(cpPolyShapeContainsVert(poly, va))
274
+ cpContactInit(addContactPoint(arr, &max, &num), va, poly_n, poly_min, CP_HASH_PAIR(seg, 0));
275
+ if(cpPolyShapeContainsVert(poly, vb))
276
+ cpContactInit(addContactPoint(arr, &max, &num), vb, poly_n, poly_min, CP_HASH_PAIR(seg, 1));
277
+
278
+ // Floating point precision problems here.
279
+ // This will have to do for now.
280
+ poly_min -= cp_collision_slop;
281
+ if(minNorm >= poly_min || minNeg >= poly_min) {
282
+ if(minNorm > minNeg)
283
+ findPointsBehindSeg(arr, &max, &num, seg, poly, minNorm, 1.0f);
284
+ else
285
+ findPointsBehindSeg(arr, &max, &num, seg, poly, minNeg, -1.0f);
286
+ }
287
+
288
+ // If no other collision points are found, try colliding endpoints.
289
+ if(num == 0){
290
+ cpVect poly_a = poly->tVerts[mini];
291
+ cpVect poly_b = poly->tVerts[(mini + 1)%poly->numVerts];
292
+
293
+ if(circle2circleQuery(seg->ta, poly_a, seg->r, 0.0f, arr))
294
+ return 1;
295
+
296
+ if(circle2circleQuery(seg->tb, poly_a, seg->r, 0.0f, arr))
297
+ return 1;
298
+
299
+ if(circle2circleQuery(seg->ta, poly_b, seg->r, 0.0f, arr))
300
+ return 1;
301
+
302
+ if(circle2circleQuery(seg->tb, poly_b, seg->r, 0.0f, arr))
303
+ return 1;
304
+ }
305
+
306
+ return num;
307
+ }
308
+
309
+ // This one is less gross, but still gross.
310
+ // TODO: Comment me!
311
+ static int
312
+ circle2poly(cpShape *shape1, cpShape *shape2, cpContact **con)
313
+ {
314
+ cpCircleShape *circ = (cpCircleShape *)shape1;
315
+ cpPolyShape *poly = (cpPolyShape *)shape2;
316
+ cpPolyShapeAxis *axes = poly->tAxes;
317
+
318
+ int mini = 0;
319
+ cpFloat min = cpvdot(axes->n, circ->tc) - axes->d - circ->r;
320
+ for(int i=0; i<poly->numVerts; i++){
321
+ cpFloat dist = cpvdot(axes[i].n, circ->tc) - axes[i].d - circ->r;
322
+ if(dist > 0.0){
323
+ return 0;
324
+ } else if(dist > min) {
325
+ min = dist;
326
+ mini = i;
327
+ }
328
+ }
329
+
330
+ cpVect n = axes[mini].n;
331
+ cpVect a = poly->tVerts[mini];
332
+ cpVect b = poly->tVerts[(mini + 1)%poly->numVerts];
333
+ cpFloat dta = cpvcross(n, a);
334
+ cpFloat dtb = cpvcross(n, b);
335
+ cpFloat dt = cpvcross(n, circ->tc);
336
+
337
+ if(dt < dtb){
338
+ return circle2circleQuery(circ->tc, b, circ->r, 0.0f, con);
339
+ } else if(dt < dta) {
340
+ (*con) = (cpContact *)malloc(sizeof(cpContact));
341
+ cpContactInit(
342
+ (*con),
343
+ cpvsub(circ->tc, cpvmult(n, circ->r + min/2.0f)),
344
+ cpvneg(n),
345
+ min,
346
+ 0
347
+ );
348
+
349
+ return 1;
350
+ } else {
351
+ return circle2circleQuery(circ->tc, a, circ->r, 0.0f, con);
352
+ }
353
+ }
354
+
355
+ static void
356
+ addColFunc(cpShapeType a, cpShapeType b, collisionFunc func)
357
+ {
358
+ colfuncs[a + b*CP_NUM_SHAPES] = func;
359
+ }
360
+
361
+ #ifdef __cplusplus
362
+ extern "C" {
363
+ #endif
364
+ // Initializes the array of collision functions.
365
+ // Called by cpInitChipmunk().
366
+ void
367
+ cpInitCollisionFuncs(void)
368
+ {
369
+ if(!colfuncs)
370
+ colfuncs = (collisionFunc *)calloc(CP_NUM_SHAPES*CP_NUM_SHAPES, sizeof(collisionFunc));
371
+
372
+ addColFunc(CP_CIRCLE_SHAPE, CP_CIRCLE_SHAPE, circle2circle);
373
+ addColFunc(CP_CIRCLE_SHAPE, CP_SEGMENT_SHAPE, circle2segment);
374
+ addColFunc(CP_SEGMENT_SHAPE, CP_POLY_SHAPE, seg2poly);
375
+ addColFunc(CP_CIRCLE_SHAPE, CP_POLY_SHAPE, circle2poly);
376
+ addColFunc(CP_POLY_SHAPE, CP_POLY_SHAPE, poly2poly);
377
+ }
378
+ #ifdef __cplusplus
379
+ }
380
+ #endif
381
+
382
+ int
383
+ cpCollideShapes(cpShape *a, cpShape *b, cpContact **arr)
384
+ {
385
+ // Their shape types must be in order.
386
+ assert(a->klass->type <= b->klass->type);
387
+
388
+ collisionFunc cfunc = colfuncs[a->klass->type + b->klass->type*CP_NUM_SHAPES];
389
+ return (cfunc) ? cfunc(a, b, arr) : 0;
390
+ }