chipmunk 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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);