bad char
[vg.git] / vg_rigidbody_collision.h
1 #pragma once
2 #include "vg_rigidbody.h"
3
4 typedef struct rb_ct rb_ct;
5 static struct rb_ct{
6 rigidbody *rba, *rbb;
7 v3f co, n;
8 v3f t[2];
9 float p, bias, norm_impulse, tangent_impulse[2],
10 normal_mass, tangent_mass[2];
11
12 u32 element_id;
13
14 enum contact_type type;
15 }
16 rb_contact_buffer[256];
17 static int rb_contact_count = 0;
18
19 /*
20 * Contact generators
21 *
22 * These do not automatically allocate contacts, an appropriately sized
23 * buffer must be supplied. The function returns the size of the manifold
24 * which was generated.
25 *
26 * The values set on the contacts are: n, co, p, rba, rbb
27 */
28
29 /*
30 * By collecting the minimum(time) and maximum(time) pairs of points, we
31 * build a reduced and stable exact manifold.
32 *
33 * tx: time at point
34 * rx: minimum distance of these points
35 * dx: the delta between the two points
36 *
37 * pairs will only ammend these if they are creating a collision
38 */
39 typedef struct capsule_manifold capsule_manifold;
40 struct capsule_manifold{
41 f32 t0, t1;
42 f32 r0, r1;
43 v3f d0, d1;
44 };
45
46 /*
47 * Expand a line manifold with a new pair. t value is the time along segment
48 * on the oriented object which created this pair.
49 */
50 static void rb_capsule_manifold( v3f pa, v3f pb, f32 t, f32 r,
51 capsule_manifold *manifold ){
52 v3f delta;
53 v3_sub( pa, pb, delta );
54
55 if( v3_length2(delta) < r*r ){
56 if( t < manifold->t0 ){
57 v3_copy( delta, manifold->d0 );
58 manifold->t0 = t;
59 manifold->r0 = r;
60 }
61
62 if( t > manifold->t1 ){
63 v3_copy( delta, manifold->d1 );
64 manifold->t1 = t;
65 manifold->r1 = r;
66 }
67 }
68 }
69
70 static void rb_capsule_manifold_init( capsule_manifold *manifold ){
71 manifold->t0 = INFINITY;
72 manifold->t1 = -INFINITY;
73 }
74
75 static int rb_capsule__manifold_done( m4x3f mtx, rb_capsule *c,
76 capsule_manifold *manifold,
77 rb_ct *buf ){
78 v3f p0, p1;
79 v3_muladds( mtx[3], mtx[1], -c->h*0.5f+c->r, p0 );
80 v3_muladds( mtx[3], mtx[1], c->h*0.5f-c->r, p1 );
81
82 int count = 0;
83 if( manifold->t0 <= 1.0f ){
84 rb_ct *ct = buf;
85
86 v3f pa;
87 v3_muls( p0, 1.0f-manifold->t0, pa );
88 v3_muladds( pa, p1, manifold->t0, pa );
89
90 f32 d = v3_length( manifold->d0 );
91 v3_muls( manifold->d0, 1.0f/d, ct->n );
92 v3_muladds( pa, ct->n, -c->r, ct->co );
93
94 ct->p = manifold->r0 - d;
95 ct->type = k_contact_type_default;
96 count ++;
97 }
98
99 if( (manifold->t1 >= 0.0f) && (manifold->t0 != manifold->t1) ){
100 rb_ct *ct = buf+count;
101
102 v3f pa;
103 v3_muls( p0, 1.0f-manifold->t1, pa );
104 v3_muladds( pa, p1, manifold->t1, pa );
105
106 f32 d = v3_length( manifold->d1 );
107 v3_muls( manifold->d1, 1.0f/d, ct->n );
108 v3_muladds( pa, ct->n, -c->r, ct->co );
109
110 ct->p = manifold->r1 - d;
111 ct->type = k_contact_type_default;
112
113 count ++;
114 }
115
116 /*
117 * Debugging
118 */
119
120 if( count == 2 )
121 vg_line( buf[0].co, buf[1].co, 0xff0000ff );
122
123 return count;
124 }
125
126 #if 0
127 static int rb_capsule_sphere( rb_object *obja, rb_object *objb, rb_ct *buf ){
128 rigidbody *rba = &obja->rb, *rbb = &objb->rb;
129 f32 h = obja->inf.capsule.h,
130 ra = obja->inf.capsule.r,
131 rb = objb->inf.sphere.r;
132
133 v3f p0, p1;
134 v3_muladds( rba->co, rba->to_world[1], -h*0.5f+ra, p0 );
135 v3_muladds( rba->co, rba->to_world[1], h*0.5f-ra, p1 );
136
137 v3f c, delta;
138 closest_point_segment( p0, p1, rbb->co, c );
139 v3_sub( c, rbb->co, delta );
140
141 f32 d2 = v3_length2(delta),
142 r = ra + rb;
143
144 if( d2 < r*r ){
145 f32 d = sqrtf(d2);
146
147 rb_ct *ct = buf;
148 v3_muls( delta, 1.0f/d, ct->n );
149 ct->p = r-d;
150
151 v3f p0, p1;
152 v3_muladds( c, ct->n, -ra, p0 );
153 v3_muladds( rbb->co, ct->n, rb, p1 );
154 v3_add( p0, p1, ct->co );
155 v3_muls( ct->co, 0.5f, ct->co );
156
157 ct->rba = rba;
158 ct->rbb = rbb;
159 ct->type = k_contact_type_default;
160
161 return 1;
162 }
163
164 return 0;
165 }
166 #endif
167
168 static int rb_capsule__capsule( m4x3f mtxA, rb_capsule *ca,
169 m4x3f mtxB, rb_capsule *cb, rb_ct *buf ){
170 f32 ha = ca->h,
171 hb = cb->h,
172 ra = ca->r,
173 rb = cb->r,
174 r = ra+rb;
175
176 v3f p0, p1, p2, p3;
177 v3_muladds( mtxA[3], mtxA[1], -ha*0.5f+ra, p0 );
178 v3_muladds( mtxA[3], mtxA[1], ha*0.5f-ra, p1 );
179 v3_muladds( mtxB[3], mtxB[1], -hb*0.5f+rb, p2 );
180 v3_muladds( mtxB[3], mtxB[1], hb*0.5f-rb, p3 );
181
182 capsule_manifold manifold;
183 rb_capsule_manifold_init( &manifold );
184
185 v3f pa, pb;
186 f32 ta, tb;
187 closest_segment_segment( p0, p1, p2, p3, &ta, &tb, pa, pb );
188 rb_capsule_manifold( pa, pb, ta, r, &manifold );
189
190 ta = closest_point_segment( p0, p1, p2, pa );
191 tb = closest_point_segment( p0, p1, p3, pb );
192 rb_capsule_manifold( pa, p2, ta, r, &manifold );
193 rb_capsule_manifold( pb, p3, tb, r, &manifold );
194
195 closest_point_segment( p2, p3, p0, pa );
196 closest_point_segment( p2, p3, p1, pb );
197 rb_capsule_manifold( p0, pa, 0.0f, r, &manifold );
198 rb_capsule_manifold( p1, pb, 1.0f, r, &manifold );
199
200 return rb_capsule__manifold_done( mtxA, ca, &manifold, buf );
201 }
202
203 #if 0
204 static int rb_sphere_box( rb_object *obja, rb_object *objb, rb_ct *buf ){
205 v3f co, delta;
206 rigidbody *rba = &obja->rb, *rbb = &objb->rb;
207
208 closest_point_obb( rba->co, rbb->bbx, rbb->to_world, rbb->to_local, co );
209 v3_sub( rba->co, co, delta );
210
211 f32 d2 = v3_length2(delta),
212 r = obja->inf.sphere.radius;
213
214 if( d2 <= r*r ){
215 f32 d;
216
217 rb_ct *ct = buf;
218 if( d2 <= 0.0001f ){
219 v3_sub( rba->co, rbb->co, delta );
220
221 /*
222 * some extra testing is required to find the best axis to push the
223 * object back outside the box. Since there isnt a clear seperating
224 * vector already, especially on really high aspect boxes.
225 */
226 f32 lx = v3_dot( rbb->to_world[0], delta ),
227 ly = v3_dot( rbb->to_world[1], delta ),
228 lz = v3_dot( rbb->to_world[2], delta ),
229 px = rbb->bbx[1][0] - fabsf(lx),
230 py = rbb->bbx[1][1] - fabsf(ly),
231 pz = rbb->bbx[1][2] - fabsf(lz);
232
233 if( px < py && px < pz )
234 v3_muls( rbb->to_world[0], vg_signf(lx), ct->n );
235 else if( py < pz )
236 v3_muls( rbb->to_world[1], vg_signf(ly), ct->n );
237 else
238 v3_muls( rbb->to_world[2], vg_signf(lz), ct->n );
239
240 v3_muladds( rba->co, ct->n, -r, ct->co );
241 ct->p = r;
242 }
243 else{
244 d = sqrtf(d2);
245 v3_muls( delta, 1.0f/d, ct->n );
246 ct->p = r-d;
247 v3_copy( co, ct->co );
248 }
249
250 ct->rba = rba;
251 ct->rbb = rbb;
252 ct->type = k_contact_type_default;
253 return 1;
254 }
255
256 return 0;
257 }
258 #endif
259
260 #if 0
261 static int rb_sphere_sphere( rb_object *obja, rb_object *objb, rb_ct *buf ){
262 rigidbody *rba = &obja->rb, *rbb = &objb->rb;
263 v3f delta;
264 v3_sub( rba->co, rbb->co, delta );
265
266 f32 d2 = v3_length2(delta),
267 r = obja->inf.sphere.radius + objb->inf.sphere.radius;
268
269 if( d2 < r*r ){
270 f32 d = sqrtf(d2);
271
272 rb_ct *ct = buf;
273 v3_muls( delta, 1.0f/d, ct->n );
274
275 v3f p0, p1;
276 v3_muladds( rba->co, ct->n,-obja->inf.sphere.radius, p0 );
277 v3_muladds( rbb->co, ct->n, objb->inf.sphere.radius, p1 );
278 v3_add( p0, p1, ct->co );
279 v3_muls( ct->co, 0.5f, ct->co );
280 ct->type = k_contact_type_default;
281 ct->p = r-d;
282 ct->rba = rba;
283 ct->rbb = rbb;
284 return 1;
285 }
286
287 return 0;
288 }
289 #endif
290
291 static int rb_sphere__triangle( m4x3f mtxA, f32 r,
292 v3f tri[3], rb_ct *buf ){
293 v3f delta, co;
294 enum contact_type type = closest_on_triangle_1( mtxA[3], tri, co );
295 v3_sub( mtxA[3], co, delta );
296 f32 d2 = v3_length2( delta );
297
298 if( d2 <= r*r ){
299 rb_ct *ct = buf;
300
301 v3f ab, ac, tn;
302 v3_sub( tri[2], tri[0], ab );
303 v3_sub( tri[1], tri[0], ac );
304 v3_cross( ac, ab, tn );
305 v3_copy( tn, ct->n );
306
307 if( v3_length2( ct->n ) <= 0.00001f ){
308 #ifdef RIGIDBODY_CRY_ABOUT_EVERYTHING
309 vg_error( "Zero area triangle!\n" );
310 #endif
311 return 0;
312 }
313
314 v3_normalize( ct->n );
315
316 f32 d = sqrtf(d2);
317
318 v3_copy( co, ct->co );
319 ct->type = type;
320 ct->p = r-d;
321 return 1;
322 }
323
324 return 0;
325 }
326
327 static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c,
328 v3f tri[3], rb_ct *buf ){
329 v3f pc, p0w, p1w;
330 v3_muladds( mtxA[3], mtxA[1], -c->h*0.5f+c->r, p0w );
331 v3_muladds( mtxA[3], mtxA[1], c->h*0.5f-c->r, p1w );
332
333 capsule_manifold manifold;
334 rb_capsule_manifold_init( &manifold );
335
336 v3f v0, v1, n;
337 v3_sub( tri[1], tri[0], v0 );
338 v3_sub( tri[2], tri[0], v1 );
339 v3_cross( v0, v1, n );
340
341 if( v3_length2( n ) <= 0.00001f ){
342 #ifdef RIGIDBODY_CRY_ABOUT_EVERYTHING
343 vg_error( "Zero area triangle!\n" );
344 #endif
345 return 0;
346 }
347
348 v3_normalize( n );
349
350 #if 1
351 /* deep penetration recovery. for when we clip through the triangles. so its
352 * not very 'correct' */
353 f32 dist;
354 if( ray_tri( tri, p0w, mtxA[1], &dist, 1 ) ){
355 f32 l = c->h - c->r*2.0f;
356 if( (dist >= 0.0f) && (dist < l) ){
357 v3f co;
358 v3_muladds( p0w, mtxA[1], dist, co );
359 vg_line_point( co, 0.02f, 0xffffff00 );
360
361 v3f d0, d1;
362 v3_sub( p0w, co, d0 );
363 v3_sub( p1w, co, d1 );
364
365 f32 p = vg_minf( v3_dot( n, d0 ), v3_dot( n, d1 ) ) - c->r;
366
367 rb_ct *ct = buf;
368 ct->p = -p;
369 ct->type = k_contact_type_default;
370 v3_copy( n, ct->n );
371 v3_muladds( co, n, p, ct->co );
372
373 return 1;
374 }
375 }
376 #endif
377
378 v3f c0, c1;
379 closest_on_triangle_1( p0w, tri, c0 );
380 closest_on_triangle_1( p1w, tri, c1 );
381
382 v3f d0, d1, da;
383 v3_sub( c0, p0w, d0 );
384 v3_sub( c1, p1w, d1 );
385 v3_sub( p1w, p0w, da );
386
387 v3_normalize(d0);
388 v3_normalize(d1);
389 v3_normalize(da);
390
391 /* the two balls at the ends */
392 if( v3_dot( da, d0 ) <= 0.01f )
393 rb_capsule_manifold( p0w, c0, 0.0f, c->r, &manifold );
394 if( v3_dot( da, d1 ) >= -0.01f )
395 rb_capsule_manifold( p1w, c1, 1.0f, c->r, &manifold );
396
397 /* the edges to edges */
398 for( int i=0; i<3; i++ ){
399 int i0 = i,
400 i1 = (i+1)%3;
401
402 v3f ca, cb;
403 f32 ta, tb;
404 closest_segment_segment( p0w, p1w, tri[i0], tri[i1], &ta, &tb, ca, cb );
405 rb_capsule_manifold( ca, cb, ta, c->r, &manifold );
406 }
407
408 int count = rb_capsule__manifold_done( mtxA, c, &manifold, buf );
409 for( int i=0; i<count; i++ )
410 v3_copy( n, buf[i].n );
411
412 return count;
413 }
414
415 static int rb_global_has_space( void ){
416 if( rb_contact_count + 16 > vg_list_size(rb_contact_buffer) )
417 return 0;
418
419 return 1;
420 }
421
422 static rb_ct *rb_global_buffer( void ){
423 return &rb_contact_buffer[ rb_contact_count ];
424 }
425
426 /*
427 * -----------------------------------------------------------------------------
428 * Boolean shape overlap functions
429 * -----------------------------------------------------------------------------
430 */
431
432 /*
433 * Project AABB, and triangle interval onto axis to check if they overlap
434 */
435 static int rb_box_triangle_interval( v3f extent, v3f axis, v3f tri[3] ){
436 float
437
438 r = extent[0] * fabsf(axis[0]) +
439 extent[1] * fabsf(axis[1]) +
440 extent[2] * fabsf(axis[2]),
441
442 p0 = v3_dot( axis, tri[0] ),
443 p1 = v3_dot( axis, tri[1] ),
444 p2 = v3_dot( axis, tri[2] ),
445
446 e = vg_maxf(-vg_maxf(p0,vg_maxf(p1,p2)), vg_minf(p0,vg_minf(p1,p2)));
447
448 if( e > r ) return 0;
449 else return 1;
450 }
451
452 /*
453 * Seperating axis test box vs triangle
454 */
455 static int rb_box_triangle_sat( v3f extent, v3f center,
456 m4x3f to_local, v3f tri_src[3] ){
457 v3f tri[3];
458
459 for( int i=0; i<3; i++ ){
460 m4x3_mulv( to_local, tri_src[i], tri[i] );
461 v3_sub( tri[i], center, tri[i] );
462 }
463
464 v3f f0,f1,f2,n;
465 v3_sub( tri[1], tri[0], f0 );
466 v3_sub( tri[2], tri[1], f1 );
467 v3_sub( tri[0], tri[2], f2 );
468
469
470 v3f axis[9];
471 v3_cross( (v3f){1.0f,0.0f,0.0f}, f0, axis[0] );
472 v3_cross( (v3f){1.0f,0.0f,0.0f}, f1, axis[1] );
473 v3_cross( (v3f){1.0f,0.0f,0.0f}, f2, axis[2] );
474 v3_cross( (v3f){0.0f,1.0f,0.0f}, f0, axis[3] );
475 v3_cross( (v3f){0.0f,1.0f,0.0f}, f1, axis[4] );
476 v3_cross( (v3f){0.0f,1.0f,0.0f}, f2, axis[5] );
477 v3_cross( (v3f){0.0f,0.0f,1.0f}, f0, axis[6] );
478 v3_cross( (v3f){0.0f,0.0f,1.0f}, f1, axis[7] );
479 v3_cross( (v3f){0.0f,0.0f,1.0f}, f2, axis[8] );
480
481 for( int i=0; i<9; i++ )
482 if(!rb_box_triangle_interval( extent, axis[i], tri )) return 0;
483
484 /* u0, u1, u2 */
485 if(!rb_box_triangle_interval( extent, (v3f){1.0f,0.0f,0.0f}, tri )) return 0;
486 if(!rb_box_triangle_interval( extent, (v3f){0.0f,1.0f,0.0f}, tri )) return 0;
487 if(!rb_box_triangle_interval( extent, (v3f){0.0f,0.0f,1.0f}, tri )) return 0;
488
489 /* normal */
490 v3_cross( f0, f1, n );
491 if(!rb_box_triangle_interval( extent, n, tri )) return 0;
492
493 return 1;
494 }
495
496 /*
497 * -----------------------------------------------------------------------------
498 * Manifold
499 * -----------------------------------------------------------------------------
500 */
501
502 static int rb_manifold_apply_filtered( rb_ct *man, int len ){
503 int k = 0;
504
505 for( int i=0; i<len; i++ ){
506 rb_ct *ct = &man[i];
507
508 if( ct->type == k_contact_type_disabled )
509 continue;
510
511 man[k ++] = man[i];
512 }
513
514 return k;
515 }
516
517 /*
518 * Merge two contacts if they are within radius(r) of eachother
519 */
520 static void rb_manifold_contact_weld( rb_ct *ci, rb_ct *cj, float r ){
521 if( v3_dist2( ci->co, cj->co ) < r*r ){
522 cj->type = k_contact_type_disabled;
523 ci->p = (ci->p + cj->p) * 0.5f;
524
525 v3_add( ci->co, cj->co, ci->co );
526 v3_muls( ci->co, 0.5f, ci->co );
527
528 v3f delta;
529 v3_sub( ci->rba->co, ci->co, delta );
530
531 float c0 = v3_dot( ci->n, delta ),
532 c1 = v3_dot( cj->n, delta );
533
534 if( c0 < 0.0f || c1 < 0.0f ){
535 /* error */
536 ci->type = k_contact_type_disabled;
537 }
538 else{
539 v3f n;
540 v3_muls( ci->n, c0, n );
541 v3_muladds( n, cj->n, c1, n );
542 v3_normalize( n );
543 v3_copy( n, ci->n );
544 }
545 }
546 }
547
548 /*
549 *
550 */
551 static void rb_manifold_filter_joint_edges( rb_ct *man, int len, float r ){
552 for( int i=0; i<len-1; i++ ){
553 rb_ct *ci = &man[i];
554 if( ci->type != k_contact_type_edge )
555 continue;
556
557 for( int j=i+1; j<len; j++ ){
558 rb_ct *cj = &man[j];
559 if( cj->type != k_contact_type_edge )
560 continue;
561
562 rb_manifold_contact_weld( ci, cj, r );
563 }
564 }
565 }
566
567 /*
568 * Resolve overlapping pairs
569 */
570 static void rb_manifold_filter_pairs( rb_ct *man, int len, float r ){
571 for( int i=0; i<len-1; i++ ){
572 rb_ct *ci = &man[i];
573 int similar = 0;
574
575 if( ci->type == k_contact_type_disabled ) continue;
576
577 for( int j=i+1; j<len; j++ ){
578 rb_ct *cj = &man[j];
579
580 if( cj->type == k_contact_type_disabled ) continue;
581
582 if( v3_dist2( ci->co, cj->co ) < r*r ){
583 cj->type = k_contact_type_disabled;
584 v3_add( cj->n, ci->n, ci->n );
585 ci->p += cj->p;
586 similar ++;
587 }
588 }
589
590 if( similar ){
591 float n = 1.0f/((float)similar+1.0f);
592 v3_muls( ci->n, n, ci->n );
593 ci->p *= n;
594
595 if( v3_length2(ci->n) < 0.1f*0.1f )
596 ci->type = k_contact_type_disabled;
597 else
598 v3_normalize( ci->n );
599 }
600 }
601 }
602
603 /*
604 * Remove contacts that are facing away from A
605 */
606 static void rb_manifold_filter_backface( rb_ct *man, int len ){
607 for( int i=0; i<len; i++ ){
608 rb_ct *ct = &man[i];
609 if( ct->type == k_contact_type_disabled )
610 continue;
611
612 v3f delta;
613 v3_sub( ct->co, ct->rba->co, delta );
614
615 if( v3_dot( delta, ct->n ) > -0.001f )
616 ct->type = k_contact_type_disabled;
617 }
618 }
619
620 /*
621 * Filter out duplicate coplanar results. Good for spheres.
622 */
623 static void rb_manifold_filter_coplanar( rb_ct *man, int len, float w ){
624 for( int i=0; i<len; i++ ){
625 rb_ct *ci = &man[i];
626 if( ci->type == k_contact_type_disabled ||
627 ci->type == k_contact_type_edge )
628 continue;
629
630 float d1 = v3_dot( ci->co, ci->n );
631
632 for( int j=0; j<len; j++ ){
633 if( j == i )
634 continue;
635
636 rb_ct *cj = &man[j];
637 if( cj->type == k_contact_type_disabled )
638 continue;
639
640 float d2 = v3_dot( cj->co, ci->n ),
641 d = d2-d1;
642
643 if( fabsf( d ) <= w ){
644 cj->type = k_contact_type_disabled;
645 }
646 }
647 }
648 }
649
650 static void rb_debug_contact( rb_ct *ct ){
651 v3f p1;
652 v3_muladds( ct->co, ct->n, 0.05f, p1 );
653
654 if( ct->type == k_contact_type_default ){
655 vg_line_point( ct->co, 0.0125f, 0xff0000ff );
656 vg_line( ct->co, p1, 0xffffffff );
657 }
658 else if( ct->type == k_contact_type_edge ){
659 vg_line_point( ct->co, 0.0125f, 0xff00ffc0 );
660 vg_line( ct->co, p1, 0xffffffff );
661 }
662 }
663
664 static void rb_solver_reset(void){
665 rb_contact_count = 0;
666 }
667
668 static rb_ct *rb_global_ct(void){
669 return rb_contact_buffer + rb_contact_count;
670 }
671
672 static void rb_prepare_contact( rb_ct *ct, float timestep ){
673 ct->bias = -k_phys_baumgarte * (timestep*3600.0f)
674 * vg_minf( 0.0f, -ct->p+k_penetration_slop );
675
676 v3_tangent_basis( ct->n, ct->t[0], ct->t[1] );
677 ct->norm_impulse = 0.0f;
678 ct->tangent_impulse[0] = 0.0f;
679 ct->tangent_impulse[1] = 0.0f;
680 }
681
682 /*
683 * calculate total move to depenetrate object from contacts.
684 * manifold should belong to ONE object only
685 */
686 static void rb_depenetrate( rb_ct *manifold, int len, v3f dt ){
687 v3_zero( dt );
688
689 for( int j=0; j<7; j++ ){
690 for( int i=0; i<len; i++ ){
691 rb_ct *ct = &manifold[i];
692
693 float resolved_amt = v3_dot( ct->n, dt ),
694 remaining = (ct->p-k_penetration_slop) - resolved_amt,
695 apply = vg_maxf( remaining, 0.0f ) * 0.4f;
696
697 v3_muladds( dt, ct->n, apply, dt );
698 }
699 }
700 }
701
702 /*
703 * Initializing things like tangent vectors
704 */
705 static void rb_presolve_contacts( rb_ct *buffer, int len ){
706 for( int i=0; i<len; i++ ){
707 rb_ct *ct = &buffer[i];
708 rb_prepare_contact( ct, k_rb_delta );
709
710 v3f ra, rb, raCn, rbCn, raCt, rbCt;
711 v3_sub( ct->co, ct->rba->co, ra );
712 v3_sub( ct->co, ct->rbb->co, rb );
713 v3_cross( ra, ct->n, raCn );
714 v3_cross( rb, ct->n, rbCn );
715
716 /* orient inverse inertia tensors */
717 v3f raCnI, rbCnI;
718 m3x3_mulv( ct->rba->iIw, raCn, raCnI );
719 m3x3_mulv( ct->rbb->iIw, rbCn, rbCnI );
720
721 ct->normal_mass = ct->rba->inv_mass + ct->rbb->inv_mass;
722 ct->normal_mass += v3_dot( raCn, raCnI );
723 ct->normal_mass += v3_dot( rbCn, rbCnI );
724 ct->normal_mass = 1.0f/ct->normal_mass;
725
726 for( int j=0; j<2; j++ ){
727 v3f raCtI, rbCtI;
728 v3_cross( ct->t[j], ra, raCt );
729 v3_cross( ct->t[j], rb, rbCt );
730 m3x3_mulv( ct->rba->iIw, raCt, raCtI );
731 m3x3_mulv( ct->rbb->iIw, rbCt, rbCtI );
732
733 ct->tangent_mass[j] = ct->rba->inv_mass + ct->rbb->inv_mass;
734 ct->tangent_mass[j] += v3_dot( raCt, raCtI );
735 ct->tangent_mass[j] += v3_dot( rbCt, rbCtI );
736 ct->tangent_mass[j] = 1.0f/ct->tangent_mass[j];
737 }
738
739 rb_debug_contact( ct );
740 }
741 }
742
743 static void rb_contact_restitution( rb_ct *ct, float cr ){
744 v3f rv, ra, rb;
745 v3_sub( ct->co, ct->rba->co, ra );
746 v3_sub( ct->co, ct->rbb->co, rb );
747 rb_rcv( ct->rba, ct->rbb, ra, rb, rv );
748
749 float v = v3_dot( rv, ct->n );
750
751 if( v < -1.0f ){
752 ct->bias += -cr * v;
753 }
754 }
755
756 /*
757 * One iteration to solve the contact constraint
758 */
759 static void rb_solve_contacts( rb_ct *buf, int len ){
760 for( int i=0; i<len; i++ ){
761 rb_ct *ct = &buf[i];
762
763 v3f rv, ra, rb;
764 v3_sub( ct->co, ct->rba->co, ra );
765 v3_sub( ct->co, ct->rbb->co, rb );
766 rb_rcv( ct->rba, ct->rbb, ra, rb, rv );
767
768 /* Friction */
769 for( int j=0; j<2; j++ ){
770 float f = k_friction * ct->norm_impulse,
771 vt = v3_dot( rv, ct->t[j] ),
772 lambda = ct->tangent_mass[j] * -vt;
773
774 float temp = ct->tangent_impulse[j];
775 ct->tangent_impulse[j] = vg_clampf( temp + lambda, -f, f );
776 lambda = ct->tangent_impulse[j] - temp;
777
778 v3f impulse;
779 v3_muls( ct->t[j], lambda, impulse );
780 rb_linear_impulse( ct->rba, ra, impulse );
781
782 v3_muls( ct->t[j], -lambda, impulse );
783 rb_linear_impulse( ct->rbb, rb, impulse );
784 }
785
786 /* Normal */
787 rb_rcv( ct->rba, ct->rbb, ra, rb, rv );
788 float vn = v3_dot( rv, ct->n ),
789 lambda = ct->normal_mass * (-vn + ct->bias);
790
791 float temp = ct->norm_impulse;
792 ct->norm_impulse = vg_maxf( temp + lambda, 0.0f );
793 lambda = ct->norm_impulse - temp;
794
795 v3f impulse;
796 v3_muls( ct->n, lambda, impulse );
797 rb_linear_impulse( ct->rba, ra, impulse );
798
799 v3_muls( ct->n, -lambda, impulse );
800 rb_linear_impulse( ct->rbb, rb, impulse );
801 }
802 }
803