chipmunk 5.3.4.5 → 6.1.3.0.rc1
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/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
|
|