update vg
[carveJwlIkooP6JGAAIwe30JlM.git] / player_ragdoll.h
index 3fd552471001449920d1fe49d589f5add73352d9..d6607ae89331a9ef7ec2883e37099f7665043f73 100644 (file)
@@ -7,11 +7,10 @@
 #include "rigidbody.h"
 #include "player_model.h"
 #include "world.h"
+#include "audio.h"
 
-struct player_ragdoll
-{
-   struct ragdoll_part
-   {
+struct player_ragdoll{
+   struct ragdoll_part{
       u32 bone_id;
       
       /* Collider transform relative to bone */
@@ -21,7 +20,7 @@ struct player_ragdoll
       u32 use_limits;
       v3f limits[2];
 
-      rigidbody  rb;
+      rb_object obj;
       u32 parent;
       u32 colour;
    }
@@ -37,6 +36,23 @@ struct player_ragdoll
    int shoes[2];
 };
 
+VG_STATIC float k_ragdoll_floatyiness = 20.0f,
+                k_ragdoll_floatydrag  = 1.0f,
+                k_ragdoll_limit_scale = 1.0f;
+
+VG_STATIC int   k_ragdoll_div = 1,
+                ragdoll_frame = 0,
+                k_ragdoll_debug_collider = 1,
+                k_ragdoll_debug_constraints = 0;
+
+VG_STATIC void player_ragdoll_init(void)
+{
+   VG_VAR_F32( k_ragdoll_limit_scale );
+   VG_VAR_I32( k_ragdoll_div );
+   VG_VAR_I32( k_ragdoll_debug_collider );
+   VG_VAR_I32( k_ragdoll_debug_constraints );
+}
+
 VG_STATIC void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
                                                   struct ragdoll_part *rp )
 {
@@ -48,11 +64,11 @@ VG_STATIC void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
       v3_muls( delta, 0.5f, delta );
       v3_add( bone->hitbox[0], delta, rp->collider_mtx[3] );
 
-      v3_copy( delta, rp->rb.bbx[1] );
-      v3_muls( delta, -1.0f, rp->rb.bbx[0] );
+      v3_copy( delta, rp->obj.rb.bbx[1] );
+      v3_muls( delta, -1.0f, rp->obj.rb.bbx[0] );
 
-      q_identity( rp->rb.q );
-      rp->rb.type = k_rb_shape_box;
+      q_identity( rp->obj.rb.q );
+      rp->obj.type = k_rb_shape_box;
       rp->colour = 0xffcccccc;
    }
    else if( bone->collider == k_bone_collider_capsule ){
@@ -83,22 +99,25 @@ VG_STATIC void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
       v3_add( bone->hitbox[0], bone->hitbox[1], rp->collider_mtx[3] );
       v3_muls( rp->collider_mtx[3], 0.5f, rp->collider_mtx[3] );
 
-      rp->rb.type = k_rb_shape_capsule;
-      rp->rb.inf.capsule.height = l;
-      rp->rb.inf.capsule.radius = r;
+      rp->obj.type = k_rb_shape_capsule;
+      rp->obj.inf.capsule.height = l;
+      rp->obj.inf.capsule.radius = r;
 
       rp->colour = 0xff000000 | (0xff << (major_axis*8));
    }
-   else
+   else{
+      vg_warn( "type: %u\n", bone->collider );
       vg_fatal_exit_loop( "Invalid bone collider type" );
+   }
 
    m4x3_invert_affine( rp->collider_mtx, rp->inv_collider_mtx );
 
    /* Position collider into rest */
-   m3x3_q( rp->collider_mtx, rp->rb.q );
-   v3_add( rp->collider_mtx[3], bone->co, rp->rb.co );
-   rp->rb.is_world = 0;
-   rb_init( &rp->rb );
+   m3x3_q( rp->collider_mtx, rp->obj.rb.q );
+   v3_add( rp->collider_mtx[3], bone->co, rp->obj.rb.co );
+   v3_zero( rp->obj.rb.v );
+   v3_zero( rp->obj.rb.w );
+   rb_init_object( &rp->obj );
 }
 
 /*
@@ -129,7 +148,7 @@ VG_STATIC void player_setup_ragdoll_from_avatar( struct player_ragdoll *rd,
    rd->position_constraints_count = 0;
    rd->cone_constraints_count = 0;
 
-   for( u32 i=0; i<av->sk.bone_count; i ++ ){
+   for( u32 i=1; i<av->sk.bone_count; i ++ ){
       struct skeleton_bone *bone = &av->sk.bones[i];
 
       /*
@@ -165,8 +184,8 @@ VG_STATIC void player_setup_ragdoll_from_avatar( struct player_ragdoll *rd,
          struct skeleton_bone *bp = &av->sk.bones[pp->bone_id];
 
          /* Convention: rba -- parent, rbb -- child */
