chipmunk 4.1.0

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.
@@ -0,0 +1,553 @@
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
+
25
+ #include "chipmunk.h"
26
+
27
+ // TODO: Comment me!
28
+
29
+ cpFloat cp_joint_bias_coef = 0.1f;
30
+
31
+ void cpJointDestroy(cpJoint *joint){}
32
+
33
+ void
34
+ cpJointFree(cpJoint *joint)
35
+ {
36
+ if(joint) cpJointDestroy(joint);
37
+ free(joint);
38
+ }
39
+
40
+ static void
41
+ cpJointInit(cpJoint *joint, const cpJointClass *klass, cpBody *a, cpBody *b)
42
+ {
43
+ joint->klass = klass;
44
+ joint->a = a;
45
+ joint->b = b;
46
+ }
47
+
48
+
49
+ static inline cpVect
50
+ relative_velocity(cpVect r1, cpVect v1, cpFloat w1, cpVect r2, cpVect v2, cpFloat w2){
51
+ cpVect v1_sum = cpvadd(v1, cpvmult(cpvperp(r1), w1));
52
+ cpVect v2_sum = cpvadd(v2, cpvmult(cpvperp(r2), w2));
53
+
54
+ return cpvsub(v2_sum, v1_sum);
55
+ }
56
+
57
+ static inline cpFloat
58
+ scalar_k(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n)
59
+ {
60
+ cpFloat mass_sum = a->m_inv + b->m_inv;
61
+ cpFloat r1cn = cpvcross(r1, n);
62
+ cpFloat r2cn = cpvcross(r2, n);
63
+
64
+ return mass_sum + a->i_inv*r1cn*r1cn + b->i_inv*r2cn*r2cn;
65
+ }
66
+
67
+ static inline void
68
+ apply_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j)
69
+ {
70
+ cpBodyApplyImpulse(a, cpvneg(j), r1);
71
+ cpBodyApplyImpulse(b, j, r2);
72
+ }
73
+
74
+ static inline void
75
+ apply_bias_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j)
76
+ {
77
+ cpBodyApplyBiasImpulse(a, cpvneg(j), r1);
78
+ cpBodyApplyBiasImpulse(b, j, r2);
79
+ }
80
+
81
+
82
+ static void
83
+ pinJointPreStep(cpJoint *joint, cpFloat dt_inv)
84
+ {
85
+ cpBody *a = joint->a;
86
+ cpBody *b = joint->b;
87
+ cpPinJoint *jnt = (cpPinJoint *)joint;
88
+
89
+ jnt->r1 = cpvrotate(jnt->anchr1, a->rot);
90
+ jnt->r2 = cpvrotate(jnt->anchr2, b->rot);
91
+
92
+ cpVect delta = cpvsub(cpvadd(b->p, jnt->r2), cpvadd(a->p, jnt->r1));
93
+ cpFloat dist = cpvlength(delta);
94
+ jnt->n = cpvmult(delta, 1.0f/(dist ? dist : INFINITY));
95
+
96
+ // calculate mass normal
97
+ jnt->nMass = 1.0f/scalar_k(a, b, jnt->r1, jnt->r2, jnt->n);
98
+
99
+ // calculate bias velocity
100
+ jnt->bias = -cp_joint_bias_coef*dt_inv*(dist - jnt->dist);
101
+ jnt->jBias = 0.0f;
102
+
103
+ // apply accumulated impulse
104
+ cpVect j = cpvmult(jnt->n, jnt->jnAcc);
105
+ apply_impulses(a, b, jnt->r1, jnt->r2, j);
106
+ }
107
+
108
+ static void
109
+ pinJointApplyImpulse(cpJoint *joint)
110
+ {
111
+ cpBody *a = joint->a;
112
+ cpBody *b = joint->b;
113
+
114
+ cpPinJoint *jnt = (cpPinJoint *)joint;
115
+ cpVect n = jnt->n;
116
+ cpVect r1 = jnt->r1;
117
+ cpVect r2 = jnt->r2;
118
+
119
+ //calculate bias impulse
120
+ cpVect vbr = relative_velocity(r1, a->v_bias, a->w_bias, r2, b->v_bias, b->w_bias);
121
+ cpFloat vbn = cpvdot(vbr, n);
122
+
123
+ cpFloat jbn = (jnt->bias - vbn)*jnt->nMass;
124
+ jnt->jBias += jbn;
125
+
126
+ cpVect jb = cpvmult(n, jbn);
127
+ apply_bias_impulses(a, b, jnt->r1, jnt->r2, jb);
128
+
129
+ // compute relative velocity
130
+ cpVect vr = relative_velocity(r1, a->v, a->w, r2, b->v, b->w);
131
+ cpFloat vrn = cpvdot(vr, n);
132
+
133
+ // compute normal impulse
134
+ cpFloat jn = -vrn*jnt->nMass;
135
+ jnt->jnAcc =+ jn;
136
+
137
+ // apply impulse
138
+ cpVect j = cpvmult(n, jn);
139
+ apply_impulses(a, b, jnt->r1, jnt->r2, j);
140
+ }
141
+
142
+ static const cpJointClass pinJointClass = {
143
+ CP_PIN_JOINT,
144
+ pinJointPreStep,
145
+ pinJointApplyImpulse,
146
+ };
147
+
148
+ cpPinJoint *
149
+ cpPinJointAlloc(void)
150
+ {
151
+ return (cpPinJoint *)malloc(sizeof(cpPinJoint));
152
+ }
153
+
154
+ cpPinJoint *
155
+ cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2)
156
+ {
157
+ cpJointInit((cpJoint *)joint, &pinJointClass, a, b);
158
+
159
+ joint->anchr1 = anchr1;
160
+ joint->anchr2 = anchr2;
161
+
162
+ cpVect p1 = cpvadd(a->p, cpvrotate(anchr1, a->rot));
163
+ cpVect p2 = cpvadd(b->p, cpvrotate(anchr2, b->rot));
164
+ joint->dist = cpvlength(cpvsub(p2, p1));
165
+
166
+ joint->jnAcc = 0.0;
167
+
168
+ return joint;
169
+ }
170
+
171
+ cpJoint *
172
+ cpPinJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2)
173
+ {
174
+ return (cpJoint *)cpPinJointInit(cpPinJointAlloc(), a, b, anchr1, anchr2);
175
+ }
176
+
177
+
178
+
179
+
180
+ static void
181
+ slideJointPreStep(cpJoint *joint, cpFloat dt_inv)
182
+ {
183
+ cpBody *a = joint->a;
184
+ cpBody *b = joint->b;
185
+ cpSlideJoint *jnt = (cpSlideJoint *)joint;
186
+
187
+ jnt->r1 = cpvrotate(jnt->anchr1, a->rot);
188
+ jnt->r2 = cpvrotate(jnt->anchr2, b->rot);
189
+
190
+ cpVect delta = cpvsub(cpvadd(b->p, jnt->r2), cpvadd(a->p, jnt->r1));
191
+ cpFloat dist = cpvlength(delta);
192
+ cpFloat pdist = 0.0;
193
+ if(dist > jnt->max) {
194
+ pdist = dist - jnt->max;
195
+ } else if(dist < jnt->min) {
196
+ pdist = jnt->min - dist;
197
+ dist = -dist;
198
+ }
199
+ jnt->n = cpvmult(delta, 1.0f/(dist ? dist : INFINITY));
200
+
201
+ // calculate mass normal
202
+ jnt->nMass = 1.0f/scalar_k(a, b, jnt->r1, jnt->r2, jnt->n);
203
+
204
+ // calculate bias velocity
205
+ jnt->bias = -cp_joint_bias_coef*dt_inv*(pdist);
206
+ jnt->jBias = 0.0f;
207
+
208
+ // apply accumulated impulse
209
+ if(!jnt->bias) //{
210
+ // if bias is 0, then the joint is not at a limit.
211
+ jnt->jnAcc = 0.0f;
212
+ // } else {
213
+ cpVect j = cpvmult(jnt->n, jnt->jnAcc);
214
+ apply_impulses(a, b, jnt->r1, jnt->r2, j);
215
+ // }
216
+ }
217
+
218
+ static void
219
+ slideJointApplyImpulse(cpJoint *joint)
220
+ {
221
+ cpSlideJoint *jnt = (cpSlideJoint *)joint;
222
+ if(!jnt->bias) return; // early exit
223
+
224
+ cpBody *a = joint->a;
225
+ cpBody *b = joint->b;
226
+
227
+ cpVect n = jnt->n;
228
+ cpVect r1 = jnt->r1;
229
+ cpVect r2 = jnt->r2;
230
+
231
+ //calculate bias impulse
232
+ cpVect vbr = relative_velocity(r1, a->v_bias, a->w_bias, r2, b->v_bias, b->w_bias);
233
+ cpFloat vbn = cpvdot(vbr, n);
234
+
235
+ cpFloat jbn = (jnt->bias - vbn)*jnt->nMass;
236
+ cpFloat jbnOld = jnt->jBias;
237
+ jnt->jBias = cpfmin(jbnOld + jbn, 0.0f);
238
+ jbn = jnt->jBias - jbnOld;
239
+
240
+ cpVect jb = cpvmult(n, jbn);
241
+ apply_bias_impulses(a, b, jnt->r1, jnt->r2, jb);
242
+
243
+ // compute relative velocity
244
+ cpVect vr = relative_velocity(r1, a->v, a->w, r2, b->v, b->w);
245
+ cpFloat vrn = cpvdot(vr, n);
246
+
247
+ // compute normal impulse
248
+ cpFloat jn = -vrn*jnt->nMass;
249
+ cpFloat jnOld = jnt->jnAcc;
250
+ jnt->jnAcc = cpfmin(jnOld + jn, 0.0f);
251
+ jn = jnt->jnAcc - jnOld;
252
+
253
+ // apply impulse
254
+ cpVect j = cpvmult(n, jn);
255
+ apply_impulses(a, b, jnt->r1, jnt->r2, j);
256
+ }
257
+
258
+ static const cpJointClass slideJointClass = {
259
+ CP_SLIDE_JOINT,
260
+ slideJointPreStep,
261
+ slideJointApplyImpulse,
262
+ };
263
+
264
+ cpSlideJoint *
265
+ cpSlideJointAlloc(void)
266
+ {
267
+ return (cpSlideJoint *)malloc(sizeof(cpSlideJoint));
268
+ }
269
+
270
+ cpSlideJoint *
271
+ cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max)
272
+ {
273
+ cpJointInit((cpJoint *)joint, &slideJointClass, a, b);
274
+
275
+ joint->anchr1 = anchr1;
276
+ joint->anchr2 = anchr2;
277
+ joint->min = min;
278
+ joint->max = max;
279
+
280
+ joint->jnAcc = 0.0;
281
+
282
+ return joint;
283
+ }
284
+
285
+ cpJoint *
286
+ cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max)
287
+ {
288
+ return (cpJoint *)cpSlideJointInit(cpSlideJointAlloc(), a, b, anchr1, anchr2, min, max);
289
+ }
290
+
291
+
292
+
293
+
294
+ static void
295
+ pivotJointPreStep(cpJoint *joint, cpFloat dt_inv)
296
+ {
297
+ cpBody *a = joint->a;
298
+ cpBody *b = joint->b;
299
+ cpPivotJoint *jnt = (cpPivotJoint *)joint;
300
+
301
+ jnt->r1 = cpvrotate(jnt->anchr1, a->rot);
302
+ jnt->r2 = cpvrotate(jnt->anchr2, b->rot);
303
+
304
+ // calculate mass matrix
305
+ // If I wasn't lazy, this wouldn't be so gross...
306
+ cpFloat k11, k12, k21, k22;
307
+
308
+ cpFloat m_sum = a->m_inv + b->m_inv;
309
+ k11 = m_sum; k12 = 0.0f;
310
+ k21 = 0.0f; k22 = m_sum;
311
+
312
+ cpFloat r1xsq = jnt->r1.x * jnt->r1.x * a->i_inv;
313
+ cpFloat r1ysq = jnt->r1.y * jnt->r1.y * a->i_inv;
314
+ cpFloat r1nxy = -jnt->r1.x * jnt->r1.y * a->i_inv;
315
+ k11 += r1ysq; k12 += r1nxy;
316
+ k21 += r1nxy; k22 += r1xsq;
317
+
318
+ cpFloat r2xsq = jnt->r2.x * jnt->r2.x * b->i_inv;
319
+ cpFloat r2ysq = jnt->r2.y * jnt->r2.y * b->i_inv;
320
+ cpFloat r2nxy = -jnt->r2.x * jnt->r2.y * b->i_inv;
321
+ k11 += r2ysq; k12 += r2nxy;
322
+ k21 += r2nxy; k22 += r2xsq;
323
+
324
+ cpFloat det_inv = 1.0f/(k11*k22 - k12*k21);
325
+ jnt->k1 = cpv( k22*det_inv, -k12*det_inv);
326
+ jnt->k2 = cpv(-k21*det_inv, k11*det_inv);
327
+
328
+
329
+ // calculate bias velocity
330
+ cpVect delta = cpvsub(cpvadd(b->p, jnt->r2), cpvadd(a->p, jnt->r1));
331
+ jnt->bias = cpvmult(delta, -cp_joint_bias_coef*dt_inv);
332
+ jnt->jBias = cpvzero;
333
+
334
+ // apply accumulated impulse
335
+ apply_impulses(a, b, jnt->r1, jnt->r2, jnt->jAcc);
336
+ }
337
+
338
+ static void
339
+ pivotJointApplyImpulse(cpJoint *joint)
340
+ {
341
+ cpBody *a = joint->a;
342
+ cpBody *b = joint->b;
343
+
344
+ cpPivotJoint *jnt = (cpPivotJoint *)joint;
345
+ cpVect r1 = jnt->r1;
346
+ cpVect r2 = jnt->r2;
347
+ cpVect k1 = jnt->k1;
348
+ cpVect k2 = jnt->k2;
349
+
350
+ //calculate bias impulse
351
+ cpVect vbr = relative_velocity(r1, a->v_bias, a->w_bias, r2, b->v_bias, b->w_bias);
352
+ vbr = cpvsub(jnt->bias, vbr);
353
+
354
+ cpVect jb = cpv(cpvdot(vbr, k1), cpvdot(vbr, k2));
355
+ jnt->jBias = cpvadd(jnt->jBias, jb);
356
+
357
+ apply_bias_impulses(a, b, jnt->r1, jnt->r2, jb);
358
+
359
+ // compute relative velocity
360
+ cpVect vr = relative_velocity(r1, a->v, a->w, r2, b->v, b->w);
361
+
362
+ // compute normal impulse
363
+ cpVect j = cpv(-cpvdot(vr, k1), -cpvdot(vr, k2));
364
+ jnt->jAcc = cpvadd(jnt->jAcc, j);
365
+
366
+ // apply impulse
367
+ apply_impulses(a, b, jnt->r1, jnt->r2, j);
368
+ }
369
+
370
+ static const cpJointClass pivotJointClass = {
371
+ CP_PIVOT_JOINT,
372
+ pivotJointPreStep,
373
+ pivotJointApplyImpulse,
374
+ };
375
+
376
+ cpPivotJoint *
377
+ cpPivotJointAlloc(void)
378
+ {
379
+ return (cpPivotJoint *)malloc(sizeof(cpPivotJoint));
380
+ }
381
+
382
+ cpPivotJoint *
383
+ cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect pivot)
384
+ {
385
+ cpJointInit((cpJoint *)joint, &pivotJointClass, a, b);
386
+
387
+ joint->anchr1 = cpvunrotate(cpvsub(pivot, a->p), a->rot);
388
+ joint->anchr2 = cpvunrotate(cpvsub(pivot, b->p), b->rot);
389
+
390
+ joint->jAcc = cpvzero;
391
+
392
+ return joint;
393
+ }
394
+
395
+ cpJoint *
396
+ cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot)
397
+ {
398
+ return (cpJoint *)cpPivotJointInit(cpPivotJointAlloc(), a, b, pivot);
399
+ }
400
+
401
+
402
+
403
+
404
+ static void
405
+ grooveJointPreStep(cpJoint *joint, cpFloat dt_inv)
406
+ {
407
+ cpBody *a = joint->a;
408
+ cpBody *b = joint->b;
409
+ cpGrooveJoint *jnt = (cpGrooveJoint *)joint;
410
+
411
+ // calculate endpoints in worldspace
412
+ cpVect ta = cpBodyLocal2World(a, jnt->grv_a);
413
+ cpVect tb = cpBodyLocal2World(a, jnt->grv_b);
414
+
415
+ // calculate axis
416
+ cpVect n = cpvrotate(jnt->grv_n, a->rot);
417
+ cpFloat d = cpvdot(ta, n);
418
+
419
+ jnt->grv_tn = n;
420
+ jnt->r2 = cpvrotate(jnt->anchr2, b->rot);
421
+
422
+ // calculate tangential distance along the axis of r2
423
+ cpFloat td = cpvcross(cpvadd(b->p, jnt->r2), n);
424
+ // calculate clamping factor and r2
425
+ if(td <= cpvcross(ta, n)){
426
+ jnt->clamp = 1.0f;
427
+ jnt->r1 = cpvsub(ta, a->p);
428
+ } else if(td >= cpvcross(tb, n)){
429
+ jnt->clamp = -1.0f;
430
+ jnt->r1 = cpvsub(tb, a->p);
431
+ } else {
432
+ jnt->clamp = 0.0f;
433
+ jnt->r1 = cpvsub(cpvadd(cpvmult(cpvperp(n), -td), cpvmult(n, d)), a->p);
434
+ }
435
+
436
+ // calculate mass matrix
437
+ // If I wasn't lazy and wrote a proper matrix class, this wouldn't be so gross...
438
+ cpFloat k11, k12, k21, k22;
439
+ cpFloat m_sum = a->m_inv + b->m_inv;
440
+
441
+ // start with I*m_sum
442
+ k11 = m_sum; k12 = 0.0f;
443
+ k21 = 0.0f; k22 = m_sum;
444
+
445
+ // add the influence from r1
446
+ cpFloat r1xsq = jnt->r1.x * jnt->r1.x * a->i_inv;
447
+ cpFloat r1ysq = jnt->r1.y * jnt->r1.y * a->i_inv;
448
+ cpFloat r1nxy = -jnt->r1.x * jnt->r1.y * a->i_inv;
449
+ k11 += r1ysq; k12 += r1nxy;
450
+ k21 += r1nxy; k22 += r1xsq;
451
+
452
+ // add the influnce from r2
453
+ cpFloat r2xsq = jnt->r2.x * jnt->r2.x * b->i_inv;
454
+ cpFloat r2ysq = jnt->r2.y * jnt->r2.y * b->i_inv;
455
+ cpFloat r2nxy = -jnt->r2.x * jnt->r2.y * b->i_inv;
456
+ k11 += r2ysq; k12 += r2nxy;
457
+ k21 += r2nxy; k22 += r2xsq;
458
+
459
+ // invert
460
+ cpFloat det_inv = 1.0f/(k11*k22 - k12*k21);
461
+ jnt->k1 = cpv( k22*det_inv, -k12*det_inv);
462
+ jnt->k2 = cpv(-k21*det_inv, k11*det_inv);
463
+
464
+
465
+ // calculate bias velocity
466
+ cpVect delta = cpvsub(cpvadd(b->p, jnt->r2), cpvadd(a->p, jnt->r1));
467
+ jnt->bias = cpvmult(delta, -cp_joint_bias_coef*dt_inv);
468
+ jnt->jBias = cpvzero;
469
+
470
+ // apply accumulated impulse
471
+ apply_impulses(a, b, jnt->r1, jnt->r2, jnt->jAcc);
472
+ }
473
+
474
+ static inline cpVect
475
+ grooveConstrain(cpGrooveJoint *jnt, cpVect j){
476
+ cpVect n = jnt->grv_tn;
477
+ cpVect jn = cpvmult(n, cpvdot(j, n));
478
+
479
+ cpVect t = cpvperp(n);
480
+ cpFloat coef = (jnt->clamp*cpvcross(j, n) > 0.0f) ? 1.0f : 0.0f;
481
+ cpVect jt = cpvmult(t, cpvdot(j, t)*coef);
482
+
483
+ return cpvadd(jn, jt);
484
+ }
485
+
486
+ static void
487
+ grooveJointApplyImpulse(cpJoint *joint)
488
+ {
489
+ cpBody *a = joint->a;
490
+ cpBody *b = joint->b;
491
+
492
+ cpGrooveJoint *jnt = (cpGrooveJoint *)joint;
493
+ cpVect r1 = jnt->r1;
494
+ cpVect r2 = jnt->r2;
495
+ cpVect k1 = jnt->k1;
496
+ cpVect k2 = jnt->k2;
497
+
498
+ //calculate bias impulse
499
+ cpVect vbr = relative_velocity(r1, a->v_bias, a->w_bias, r2, b->v_bias, b->w_bias);
500
+ vbr = cpvsub(jnt->bias, vbr);
501
+
502
+ cpVect jb = cpv(cpvdot(vbr, k1), cpvdot(vbr, k2));
503
+ cpVect jbOld = jnt->jBias;
504
+ jnt->jBias = grooveConstrain(jnt, cpvadd(jbOld, jb));
505
+ jb = cpvsub(jnt->jBias, jbOld);
506
+
507
+ apply_bias_impulses(a, b, jnt->r1, jnt->r2, jb);
508
+
509
+ // compute impulse
510
+ cpVect vr = relative_velocity(r1, a->v, a->w, r2, b->v, b->w);
511
+
512
+ cpVect j = cpv(-cpvdot(vr, k1), -cpvdot(vr, k2));
513
+ cpVect jOld = jnt->jAcc;
514
+ jnt->jAcc = grooveConstrain(jnt, cpvadd(jOld, j));
515
+ j = cpvsub(jnt->jAcc, jOld);
516
+
517
+ // apply impulse
518
+ apply_impulses(a, b, jnt->r1, jnt->r2, j);
519
+ }
520
+
521
+ static const cpJointClass grooveJointClass = {
522
+ CP_GROOVE_JOINT,
523
+ grooveJointPreStep,
524
+ grooveJointApplyImpulse,
525
+ };
526
+
527
+ cpGrooveJoint *
528
+ cpGrooveJointAlloc(void)
529
+ {
530
+ return (cpGrooveJoint *)malloc(sizeof(cpGrooveJoint));
531
+ }
532
+
533
+ cpGrooveJoint *
534
+ cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2)
535
+ {
536
+ cpJointInit((cpJoint *)joint, &grooveJointClass, a, b);
537
+
538
+ joint->grv_a = groove_a;
539
+ joint->grv_b = groove_b;
540
+ joint->grv_n = cpvperp(cpvnormalize(cpvsub(groove_b, groove_a)));
541
+ joint->anchr2 = anchr2;
542
+
543
+ joint->jAcc = cpvzero;
544
+
545
+ return joint;
546
+ }
547
+
548
+ cpJoint *
549
+ cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2)
550
+ {
551
+ return (cpJoint *)cpGrooveJointInit(cpGrooveJointAlloc(), a, b, groove_a, groove_b, anchr2);
552
+ }
553
+
@@ -0,0 +1,122 @@
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
+ // TODO: Comment me!
23
+
24
+ extern cpFloat cp_joint_bias_coef;
25
+
26
+ typedef enum cpJointType {
27
+ CP_PIN_JOINT,
28
+ CP_PIVOT_JOINT,
29
+ CP_SLIDE_JOINT,
30
+ CP_GROOVE_JOINT,
31
+ CP_CUSTOM_JOINT, // For user definable joint types.
32
+ } cpJointType;
33
+
34
+ struct cpJoint;
35
+ struct cpJointClass;
36
+
37
+ typedef struct cpJointClass {
38
+ cpJointType type;
39
+
40
+ void (*preStep)(struct cpJoint *joint, cpFloat dt_inv);
41
+ void (*applyImpulse)(struct cpJoint *joint);
42
+ } cpJointClass;
43
+
44
+ typedef struct cpJoint {
45
+ const cpJointClass *klass;
46
+
47
+ cpBody *a, *b;
48
+ } cpJoint;
49
+
50
+ void cpJointDestroy(cpJoint *joint);
51
+ void cpJointFree(cpJoint *joint);
52
+
53
+
54
+ typedef struct cpPinJoint {
55
+ cpJoint joint;
56
+ cpVect anchr1, anchr2;
57
+ cpFloat dist;
58
+
59
+ cpVect r1, r2;
60
+ cpVect n;
61
+ cpFloat nMass;
62
+
63
+ cpFloat jnAcc, jBias;
64
+ cpFloat bias;
65
+ } cpPinJoint;
66
+
67
+ cpPinJoint *cpPinJointAlloc(void);
68
+ cpPinJoint *cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2);
69
+ cpJoint *cpPinJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2);
70
+
71
+
72
+ typedef struct cpSlideJoint {
73
+ cpJoint joint;
74
+ cpVect anchr1, anchr2;
75
+ cpFloat min, max;
76
+
77
+ cpVect r1, r2;
78
+ cpVect n;
79
+ cpFloat nMass;
80
+
81
+ cpFloat jnAcc, jBias;
82
+ cpFloat bias;
83
+ } cpSlideJoint;
84
+
85
+ cpSlideJoint *cpSlideJointAlloc(void);
86
+ cpSlideJoint *cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max);
87
+ cpJoint *cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max);
88
+
89
+
90
+ typedef struct cpPivotJoint {
91
+ cpJoint joint;
92
+ cpVect anchr1, anchr2;
93
+
94
+ cpVect r1, r2;
95
+ cpVect k1, k2;
96
+
97
+ cpVect jAcc, jBias;
98
+ cpVect bias;
99
+ } cpPivotJoint;
100
+
101
+ cpPivotJoint *cpPivotJointAlloc(void);
102
+ cpPivotJoint *cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect pivot);
103
+ cpJoint *cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot);
104
+
105
+
106
+ typedef struct cpGrooveJoint {
107
+ cpJoint joint;
108
+ cpVect grv_n, grv_a, grv_b;
109
+ cpVect anchr2;
110
+
111
+ cpVect grv_tn;
112
+ cpFloat clamp;
113
+ cpVect r1, r2;
114
+ cpVect k1, k2;
115
+
116
+ cpVect jAcc, jBias;
117
+ cpVect bias;
118
+ } cpGrooveJoint;
119
+
120
+ cpGrooveJoint *cpGrooveJointAlloc(void);
121
+ cpGrooveJoint *cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2);
122
+ cpJoint *cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2);