add motion vectors to all shaders
[carveJwlIkooP6JGAAIwe30JlM.git] / rigidbody.h
1 /*
2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
3 */
4
5 /*
6 * Resources: Box2D - Erin Catto
7 * qu3e - Randy Gaul
8 */
9
10 #include "common.h"
11 #include "bvh.h"
12 #include "scene.h"
13 #include "distq.h"
14
15 VG_STATIC void rb_tangent_basis( v3f n, v3f tx, v3f ty );
16 VG_STATIC bh_system bh_system_rigidbodies;
17
18 #ifndef RIGIDBODY_H
19 #define RIGIDBODY_H
20
21 /*
22 * -----------------------------------------------------------------------------
23 * (K)onstants
24 * -----------------------------------------------------------------------------
25 */
26
27 VG_STATIC const float
28 k_rb_rate = (1.0/VG_TIMESTEP_FIXED),
29 k_rb_delta = (1.0/k_rb_rate),
30 k_friction = 0.6f,
31 k_damp_linear = 0.05f, /* scale velocity 1/(1+x) */
32 k_damp_angular = 0.1f, /* scale angular 1/(1+x) */
33 k_limit_bias = 0.02f,
34 k_joint_bias = 0.08f, /* positional joints */
35 k_joint_correction = 0.01f,
36 k_penetration_slop = 0.01f,
37 k_inertia_scale = 4.0f;
38
39 /*
40 * -----------------------------------------------------------------------------
41 * structure definitions
42 * -----------------------------------------------------------------------------
43 */
44
45 typedef struct rigidbody rigidbody;
46 typedef struct contact rb_ct;
47
48 struct rigidbody
49 {
50 v3f co, v, w;
51 v4f q;
52
53 enum rb_shape
54 {
55 k_rb_shape_box = 0,
56 k_rb_shape_sphere = 1,
57 k_rb_shape_capsule = 2,
58 k_rb_shape_scene = 3
59 }
60 type;
61
62 union
63 {
64 struct rb_sphere
65 {
66 float radius;
67 }
68 sphere;
69
70 struct rb_capsule
71 {
72 float height, radius;
73 }
74 capsule;
75
76 struct rb_scene
77 {
78 bh_tree *bh_scene;
79 }
80 scene;
81 }
82 inf;
83
84 v3f right, up, forward;
85
86 int is_world;
87
88 boxf bbx, bbx_world;
89 float inv_mass;
90
91 /* inertia model and inverse world tensor */
92 v3f I;
93 m3x3f iI, iIw;
94
95 m4x3f to_world, to_local;
96 };
97
98 VG_STATIC struct contact
99 {
100 rigidbody *rba, *rbb;
101 v3f co, n;
102 v3f t[2];
103 float p, bias, norm_impulse, tangent_impulse[2],
104 normal_mass, tangent_mass[2];
105
106 u32 element_id;
107
108 enum contact_type type;
109 }
110 rb_contact_buffer[256];
111 VG_STATIC int rb_contact_count = 0;
112
113 /*
114 * -----------------------------------------------------------------------------
115 * Math Utils
116 * -----------------------------------------------------------------------------
117 */
118
119 VG_STATIC float sphere_volume( float radius )
120 {
121 float r3 = radius*radius*radius;
122 return (4.0f/3.0f) * VG_PIf * r3;
123 }
124
125 VG_STATIC void rb_tangent_basis( v3f n, v3f tx, v3f ty )
126 {
127 /* Compute tangent basis (box2d) */
128 if( fabsf( n[0] ) >= 0.57735027f )
129 {
130 tx[0] = n[1];
131 tx[1] = -n[0];
132 tx[2] = 0.0f;
133 }
134 else
135 {
136 tx[0] = 0.0f;
137 tx[1] = n[2];
138 tx[2] = -n[1];
139 }
140
141 v3_normalize( tx );
142 v3_cross( n, tx, ty );
143 }
144
145 /*
146 * -----------------------------------------------------------------------------
147 * Debugging
148 * -----------------------------------------------------------------------------
149 */
150
151 VG_STATIC void rb_debug_contact( rb_ct *ct )
152 {
153 if( ct->type != k_contact_type_disabled )
154 {
155 v3f p1;
156 v3_muladds( ct->co, ct->n, 0.1f, p1 );
157 vg_line_pt3( ct->co, 0.025f, 0xff0000ff );
158 vg_line( ct->co, p1, 0xffffffff );
159 }
160 }
161
162 VG_STATIC void debug_sphere( m4x3f m, float radius, u32 colour )
163 {
164 v3f ly = { 0.0f, 0.0f, radius },
165 lx = { 0.0f, radius, 0.0f },
166 lz = { 0.0f, 0.0f, radius };
167
168 for( int i=0; i<16; i++ )
169 {
170 float t = ((float)(i+1) * (1.0f/16.0f)) * VG_PIf * 2.0f,
171 s = sinf(t),
172 c = cosf(t);
173
174 v3f py = { s*radius, 0.0f, c*radius },
175 px = { s*radius, c*radius, 0.0f },
176 pz = { 0.0f, s*radius, c*radius };
177
178 v3f p0, p1, p2, p3, p4, p5;
179 m4x3_mulv( m, py, p0 );
180 m4x3_mulv( m, ly, p1 );
181 m4x3_mulv( m, px, p2 );
182 m4x3_mulv( m, lx, p3 );
183 m4x3_mulv( m, pz, p4 );
184 m4x3_mulv( m, lz, p5 );
185
186 vg_line( p0, p1, colour == 0x00? 0xff00ff00: colour );
187 vg_line( p2, p3, colour == 0x00? 0xff0000ff: colour );
188 vg_line( p4, p5, colour == 0x00? 0xffff0000: colour );
189
190 v3_copy( py, ly );
191 v3_copy( px, lx );
192 v3_copy( pz, lz );
193 }
194 }
195
196 VG_STATIC void debug_capsule( m4x3f m, float radius, float h, u32 colour )
197 {
198 v3f ly = { 0.0f, 0.0f, radius },
199 lx = { 0.0f, radius, 0.0f },
200 lz = { 0.0f, 0.0f, radius };
201
202 float s0 = sinf(0.0f)*radius,
203 c0 = cosf(0.0f)*radius;
204
205 v3f p0, p1, up, right, forward;
206 m3x3_mulv( m, (v3f){0.0f,1.0f,0.0f}, up );
207 m3x3_mulv( m, (v3f){1.0f,0.0f,0.0f}, right );
208 m3x3_mulv( m, (v3f){0.0f,0.0f,-1.0f}, forward );
209 v3_muladds( m[3], up, -h*0.5f+radius, p0 );
210 v3_muladds( m[3], up, h*0.5f-radius, p1 );
211
212 v3f a0, a1, b0, b1;
213 v3_muladds( p0, right, radius, a0 );
214 v3_muladds( p1, right, radius, a1 );
215 v3_muladds( p0, forward, radius, b0 );
216 v3_muladds( p1, forward, radius, b1 );
217 vg_line( a0, a1, colour );
218 vg_line( b0, b1, colour );
219
220 v3_muladds( p0, right, -radius, a0 );
221 v3_muladds( p1, right, -radius, a1 );
222 v3_muladds( p0, forward, -radius, b0 );
223 v3_muladds( p1, forward, -radius, b1 );
224 vg_line( a0, a1, colour );
225 vg_line( b0, b1, colour );
226
227 for( int i=0; i<16; i++ )
228 {
229 float t = ((float)(i+1) * (1.0f/16.0f)) * VG_PIf * 2.0f,
230 s1 = sinf(t)*radius,
231 c1 = cosf(t)*radius;
232
233 v3f e0 = { s0, 0.0f, c0 },
234 e1 = { s1, 0.0f, c1 },
235 e2 = { s0, c0, 0.0f },
236 e3 = { s1, c1, 0.0f },
237 e4 = { 0.0f, c0, s0 },
238 e5 = { 0.0f, c1, s1 };
239
240 m3x3_mulv( m, e0, e0 );
241 m3x3_mulv( m, e1, e1 );
242 m3x3_mulv( m, e2, e2 );
243 m3x3_mulv( m, e3, e3 );
244 m3x3_mulv( m, e4, e4 );
245 m3x3_mulv( m, e5, e5 );
246
247 v3_add( p0, e0, a0 );
248 v3_add( p0, e1, a1 );
249 v3_add( p1, e0, b0 );
250 v3_add( p1, e1, b1 );
251
252 vg_line( a0, a1, colour );
253 vg_line( b0, b1, colour );
254
255 if( c0 < 0.0f )
256 {
257 v3_add( p0, e2, a0 );
258 v3_add( p0, e3, a1 );
259 v3_add( p0, e4, b0 );
260 v3_add( p0, e5, b1 );
261 }
262 else
263 {
264 v3_add( p1, e2, a0 );
265 v3_add( p1, e3, a1 );
266 v3_add( p1, e4, b0 );
267 v3_add( p1, e5, b1 );
268 }
269
270 vg_line( a0, a1, colour );
271 vg_line( b0, b1, colour );
272
273 s0 = s1;
274 c0 = c1;
275 }
276 }
277
278 VG_STATIC void rb_debug( rigidbody *rb, u32 colour )
279 {
280 if( rb->type == k_rb_shape_box )
281 {
282 v3f *box = rb->bbx;
283 vg_line_boxf_transformed( rb->to_world, rb->bbx, colour );
284 }
285 else if( rb->type == k_rb_shape_sphere )
286 {
287 debug_sphere( rb->to_world, rb->inf.sphere.radius, colour );
288 }
289 else if( rb->type == k_rb_shape_capsule )
290 {
291 m4x3f m0, m1;
292 float h = rb->inf.capsule.height,
293 r = rb->inf.capsule.radius;
294
295 debug_capsule( rb->to_world, r, h, colour );
296 }
297 else if( rb->type == k_rb_shape_scene )
298 {
299 vg_line_boxf( rb->bbx, colour );
300 }
301 }
302
303 /*
304 * -----------------------------------------------------------------------------
305 * Integration
306 * -----------------------------------------------------------------------------
307 */
308
309 /*
310 * Update world space bounding box based on local one
311 */
312 VG_STATIC void rb_update_bounds( rigidbody *rb )
313 {
314 box_copy( rb->bbx, rb->bbx_world );
315 m4x3_transform_aabb( rb->to_world, rb->bbx_world );
316 }
317
318 /*
319 * Commit transform to rigidbody. Updates matrices
320 */
321 VG_STATIC void rb_update_transform( rigidbody *rb )
322 {
323 q_normalize( rb->q );
324 q_m3x3( rb->q, rb->to_world );
325 v3_copy( rb->co, rb->to_world[3] );
326
327 m4x3_invert_affine( rb->to_world, rb->to_local );
328
329 m3x3_mulv( rb->to_world, (v3f){1.0f,0.0f, 0.0f}, rb->right );
330 m3x3_mulv( rb->to_world, (v3f){0.0f,1.0f, 0.0f}, rb->up );
331 m3x3_mulv( rb->to_world, (v3f){0.0f,0.0f,-1.0f}, rb->forward );
332
333 m3x3_mul( rb->iI, rb->to_local, rb->iIw );
334 m3x3_mul( rb->to_world, rb->iIw, rb->iIw );
335
336 rb_update_bounds( rb );
337 }
338
339 /*
340 * Extrapolate rigidbody into a transform based on vg accumulator.
341 * Useful for rendering
342 */
343 VG_STATIC void rb_extrapolate_transform( rigidbody *rb, m4x3f transform )
344 {
345 float substep = vg_clampf( vg.accumulator / k_rb_delta, 0.0f, 1.0f );
346
347 v3f co;
348 v4f q;
349
350 v3_muladds( rb->co, rb->v, k_rb_delta*substep, co );
351
352 if( v3_length2( rb->w ) > 0.0f )
353 {
354 v4f rotation;
355 v3f axis;
356 v3_copy( rb->w, axis );
357
358 float mag = v3_length( axis );
359 v3_divs( axis, mag, axis );
360 q_axis_angle( rotation, axis, mag*k_rb_delta*substep );
361 q_mul( rotation, rb->q, q );
362 q_normalize( q );
363 }
364 else
365 {
366 v4_copy( rb->q, q );
367 }
368
369 q_m3x3( q, transform );
370 v3_copy( co, transform[3] );
371 }
372
373 /*
374 * Initialize rigidbody and calculate masses, inertia
375 */
376 VG_STATIC void rb_init( rigidbody *rb )
377 {
378 float volume = 1.0f;
379
380 if( rb->type == k_rb_shape_box )
381 {
382 v3f dims;
383 v3_sub( rb->bbx[1], rb->bbx[0], dims );
384 volume = dims[0]*dims[1]*dims[2];
385 }
386 else if( rb->type == k_rb_shape_sphere )
387 {
388 volume = sphere_volume( rb->inf.sphere.radius );
389 v3_fill( rb->bbx[0], -rb->inf.sphere.radius );
390 v3_fill( rb->bbx[1], rb->inf.sphere.radius );
391 }
392 else if( rb->type == k_rb_shape_capsule )
393 {
394 float r = rb->inf.capsule.radius,
395 h = rb->inf.capsule.height;
396 volume = sphere_volume( r ) + VG_PIf * r*r * (h - r*2.0f);
397
398 v3_fill( rb->bbx[0], -rb->inf.sphere.radius );
399 v3_fill( rb->bbx[1], rb->inf.sphere.radius );
400 rb->bbx[0][1] = -h;
401 rb->bbx[1][1] = h;
402 }
403 else if( rb->type == k_rb_shape_scene )
404 {
405 rb->is_world = 1;
406 box_copy( rb->inf.scene.bh_scene->nodes[0].bbx, rb->bbx );
407 }
408
409 if( rb->is_world )
410 {
411 rb->inv_mass = 0.0f;
412 v3_zero( rb->I );
413 m3x3_zero(rb->iI);
414 }
415 else
416 {
417 float mass = 2.0f*volume;
418 rb->inv_mass = 1.0f/mass;
419
420 v3f extent;
421 v3_sub( rb->bbx[1], rb->bbx[0], extent );
422 v3_muls( extent, 0.5f, extent );
423
424 /* local intertia tensor */
425 float scale = k_inertia_scale;
426 float ex2 = scale*extent[0]*extent[0],
427 ey2 = scale*extent[1]*extent[1],
428 ez2 = scale*extent[2]*extent[2];
429
430 rb->I[0] = ((1.0f/12.0f) * mass * (ey2+ez2));
431 rb->I[1] = ((1.0f/12.0f) * mass * (ex2+ez2));
432 rb->I[2] = ((1.0f/12.0f) * mass * (ex2+ey2));
433
434 m3x3_identity( rb->iI );
435 rb->iI[0][0] = rb->I[0];
436 rb->iI[1][1] = rb->I[1];
437 rb->iI[2][2] = rb->I[2];
438 m3x3_inv( rb->iI, rb->iI );
439 }
440
441 v3_zero( rb->v );
442 v3_zero( rb->w );
443
444 rb_update_transform( rb );
445 }
446
447 VG_STATIC void rb_iter( rigidbody *rb )
448 {
449 if( isnanf( rb->v[0] ) ||
450 isnanf( rb->v[1] ) ||
451 isnanf( rb->v[2] ) )
452 {
453 vg_fatal_exit_loop( "NaN velocity" );
454 }
455
456 v3f gravity = { 0.0f, -9.8f, 0.0f };
457 v3_muladds( rb->v, gravity, k_rb_delta, rb->v );
458
459 /* intergrate velocity */
460 v3_muladds( rb->co, rb->v, k_rb_delta, rb->co );
461 v3_lerp( rb->w, (v3f){0.0f,0.0f,0.0f}, 0.0025f, rb->w );
462
463 /* inegrate inertia */
464 if( v3_length2( rb->w ) > 0.0f )
465 {
466 v4f rotation;
467 v3f axis;
468 v3_copy( rb->w, axis );
469
470 float mag = v3_length( axis );
471 v3_divs( axis, mag, axis );
472 q_axis_angle( rotation, axis, mag*k_rb_delta );
473 q_mul( rotation, rb->q, rb->q );
474 }
475
476 /* damping */
477 v3_muls( rb->v, 1.0f/(1.0f+k_rb_delta*k_damp_linear), rb->v );
478 v3_muls( rb->w, 1.0f/(1.0f+k_rb_delta*k_damp_angular), rb->w );
479 }
480
481
482 /*
483 * -----------------------------------------------------------------------------
484 * Boolean shape overlap functions
485 * -----------------------------------------------------------------------------
486 */
487
488 /*
489 * Project AABB, and triangle interval onto axis to check if they overlap
490 */
491 VG_STATIC int rb_box_triangle_interval( v3f extent, v3f axis, v3f tri[3] )
492 {
493 float
494
495 r = extent[0] * fabsf(axis[0]) +
496 extent[1] * fabsf(axis[1]) +
497 extent[2] * fabsf(axis[2]),
498
499 p0 = v3_dot( axis, tri[0] ),
500 p1 = v3_dot( axis, tri[1] ),
501 p2 = v3_dot( axis, tri[2] ),
502
503 e = vg_maxf(-vg_maxf(p0,vg_maxf(p1,p2)), vg_minf(p0,vg_minf(p1,p2)));
504
505 if( e > r ) return 0;
506 else return 1;
507 }
508
509 /*
510 * Seperating axis test box vs triangle
511 */
512 VG_STATIC int rb_box_triangle_sat( rigidbody *rba, v3f tri_src[3] )
513 {
514 v3f tri[3];
515
516 v3f extent, c;
517 v3_sub( rba->bbx[1], rba->bbx[0], extent );
518 v3_muls( extent, 0.5f, extent );
519 v3_add( rba->bbx[0], extent, c );
520
521 for( int i=0; i<3; i++ )
522 {
523 m4x3_mulv( rba->to_local, tri_src[i], tri[i] );
524 v3_sub( tri[i], c, tri[i] );
525 }
526
527 /* u0, u1, u2 */
528 if(!rb_box_triangle_interval( extent, (v3f){1.0f,0.0f,0.0f}, tri )) return 0;
529 if(!rb_box_triangle_interval( extent, (v3f){0.0f,1.0f,0.0f}, tri )) return 0;
530 if(!rb_box_triangle_interval( extent, (v3f){0.0f,0.0f,1.0f}, tri )) return 0;
531
532 v3f v0,v1,v2,n, e0,e1,e2;
533 v3_sub( tri[1], tri[0], v0 );
534 v3_sub( tri[2], tri[0], v1 );
535 v3_sub( tri[2], tri[1], v2 );
536 v3_normalize( v0 );
537 v3_normalize( v1 );
538 v3_normalize( v2 );
539 v3_cross( v0, v1, n );
540 v3_cross( v0, n, e0 );
541 v3_cross( n, v1, e1 );
542 v3_cross( v2, n, e2 );
543
544 /* normal */
545 if(!rb_box_triangle_interval( extent, n, tri )) return 0;
546
547 v3f axis[9];
548 v3_cross( e0, (v3f){1.0f,0.0f,0.0f}, axis[0] );
549 v3_cross( e0, (v3f){0.0f,1.0f,0.0f}, axis[1] );
550 v3_cross( e0, (v3f){0.0f,0.0f,1.0f}, axis[2] );
551 v3_cross( e1, (v3f){1.0f,0.0f,0.0f}, axis[3] );
552 v3_cross( e1, (v3f){0.0f,1.0f,0.0f}, axis[4] );
553 v3_cross( e1, (v3f){0.0f,0.0f,1.0f}, axis[5] );
554 v3_cross( e2, (v3f){1.0f,0.0f,0.0f}, axis[6] );
555 v3_cross( e2, (v3f){0.0f,1.0f,0.0f}, axis[7] );
556 v3_cross( e2, (v3f){0.0f,0.0f,1.0f}, axis[8] );
557
558 for( int i=0; i<9; i++ )
559 if(!rb_box_triangle_interval( extent, axis[i], tri )) return 0;
560
561 return 1;
562 }
563
564 /*
565 * -----------------------------------------------------------------------------
566 * Manifold
567 * -----------------------------------------------------------------------------
568 */
569
570 VG_STATIC int rb_manifold_apply_filtered( rb_ct *man, int len )
571 {
572 int k = 0;
573
574 for( int i=0; i<len; i++ )
575 {
576 rb_ct *ct = &man[i];
577
578 if( ct->type == k_contact_type_disabled )
579 continue;
580
581 man[k ++] = man[i];
582 }
583
584 return k;
585 }
586
587 VG_STATIC void rb_manifold_filter_joint_edges( rb_ct *man, int len, float r )
588 {
589 for( int i=0; i<len-1; i++ )
590 {
591 rb_ct *ci = &man[i];
592 if( ci->type != k_contact_type_edge )
593 continue;
594
595 for( int j=i+1; j<len; j++ )
596 {
597 rb_ct *cj = &man[j];
598 if( cj->type != k_contact_type_edge )
599 continue;
600
601 if( v3_dist2( ci->co, cj->co ) < r*r )
602 {
603 cj->type = k_contact_type_disabled;
604 ci->p = (ci->p + cj->p) * 0.5f;
605
606 v3_add( ci->co, cj->co, ci->co );
607 v3_muls( ci->co, 0.5f, ci->co );
608
609 v3f delta;
610 v3_sub( ci->rba->co, ci->co, delta );
611
612 float c0 = v3_dot( ci->n, delta ),
613 c1 = v3_dot( cj->n, delta );
614
615 if( c0 < 0.0f || c1 < 0.0f )
616 {
617 /* error */
618 ci->type = k_contact_type_disabled;
619 }
620 else
621 {
622 v3f n;
623 v3_muls( ci->n, c0, n );
624 v3_muladds( n, cj->n, c1, n );
625 v3_normalize( n );
626 v3_copy( n, ci->n );
627 }
628 }
629 }
630 }
631 }
632
633 /*
634 * Resolve overlapping pairs
635 */
636 VG_STATIC void rb_manifold_filter_pairs( rb_ct *man, int len, float r )
637 {
638 for( int i=0; i<len-1; i++ )
639 {
640 rb_ct *ci = &man[i];
641 int similar = 0;
642
643 if( ci->type == k_contact_type_disabled ) continue;
644
645 for( int j=i+1; j<len; j++ )
646 {
647 rb_ct *cj = &man[j];
648
649 if( cj->type == k_contact_type_disabled ) continue;
650
651 if( v3_dist2( ci->co, cj->co ) < r*r )
652 {
653 cj->type = k_contact_type_disabled;
654 v3_add( cj->n, ci->n, ci->n );
655 ci->p += cj->p;
656 similar ++;
657 }
658 }
659
660 if( similar )
661 {
662 float n = 1.0f/((float)similar+1.0f);
663 v3_muls( ci->n, n, ci->n );
664 ci->p *= n;
665
666 if( v3_length2(ci->n) < 0.1f*0.1f )
667 ci->type = k_contact_type_disabled;
668 else
669 v3_normalize( ci->n );
670 }
671 }
672 }
673
674 /*
675 * Remove contacts that are facing away from A
676 */
677 VG_STATIC void rb_manifold_filter_backface( rb_ct *man, int len )
678 {
679 for( int i=0; i<len; i++ )
680 {
681 rb_ct *ct = &man[i];
682 if( ct->type == k_contact_type_disabled )
683 continue;
684
685 v3f delta;
686 v3_sub( ct->co, ct->rba->co, delta );
687
688 if( v3_dot( delta, ct->n ) > -0.001f )
689 ct->type = k_contact_type_disabled;
690 }
691 }
692
693 /*
694 * Filter out duplicate coplanar results. Good for spheres.
695 */
696 VG_STATIC void rb_manifold_filter_coplanar( rb_ct *man, int len, float w )
697 {
698 for( int i=0; i<len; i++ )
699 {
700 rb_ct *ci = &man[i];
701 if( ci->type == k_contact_type_disabled ||
702 ci->type == k_contact_type_edge )
703 continue;
704
705 float d1 = v3_dot( ci->co, ci->n );
706
707 for( int j=0; j<len; j++ )
708 {
709 if( j == i )
710 continue;
711
712 rb_ct *cj = &man[j];
713 if( cj->type == k_contact_type_disabled )
714 continue;
715
716 float d2 = v3_dot( cj->co, ci->n ),
717 d = d2-d1;
718
719 if( fabsf( d ) <= w )
720 {
721 cj->type = k_contact_type_disabled;
722 }
723 }
724 }
725 }
726
727 /*
728 * -----------------------------------------------------------------------------
729 * Collision matrix
730 * -----------------------------------------------------------------------------
731 */
732
733 /*
734 * Contact generators
735 *
736 * These do not automatically allocate contacts, an appropriately sized
737 * buffer must be supplied. The function returns the size of the manifold
738 * which was generated.
739 *
740 * The values set on the contacts are: n, co, p, rba, rbb
741 */
742
743 /*
744 * By collecting the minimum(time) and maximum(time) pairs of points, we
745 * build a reduced and stable exact manifold.
746 *
747 * tx: time at point
748 * rx: minimum distance of these points
749 * dx: the delta between the two points
750 *
751 * pairs will only ammend these if they are creating a collision
752 */
753 typedef struct capsule_manifold capsule_manifold;
754 struct capsule_manifold
755 {
756 float t0, t1;
757 float r0, r1;
758 v3f d0, d1;
759 };
760
761 /*
762 * Expand a line manifold with a new pair. t value is the time along segment
763 * on the oriented object which created this pair.
764 */
765 VG_STATIC void rb_capsule_manifold( v3f pa, v3f pb, float t, float r,
766 capsule_manifold *manifold )
767 {
768 v3f delta;
769 v3_sub( pa, pb, delta );
770
771 if( v3_length2(delta) < r*r )
772 {
773 if( t < manifold->t0 )
774 {
775 v3_copy( delta, manifold->d0 );
776 manifold->t0 = t;
777 manifold->r0 = r;
778 }
779
780 if( t > manifold->t1 )
781 {
782 v3_copy( delta, manifold->d1 );
783 manifold->t1 = t;
784 manifold->r1 = r;
785 }
786 }
787 }
788
789 VG_STATIC void rb_capsule_manifold_init( capsule_manifold *manifold )
790 {
791 manifold->t0 = INFINITY;
792 manifold->t1 = -INFINITY;
793 }
794
795 VG_STATIC int rb_capsule_manifold_done( rigidbody *rba, rigidbody *rbb,
796 capsule_manifold *manifold, rb_ct *buf )
797 {
798 float h = rba->inf.capsule.height,
799 ra = rba->inf.capsule.radius;
800
801 v3f p0, p1;
802 v3_muladds( rba->co, rba->up, -h*0.5f+ra, p0 );
803 v3_muladds( rba->co, rba->up, h*0.5f-ra, p1 );
804
805 int count = 0;
806 if( manifold->t0 <= 1.0f )
807 {
808 rb_ct *ct = buf;
809
810 v3f pa;
811 v3_muls( p0, 1.0f-manifold->t0, pa );
812 v3_muladds( pa, p1, manifold->t0, pa );
813
814 float d = v3_length( manifold->d0 );
815 v3_muls( manifold->d0, 1.0f/d, ct->n );
816 v3_muladds( pa, ct->n, -ra, ct->co );
817
818 ct->p = manifold->r0 - d;
819 ct->rba = rba;
820 ct->rbb = rbb;
821 ct->type = k_contact_type_default;
822
823 count ++;
824 }
825
826 if( (manifold->t1 >= 0.0f) && (manifold->t0 != manifold->t1) )
827 {
828 rb_ct *ct = buf+count;
829
830 v3f pa;
831 v3_muls( p0, 1.0f-manifold->t1, pa );
832 v3_muladds( pa, p1, manifold->t1, pa );
833
834 float d = v3_length( manifold->d1 );
835 v3_muls( manifold->d1, 1.0f/d, ct->n );
836 v3_muladds( pa, ct->n, -ra, ct->co );
837
838 ct->p = manifold->r1 - d;
839 ct->rba = rba;
840 ct->rbb = rbb;
841 ct->type = k_contact_type_default;
842
843 count ++;
844 }
845
846 /*
847 * Debugging
848 */
849
850 if( count == 2 )
851 vg_line( buf[0].co, buf[1].co, 0xff0000ff );
852
853 return count;
854 }
855
856 VG_STATIC int rb_capsule_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf )
857 {
858 float h = rba->inf.capsule.height,
859 ra = rba->inf.capsule.radius,
860 rb = rbb->inf.sphere.radius;
861
862 v3f p0, p1;
863 v3_muladds( rba->co, rba->up, -h*0.5f+ra, p0 );
864 v3_muladds( rba->co, rba->up, h*0.5f-ra, p1 );
865
866 v3f c, delta;
867 closest_point_segment( p0, p1, rbb->co, c );
868 v3_sub( c, rbb->co, delta );
869
870 float d2 = v3_length2(delta),
871 r = ra + rb;
872
873 if( d2 < r*r )
874 {
875 float d = sqrtf(d2);
876
877 rb_ct *ct = buf;
878 v3_muls( delta, 1.0f/d, ct->n );
879 ct->p = r-d;
880
881 v3f p0, p1;
882 v3_muladds( c, ct->n, -ra, p0 );
883 v3_muladds( rbb->co, ct->n, rb, p1 );
884 v3_add( p0, p1, ct->co );
885 v3_muls( ct->co, 0.5f, ct->co );
886
887 ct->rba = rba;
888 ct->rbb = rbb;
889 ct->type = k_contact_type_default;
890
891 return 1;
892 }
893
894 return 0;
895 }
896
897 VG_STATIC int rb_capsule_capsule( rigidbody *rba, rigidbody *rbb, rb_ct *buf )
898 {
899 float ha = rba->inf.capsule.height,
900 hb = rbb->inf.capsule.height,
901 ra = rba->inf.capsule.radius,
902 rb = rbb->inf.capsule.radius,
903 r = ra+rb;
904
905 v3f p0, p1, p2, p3;
906 v3_muladds( rba->co, rba->up, -ha*0.5f+ra, p0 );
907 v3_muladds( rba->co, rba->up, ha*0.5f-ra, p1 );
908 v3_muladds( rbb->co, rbb->up, -hb*0.5f+rb, p2 );
909 v3_muladds( rbb->co, rbb->up, hb*0.5f-rb, p3 );
910
911 capsule_manifold manifold;
912 rb_capsule_manifold_init( &manifold );
913
914 v3f pa, pb;
915 float ta, tb;
916 closest_segment_segment( p0, p1, p2, p3, &ta, &tb, pa, pb );
917 rb_capsule_manifold( pa, pb, ta, r, &manifold );
918
919 ta = closest_point_segment( p0, p1, p2, pa );
920 tb = closest_point_segment( p0, p1, p3, pb );
921 rb_capsule_manifold( pa, p2, ta, r, &manifold );
922 rb_capsule_manifold( pb, p3, tb, r, &manifold );
923
924 closest_point_segment( p2, p3, p0, pa );
925 closest_point_segment( p2, p3, p1, pb );
926 rb_capsule_manifold( p0, pa, 0.0f, r, &manifold );
927 rb_capsule_manifold( p1, pb, 1.0f, r, &manifold );
928
929 return rb_capsule_manifold_done( rba, rbb, &manifold, buf );
930 }
931
932 /*
933 * Generates up to two contacts; optimised for the most stable manifold
934 */
935 VG_STATIC int rb_capsule_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf )
936 {
937 float h = rba->inf.capsule.height,
938 r = rba->inf.capsule.radius;
939
940 /*
941 * Solving this in symetric local space of the cube saves us some time and a
942 * couple branches when it comes to the quad stage.
943 */
944 v3f centroid;
945 v3_add( rbb->bbx[0], rbb->bbx[1], centroid );
946 v3_muls( centroid, 0.5f, centroid );
947
948 boxf bbx;
949 v3_sub( rbb->bbx[0], centroid, bbx[0] );
950 v3_sub( rbb->bbx[1], centroid, bbx[1] );
951
952 v3f pc, p0w, p1w, p0, p1;
953 v3_muladds( rba->co, rba->up, -h*0.5f+r, p0w );
954 v3_muladds( rba->co, rba->up, h*0.5f-r, p1w );
955
956 m4x3_mulv( rbb->to_local, p0w, p0 );
957 m4x3_mulv( rbb->to_local, p1w, p1 );
958 v3_sub( p0, centroid, p0 );
959 v3_sub( p1, centroid, p1 );
960 v3_add( p0, p1, pc );
961 v3_muls( pc, 0.5f, pc );
962
963 /*
964 * Finding an appropriate quad to collide lines with
965 */
966 v3f region;
967 v3_div( pc, bbx[1], region );
968
969 v3f quad[4];
970 if( (fabsf(region[0]) > fabsf(region[1])) &&
971 (fabsf(region[0]) > fabsf(region[2])) )
972 {
973 float px = vg_signf(region[0]) * bbx[1][0];
974 v3_copy( (v3f){ px, bbx[0][1], bbx[0][2] }, quad[0] );
975 v3_copy( (v3f){ px, bbx[1][1], bbx[0][2] }, quad[1] );
976 v3_copy( (v3f){ px, bbx[1][1], bbx[1][2] }, quad[2] );
977 v3_copy( (v3f){ px, bbx[0][1], bbx[1][2] }, quad[3] );
978 }
979 else if( fabsf(region[1]) > fabsf(region[2]) )
980 {
981 float py = vg_signf(region[1]) * bbx[1][1];
982 v3_copy( (v3f){ bbx[0][0], py, bbx[0][2] }, quad[0] );
983 v3_copy( (v3f){ bbx[1][0], py, bbx[0][2] }, quad[1] );
984 v3_copy( (v3f){ bbx[1][0], py, bbx[1][2] }, quad[2] );
985 v3_copy( (v3f){ bbx[0][0], py, bbx[1][2] }, quad[3] );
986 }
987 else
988 {
989 float pz = vg_signf(region[2]) * bbx[1][2];
990 v3_copy( (v3f){ bbx[0][0], bbx[0][1], pz }, quad[0] );
991 v3_copy( (v3f){ bbx[1][0], bbx[0][1], pz }, quad[1] );
992 v3_copy( (v3f){ bbx[1][0], bbx[1][1], pz }, quad[2] );
993 v3_copy( (v3f){ bbx[0][0], bbx[1][1], pz }, quad[3] );
994 }
995
996 capsule_manifold manifold;
997 rb_capsule_manifold_init( &manifold );
998
999 v3f c0, c1;
1000 closest_point_aabb( p0, bbx, c0 );
1001 closest_point_aabb( p1, bbx, c1 );
1002
1003 v3f d0, d1, da;
1004 v3_sub( c0, p0, d0 );
1005 v3_sub( c1, p1, d1 );
1006 v3_sub( p1, p0, da );
1007
1008 v3_normalize(d0);
1009 v3_normalize(d1);
1010 v3_normalize(da);
1011
1012 if( v3_dot( da, d0 ) <= 0.01f )
1013 rb_capsule_manifold( p0, c0, 0.0f, r, &manifold );
1014
1015 if( v3_dot( da, d1 ) >= -0.01f )
1016 rb_capsule_manifold( p1, c1, 1.0f, r, &manifold );
1017
1018 for( int i=0; i<4; i++ )
1019 {
1020 int i0 = i,
1021 i1 = (i+1)%4;
1022
1023 v3f ca, cb;
1024 float ta, tb;
1025 closest_segment_segment( p0, p1, quad[i0], quad[i1], &ta, &tb, ca, cb );
1026 rb_capsule_manifold( ca, cb, ta, r, &manifold );
1027 }
1028
1029 /*
1030 * Create final contacts based on line manifold
1031 */
1032 m3x3_mulv( rbb->to_world, manifold.d0, manifold.d0 );
1033 m3x3_mulv( rbb->to_world, manifold.d1, manifold.d1 );
1034
1035 /*
1036 * Debugging
1037 */
1038
1039 #if 0
1040 for( int i=0; i<4; i++ )
1041 {
1042 v3f q0, q1;
1043 int i0 = i,
1044 i1 = (i+1)%4;
1045
1046 v3_add( quad[i0], centroid, q0 );
1047 v3_add( quad[i1], centroid, q1 );
1048
1049 m4x3_mulv( rbb->to_world, q0, q0 );
1050 m4x3_mulv( rbb->to_world, q1, q1 );
1051
1052 vg_line( q0, q1, 0xffffffff );
1053 }
1054 #endif
1055
1056 return rb_capsule_manifold_done( rba, rbb, &manifold, buf );
1057 }
1058
1059 VG_STATIC int rb_sphere_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf )
1060 {
1061 v3f co, delta;
1062
1063 closest_point_obb( rba->co, rbb->bbx, rbb->to_world, rbb->to_local, co );
1064 v3_sub( rba->co, co, delta );
1065
1066 float d2 = v3_length2(delta),
1067 r = rba->inf.sphere.radius;
1068
1069 if( d2 <= r*r )
1070 {
1071 float d;
1072
1073 rb_ct *ct = buf;
1074 if( d2 <= 0.0001f )
1075 {
1076 v3_sub( rba->co, rbb->co, delta );
1077
1078 /*
1079 * some extra testing is required to find the best axis to push the
1080 * object back outside the box. Since there isnt a clear seperating
1081 * vector already, especially on really high aspect boxes.
1082 */
1083 float lx = v3_dot( rbb->right, delta ),
1084 ly = v3_dot( rbb->up, delta ),
1085 lz = v3_dot( rbb->forward, delta ),
1086 px = rbb->bbx[1][0] - fabsf(lx),
1087 py = rbb->bbx[1][1] - fabsf(ly),
1088 pz = rbb->bbx[1][2] - fabsf(lz);
1089
1090 if( px < py && px < pz )
1091 v3_muls( rbb->right, vg_signf(lx), ct->n );
1092 else if( py < pz )
1093 v3_muls( rbb->up, vg_signf(ly), ct->n );
1094 else
1095 v3_muls( rbb->forward, vg_signf(lz), ct->n );
1096
1097 v3_muladds( rba->co, ct->n, -r, ct->co );
1098 ct->p = r;
1099 }
1100 else
1101 {
1102 d = sqrtf(d2);
1103 v3_muls( delta, 1.0f/d, ct->n );
1104 ct->p = r-d;
1105 v3_copy( co, ct->co );
1106 }
1107
1108 ct->rba = rba;
1109 ct->rbb = rbb;
1110 ct->type = k_contact_type_default;
1111 return 1;
1112 }
1113
1114 return 0;
1115 }
1116
1117 VG_STATIC int rb_sphere_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf )
1118 {
1119 v3f delta;
1120 v3_sub( rba->co, rbb->co, delta );
1121
1122 float d2 = v3_length2(delta),
1123 r = rba->inf.sphere.radius + rbb->inf.sphere.radius;
1124
1125 if( d2 < r*r )
1126 {
1127 float d = sqrtf(d2);
1128
1129 rb_ct *ct = buf;
1130 v3_muls( delta, 1.0f/d, ct->n );
1131
1132 v3f p0, p1;
1133 v3_muladds( rba->co, ct->n,-rba->inf.sphere.radius, p0 );
1134 v3_muladds( rbb->co, ct->n, rbb->inf.sphere.radius, p1 );
1135 v3_add( p0, p1, ct->co );
1136 v3_muls( ct->co, 0.5f, ct->co );
1137 ct->type = k_contact_type_default;
1138 ct->p = r-d;
1139 ct->rba = rba;
1140 ct->rbb = rbb;
1141 return 1;
1142 }
1143
1144 return 0;
1145 }
1146
1147 //#define RIGIDBODY_DYNAMIC_MESH_EDGES
1148
1149 VG_STATIC int rb_sphere_triangle( rigidbody *rba, rigidbody *rbb,
1150 v3f tri[3], rb_ct *buf )
1151 {
1152 v3f delta, co;
1153
1154 #ifdef RIGIDBODY_DYNAMIC_MESH_EDGES
1155 closest_on_triangle_1( rba->co, tri, co );
1156 #else
1157 enum contact_type type = closest_on_triangle_1( rba->co, tri, co );
1158 #endif
1159
1160 v3_sub( rba->co, co, delta );
1161
1162 float d2 = v3_length2( delta ),
1163 r = rba->inf.sphere.radius;
1164
1165 if( d2 < r*r )
1166 {
1167 rb_ct *ct = buf;
1168
1169 v3f ab, ac, tn;
1170 v3_sub( tri[2], tri[0], ab );
1171 v3_sub( tri[1], tri[0], ac );
1172 v3_cross( ac, ab, tn );
1173 v3_copy( tn, ct->n );
1174 v3_normalize( ct->n );
1175
1176 float d = sqrtf(d2);
1177
1178 v3_copy( co, ct->co );
1179 ct->type = type;
1180 ct->p = r-d;
1181 ct->rba = rba;
1182 ct->rbb = rbb;
1183 return 1;
1184 }
1185
1186 return 0;
1187 }
1188
1189
1190 VG_STATIC void rb_debug_sharp_scene_edges( rigidbody *rbb, float sharp_ang,
1191 boxf box, u32 colour )
1192 {
1193 sharp_ang = cosf( sharp_ang );
1194
1195 scene *sc = rbb->inf.scene.bh_scene->user;
1196 vg_line_boxf( box, 0xff00ff00 );
1197
1198 bh_iter it;
1199 bh_iter_init( 0, &it );
1200 int idx;
1201
1202 while( bh_next( rbb->inf.scene.bh_scene, &it, box, &idx ) )
1203 {
1204 u32 *ptri = &sc->arrindices[ idx*3 ];
1205 v3f tri[3];
1206
1207 for( int j=0; j<3; j++ )
1208 v3_copy( sc->arrvertices[ptri[j]].co, tri[j] );
1209
1210 for( int j=0; j<3; j++ )
1211 {
1212 #if 0
1213 v3f edir;
1214 v3_sub( tri[(j+1)%3], tri[j], edir );
1215
1216 if( v3_dot( edir, (v3f){ 0.5184758473652127f,
1217 0.2073903389460850f,
1218 -0.8295613557843402f } ) < 0.0f )
1219 continue;
1220 #endif
1221
1222 bh_iter jt;
1223 bh_iter_init( 0, &jt );
1224
1225 boxf region;
1226 float const k_r = 0.02f;
1227 v3_add( (v3f){ k_r, k_r, k_r }, tri[j], region[1] );
1228 v3_add( (v3f){ -k_r, -k_r, -k_r }, tri[j], region[0] );
1229
1230 int jdx;
1231 while( bh_next( rbb->inf.scene.bh_scene, &jt, region, &jdx ) )
1232 {
1233 if( idx <= jdx )
1234 continue;
1235
1236 u32 *ptrj = &sc->arrindices[ jdx*3 ];
1237 v3f trj[3];
1238
1239 for( int k=0; k<3; k++ )
1240 v3_copy( sc->arrvertices[ptrj[k]].co, trj[k] );
1241
1242 for( int k=0; k<3; k++ )
1243 {
1244 if( v3_dist2( tri[j], trj[k] ) <= k_r*k_r )
1245 {
1246 int jp1 = (j+1)%3,
1247 jp2 = (j+2)%3,
1248 km1 = (k+3-1)%3,
1249 km2 = (k+3-2)%3;
1250
1251 if( v3_dist2( tri[jp1], trj[km1] ) <= k_r*k_r )
1252 {
1253 v3f b0, b1, b2;
1254 v3_sub( tri[jp1], tri[j], b0 );
1255 v3_sub( tri[jp2], tri[j], b1 );
1256 v3_sub( trj[km2], tri[j], b2 );
1257
1258 v3f cx0, cx1;
1259 v3_cross( b0, b1, cx0 );
1260 v3_cross( b2, b0, cx1 );
1261
1262 float polarity = v3_dot( cx0, b2 );
1263
1264 if( polarity < 0.0f )
1265 {
1266 #if 0
1267 vg_line( tri[j], tri[jp1], 0xff00ff00 );
1268 float ang = v3_dot(cx0,cx1) /
1269 (v3_length(cx0)*v3_length(cx1));
1270 if( ang < sharp_ang )
1271 {
1272 vg_line( tri[j], tri[jp1], 0xff00ff00 );
1273 }
1274 #endif
1275 }
1276 }
1277 }
1278 }
1279 }
1280 }
1281 }
1282 }
1283
1284 VG_STATIC int rb_sphere_scene( rigidbody *rba, rigidbody *rbb, rb_ct *buf )
1285 {
1286 scene *sc = rbb->inf.scene.bh_scene->user;
1287
1288 bh_iter it;
1289 bh_iter_init( 0, &it );
1290 int idx;
1291
1292 int count = 0;
1293
1294 while( bh_next( rbb->inf.scene.bh_scene, &it, rba->bbx_world, &idx ) )
1295 {
1296 u32 *ptri = &sc->arrindices[ idx*3 ];
1297 v3f tri[3];
1298
1299 for( int j=0; j<3; j++ )
1300 v3_copy( sc->arrvertices[ptri[j]].co, tri[j] );
1301
1302 buf[ count ].element_id = ptri[0];
1303
1304 vg_line( tri[0],tri[1],0x70ff6000 );
1305 vg_line( tri[1],tri[2],0x70ff6000 );
1306 vg_line( tri[2],tri[0],0x70ff6000 );
1307
1308 int contact = rb_sphere_triangle( rba, rbb, tri, buf+count );
1309 count += contact;
1310
1311 if( count == 16 )
1312 {
1313 vg_warn( "Exceeding sphere_vs_scene capacity. Geometry too dense!\n" );
1314 return count;
1315 }
1316 }
1317
1318 return count;
1319 }
1320
1321 VG_STATIC int rb_box_scene( rigidbody *rba, rigidbody *rbb, rb_ct *buf )
1322 {
1323 scene *sc = rbb->inf.scene.bh_scene->user;
1324
1325 v3f tri[3];
1326
1327 bh_iter it;
1328 bh_iter_init( 0, &it );
1329 int idx;
1330
1331 int count = 0;
1332
1333 while( bh_next( rbb->inf.scene.bh_scene, &it, rba->bbx_world, &idx ) )
1334 {
1335 u32 *ptri = &sc->arrindices[ idx*3 ];
1336
1337 for( int j=0; j<3; j++ )
1338 v3_copy( sc->arrvertices[ptri[j]].co, tri[j] );
1339
1340 if( rb_box_triangle_sat( rba, tri ) )
1341 {
1342 vg_line(tri[0],tri[1],0xff50ff00 );
1343 vg_line(tri[1],tri[2],0xff50ff00 );
1344 vg_line(tri[2],tri[0],0xff50ff00 );
1345 }
1346 else
1347 {
1348 vg_line(tri[0],tri[1],0xff0000ff );
1349 vg_line(tri[1],tri[2],0xff0000ff );
1350 vg_line(tri[2],tri[0],0xff0000ff );
1351
1352 continue;
1353 }
1354
1355 v3f v0,v1,n;
1356 v3_sub( tri[1], tri[0], v0 );
1357 v3_sub( tri[2], tri[0], v1 );
1358 v3_cross( v0, v1, n );
1359 v3_normalize( n );
1360
1361 /* find best feature */
1362 float best = v3_dot( rba->right, n );
1363 int axis = 0;
1364
1365 float cy = v3_dot( rba->up, n );
1366 if( fabsf(cy) > fabsf(best) )
1367 {
1368 best = cy;
1369 axis = 1;
1370 }
1371
1372 float cz = -v3_dot( rba->forward, n );
1373 if( fabsf(cz) > fabsf(best) )
1374 {
1375 best = cz;
1376 axis = 2;
1377 }
1378
1379 v3f manifold[4];
1380
1381 if( axis == 0 )
1382 {
1383 float px = best > 0.0f? rba->bbx[0][0]: rba->bbx[1][0];
1384 manifold[0][0] = px;
1385 manifold[0][1] = rba->bbx[0][1];
1386 manifold[0][2] = rba->bbx[0][2];
1387 manifold[1][0] = px;
1388 manifold[1][1] = rba->bbx[1][1];
1389 manifold[1][2] = rba->bbx[0][2];
1390 manifold[2][0] = px;
1391 manifold[2][1] = rba->bbx[1][1];
1392 manifold[2][2] = rba->bbx[1][2];
1393 manifold[3][0] = px;
1394 manifold[3][1] = rba->bbx[0][1];
1395 manifold[3][2] = rba->bbx[1][2];
1396 }
1397 else if( axis == 1 )
1398 {
1399 float py = best > 0.0f? rba->bbx[0][1]: rba->bbx[1][1];
1400 manifold[0][0] = rba->bbx[0][0];
1401 manifold[0][1] = py;
1402 manifold[0][2] = rba->bbx[0][2];
1403 manifold[1][0] = rba->bbx[1][0];
1404 manifold[1][1] = py;
1405 manifold[1][2] = rba->bbx[0][2];
1406 manifold[2][0] = rba->bbx[1][0];
1407 manifold[2][1] = py;
1408 manifold[2][2] = rba->bbx[1][2];
1409 manifold[3][0] = rba->bbx[0][0];
1410 manifold[3][1] = py;
1411 manifold[3][2] = rba->bbx[1][2];
1412 }
1413 else
1414 {
1415 float pz = best > 0.0f? rba->bbx[0][2]: rba->bbx[1][2];
1416 manifold[0][0] = rba->bbx[0][0];
1417 manifold[0][1] = rba->bbx[0][1];
1418 manifold[0][2] = pz;
1419 manifold[1][0] = rba->bbx[1][0];
1420 manifold[1][1] = rba->bbx[0][1];
1421 manifold[1][2] = pz;
1422 manifold[2][0] = rba->bbx[1][0];
1423 manifold[2][1] = rba->bbx[1][1];
1424 manifold[2][2] = pz;
1425 manifold[3][0] = rba->bbx[0][0];
1426 manifold[3][1] = rba->bbx[1][1];
1427 manifold[3][2] = pz;
1428 }
1429
1430 for( int j=0; j<4; j++ )
1431 m4x3_mulv( rba->to_world, manifold[j], manifold[j] );
1432
1433 vg_line( manifold[0], manifold[1], 0xffffffff );
1434 vg_line( manifold[1], manifold[2], 0xffffffff );
1435 vg_line( manifold[2], manifold[3], 0xffffffff );
1436 vg_line( manifold[3], manifold[0], 0xffffffff );
1437
1438 for( int j=0; j<4; j++ )
1439 {
1440 rb_ct *ct = buf+count;
1441
1442 v3_copy( manifold[j], ct->co );
1443 v3_copy( n, ct->n );
1444
1445 float l0 = v3_dot( tri[0], n ),
1446 l1 = v3_dot( manifold[j], n );
1447
1448 ct->p = (l0-l1)*0.5f;
1449 if( ct->p < 0.0f )
1450 continue;
1451
1452 ct->type = k_contact_type_default;
1453 ct->rba = rba;
1454 ct->rbb = rbb;
1455 count ++;
1456
1457 if( count >= 12 )
1458 return count;
1459 }
1460 }
1461 return count;
1462 }
1463
1464 VG_STATIC int RB_MATRIX_ERROR( rigidbody *rba, rigidbody *rbb, rb_ct *buf )
1465 {
1466 vg_error( "Collision type is unimplemented between types %d and %d\n",
1467 rba->type, rbb->type );
1468
1469 return 0;
1470 }
1471
1472 VG_STATIC int rb_sphere_capsule( rigidbody *rba, rigidbody *rbb, rb_ct *buf )
1473 {
1474 return rb_capsule_sphere( rbb, rba, buf );
1475 }
1476
1477 VG_STATIC int rb_box_capsule( rigidbody *rba, rigidbody *rbb, rb_ct *buf )
1478 {
1479 return rb_capsule_box( rbb, rba, buf );
1480 }
1481
1482 VG_STATIC int rb_box_sphere( rigidbody *rba, rigidbody *rbb, rb_ct *buf )
1483 {
1484 return rb_sphere_box( rbb, rba, buf );
1485 }
1486
1487 VG_STATIC int rb_scene_box( rigidbody *rba, rigidbody *rbb, rb_ct *buf )
1488 {
1489 return rb_box_scene( rbb, rba, buf );
1490 }
1491
1492 VG_STATIC int (*rb_jump_table[4][4])( rigidbody *a, rigidbody *b, rb_ct *buf ) =
1493 {
1494 /* box */ /* Sphere */ /* Capsule */ /* Mesh */
1495 { RB_MATRIX_ERROR, rb_box_sphere, rb_box_capsule, rb_box_scene },
1496 { rb_sphere_box, rb_sphere_sphere, rb_sphere_capsule, rb_sphere_scene },
1497 { rb_capsule_box, rb_capsule_sphere, rb_capsule_capsule, RB_MATRIX_ERROR },
1498 { rb_scene_box, RB_MATRIX_ERROR, RB_MATRIX_ERROR, RB_MATRIX_ERROR }
1499 };
1500
1501 VG_STATIC int rb_collide( rigidbody *rba, rigidbody *rbb )
1502 {
1503 int (*collider_jump)(rigidbody *rba, rigidbody *rbb, rb_ct *buf )
1504 = rb_jump_table[rba->type][rbb->type];
1505
1506 /*
1507 * 12 is the maximum manifold size we can generate, so we are forced to abort
1508 * potentially checking any more.
1509 */
1510 if( rb_contact_count + 12 > vg_list_size(rb_contact_buffer) )
1511 {
1512 vg_warn( "Too many contacts made in global collider buffer (%d of %d\n)",
1513 rb_contact_count, vg_list_size(rb_contact_buffer) );
1514 return 0;
1515 }
1516
1517 /*
1518 * FUTURE: Replace this with a more dedicated broad phase pass
1519 */
1520 if( box_overlap( rba->bbx_world, rbb->bbx_world ) )
1521 {
1522 int count = collider_jump( rba, rbb, rb_contact_buffer+rb_contact_count);
1523 rb_contact_count += count;
1524 return count;
1525 }
1526 else
1527 return 0;
1528 }
1529
1530 /*
1531 * -----------------------------------------------------------------------------
1532 * Dynamics
1533 * -----------------------------------------------------------------------------
1534 */
1535
1536 VG_STATIC void rb_solver_reset(void)
1537 {
1538 rb_contact_count = 0;
1539 }
1540
1541 VG_STATIC rb_ct *rb_global_ct(void)
1542 {
1543 return rb_contact_buffer + rb_contact_count;
1544 }
1545
1546 /*
1547 * Initializing things like tangent vectors
1548 */
1549 VG_STATIC void rb_presolve_contacts( rb_ct *buffer, int len )
1550 {
1551 for( int i=0; i<len; i++ )
1552 {
1553 rb_ct *ct = &buffer[i];
1554
1555 ct->bias = -0.2f * k_rb_rate * vg_minf( 0.0f, -ct->p+k_penetration_slop );
1556 rb_tangent_basis( ct->n, ct->t[0], ct->t[1] );
1557
1558 #if 0
1559 ct->type = k_contact_type_default;
1560 #endif
1561 ct->norm_impulse = 0.0f;
1562 ct->tangent_impulse[0] = 0.0f;
1563 ct->tangent_impulse[1] = 0.0f;
1564
1565 v3f ra, rb, raCn, rbCn, raCt, rbCt;
1566 v3_sub( ct->co, ct->rba->co, ra );
1567 v3_sub( ct->co, ct->rbb->co, rb );
1568 v3_cross( ra, ct->n, raCn );
1569 v3_cross( rb, ct->n, rbCn );
1570
1571 /* orient inverse inertia tensors */
1572 v3f raCnI, rbCnI;
1573 m3x3_mulv( ct->rba->iIw, raCn, raCnI );
1574 m3x3_mulv( ct->rbb->iIw, rbCn, rbCnI );
1575
1576 ct->normal_mass = ct->rba->inv_mass + ct->rbb->inv_mass;
1577 ct->normal_mass += v3_dot( raCn, raCnI );
1578 ct->normal_mass += v3_dot( rbCn, rbCnI );
1579 ct->normal_mass = 1.0f/ct->normal_mass;
1580
1581 for( int j=0; j<2; j++ )
1582 {
1583 v3f raCtI, rbCtI;
1584 v3_cross( ct->t[j], ra, raCt );
1585 v3_cross( ct->t[j], rb, rbCt );
1586 m3x3_mulv( ct->rba->iIw, raCt, raCtI );
1587 m3x3_mulv( ct->rbb->iIw, rbCt, rbCtI );
1588
1589 ct->tangent_mass[j] = ct->rba->inv_mass + ct->rbb->inv_mass;
1590 ct->tangent_mass[j] += v3_dot( raCt, raCtI );
1591 ct->tangent_mass[j] += v3_dot( rbCt, rbCtI );
1592 ct->tangent_mass[j] = 1.0f/ct->tangent_mass[j];
1593 }
1594
1595 rb_debug_contact( ct );
1596 }
1597 }
1598
1599 /*
1600 * Creates relative contact velocity vector, and offsets between each body
1601 */
1602 VG_STATIC void rb_rcv( rb_ct *ct, v3f rv, v3f da, v3f db )
1603 {
1604 rigidbody *rba = ct->rba,
1605 *rbb = ct->rbb;
1606
1607 v3_sub( ct->co, rba->co, da );
1608 v3_sub( ct->co, rbb->co, db );
1609
1610 v3f rva, rvb;
1611 v3_cross( rba->w, da, rva );
1612 v3_add( rba->v, rva, rva );
1613 v3_cross( rbb->w, db, rvb );
1614 v3_add( rbb->v, rvb, rvb );
1615
1616 v3_sub( rva, rvb, rv );
1617 }
1618
1619 /*
1620 * Apply impulse to object
1621 */
1622 VG_STATIC void rb_linear_impulse( rigidbody *rb, v3f delta, v3f impulse )
1623 {
1624 /* linear */
1625 v3_muladds( rb->v, impulse, rb->inv_mass, rb->v );
1626
1627 /* Angular velocity */
1628 v3f wa;
1629 v3_cross( delta, impulse, wa );
1630
1631 m3x3_mulv( rb->iIw, wa, wa );
1632 v3_add( rb->w, wa, rb->w );
1633 }
1634
1635 /*
1636 * One iteration to solve the contact constraint
1637 */
1638 VG_STATIC void rb_solve_contacts( rb_ct *buf, int len )
1639 {
1640 for( int i=0; i<len; i++ )
1641 {
1642 struct contact *ct = &buf[i];
1643
1644 rigidbody *rb = ct->rba;
1645
1646 v3f rv, da, db;
1647 rb_rcv( ct, rv, da, db );
1648
1649 /* Friction */
1650 for( int j=0; j<2; j++ )
1651 {
1652 float f = k_friction * ct->norm_impulse,
1653 vt = v3_dot( rv, ct->t[j] ),
1654 lambda = ct->tangent_mass[j] * -vt;
1655
1656 float temp = ct->tangent_impulse[j];
1657 ct->tangent_impulse[j] = vg_clampf( temp + lambda, -f, f );
1658 lambda = ct->tangent_impulse[j] - temp;
1659
1660 v3f impulse;
1661 v3_muls( ct->t[j], lambda, impulse );
1662 rb_linear_impulse( ct->rba, da, impulse );
1663
1664 v3_muls( ct->t[j], -lambda, impulse );
1665 rb_linear_impulse( ct->rbb, db, impulse );
1666 }
1667
1668 /* Normal */
1669 rb_rcv( ct, rv, da, db );
1670 float vn = v3_dot( rv, ct->n ),
1671 lambda = ct->normal_mass * (-vn + ct->bias);
1672
1673 float temp = ct->norm_impulse;
1674 ct->norm_impulse = vg_maxf( temp + lambda, 0.0f );
1675 lambda = ct->norm_impulse - temp;
1676
1677 v3f impulse;
1678 v3_muls( ct->n, lambda, impulse );
1679 rb_linear_impulse( ct->rba, da, impulse );
1680
1681 v3_muls( ct->n, -lambda, impulse );
1682 rb_linear_impulse( ct->rbb, db, impulse );
1683 }
1684 }
1685
1686 /*
1687 * -----------------------------------------------------------------------------
1688 * Constraints
1689 * -----------------------------------------------------------------------------
1690 */
1691
1692 VG_STATIC void draw_angle_limit( v3f c, v3f major, v3f minor,
1693 float amin, float amax, float measured,
1694 u32 colour )
1695 {
1696 float f = 0.05f;
1697 v3f ay, ax;
1698 v3_muls( major, f, ay );
1699 v3_muls( minor, f, ax );
1700
1701 for( int x=0; x<16; x++ )
1702 {
1703 float t0 = (float)x / 16.0f,
1704 t1 = (float)(x+1) / 16.0f,
1705 a0 = vg_lerpf( amin, amax, t0 ),
1706 a1 = vg_lerpf( amin, amax, t1 );
1707
1708 v3f p0, p1;
1709 v3_muladds( c, ay, cosf(a0), p0 );
1710 v3_muladds( p0, ax, sinf(a0), p0 );
1711 v3_muladds( c, ay, cosf(a1), p1 );
1712 v3_muladds( p1, ax, sinf(a1), p1 );
1713
1714 vg_line( p0, p1, colour );
1715
1716 if( x == 0 )
1717 vg_line( c, p0, colour );
1718 if( x == 15 )
1719 vg_line( c, p1, colour );
1720 }
1721
1722 v3f p2;
1723 v3_muladds( c, ay, cosf(measured)*1.2f, p2 );
1724 v3_muladds( p2, ax, sinf(measured)*1.2f, p2 );
1725 vg_line( c, p2, colour );
1726 }
1727
1728 VG_STATIC void rb_debug_constraint_limits( rigidbody *ra, rigidbody *rb, v3f lca,
1729 v3f limits[2] )
1730 {
1731 v3f ax, ay, az, bx, by, bz;
1732 m3x3_mulv( ra->to_world, (v3f){1.0f,0.0f,0.0f}, ax );
1733 m3x3_mulv( ra->to_world, (v3f){0.0f,1.0f,0.0f}, ay );
1734 m3x3_mulv( ra->to_world, (v3f){0.0f,0.0f,1.0f}, az );
1735 m3x3_mulv( rb->to_world, (v3f){1.0f,0.0f,0.0f}, bx );
1736 m3x3_mulv( rb->to_world, (v3f){0.0f,1.0f,0.0f}, by );
1737 m3x3_mulv( rb->to_world, (v3f){0.0f,0.0f,1.0f}, bz );
1738
1739 v2f px, py, pz;
1740 px[0] = v3_dot( ay, by );
1741 px[1] = v3_dot( az, by );
1742
1743 py[0] = v3_dot( az, bz );
1744 py[1] = v3_dot( ax, bz );
1745
1746 pz[0] = v3_dot( ax, bx );
1747 pz[1] = v3_dot( ay, bx );
1748
1749 float r0 = atan2f( px[1], px[0] ),
1750 r1 = atan2f( py[1], py[0] ),
1751 r2 = atan2f( pz[1], pz[0] );
1752
1753 v3f c;
1754 m4x3_mulv( ra->to_world, lca, c );
1755 draw_angle_limit( c, ay, az, limits[0][0], limits[1][0], r0, 0xff0000ff );
1756 draw_angle_limit( c, az, ax, limits[0][1], limits[1][1], r1, 0xff00ff00 );
1757 draw_angle_limit( c, ax, ay, limits[0][2], limits[1][2], r2, 0xffff0000 );
1758 }
1759
1760 VG_STATIC void rb_limit_cure( rigidbody *ra, rigidbody *rb, v3f axis, float d )
1761 {
1762 if( d != 0.0f )
1763 {
1764 float avx = v3_dot( ra->w, axis ) - v3_dot( rb->w, axis );
1765 float joint_mass = rb->inv_mass + ra->inv_mass;
1766 joint_mass = 1.0f/joint_mass;
1767
1768 float bias = (k_limit_bias * k_rb_rate) * d,
1769 lambda = -(avx + bias) * joint_mass;
1770
1771 /* Angular velocity */
1772 v3f wa, wb;
1773 v3_muls( axis, lambda * ra->inv_mass, wa );
1774 v3_muls( axis, -lambda * rb->inv_mass, wb );
1775
1776 v3_add( ra->w, wa, ra->w );
1777 v3_add( rb->w, wb, rb->w );
1778 }
1779 }
1780
1781 VG_STATIC void rb_constraint_limits( rigidbody *ra, v3f lca,
1782 rigidbody *rb, v3f lcb, v3f limits[2] )
1783 {
1784 v3f ax, ay, az, bx, by, bz;
1785 m3x3_mulv( ra->to_world, (v3f){1.0f,0.0f,0.0f}, ax );
1786 m3x3_mulv( ra->to_world, (v3f){0.0f,1.0f,0.0f}, ay );
1787 m3x3_mulv( ra->to_world, (v3f){0.0f,0.0f,1.0f}, az );
1788 m3x3_mulv( rb->to_world, (v3f){1.0f,0.0f,0.0f}, bx );
1789 m3x3_mulv( rb->to_world, (v3f){0.0f,1.0f,0.0f}, by );
1790 m3x3_mulv( rb->to_world, (v3f){0.0f,0.0f,1.0f}, bz );
1791
1792 v2f px, py, pz;
1793 px[0] = v3_dot( ay, by );
1794 px[1] = v3_dot( az, by );
1795
1796 py[0] = v3_dot( az, bz );
1797 py[1] = v3_dot( ax, bz );
1798
1799 pz[0] = v3_dot( ax, bx );
1800 pz[1] = v3_dot( ay, bx );
1801
1802 float r0 = atan2f( px[1], px[0] ),
1803 r1 = atan2f( py[1], py[0] ),
1804 r2 = atan2f( pz[1], pz[0] );
1805
1806 /* calculate angle deltas */
1807 float dx = 0.0f, dy = 0.0f, dz = 0.0f;
1808
1809 if( r0 < limits[0][0] ) dx = limits[0][0] - r0;
1810 if( r0 > limits[1][0] ) dx = limits[1][0] - r0;
1811 if( r1 < limits[0][1] ) dy = limits[0][1] - r1;
1812 if( r1 > limits[1][1] ) dy = limits[1][1] - r1;
1813 if( r2 < limits[0][2] ) dz = limits[0][2] - r2;
1814 if( r2 > limits[1][2] ) dz = limits[1][2] - r2;
1815
1816 v3f wca, wcb;
1817 m3x3_mulv( ra->to_world, lca, wca );
1818 m3x3_mulv( rb->to_world, lcb, wcb );
1819
1820 rb_limit_cure( ra, rb, ax, dx );
1821 rb_limit_cure( ra, rb, ay, dy );
1822 rb_limit_cure( ra, rb, az, dz );
1823 }
1824
1825 VG_STATIC void rb_debug_constraint_position( rigidbody *ra, v3f lca,
1826 rigidbody *rb, v3f lcb )
1827 {
1828 v3f wca, wcb;
1829 m3x3_mulv( ra->to_world, lca, wca );
1830 m3x3_mulv( rb->to_world, lcb, wcb );
1831
1832 v3f p0, p1;
1833 v3_add( wca, ra->co, p0 );
1834 v3_add( wcb, rb->co, p1 );
1835 vg_line_pt3( p0, 0.005f, 0xffffff00 );
1836 vg_line_pt3( p1, 0.005f, 0xffffff00 );
1837 vg_line( p0, p1, 0xffffff00 );
1838 }
1839
1840 VG_STATIC void rb_constraint_position( rigidbody *ra, v3f lca,
1841 rigidbody *rb, v3f lcb )
1842 {
1843 /* C = (COa + Ra*LCa) - (COb + Rb*LCb) = 0 */
1844 v3f wca, wcb;
1845 m3x3_mulv( ra->to_world, lca, wca );
1846 m3x3_mulv( rb->to_world, lcb, wcb );
1847
1848 v3f rcv;
1849 v3_sub( ra->v, rb->v, rcv );
1850
1851 v3f rcv_Ra, rcv_Rb;
1852 v3_cross( ra->w, wca, rcv_Ra );
1853 v3_cross( rb->w, wcb, rcv_Rb );
1854 v3_add( rcv_Ra, rcv, rcv );
1855 v3_sub( rcv, rcv_Rb, rcv );
1856
1857 v3f delta;
1858 v3f p0, p1;
1859 v3_add( wca, ra->co, p0 );
1860 v3_add( wcb, rb->co, p1 );
1861 v3_sub( p1, p0, delta );
1862
1863 float dist2 = v3_length2( delta );
1864
1865 if( dist2 > 0.00001f )
1866 {
1867 float dist = sqrtf(dist2);
1868 v3_muls( delta, 1.0f/dist, delta );
1869
1870 float joint_mass = rb->inv_mass + ra->inv_mass;
1871
1872 v3f raCn, rbCn, raCt, rbCt;
1873 v3_cross( wca, delta, raCn );
1874 v3_cross( wcb, delta, rbCn );
1875
1876 /* orient inverse inertia tensors */
1877 v3f raCnI, rbCnI;
1878 m3x3_mulv( ra->iIw, raCn, raCnI );
1879 m3x3_mulv( rb->iIw, rbCn, rbCnI );
1880 joint_mass += v3_dot( raCn, raCnI );
1881 joint_mass += v3_dot( rbCn, rbCnI );
1882 joint_mass = 1.0f/joint_mass;
1883
1884 float vd = v3_dot( rcv, delta ),
1885 bias = -(k_joint_bias * k_rb_rate) * dist,
1886 lambda = -(vd + bias) * joint_mass;
1887
1888 v3f impulse;
1889 v3_muls( delta, lambda, impulse );
1890 rb_linear_impulse( ra, wca, impulse );
1891 v3_muls( delta, -lambda, impulse );
1892 rb_linear_impulse( rb, wcb, impulse );
1893
1894 /* 'fake' snap */
1895 v3_muladds( ra->co, delta, dist * k_joint_correction, ra->co );
1896 v3_muladds( rb->co, delta, -dist * k_joint_correction, rb->co );
1897 }
1898 }
1899
1900 /*
1901 * Effectors
1902 */
1903
1904 VG_STATIC void rb_effect_simple_bouyency( rigidbody *ra, v4f plane,
1905 float amt, float drag )
1906 {
1907 /* float */
1908 float depth = v3_dot( plane, ra->co ) - plane[3],
1909 lambda = vg_clampf( -depth, 0.0f, 1.0f ) * amt;
1910
1911 v3_muladds( ra->v, plane, lambda * k_rb_delta, ra->v );
1912
1913 if( depth < 0.0f )
1914 v3_muls( ra->v, 1.0f-(drag*k_rb_delta), ra->v );
1915 }
1916
1917 /*
1918 * -----------------------------------------------------------------------------
1919 * BVH implementation, this is ONLY for VG_STATIC rigidbodies, its to slow for
1920 * realtime use.
1921 * -----------------------------------------------------------------------------
1922 */
1923
1924 VG_STATIC void rb_bh_expand_bound( void *user, boxf bound, u32 item_index )
1925 {
1926 rigidbody *rb = &((rigidbody *)user)[ item_index ];
1927 box_concat( bound, rb->bbx_world );
1928 }
1929
1930 VG_STATIC float rb_bh_centroid( void *user, u32 item_index, int axis )
1931 {
1932 rigidbody *rb = &((rigidbody *)user)[ item_index ];
1933 return (rb->bbx_world[axis][0] + rb->bbx_world[1][axis]) * 0.5f;
1934 }
1935
1936 VG_STATIC void rb_bh_swap( void *user, u32 ia, u32 ib )
1937 {
1938 rigidbody temp, *rba, *rbb;
1939 rba = &((rigidbody *)user)[ ia ];
1940 rbb = &((rigidbody *)user)[ ib ];
1941
1942 temp = *rba;
1943 *rba = *rbb;
1944 *rbb = temp;
1945 }
1946
1947 VG_STATIC void rb_bh_debug( void *user, u32 item_index )
1948 {
1949 rigidbody *rb = &((rigidbody *)user)[ item_index ];
1950 rb_debug( rb, 0xff00ffff );
1951 }
1952
1953 VG_STATIC bh_system bh_system_rigidbodies =
1954 {
1955 .expand_bound = rb_bh_expand_bound,
1956 .item_centroid = rb_bh_centroid,
1957 .item_swap = rb_bh_swap,
1958 .item_debug = rb_bh_debug,
1959 .cast_ray = NULL
1960 };
1961
1962 #endif /* RIGIDBODY_H */