-         c->rba = &pp->rb;
-         c->rbb = &rp->rb;
+         c->rba = &pp->obj.rb;
+         c->rbb = &rp->obj.rb;
 
          v3f delta;
          v3_sub( bj->co, bp->co, delta );
@@ -179,8 +198,8 @@ VG_STATIC void player_setup_ragdoll_from_avatar( struct player_ragdoll *rd,
          struct rb_constr_swingtwist *a = 
             &rd->cone_constraints[ rd->cone_constraints_count ++ ];
 
-         a->rba = &pp->rb;
-         a->rbb = &rp->rb;
+         a->rba = &pp->obj.rb;
+         a->rbb = &rp->obj.rb;
          a->conet = cosf( inf->conet )-0.0001f;
          
          /* Store constraint in local space vectors */
@@ -215,10 +234,26 @@ VG_STATIC void copy_ragdoll_pose_to_avatar( struct player_ragdoll *rd,
       struct ragdoll_part *part = &rd->parts[i];
       m4x3f offset;
       m3x3_identity(offset);
-      m4x3_mul( part->rb.to_world, part->inv_collider_mtx, 
+      m4x3_mul( part->obj.rb.to_world, part->inv_collider_mtx, 
                   av->sk.final_mtx[part->bone_id] );
    }
 
+   for( u32 i=1; i<av->sk.bone_count; i++ ){
+      struct skeleton_bone *sb = &av->sk.bones[i];
+
+      if( sb->parent && !sb->collider ){
+         v3f delta;
+         v3_sub( av->sk.bones[i].co, av->sk.bones[sb->parent].co, delta );
+
+         m4x3f posemtx;
+         m3x3_identity( posemtx );
+         v3_copy( delta, posemtx[3] );
+
+         /* final matrix */
+         m4x3_mul( av->sk.final_mtx[sb->parent], posemtx, av->sk.final_mtx[i] );
+      }
+   }
+
    skeleton_apply_inverses( &av->sk );
 }
 
@@ -237,16 +272,16 @@ VG_STATIC void copy_avatar_pose_to_ragdoll( struct player_avatar *av,
 
       m4x3_mulv( av->sk.final_mtx[bone], av->sk.bones[bone].co, pos );
       m3x3_mulv( av->sk.final_mtx[bone], part->collider_mtx[3], offset );
-      v3_add( pos, offset, part->rb.co );
+      v3_add( pos, offset, part->obj.rb.co );
 
       m3x3f r;
       m3x3_mul( av->sk.final_mtx[bone], part->collider_mtx, r );
-      m3x3_q( r, part->rb.q );
+      m3x3_q( r, part->obj.rb.q );
 
-      v3_copy( velocity, part->rb.v );
-      v3_zero( part->rb.w );
+      v3_copy( velocity, part->obj.rb.v );
+      v3_zero( part->obj.rb.w );
       
-      rb_update_transform( &part->rb );
+      rb_update_transform( &part->obj.rb );
    }
 }
 
@@ -273,27 +308,30 @@ VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd )
    }
 
    rb_solver_reset();
