chipmunk 5.3.4.5 → 6.1.3.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/chipmunk/chipmunk.c +199 -28
- data/ext/chipmunk/chipmunk.h +123 -68
- data/ext/chipmunk/chipmunk_ffi.h +129 -11
- data/ext/chipmunk/chipmunk_private.h +232 -16
- data/ext/chipmunk/chipmunk_types.h +94 -30
- data/ext/chipmunk/chipmunk_unsafe.h +12 -3
- data/ext/chipmunk/constraints/cpConstraint.h +90 -34
- data/ext/chipmunk/{cpDampedRotarySpring.h → constraints/cpDampedRotarySpring.h} +18 -8
- data/ext/chipmunk/{cpDampedSpring.h → constraints/cpDampedSpring.h} +27 -16
- data/ext/chipmunk/constraints/cpGearJoint.h +17 -7
- data/ext/chipmunk/constraints/cpGrooveJoint.h +19 -10
- data/ext/chipmunk/constraints/cpPinJoint.h +17 -8
- data/ext/chipmunk/constraints/cpPivotJoint.h +18 -9
- data/ext/chipmunk/constraints/cpRatchetJoint.h +17 -8
- data/ext/chipmunk/constraints/cpRotaryLimitJoint.h +16 -7
- data/ext/chipmunk/{cpSimpleMotor.h → constraints/cpSimpleMotor.h} +15 -6
- data/ext/chipmunk/constraints/cpSlideJoint.h +18 -9
- data/ext/chipmunk/constraints/util.h +36 -44
- data/ext/chipmunk/cpArbiter.c +159 -94
- data/ext/chipmunk/cpArbiter.h +135 -129
- data/ext/chipmunk/cpArray.c +37 -56
- data/ext/chipmunk/cpBB.c +1 -12
- data/ext/chipmunk/cpBB.h +80 -18
- data/ext/chipmunk/cpBBTree.c +891 -0
- data/ext/chipmunk/cpBody.c +185 -47
- data/ext/chipmunk/cpBody.h +156 -124
- data/ext/chipmunk/cpCollision.c +126 -115
- data/ext/chipmunk/cpConstraint.c +10 -6
- data/ext/chipmunk/cpDampedRotarySpring.c +26 -17
- data/ext/chipmunk/cpDampedSpring.c +25 -18
- data/ext/chipmunk/cpGearJoint.c +23 -17
- data/ext/chipmunk/cpGrooveJoint.c +26 -22
- data/ext/chipmunk/cpHashSet.c +51 -51
- data/ext/chipmunk/cpPinJoint.c +26 -19
- data/ext/chipmunk/cpPivotJoint.c +23 -19
- data/ext/chipmunk/cpPolyShape.c +93 -69
- data/ext/chipmunk/cpPolyShape.h +33 -69
- data/ext/chipmunk/cpRatchetJoint.c +26 -21
- data/ext/chipmunk/cpRotaryLimitJoint.c +28 -22
- data/ext/chipmunk/cpShape.c +122 -133
- data/ext/chipmunk/cpShape.h +146 -95
- data/ext/chipmunk/cpSimpleMotor.c +24 -17
- data/ext/chipmunk/cpSlideJoint.c +28 -26
- data/ext/chipmunk/cpSpace.c +251 -196
- data/ext/chipmunk/cpSpace.h +173 -103
- data/ext/chipmunk/cpSpaceComponent.c +236 -159
- data/ext/chipmunk/cpSpaceHash.c +259 -159
- data/ext/chipmunk/cpSpaceQuery.c +127 -59
- data/ext/chipmunk/cpSpaceStep.c +235 -197
- data/ext/chipmunk/cpSpatialIndex.c +69 -0
- data/ext/chipmunk/cpSpatialIndex.h +227 -0
- data/ext/chipmunk/cpSweep1D.c +254 -0
- data/ext/chipmunk/cpVect.c +11 -26
- data/ext/chipmunk/cpVect.h +76 -71
- data/ext/chipmunk/extconf.rb +4 -31
- data/ext/chipmunk/prime.h +1 -1
- data/ext/chipmunk/rb_chipmunk.c +36 -45
- data/ext/chipmunk/rb_chipmunk.h +6 -3
- data/ext/chipmunk/rb_cpArbiter.c +2 -2
- data/ext/chipmunk/rb_cpBB.c +116 -35
- data/ext/chipmunk/rb_cpBody.c +5 -12
- data/ext/chipmunk/rb_cpConstraint.c +144 -9
- data/ext/chipmunk/rb_cpShape.c +69 -78
- data/ext/chipmunk/rb_cpSpace.c +81 -76
- metadata +61 -61
- data/LICENSE +0 -22
- data/README +0 -110
- data/Rakefile +0 -102
- data/ext/chipmunk/cpArray.h +0 -49
- data/ext/chipmunk/cpCollision.h +0 -28
- data/ext/chipmunk/cpHashSet.h +0 -82
- data/ext/chipmunk/cpSpaceHash.h +0 -110
- data/lib/chipmunk.rb +0 -194
data/ext/chipmunk/cpCollision.c
CHANGED
@@ -19,10 +19,6 @@
|
|
19
19
|
* SOFTWARE.
|
20
20
|
*/
|
21
21
|
|
22
|
-
#include <stdlib.h>
|
23
|
-
#include <math.h>
|
24
|
-
//#include <stdio.h>
|
25
|
-
|
26
22
|
#include "chipmunk_private.h"
|
27
23
|
|
28
24
|
typedef int (*collisionFunc)(const cpShape *, const cpShape *, cpContact *);
|
@@ -55,60 +51,36 @@ circle2circleQuery(const cpVect p1, const cpVect p2, const cpFloat r1, const cpF
|
|
55
51
|
static int
|
56
52
|
circle2circle(const cpShape *shape1, const cpShape *shape2, cpContact *arr)
|
57
53
|
{
|
58
|
-
cpCircleShape *circ1 = (cpCircleShape *)shape1;
|
54
|
+
cpCircleShape *circ1 = (cpCircleShape *)shape1; //TODO
|
59
55
|
cpCircleShape *circ2 = (cpCircleShape *)shape2;
|
60
56
|
|
61
57
|
return circle2circleQuery(circ1->tc, circ2->tc, circ1->r, circ2->r, arr);
|
62
58
|
}
|
63
59
|
|
64
|
-
// Collide circles to segment shapes.
|
65
60
|
static int
|
66
|
-
circle2segment(const
|
61
|
+
circle2segment(const cpCircleShape *circleShape, const cpSegmentShape *segmentShape, cpContact *con)
|
67
62
|
{
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
// Radius sum
|
72
|
-
cpFloat rsum = circ->r + seg->r;
|
63
|
+
cpVect seg_a = segmentShape->ta;
|
64
|
+
cpVect seg_b = segmentShape->tb;
|
65
|
+
cpVect center = circleShape->tc;
|
73
66
|
|
74
|
-
|
75
|
-
cpFloat
|
76
|
-
|
77
|
-
if(dist > 0.0f) return 0;
|
67
|
+
cpVect seg_delta = cpvsub(seg_b, seg_a);
|
68
|
+
cpFloat closest_t = cpfclamp01(cpvdot(seg_delta, cpvsub(center, seg_a))/cpvlengthsq(seg_delta));
|
69
|
+
cpVect closest = cpvadd(seg_a, cpvmult(seg_delta, closest_t));
|
78
70
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
return circle2circleQuery(circ->tc, seg->ta, circ->r, seg->r, con);
|
90
|
-
}
|
71
|
+
if(circle2circleQuery(center, closest, circleShape->r, segmentShape->r, con)){
|
72
|
+
cpVect n = con[0].n;
|
73
|
+
|
74
|
+
// Reject endcap collisions if tangents are provided.
|
75
|
+
if(
|
76
|
+
(closest_t == 0.0f && cpvdot(n, segmentShape->a_tangent) < 0.0) ||
|
77
|
+
(closest_t == 1.0f && cpvdot(n, segmentShape->b_tangent) < 0.0)
|
78
|
+
) return 0;
|
79
|
+
|
80
|
+
return 1;
|
91
81
|
} else {
|
92
|
-
|
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
|
-
}
|
82
|
+
return 0;
|
109
83
|
}
|
110
|
-
|
111
|
-
return 1;
|
112
84
|
}
|
113
85
|
|
114
86
|
// Helper function for working with contact buffers
|
@@ -128,14 +100,14 @@ nextContactPoint(cpContact *arr, int *numPtr)
|
|
128
100
|
|
129
101
|
// Find the minimum separating axis for the give poly and axis list.
|
130
102
|
static inline int
|
131
|
-
findMSA(const cpPolyShape *poly, const
|
103
|
+
findMSA(const cpPolyShape *poly, const cpSplittingPlane *planes, const int num, cpFloat *min_out)
|
132
104
|
{
|
133
105
|
int min_index = 0;
|
134
|
-
cpFloat min = cpPolyShapeValueOnAxis(poly,
|
106
|
+
cpFloat min = cpPolyShapeValueOnAxis(poly, planes->n, planes->d);
|
135
107
|
if(min > 0.0f) return -1;
|
136
108
|
|
137
109
|
for(int i=1; i<num; i++){
|
138
|
-
cpFloat dist = cpPolyShapeValueOnAxis(poly,
|
110
|
+
cpFloat dist = cpPolyShapeValueOnAxis(poly, planes[i].n, planes[i].d);
|
139
111
|
if(dist > 0.0f) {
|
140
112
|
return -1;
|
141
113
|
} else if(dist > min){
|
@@ -200,18 +172,18 @@ poly2poly(const cpShape *shape1, const cpShape *shape2, cpContact *arr)
|
|
200
172
|
cpPolyShape *poly2 = (cpPolyShape *)shape2;
|
201
173
|
|
202
174
|
cpFloat min1;
|
203
|
-
int mini1 = findMSA(poly2, poly1->
|
175
|
+
int mini1 = findMSA(poly2, poly1->tPlanes, poly1->numVerts, &min1);
|
204
176
|
if(mini1 == -1) return 0;
|
205
177
|
|
206
178
|
cpFloat min2;
|
207
|
-
int mini2 = findMSA(poly1, poly2->
|
179
|
+
int mini2 = findMSA(poly1, poly2->tPlanes, poly2->numVerts, &min2);
|
208
180
|
if(mini2 == -1) return 0;
|
209
181
|
|
210
182
|
// There is overlap, find the penetrating verts
|
211
183
|
if(min1 > min2)
|
212
|
-
return findVerts(arr, poly1, poly2, poly1->
|
184
|
+
return findVerts(arr, poly1, poly2, poly1->tPlanes[mini1].n, min1);
|
213
185
|
else
|
214
|
-
return findVerts(arr, poly1, poly2, cpvneg(poly2->
|
186
|
+
return findVerts(arr, poly1, poly2, cpvneg(poly2->tPlanes[mini2].n), min2);
|
215
187
|
}
|
216
188
|
|
217
189
|
// Like cpPolyValueOnAxis(), but for segments.
|
@@ -249,7 +221,7 @@ seg2poly(const cpShape *shape1, const cpShape *shape2, cpContact *arr)
|
|
249
221
|
{
|
250
222
|
cpSegmentShape *seg = (cpSegmentShape *)shape1;
|
251
223
|
cpPolyShape *poly = (cpPolyShape *)shape2;
|
252
|
-
|
224
|
+
cpSplittingPlane *planes = poly->tPlanes;
|
253
225
|
|
254
226
|
cpFloat segD = cpvdot(seg->tn, seg->ta);
|
255
227
|
cpFloat minNorm = cpPolyShapeValueOnAxis(poly, seg->tn, segD) - seg->r;
|
@@ -257,10 +229,10 @@ seg2poly(const cpShape *shape1, const cpShape *shape2, cpContact *arr)
|
|
257
229
|
if(minNeg > 0.0f || minNorm > 0.0f) return 0;
|
258
230
|
|
259
231
|
int mini = 0;
|
260
|
-
cpFloat poly_min = segValueOnAxis(seg,
|
232
|
+
cpFloat poly_min = segValueOnAxis(seg, planes->n, planes->d);
|
261
233
|
if(poly_min > 0.0f) return 0;
|
262
234
|
for(int i=0; i<poly->numVerts; i++){
|
263
|
-
cpFloat dist = segValueOnAxis(seg,
|
235
|
+
cpFloat dist = segValueOnAxis(seg, planes[i].n, planes[i].d);
|
264
236
|
if(dist > 0.0f){
|
265
237
|
return 0;
|
266
238
|
} else if(dist > poly_min){
|
@@ -271,7 +243,7 @@ seg2poly(const cpShape *shape1, const cpShape *shape2, cpContact *arr)
|
|
271
243
|
|
272
244
|
int num = 0;
|
273
245
|
|
274
|
-
cpVect poly_n = cpvneg(
|
246
|
+
cpVect poly_n = cpvneg(planes[mini].n);
|
275
247
|
|
276
248
|
cpVect va = cpvadd(seg->ta, cpvmult(poly_n, seg->r));
|
277
249
|
cpVect vb = cpvadd(seg->tb, cpvmult(poly_n, seg->r));
|
@@ -279,10 +251,11 @@ seg2poly(const cpShape *shape1, const cpShape *shape2, cpContact *arr)
|
|
279
251
|
cpContactInit(nextContactPoint(arr, &num), va, poly_n, poly_min, CP_HASH_PAIR(seg->shape.hashid, 0));
|
280
252
|
if(cpPolyShapeContainsVert(poly, vb))
|
281
253
|
cpContactInit(nextContactPoint(arr, &num), vb, poly_n, poly_min, CP_HASH_PAIR(seg->shape.hashid, 1));
|
282
|
-
|
254
|
+
|
283
255
|
// Floating point precision problems here.
|
284
256
|
// This will have to do for now.
|
285
|
-
poly_min -= cp_collision_slop;
|
257
|
+
// poly_min -= cp_collision_slop; // TODO is this needed anymore?
|
258
|
+
|
286
259
|
if(minNorm >= poly_min || minNeg >= poly_min) {
|
287
260
|
if(minNorm > minNeg)
|
288
261
|
findPointsBehindSeg(arr, &num, seg, poly, minNorm, 1.0f);
|
@@ -295,17 +268,10 @@ seg2poly(const cpShape *shape1, const cpShape *shape2, cpContact *arr)
|
|
295
268
|
cpVect poly_a = poly->tVerts[mini];
|
296
269
|
cpVect poly_b = poly->tVerts[(mini + 1)%poly->numVerts];
|
297
270
|
|
298
|
-
if(circle2circleQuery(seg->ta, poly_a, seg->r, 0.0f, arr))
|
299
|
-
|
300
|
-
|
301
|
-
if(circle2circleQuery(seg->tb,
|
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;
|
271
|
+
if(circle2circleQuery(seg->ta, poly_a, seg->r, 0.0f, arr)) return 1;
|
272
|
+
if(circle2circleQuery(seg->tb, poly_a, seg->r, 0.0f, arr)) return 1;
|
273
|
+
if(circle2circleQuery(seg->ta, poly_b, seg->r, 0.0f, arr)) return 1;
|
274
|
+
if(circle2circleQuery(seg->tb, poly_b, seg->r, 0.0f, arr)) return 1;
|
309
275
|
}
|
310
276
|
|
311
277
|
return num;
|
@@ -318,12 +284,12 @@ circle2poly(const cpShape *shape1, const cpShape *shape2, cpContact *con)
|
|
318
284
|
{
|
319
285
|
cpCircleShape *circ = (cpCircleShape *)shape1;
|
320
286
|
cpPolyShape *poly = (cpPolyShape *)shape2;
|
321
|
-
|
287
|
+
cpSplittingPlane *planes = poly->tPlanes;
|
322
288
|
|
323
289
|
int mini = 0;
|
324
|
-
cpFloat min =
|
290
|
+
cpFloat min = cpSplittingPlaneCompare(planes[0], circ->tc) - circ->r;
|
325
291
|
for(int i=0; i<poly->numVerts; i++){
|
326
|
-
cpFloat dist =
|
292
|
+
cpFloat dist = cpSplittingPlaneCompare(planes[i], circ->tc) - circ->r;
|
327
293
|
if(dist > 0.0f){
|
328
294
|
return 0;
|
329
295
|
} else if(dist > min) {
|
@@ -332,7 +298,7 @@ circle2poly(const cpShape *shape1, const cpShape *shape2, cpContact *con)
|
|
332
298
|
}
|
333
299
|
}
|
334
300
|
|
335
|
-
cpVect n =
|
301
|
+
cpVect n = planes[mini].n;
|
336
302
|
cpVect a = poly->tVerts[mini];
|
337
303
|
cpVect b = poly->tVerts[(mini + 1)%poly->numVerts];
|
338
304
|
cpFloat dta = cpvcross(n, a);
|
@@ -356,55 +322,100 @@ circle2poly(const cpShape *shape1, const cpShape *shape2, cpContact *con)
|
|
356
322
|
}
|
357
323
|
}
|
358
324
|
|
359
|
-
//
|
360
|
-
|
361
|
-
|
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)
|
325
|
+
// Submitted by LegoCyclon
|
326
|
+
static int
|
327
|
+
seg2seg(const cpShape* shape1, const cpShape* shape2, cpContact* con)
|
376
328
|
{
|
377
|
-
|
329
|
+
cpSegmentShape* seg1 = (cpSegmentShape *)shape1;
|
330
|
+
cpSegmentShape* seg2 = (cpSegmentShape *)shape2;
|
331
|
+
|
332
|
+
cpVect v1 = cpvsub(seg1->tb, seg1->ta);
|
333
|
+
cpVect v2 = cpvsub(seg2->tb, seg2->ta);
|
334
|
+
cpFloat v1lsq = cpvlengthsq(v1);
|
335
|
+
cpFloat v2lsq = cpvlengthsq(v2);
|
336
|
+
// project seg2 onto seg1
|
337
|
+
cpVect p1a = cpvproject(cpvsub(seg2->ta, seg1->ta), v1);
|
338
|
+
cpVect p1b = cpvproject(cpvsub(seg2->tb, seg1->ta), v1);
|
339
|
+
// project seg1 onto seg2
|
340
|
+
cpVect p2a = cpvproject(cpvsub(seg1->ta, seg2->ta), v2);
|
341
|
+
cpVect p2b = cpvproject(cpvsub(seg1->tb, seg2->ta), v2);
|
342
|
+
|
343
|
+
// clamp projections to segment endcaps
|
344
|
+
if (cpvdot(p1a, v1) < 0.0f)
|
345
|
+
p1a = cpvzero;
|
346
|
+
else if (cpvdot(p1a, v1) > 0.0f && cpvlengthsq(p1a) > v1lsq)
|
347
|
+
p1a = v1;
|
348
|
+
if (cpvdot(p1b, v1) < 0.0f)
|
349
|
+
p1b = cpvzero;
|
350
|
+
else if (cpvdot(p1b, v1) > 0.0f && cpvlengthsq(p1b) > v1lsq)
|
351
|
+
p1b = v1;
|
352
|
+
if (cpvdot(p2a, v2) < 0.0f)
|
353
|
+
p2a = cpvzero;
|
354
|
+
else if (cpvdot(p2a, v2) > 0.0f && cpvlengthsq(p2a) > v2lsq)
|
355
|
+
p2a = v2;
|
356
|
+
if (cpvdot(p2b, v2) < 0.0f)
|
357
|
+
p2b = cpvzero;
|
358
|
+
else if (cpvdot(p2b, v2) > 0.0f && cpvlengthsq(p2b) > v2lsq)
|
359
|
+
p2b = v2;
|
360
|
+
|
361
|
+
p1a = cpvadd(p1a, seg1->ta);
|
362
|
+
p1b = cpvadd(p1b, seg1->ta);
|
363
|
+
p2a = cpvadd(p2a, seg2->ta);
|
364
|
+
p2b = cpvadd(p2b, seg2->ta);
|
365
|
+
|
366
|
+
int num = 0;
|
367
|
+
|
368
|
+
if (!circle2circleQuery(p1a, p2a, seg1->r, seg2->r, nextContactPoint(con, &num)))
|
369
|
+
--num;
|
370
|
+
|
371
|
+
if (!circle2circleQuery(p1b, p2b, seg1->r, seg2->r, nextContactPoint(con, &num)))
|
372
|
+
--num;
|
373
|
+
|
374
|
+
if (!circle2circleQuery(p1a, p2b, seg1->r, seg2->r, nextContactPoint(con, &num)))
|
375
|
+
--num;
|
376
|
+
|
377
|
+
if (!circle2circleQuery(p1b, p2a, seg1->r, seg2->r, nextContactPoint(con, &num)))
|
378
|
+
--num;
|
379
|
+
|
380
|
+
return num;
|
378
381
|
}
|
379
382
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
383
|
+
static const collisionFunc builtinCollisionFuncs[9] = {
|
384
|
+
circle2circle,
|
385
|
+
NULL,
|
386
|
+
NULL,
|
387
|
+
(collisionFunc)circle2segment,
|
388
|
+
NULL,
|
389
|
+
NULL,
|
390
|
+
circle2poly,
|
391
|
+
seg2poly,
|
392
|
+
poly2poly,
|
393
|
+
};
|
394
|
+
static const collisionFunc *colfuncs = builtinCollisionFuncs;
|
395
|
+
|
396
|
+
static const collisionFunc segmentCollisions[9] = {
|
397
|
+
circle2circle,
|
398
|
+
NULL,
|
399
|
+
NULL,
|
400
|
+
(collisionFunc)circle2segment,
|
401
|
+
seg2seg,
|
402
|
+
NULL,
|
403
|
+
circle2poly,
|
404
|
+
seg2poly,
|
405
|
+
poly2poly,
|
406
|
+
};
|
407
|
+
|
408
|
+
void
|
409
|
+
cpEnableSegmentToSegmentCollisions(void)
|
410
|
+
{
|
411
|
+
colfuncs = segmentCollisions;
|
400
412
|
}
|
401
|
-
#endif
|
402
413
|
|
403
414
|
int
|
404
415
|
cpCollideShapes(const cpShape *a, const cpShape *b, cpContact *arr)
|
405
416
|
{
|
406
417
|
// Their shape types must be in order.
|
407
|
-
|
418
|
+
cpAssertSoft(a->klass->type <= b->klass->type, "Collision shapes passed to cpCollideShapes() are not sorted.");
|
408
419
|
|
409
420
|
collisionFunc cfunc = colfuncs[a->klass->type + b->klass->type*CP_NUM_SHAPES];
|
410
421
|
return (cfunc) ? cfunc(a, b, arr) : 0;
|
data/ext/chipmunk/cpConstraint.c
CHANGED
@@ -19,15 +19,11 @@
|
|
19
19
|
* SOFTWARE.
|
20
20
|
*/
|
21
21
|
|
22
|
-
#include <stdlib.h>
|
23
|
-
|
24
22
|
#include "chipmunk_private.h"
|
25
23
|
#include "constraints/util.h"
|
26
24
|
|
27
25
|
// TODO: Comment me!
|
28
26
|
|
29
|
-
cpFloat cp_constraint_bias_coef = 0.1f;
|
30
|
-
|
31
27
|
void cpConstraintDestroy(cpConstraint *constraint){}
|
32
28
|
|
33
29
|
void
|
@@ -39,16 +35,24 @@ cpConstraintFree(cpConstraint *constraint)
|
|
39
35
|
}
|
40
36
|
}
|
41
37
|
|
42
|
-
// ***
|
38
|
+
// *** declared in util.h TODO move declaration to chipmunk_private.h
|
43
39
|
|
44
40
|
void
|
45
41
|
cpConstraintInit(cpConstraint *constraint, const cpConstraintClass *klass, cpBody *a, cpBody *b)
|
46
42
|
{
|
47
43
|
constraint->klass = klass;
|
44
|
+
|
48
45
|
constraint->a = a;
|
49
46
|
constraint->b = b;
|
47
|
+
constraint->space = NULL;
|
48
|
+
|
49
|
+
constraint->next_a = NULL;
|
50
|
+
constraint->next_b = NULL;
|
50
51
|
|
51
52
|
constraint->maxForce = (cpFloat)INFINITY;
|
52
|
-
constraint->
|
53
|
+
constraint->errorBias = cpfpow(1.0f - 0.1f, 60.0f);
|
53
54
|
constraint->maxBias = (cpFloat)INFINITY;
|
55
|
+
|
56
|
+
constraint->preSolve = NULL;
|
57
|
+
constraint->postSolve = NULL;
|
54
58
|
}
|
@@ -19,9 +19,6 @@
|
|
19
19
|
* SOFTWARE.
|
20
20
|
*/
|
21
21
|
|
22
|
-
#include <stdlib.h>
|
23
|
-
#include <math.h>
|
24
|
-
|
25
22
|
#include "chipmunk_private.h"
|
26
23
|
#include "constraints/util.h"
|
27
24
|
|
@@ -31,11 +28,13 @@ defaultSpringTorque(cpDampedRotarySpring *spring, cpFloat relativeAngle){
|
|
31
28
|
}
|
32
29
|
|
33
30
|
static void
|
34
|
-
preStep(cpDampedRotarySpring *spring, cpFloat dt
|
31
|
+
preStep(cpDampedRotarySpring *spring, cpFloat dt)
|
35
32
|
{
|
36
|
-
|
33
|
+
cpBody *a = spring->constraint.a;
|
34
|
+
cpBody *b = spring->constraint.b;
|
37
35
|
|
38
36
|
cpFloat moment = a->i_inv + b->i_inv;
|
37
|
+
cpAssertSoft(moment != 0.0, "Unsolvable spring.");
|
39
38
|
spring->iSum = 1.0f/moment;
|
40
39
|
|
41
40
|
spring->w_coef = 1.0f - cpfexp(-spring->damping*dt*moment);
|
@@ -43,46 +42,54 @@ preStep(cpDampedRotarySpring *spring, cpFloat dt, cpFloat dt_inv)
|
|
43
42
|
|
44
43
|
// apply spring torque
|
45
44
|
cpFloat j_spring = spring->springTorqueFunc((cpConstraint *)spring, a->a - b->a)*dt;
|
45
|
+
spring->jAcc = j_spring;
|
46
|
+
|
46
47
|
a->w -= j_spring*a->i_inv;
|
47
48
|
b->w += j_spring*b->i_inv;
|
48
49
|
}
|
49
50
|
|
51
|
+
static void applyCachedImpulse(cpDampedRotarySpring *spring, cpFloat dt_coef){}
|
52
|
+
|
50
53
|
static void
|
51
|
-
applyImpulse(cpDampedRotarySpring *spring)
|
54
|
+
applyImpulse(cpDampedRotarySpring *spring, cpFloat dt)
|
52
55
|
{
|
53
|
-
|
56
|
+
cpBody *a = spring->constraint.a;
|
57
|
+
cpBody *b = spring->constraint.b;
|
54
58
|
|
55
59
|
// compute relative velocity
|
56
60
|
cpFloat wrn = a->w - b->w;//normal_relative_velocity(a, b, r1, r2, n) - spring->target_vrn;
|
57
61
|
|
58
62
|
// compute velocity loss from drag
|
59
63
|
// not 100% certain this is derived correctly, though it makes sense
|
60
|
-
cpFloat w_damp = wrn*spring->w_coef;
|
61
|
-
spring->target_wrn = wrn
|
64
|
+
cpFloat w_damp = (spring->target_wrn - wrn)*spring->w_coef;
|
65
|
+
spring->target_wrn = wrn + w_damp;
|
62
66
|
|
63
67
|
//apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, v_damp*spring->nMass));
|
64
68
|
cpFloat j_damp = w_damp*spring->iSum;
|
65
|
-
|
66
|
-
|
69
|
+
spring->jAcc += j_damp;
|
70
|
+
|
71
|
+
a->w += j_damp*a->i_inv;
|
72
|
+
b->w -= j_damp*b->i_inv;
|
67
73
|
}
|
68
74
|
|
69
75
|
static cpFloat
|
70
|
-
getImpulse(
|
76
|
+
getImpulse(cpDampedRotarySpring *spring)
|
71
77
|
{
|
72
|
-
return
|
78
|
+
return spring->jAcc;
|
73
79
|
}
|
74
80
|
|
75
81
|
static const cpConstraintClass klass = {
|
76
|
-
(
|
77
|
-
(
|
78
|
-
(
|
82
|
+
(cpConstraintPreStepImpl)preStep,
|
83
|
+
(cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
|
84
|
+
(cpConstraintApplyImpulseImpl)applyImpulse,
|
85
|
+
(cpConstraintGetImpulseImpl)getImpulse,
|
79
86
|
};
|
80
87
|
CP_DefineClassGetter(cpDampedRotarySpring)
|
81
88
|
|
82
89
|
cpDampedRotarySpring *
|
83
90
|
cpDampedRotarySpringAlloc(void)
|
84
91
|
{
|
85
|
-
return (cpDampedRotarySpring *)
|
92
|
+
return (cpDampedRotarySpring *)cpcalloc(1, sizeof(cpDampedRotarySpring));
|
86
93
|
}
|
87
94
|
|
88
95
|
cpDampedRotarySpring *
|
@@ -95,6 +102,8 @@ cpDampedRotarySpringInit(cpDampedRotarySpring *spring, cpBody *a, cpBody *b, cpF
|
|
95
102
|
spring->damping = damping;
|
96
103
|
spring->springTorqueFunc = (cpDampedRotarySpringTorqueFunc)defaultSpringTorque;
|
97
104
|
|
105
|
+
spring->jAcc = 0.0f;
|
106
|
+
|
98
107
|
return spring;
|
99
108
|
}
|
100
109
|
|