2 #include "vg_rigidbody.h"
4 #ifndef VG_MAX_CONTACTS
5 #define VG_MAX_CONTACTS 256
8 typedef struct rb_ct rb_ct
;
13 float p
, bias
, norm_impulse
, tangent_impulse
[2],
14 normal_mass
, tangent_mass
[2];
18 enum contact_type type
;
20 rb_contact_buffer
[VG_MAX_CONTACTS
];
21 static int rb_contact_count
= 0;
26 * These do not automatically allocate contacts, an appropriately sized
27 * buffer must be supplied. The function returns the size of the manifold
28 * which was generated.
30 * The values set on the contacts are: n, co, p, rba, rbb
34 * By collecting the minimum(time) and maximum(time) pairs of points, we
35 * build a reduced and stable exact manifold.
38 * rx: minimum distance of these points
39 * dx: the delta between the two points
41 * pairs will only ammend these if they are creating a collision
43 typedef struct capsule_manifold capsule_manifold
;
44 struct capsule_manifold
{
51 * Expand a line manifold with a new pair. t value is the time along segment
52 * on the oriented object which created this pair.
54 static void rb_capsule_manifold( v3f pa
, v3f pb
, f32 t
, f32 r
,
55 capsule_manifold
*manifold
){
57 v3_sub( pa
, pb
, delta
);
59 if( v3_length2(delta
) < r
*r
){
60 if( t
< manifold
->t0
){
61 v3_copy( delta
, manifold
->d0
);
66 if( t
> manifold
->t1
){
67 v3_copy( delta
, manifold
->d1
);
74 static void rb_capsule_manifold_init( capsule_manifold
*manifold
){
75 manifold
->t0
= INFINITY
;
76 manifold
->t1
= -INFINITY
;
79 static int rb_capsule__manifold_done( m4x3f mtx
, rb_capsule
*c
,
80 capsule_manifold
*manifold
,
83 v3_muladds( mtx
[3], mtx
[1], -c
->h
*0.5f
+c
->r
, p0
);
84 v3_muladds( mtx
[3], mtx
[1], c
->h
*0.5f
-c
->r
, p1
);
87 if( manifold
->t0
<= 1.0f
){
91 v3_muls( p0
, 1.0f
-manifold
->t0
, pa
);
92 v3_muladds( pa
, p1
, manifold
->t0
, pa
);
94 f32 d
= v3_length( manifold
->d0
);
95 v3_muls( manifold
->d0
, 1.0f
/d
, ct
->n
);
96 v3_muladds( pa
, ct
->n
, -c
->r
, ct
->co
);
98 ct
->p
= manifold
->r0
- d
;
99 ct
->type
= k_contact_type_default
;
103 if( (manifold
->t1
>= 0.0f
) && (manifold
->t0
!= manifold
->t1
) ){
104 rb_ct
*ct
= buf
+count
;
107 v3_muls( p0
, 1.0f
-manifold
->t1
, pa
);
108 v3_muladds( pa
, p1
, manifold
->t1
, pa
);
110 f32 d
= v3_length( manifold
->d1
);
111 v3_muls( manifold
->d1
, 1.0f
/d
, ct
->n
);
112 v3_muladds( pa
, ct
->n
, -c
->r
, ct
->co
);
114 ct
->p
= manifold
->r1
- d
;
115 ct
->type
= k_contact_type_default
;
126 vg_line( buf
[0].co
, buf
[1].co
, 0xff0000ff );
132 static int rb_capsule__sphere( m4x3f mtxA
, rb_capsule
*ca
,
133 v3f coB
, f32 rb
, rb_ct
*buf
){
139 v3_muladds( mtxA
[3], mtxA
[1], -ha
*0.5f
+ra
, p0
);
140 v3_muladds( mtxA
[3], mtxA
[1], ha
*0.5f
-ra
, p1
);
143 closest_point_segment( p0
, p1
, coB
, c
);
144 v3_sub( c
, coB
, delta
);
145 f32 d2
= v3_length2(delta
);
151 v3_muls( delta
, 1.0f
/d
, ct
->n
);
155 v3_muladds( c
, ct
->n
, -ra
, p0
);
156 v3_muladds( coB
, ct
->n
, rb
, p1
);
157 v3_add( p0
, p1
, ct
->co
);
158 v3_muls( ct
->co
, 0.5f
, ct
->co
);
159 ct
->type
= k_contact_type_default
;
165 static int rb_capsule__capsule( m4x3f mtxA
, rb_capsule
*ca
,
166 m4x3f mtxB
, rb_capsule
*cb
, rb_ct
*buf
){
174 v3_muladds( mtxA
[3], mtxA
[1], -ha
*0.5f
+ra
, p0
);
175 v3_muladds( mtxA
[3], mtxA
[1], ha
*0.5f
-ra
, p1
);
176 v3_muladds( mtxB
[3], mtxB
[1], -hb
*0.5f
+rb
, p2
);
177 v3_muladds( mtxB
[3], mtxB
[1], hb
*0.5f
-rb
, p3
);
179 capsule_manifold manifold
;
180 rb_capsule_manifold_init( &manifold
);
184 closest_segment_segment( p0
, p1
, p2
, p3
, &ta
, &tb
, pa
, pb
);
185 rb_capsule_manifold( pa
, pb
, ta
, r
, &manifold
);
187 ta
= closest_point_segment( p0
, p1
, p2
, pa
);
188 tb
= closest_point_segment( p0
, p1
, p3
, pb
);
189 rb_capsule_manifold( pa
, p2
, ta
, r
, &manifold
);
190 rb_capsule_manifold( pb
, p3
, tb
, r
, &manifold
);
192 closest_point_segment( p2
, p3
, p0
, pa
);
193 closest_point_segment( p2
, p3
, p1
, pb
);
194 rb_capsule_manifold( p0
, pa
, 0.0f
, r
, &manifold
);
195 rb_capsule_manifold( p1
, pb
, 1.0f
, r
, &manifold
);
197 return rb_capsule__manifold_done( mtxA
, ca
, &manifold
, buf
);
201 * Generates up to two contacts; optimised for the most stable manifold
203 static int rb_capsule__box( m4x3f mtxA
, rb_capsule
*ca
,
204 m4x3f mtxB
, m4x3f mtxB_inverse
, boxf box
,
206 f32 h
= ca
->h
, r
= ca
->r
;
209 * Solving this in symetric local space of the cube saves us some time and a
210 * couple branches when it comes to the quad stage.
213 v3_add( box
[0], box
[1], centroid
);
214 v3_muls( centroid
, 0.5f
, centroid
);
217 v3_sub( box
[0], centroid
, bbx
[0] );
218 v3_sub( box
[1], centroid
, bbx
[1] );
220 v3f pc
, p0w
, p1w
, p0
, p1
;
221 v3_muladds( mtxA
[3], mtxA
[1], -h
*0.5f
+r
, p0w
);
222 v3_muladds( mtxA
[3], mtxA
[1], h
*0.5f
-r
, p1w
);
224 m4x3_mulv( mtxB_inverse
, p0w
, p0
);
225 m4x3_mulv( mtxB_inverse
, p1w
, p1
);
226 v3_sub( p0
, centroid
, p0
);
227 v3_sub( p1
, centroid
, p1
);
228 v3_add( p0
, p1
, pc
);
229 v3_muls( pc
, 0.5f
, pc
);
232 * Finding an appropriate quad to collide lines with
235 v3_div( pc
, bbx
[1], region
);
238 if( (fabsf(region
[0]) > fabsf(region
[1])) &&
239 (fabsf(region
[0]) > fabsf(region
[2])) )
241 f32 px
= vg_signf(region
[0]) * bbx
[1][0];
242 v3_copy( (v3f
){ px
, bbx
[0][1], bbx
[0][2] }, quad
[0] );
243 v3_copy( (v3f
){ px
, bbx
[1][1], bbx
[0][2] }, quad
[1] );
244 v3_copy( (v3f
){ px
, bbx
[1][1], bbx
[1][2] }, quad
[2] );
245 v3_copy( (v3f
){ px
, bbx
[0][1], bbx
[1][2] }, quad
[3] );
247 else if( fabsf(region
[1]) > fabsf(region
[2]) )
249 f32 py
= vg_signf(region
[1]) * bbx
[1][1];
250 v3_copy( (v3f
){ bbx
[0][0], py
, bbx
[0][2] }, quad
[0] );
251 v3_copy( (v3f
){ bbx
[1][0], py
, bbx
[0][2] }, quad
[1] );
252 v3_copy( (v3f
){ bbx
[1][0], py
, bbx
[1][2] }, quad
[2] );
253 v3_copy( (v3f
){ bbx
[0][0], py
, bbx
[1][2] }, quad
[3] );
257 f32 pz
= vg_signf(region
[2]) * bbx
[1][2];
258 v3_copy( (v3f
){ bbx
[0][0], bbx
[0][1], pz
}, quad
[0] );
259 v3_copy( (v3f
){ bbx
[1][0], bbx
[0][1], pz
}, quad
[1] );
260 v3_copy( (v3f
){ bbx
[1][0], bbx
[1][1], pz
}, quad
[2] );
261 v3_copy( (v3f
){ bbx
[0][0], bbx
[1][1], pz
}, quad
[3] );
264 capsule_manifold manifold
;
265 rb_capsule_manifold_init( &manifold
);
268 closest_point_aabb( p0
, bbx
, c0
);
269 closest_point_aabb( p1
, bbx
, c1
);
272 v3_sub( c0
, p0
, d0
);
273 v3_sub( c1
, p1
, d1
);
274 v3_sub( p1
, p0
, da
);
281 if( v3_dot( da
, d0
) <= 0.01f
)
282 rb_capsule_manifold( p0
, c0
, 0.0f
, r
, &manifold
);
284 if( v3_dot( da
, d1
) >= -0.01f
)
285 rb_capsule_manifold( p1
, c1
, 1.0f
, r
, &manifold
);
287 for( i32 i
=0; i
<4; i
++ ){
293 closest_segment_segment( p0
, p1
, quad
[i0
], quad
[i1
], &ta
, &tb
, ca
, cb
);
294 rb_capsule_manifold( ca
, cb
, ta
, r
, &manifold
);
298 * Create final contacts based on line manifold
300 m3x3_mulv( mtxB
, manifold
.d0
, manifold
.d0
);
301 m3x3_mulv( mtxB
, manifold
.d1
, manifold
.d1
);
302 return rb_capsule__manifold_done( mtxA
, ca
, &manifold
, buf
);
305 static int rb_sphere__box( v3f coA
, f32 ra
,
306 m4x3f mtxB
, m4x3f mtxB_inverse
, boxf box
,
309 closest_point_obb( coA
, box
, mtxB
, mtxB_inverse
, co
);
310 v3_sub( coA
, co
, delta
);
312 f32 d2
= v3_length2(delta
);
320 v3_sub( box
[1], box
[0], e
);
321 v3_muls( e
, 0.5f
, e
);
322 v3_add( box
[0], e
, coB
);
323 v3_sub( coA
, coB
, delta
);
326 * some extra testing is required to find the best axis to push the
327 * object back outside the box. Since there isnt a clear seperating
328 * vector already, especially on really high aspect boxes.
330 f32 lx
= v3_dot( mtxB
[0], delta
),
331 ly
= v3_dot( mtxB
[1], delta
),
332 lz
= v3_dot( mtxB
[2], delta
),
333 px
= e
[0] - fabsf(lx
),
334 py
= e
[1] - fabsf(ly
),
335 pz
= e
[2] - fabsf(lz
);
337 if( px
< py
&& px
< pz
) v3_muls( mtxB
[0], vg_signf(lx
), ct
->n
);
338 else if( py
< pz
) v3_muls( mtxB
[1], vg_signf(ly
), ct
->n
);
339 else v3_muls( mtxB
[2], vg_signf(lz
), ct
->n
);
341 v3_muladds( coA
, ct
->n
, -ra
, ct
->co
);
346 v3_muls( delta
, 1.0f
/d
, ct
->n
);
348 v3_copy( co
, ct
->co
);
351 ct
->type
= k_contact_type_default
;
357 static int rb_sphere__sphere( v3f coA
, f32 ra
,
358 v3f coB
, f32 rb
, rb_ct
*buf
){
360 v3_sub( coA
, coB
, delta
);
362 f32 d2
= v3_length2(delta
),
369 v3_muls( delta
, 1.0f
/d
, ct
->n
);
372 v3_muladds( coA
, ct
->n
,-ra
, p0
);
373 v3_muladds( coB
, ct
->n
, rb
, p1
);
374 v3_add( p0
, p1
, ct
->co
);
375 v3_muls( ct
->co
, 0.5f
, ct
->co
);
376 ct
->type
= k_contact_type_default
;
383 static int rb_sphere__triangle( m4x3f mtxA
, f32 r
,
384 v3f tri
[3], rb_ct
*buf
){
386 enum contact_type type
= closest_on_triangle_1( mtxA
[3], tri
, co
);
387 v3_sub( mtxA
[3], co
, delta
);
388 f32 d2
= v3_length2( delta
);
394 v3_sub( tri
[2], tri
[0], ab
);
395 v3_sub( tri
[1], tri
[0], ac
);
396 v3_cross( ac
, ab
, tn
);
397 v3_copy( tn
, ct
->n
);
399 if( v3_length2( ct
->n
) <= 0.00001f
){
400 #ifdef RIGIDBODY_CRY_ABOUT_EVERYTHING
401 vg_error( "Zero area triangle!\n" );
406 v3_normalize( ct
->n
);
410 v3_copy( co
, ct
->co
);
419 static int rb_capsule__triangle( m4x3f mtxA
, rb_capsule
*c
,
420 v3f tri
[3], rb_ct
*buf
){
422 v3_muladds( mtxA
[3], mtxA
[1], -c
->h
*0.5f
+c
->r
, p0w
);
423 v3_muladds( mtxA
[3], mtxA
[1], c
->h
*0.5f
-c
->r
, p1w
);
425 capsule_manifold manifold
;
426 rb_capsule_manifold_init( &manifold
);
429 v3_sub( tri
[1], tri
[0], v0
);
430 v3_sub( tri
[2], tri
[0], v1
);
431 v3_cross( v0
, v1
, n
);
433 if( v3_length2( n
) <= 0.00001f
){
434 #ifdef RIGIDBODY_CRY_ABOUT_EVERYTHING
435 vg_error( "Zero area triangle!\n" );
443 /* deep penetration recovery. for when we clip through the triangles. so its
444 * not very 'correct' */
446 if( ray_tri( tri
, p0w
, mtxA
[1], &dist
, 1 ) ){
447 f32 l
= c
->h
- c
->r
*2.0f
;
448 if( (dist
>= 0.0f
) && (dist
< l
) ){
450 v3_muladds( p0w
, mtxA
[1], dist
, co
);
451 vg_line_point( co
, 0.02f
, 0xffffff00 );
454 v3_sub( p0w
, co
, d0
);
455 v3_sub( p1w
, co
, d1
);
457 f32 p
= vg_minf( v3_dot( n
, d0
), v3_dot( n
, d1
) ) - c
->r
;
461 ct
->type
= k_contact_type_default
;
463 v3_muladds( co
, n
, p
, ct
->co
);
471 closest_on_triangle_1( p0w
, tri
, c0
);
472 closest_on_triangle_1( p1w
, tri
, c1
);
475 v3_sub( c0
, p0w
, d0
);
476 v3_sub( c1
, p1w
, d1
);
477 v3_sub( p1w
, p0w
, da
);
483 /* the two balls at the ends */
484 if( v3_dot( da
, d0
) <= 0.01f
)
485 rb_capsule_manifold( p0w
, c0
, 0.0f
, c
->r
, &manifold
);
486 if( v3_dot( da
, d1
) >= -0.01f
)
487 rb_capsule_manifold( p1w
, c1
, 1.0f
, c
->r
, &manifold
);
489 /* the edges to edges */
490 for( int i
=0; i
<3; i
++ ){
496 closest_segment_segment( p0w
, p1w
, tri
[i0
], tri
[i1
], &ta
, &tb
, ca
, cb
);
497 rb_capsule_manifold( ca
, cb
, ta
, c
->r
, &manifold
);
500 int count
= rb_capsule__manifold_done( mtxA
, c
, &manifold
, buf
);
501 for( int i
=0; i
<count
; i
++ )
502 v3_copy( n
, buf
[i
].n
);
507 static int rb_global_has_space( void ){
508 if( rb_contact_count
+ 16 > vg_list_size(rb_contact_buffer
) )
514 static rb_ct
*rb_global_buffer( void ){
515 return &rb_contact_buffer
[ rb_contact_count
];
519 * -----------------------------------------------------------------------------
520 * Boolean shape overlap functions
521 * -----------------------------------------------------------------------------
525 * Project AABB, and triangle interval onto axis to check if they overlap
527 static int rb_box_triangle_interval( v3f extent
, v3f axis
, v3f tri
[3] ){
530 r
= extent
[0] * fabsf(axis
[0]) +
531 extent
[1] * fabsf(axis
[1]) +
532 extent
[2] * fabsf(axis
[2]),
534 p0
= v3_dot( axis
, tri
[0] ),
535 p1
= v3_dot( axis
, tri
[1] ),
536 p2
= v3_dot( axis
, tri
[2] ),
538 e
= vg_maxf(-vg_maxf(p0
,vg_maxf(p1
,p2
)), vg_minf(p0
,vg_minf(p1
,p2
)));
540 if( e
> r
) return 0;
545 * Seperating axis test box vs triangle
547 static int rb_box_triangle_sat( v3f extent
, v3f center
,
548 m4x3f to_local
, v3f tri_src
[3] ){
551 for( int i
=0; i
<3; i
++ ){
552 m4x3_mulv( to_local
, tri_src
[i
], tri
[i
] );
553 v3_sub( tri
[i
], center
, tri
[i
] );
557 v3_sub( tri
[1], tri
[0], f0
);
558 v3_sub( tri
[2], tri
[1], f1
);
559 v3_sub( tri
[0], tri
[2], f2
);
563 v3_cross( (v3f
){1.0f
,0.0f
,0.0f
}, f0
, axis
[0] );
564 v3_cross( (v3f
){1.0f
,0.0f
,0.0f
}, f1
, axis
[1] );
565 v3_cross( (v3f
){1.0f
,0.0f
,0.0f
}, f2
, axis
[2] );
566 v3_cross( (v3f
){0.0f
,1.0f
,0.0f
}, f0
, axis
[3] );
567 v3_cross( (v3f
){0.0f
,1.0f
,0.0f
}, f1
, axis
[4] );
568 v3_cross( (v3f
){0.0f
,1.0f
,0.0f
}, f2
, axis
[5] );
569 v3_cross( (v3f
){0.0f
,0.0f
,1.0f
}, f0
, axis
[6] );
570 v3_cross( (v3f
){0.0f
,0.0f
,1.0f
}, f1
, axis
[7] );
571 v3_cross( (v3f
){0.0f
,0.0f
,1.0f
}, f2
, axis
[8] );
573 for( int i
=0; i
<9; i
++ )
574 if(!rb_box_triangle_interval( extent
, axis
[i
], tri
)) return 0;
577 if(!rb_box_triangle_interval( extent
, (v3f
){1.0f
,0.0f
,0.0f
}, tri
)) return 0;
578 if(!rb_box_triangle_interval( extent
, (v3f
){0.0f
,1.0f
,0.0f
}, tri
)) return 0;
579 if(!rb_box_triangle_interval( extent
, (v3f
){0.0f
,0.0f
,1.0f
}, tri
)) return 0;
582 v3_cross( f0
, f1
, n
);
583 if(!rb_box_triangle_interval( extent
, n
, tri
)) return 0;
589 * -----------------------------------------------------------------------------
591 * -----------------------------------------------------------------------------
594 static int rb_manifold_apply_filtered( rb_ct
*man
, int len
){
597 for( int i
=0; i
<len
; i
++ ){
600 if( ct
->type
== k_contact_type_disabled
)
610 * Merge two contacts if they are within radius(r) of eachother
612 static void rb_manifold_contact_weld( rb_ct
*ci
, rb_ct
*cj
, float r
){
613 if( v3_dist2( ci
->co
, cj
->co
) < r
*r
){
614 cj
->type
= k_contact_type_disabled
;
615 ci
->p
= (ci
->p
+ cj
->p
) * 0.5f
;
617 v3_add( ci
->co
, cj
->co
, ci
->co
);
618 v3_muls( ci
->co
, 0.5f
, ci
->co
);
621 v3_sub( ci
->rba
->co
, ci
->co
, delta
);
623 float c0
= v3_dot( ci
->n
, delta
),
624 c1
= v3_dot( cj
->n
, delta
);
626 if( c0
< 0.0f
|| c1
< 0.0f
){
628 ci
->type
= k_contact_type_disabled
;
632 v3_muls( ci
->n
, c0
, n
);
633 v3_muladds( n
, cj
->n
, c1
, n
);
643 static void rb_manifold_filter_joint_edges( rb_ct
*man
, int len
, float r
){
644 for( int i
=0; i
<len
-1; i
++ ){
646 if( ci
->type
!= k_contact_type_edge
)
649 for( int j
=i
+1; j
<len
; j
++ ){
651 if( cj
->type
!= k_contact_type_edge
)
654 rb_manifold_contact_weld( ci
, cj
, r
);
660 * Resolve overlapping pairs
662 static void rb_manifold_filter_pairs( rb_ct
*man
, int len
, float r
){
663 for( int i
=0; i
<len
-1; i
++ ){
667 if( ci
->type
== k_contact_type_disabled
) continue;
669 for( int j
=i
+1; j
<len
; j
++ ){
672 if( cj
->type
== k_contact_type_disabled
) continue;
674 if( v3_dist2( ci
->co
, cj
->co
) < r
*r
){
675 cj
->type
= k_contact_type_disabled
;
676 v3_add( cj
->n
, ci
->n
, ci
->n
);
683 float n
= 1.0f
/((float)similar
+1.0f
);
684 v3_muls( ci
->n
, n
, ci
->n
);
687 if( v3_length2(ci
->n
) < 0.1f
*0.1f
)
688 ci
->type
= k_contact_type_disabled
;
690 v3_normalize( ci
->n
);
696 * Remove contacts that are facing away from A
698 static void rb_manifold_filter_backface( rb_ct
*man
, int len
){
699 for( int i
=0; i
<len
; i
++ ){
701 if( ct
->type
== k_contact_type_disabled
)
705 v3_sub( ct
->co
, ct
->rba
->co
, delta
);
707 if( v3_dot( delta
, ct
->n
) > -0.001f
)
708 ct
->type
= k_contact_type_disabled
;
713 * Filter out duplicate coplanar results. Good for spheres.
715 static void rb_manifold_filter_coplanar( rb_ct
*man
, int len
, float w
){
716 for( int i
=0; i
<len
; i
++ ){
718 if( ci
->type
== k_contact_type_disabled
||
719 ci
->type
== k_contact_type_edge
)
722 float d1
= v3_dot( ci
->co
, ci
->n
);
724 for( int j
=0; j
<len
; j
++ ){
729 if( cj
->type
== k_contact_type_disabled
)
732 float d2
= v3_dot( cj
->co
, ci
->n
),
735 if( fabsf( d
) <= w
){
736 cj
->type
= k_contact_type_disabled
;
742 static void rb_debug_contact( rb_ct
*ct
){
744 v3_muladds( ct
->co
, ct
->n
, 0.05f
, p1
);
746 if( ct
->type
== k_contact_type_default
){
747 vg_line_point( ct
->co
, 0.0125f
, 0xff0000ff );
748 vg_line( ct
->co
, p1
, 0xffffffff );
750 else if( ct
->type
== k_contact_type_edge
){
751 vg_line_point( ct
->co
, 0.0125f
, 0xff00ffc0 );
752 vg_line( ct
->co
, p1
, 0xffffffff );
756 static void rb_solver_reset(void){
757 rb_contact_count
= 0;
760 static rb_ct
*rb_global_ct(void){
761 return rb_contact_buffer
+ rb_contact_count
;
764 static void rb_prepare_contact( rb_ct
*ct
){
765 ct
->bias
= -k_phys_baumgarte
* (vg
.time_fixed_delta
*3600.0f
)
766 * vg_minf( 0.0f
, -ct
->p
+k_penetration_slop
);
768 v3_tangent_basis( ct
->n
, ct
->t
[0], ct
->t
[1] );
769 ct
->norm_impulse
= 0.0f
;
770 ct
->tangent_impulse
[0] = 0.0f
;
771 ct
->tangent_impulse
[1] = 0.0f
;
775 * calculate total move to depenetrate object from contacts.
776 * manifold should belong to ONE object only
778 static void rb_depenetrate( rb_ct
*manifold
, int len
, v3f dt
){
781 for( int j
=0; j
<7; j
++ ){
782 for( int i
=0; i
<len
; i
++ ){
783 rb_ct
*ct
= &manifold
[i
];
785 float resolved_amt
= v3_dot( ct
->n
, dt
),
786 remaining
= (ct
->p
-k_penetration_slop
) - resolved_amt
,
787 apply
= vg_maxf( remaining
, 0.0f
) * 0.4f
;
789 v3_muladds( dt
, ct
->n
, apply
, dt
);
795 * Initializing things like tangent vectors
797 static void rb_presolve_contacts( rb_ct
*buffer
, int len
){
798 for( int i
=0; i
<len
; i
++ ){
799 rb_ct
*ct
= &buffer
[i
];
800 rb_prepare_contact( ct
);
802 v3f ra
, rb
, raCn
, rbCn
, raCt
, rbCt
;
803 v3_sub( ct
->co
, ct
->rba
->co
, ra
);
804 v3_sub( ct
->co
, ct
->rbb
->co
, rb
);
805 v3_cross( ra
, ct
->n
, raCn
);
806 v3_cross( rb
, ct
->n
, rbCn
);
808 /* orient inverse inertia tensors */
810 m3x3_mulv( ct
->rba
->iIw
, raCn
, raCnI
);
811 m3x3_mulv( ct
->rbb
->iIw
, rbCn
, rbCnI
);
813 ct
->normal_mass
= ct
->rba
->inv_mass
+ ct
->rbb
->inv_mass
;
814 ct
->normal_mass
+= v3_dot( raCn
, raCnI
);
815 ct
->normal_mass
+= v3_dot( rbCn
, rbCnI
);
816 ct
->normal_mass
= 1.0f
/ct
->normal_mass
;
818 for( int j
=0; j
<2; j
++ ){
820 v3_cross( ct
->t
[j
], ra
, raCt
);
821 v3_cross( ct
->t
[j
], rb
, rbCt
);
822 m3x3_mulv( ct
->rba
->iIw
, raCt
, raCtI
);
823 m3x3_mulv( ct
->rbb
->iIw
, rbCt
, rbCtI
);
825 ct
->tangent_mass
[j
] = ct
->rba
->inv_mass
+ ct
->rbb
->inv_mass
;
826 ct
->tangent_mass
[j
] += v3_dot( raCt
, raCtI
);
827 ct
->tangent_mass
[j
] += v3_dot( rbCt
, rbCtI
);
828 ct
->tangent_mass
[j
] = 1.0f
/ct
->tangent_mass
[j
];
833 static void rb_contact_restitution( rb_ct
*ct
, float cr
){
835 v3_sub( ct
->co
, ct
->rba
->co
, ra
);
836 v3_sub( ct
->co
, ct
->rbb
->co
, rb
);
837 rb_rcv( ct
->rba
, ct
->rbb
, ra
, rb
, rv
);
839 float v
= v3_dot( rv
, ct
->n
);
847 * One iteration to solve the contact constraint
849 static void rb_solve_contacts( rb_ct
*buf
, int len
){
850 for( int i
=0; i
<len
; i
++ ){
854 v3_sub( ct
->co
, ct
->rba
->co
, ra
);
855 v3_sub( ct
->co
, ct
->rbb
->co
, rb
);
856 rb_rcv( ct
->rba
, ct
->rbb
, ra
, rb
, rv
);
859 for( int j
=0; j
<2; j
++ ){
860 float f
= k_friction
* ct
->norm_impulse
,
861 vt
= v3_dot( rv
, ct
->t
[j
] ),
862 lambda
= ct
->tangent_mass
[j
] * -vt
;
864 float temp
= ct
->tangent_impulse
[j
];
865 ct
->tangent_impulse
[j
] = vg_clampf( temp
+ lambda
, -f
, f
);
866 lambda
= ct
->tangent_impulse
[j
] - temp
;
869 v3_muls( ct
->t
[j
], lambda
, impulse
);
870 rb_linear_impulse( ct
->rba
, ra
, impulse
);
872 v3_muls( ct
->t
[j
], -lambda
, impulse
);
873 rb_linear_impulse( ct
->rbb
, rb
, impulse
);
877 rb_rcv( ct
->rba
, ct
->rbb
, ra
, rb
, rv
);
878 float vn
= v3_dot( rv
, ct
->n
),
879 lambda
= ct
->normal_mass
* (-vn
+ ct
->bias
);
881 float temp
= ct
->norm_impulse
;
882 ct
->norm_impulse
= vg_maxf( temp
+ lambda
, 0.0f
);
883 lambda
= ct
->norm_impulse
- temp
;
886 v3_muls( ct
->n
, lambda
, impulse
);
887 rb_linear_impulse( ct
->rba
, ra
, impulse
);
889 v3_muls( ct
->n
, -lambda
, impulse
);
890 rb_linear_impulse( ct
->rbb
, rb
, impulse
);