+   
+   float contact_velocities[256];
+
    for( int i=0; i<rd->part_count; i ++ ){
       if( rb_global_has_space() ){
          rb_ct *buf = rb_global_buffer();
 
          int l;
          
-         if( rd->parts[i].rb.type == k_rb_shape_capsule ){
-            l = rb_capsule__scene( rd->parts[i].rb.to_world,
-                                   &rd->parts[i].rb.inf.capsule,
+         if( rd->parts[i].obj.type == k_rb_shape_capsule ){
+            l = rb_capsule__scene( rd->parts[i].obj.rb.to_world,
+                                   &rd->parts[i].obj.inf.capsule,
                                    NULL, &world->rb_geo.inf.scene, buf );
          }
-         else if( rd->parts[i].rb.type == k_rb_shape_box ){
-            l = rb_box__scene( rd->parts[i].rb.to_world,
-                               rd->parts[i].rb.bbx,
+         else if( rd->parts[i].obj.type == k_rb_shape_box ){
+            l = rb_box__scene( rd->parts[i].obj.rb.to_world,
+                               rd->parts[i].obj.rb.bbx,
                                NULL, &world->rb_geo.inf.scene, buf );
          }
          else continue;
 
          for( int j=0; j<l; j++ ){
-            buf[j].rba = &rd->parts[i].rb;
-            buf[j].rbb = &world->rb_geo;
+            buf[j].rba = &rd->parts[i].obj.rb;
+            buf[j].rbb = &world->rb_geo.rb;
          }
 
          rb_contact_count += l;
@@ -309,23 +347,23 @@ VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd )
             if( !rb_global_has_space() )
                break;
 
-            if( rd->parts[j].rb.type != k_rb_shape_capsule )
+            if( rd->parts[j].obj.type != k_rb_shape_capsule )
                continue;
 
-            if( rd->parts[i].rb.type != k_rb_shape_capsule )
+            if( rd->parts[i].obj.type != k_rb_shape_capsule )
                continue;
 
             rb_ct *buf = rb_global_buffer();
 
-            int l = rb_capsule__capsule( rd->parts[i].rb.to_world,
-                                         &rd->parts[i].rb.inf.capsule,
-                                         rd->parts[j].rb.to_world,
-                                         &rd->parts[j].rb.inf.capsule,
+            int l = rb_capsule__capsule( rd->parts[i].obj.rb.to_world,
+                                         &rd->parts[i].obj.inf.capsule,
+                                         rd->parts[j].obj.rb.to_world,
+                                         &rd->parts[j].obj.inf.capsule,
                                          buf );
 
             for( int k=0; k<l; k++ ){
-               buf[k].rba = &rd->parts[i].rb;
-               buf[k].rbb = &rd->parts[j].rb;
+               buf[k].rba = &rd->parts[i].obj.rb;
+               buf[k].rbb = &rd->parts[j].obj.rb;
             }
 
             rb_contact_count += l;
@@ -338,14 +376,27 @@ VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd )
 
       if( run_sim ){
          v4f plane = {0.0f,1.0f,0.0f,0.0f};
-         rb_effect_simple_bouyency( &pj->rb, plane, k_ragdoll_floatyiness,
-                                                    k_ragdoll_floatydrag );
+         rb_effect_simple_bouyency( &pj->obj.rb, plane, 
+                                     k_ragdoll_floatyiness,
+                                     k_ragdoll_floatydrag );
       }
    }
 
    /*
     * PRESOLVE
     */
+   for( u32 i=0; i<rb_contact_count; i++ ){
+      rb_ct *ct = &rb_contact_buffer[i];
+
+      v3f rv, ra, rb;
+      v3_sub( ct->co, ct->rba->co, ra );
+      v3_sub( ct->co, ct->rbb->co, rb );
+      rb_rcv( ct->rba, ct->rbb, ra, rb, rv );
+      float     vn = v3_dot( rv, ct->n );
+
+      contact_velocities[i] = vn;
+   }
+
    rb_presolve_contacts( rb_contact_buffer, rb_contact_count );
    rb_presolve_swingtwist_constraints( rd->cone_constraints,
                                        rd->cone_constraints_count );
@@ -355,7 +406,7 @@ VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd )
     */
    if( k_ragdoll_debug_collider ){
       for( u32 i=0; i<rd->part_count; i ++ )
-         rb_debug( &rd->parts[i].rb, rd->parts[i].colour );
+         rb_object_debug( &rd->parts[i].obj, rd->parts[i].colour );
    }
 
    if( k_ragdoll_debug_constraints ){
@@ -379,10 +430,10 @@ VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd )
       }
 
       for( int i=0; i<rd->part_count; i++ )
-         rb_iter( &rd->parts[i].rb );
+         rb_iter( &rd->parts[i].obj.rb );
 
       for( int i=0; i<rd->part_count; i++ )
-         rb_update_transform( &rd->parts[i].rb );
+         rb_update_transform( &rd->parts[i].obj.rb );
 
       rb_correct_swingtwist_constraints( rd->cone_constraints, 
                                          rd->cone_constraints_count, 0.25f );
@@ -391,6 +442,38 @@ VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd )
                                        rd->position_constraints_count, 0.5f );
    }
 
+   rb_ct *stress = NULL;
+   float max_stress = 1.0f;
+
+   for( u32 i=0; i<rb_contact_count; i++ ){
+      rb_ct *ct = &rb_contact_buffer[i];
+
+      v3f rv, ra, rb;
+      v3_sub( ct->co, ct->rba->co, ra );
+      v3_sub( ct->co, ct->rbb->co, rb );
+      rb_rcv( ct->rba, ct->rbb, ra, rb, rv );
+      float vn = v3_dot( rv, ct->n );
+
+      float s = fabsf(vn - contact_velocities[i]);
+      if( s > max_stress ){
+         stress = ct;
+         max_stress = s;
+      }
+   }
+
+   static u32 temp_filter = 0;
+
+   if( temp_filter ){
+      temp_filter --;
+      return;
+   }
+
+   if( stress ){
+      temp_filter = 20;
+      audio_lock();
+      audio_oneshot_3d( &audio_hits[rand()%5], stress->co, 20.0f, 1.0f );
+      audio_unlock();
+   }
 }
 
 #endif /* PLAYER_RAGDOLL_H */