ignore this 2
[carveJwlIkooP6JGAAIwe30JlM.git] / player_ragdoll.c
diff --git a/player_ragdoll.c b/player_ragdoll.c
deleted file mode 100644 (file)
index 6dc171d..0000000
+++ /dev/null
@@ -1,607 +0,0 @@
-#pragma once
-#include "vg/vg_rigidbody.h"
-#include "vg/vg_rigidbody_collision.h"
-#include "vg/vg_rigidbody_constraints.h"
-#include "scene_rigidbody.h"
-
-#include "player.h"
-#include "audio.h"
-
-static int dev_ragdoll_saveload(int argc, const char *argv[]){
-   if( argc != 2 ){
-      vg_info( "Usage: ragdoll load/save filepath\n" );
-      return 1;
-   }
-
-   if( !strcmp(argv[0],"save") ){
-      FILE *fp = fopen( argv[1], "wb" );
-      if( !fp ){
-         vg_error( "Failed to open file\n" );
-         return 1;
-      }
-      fwrite( &localplayer.ragdoll.parts, 
-               sizeof(localplayer.ragdoll.parts), 1, fp );
-      fclose( fp );
-   }
-   else if( !strcmp(argv[0],"load") ){
-      FILE *fp = fopen( argv[1], "rb" );
-      if( !fp ){
-         vg_error( "Failed to open file\n" );
-         return 1;
-      }
-
-      fread( &localplayer.ragdoll.parts, 
-              sizeof(localplayer.ragdoll.parts), 1, fp );
-      fclose( fp );
-   }
-   else {
-      vg_error( "Unknown command: %s (options are: save,load)\n", argv[0] );
-      return 1;
-   }
-   
-   return 0;
-}
-
-static void player_ragdoll_init(void){
-   VG_VAR_F32( k_ragdoll_active_threshold );
-   VG_VAR_F32( k_ragdoll_angular_drag );
-   VG_VAR_F32( k_ragdoll_correction );
-   VG_VAR_F32( k_ragdoll_limit_scale );
-   VG_VAR_F32( k_ragdoll_spring );
-   VG_VAR_F32( k_ragdoll_dampening );
-   VG_VAR_I32( k_ragdoll_div );
-   VG_VAR_I32( k_ragdoll_debug_collider );
-   VG_VAR_I32( k_ragdoll_debug_constraints );
-   vg_console_reg_cmd( "ragdoll", dev_ragdoll_saveload, NULL );
-}
-
-static void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
-                                                  struct ragdoll_part *rp )
-{
-   f32 k_density = 8.0f,
-       k_inertia_scale = 2.0f;
-
-   m4x3_identity( rp->collider_mtx );
-
-   rp->type = bone->collider;
-   if( bone->collider == k_bone_collider_box ){
-      v3f delta;
-      v3_sub( bone->hitbox[1], bone->hitbox[0], delta );
-      v3_muls( delta, 0.5f, delta );
-      v3_add( bone->hitbox[0], delta, rp->collider_mtx[3] );
-
-      v3_muls( delta, -1.0f, rp->inf.box[0] );
-      v3_copy( delta,        rp->inf.box[1] );
-
-      rp->colour = 0xffcccccc;
-
-      rb_setbody_box( &rp->rb, rp->inf.box, k_density, k_inertia_scale );
-   }
-   else if( bone->collider == k_bone_collider_capsule ){
-      v3f v0, v1, tx, ty;
-      v3_sub( bone->hitbox[1], bone->hitbox[0], v0 );
-
-      int major_axis = 0;
-      float largest = -1.0f;
-
-      for( int i=0; i<3; i ++ ){
-         if( fabsf( v0[i] ) > largest ){
-            largest = fabsf( v0[i] );
-            major_axis = i;
-         }
-      }
-      
-      v3_zero( v1 );
-      v1[ major_axis ] = 1.0f;
-      v3_tangent_basis( v1, tx, ty );
-      
-      rp->inf.capsule.r = (fabsf(v3_dot(tx,v0)) + fabsf(v3_dot(ty,v0))) * 0.25f;
-      rp->inf.capsule.h = fabsf(v0[ major_axis ]);
-
-      /* orientation */
-      v3_muls( tx, -1.0f, rp->collider_mtx[0] );
-      v3_muls( v1, -1.0f, rp->collider_mtx[1] );
-      v3_muls( ty, -1.0f, rp->collider_mtx[2] );
-      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->colour = 0xff000000 | (0xff << (major_axis*8));
-      
-      rb_setbody_capsule( &rp->rb, rp->inf.capsule.r, rp->inf.capsule.h, 
-                           k_density, k_inertia_scale );
-   }
-   else{
-      vg_warn( "type: %u\n", bone->collider );
-      vg_fatal_error( "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 );
-   v3_zero( rp->rb.v );
-   v3_zero( rp->rb.w );
-   rb_update_matrices( &rp->rb );
-}
-
-/*
- * Get parent index in the ragdoll
- */
-static u32 ragdoll_bone_parent( struct player_ragdoll *rd, u32 bone_id ){
-   for( u32 j=0; j<rd->part_count; j++ )
-      if( rd->parts[ j ].bone_id == bone_id )
-         return j;
-
-   vg_fatal_error( "Referenced parent bone does not have a rigidbody" );
-   return 0;
-}
-
-/*
- * Setup ragdoll colliders from skeleton
- */
-static void setup_ragdoll_from_skeleton( struct skeleton *sk,
-                                         struct player_ragdoll *rd ){
-   rd->part_count = 0;
-
-   if( !sk->collider_count )
-      return;
-
-   rd->position_constraints_count = 0;
-   rd->cone_constraints_count = 0;
-
-   for( u32 i=1; i<sk->bone_count; i ++ ){
-      struct skeleton_bone *bone = &sk->bones[i];
-
-      /*
-       * Bones with colliders
-       */
-      if( !(bone->collider) )
-         continue;
-
-      if( rd->part_count > vg_list_size(rd->parts) )
-         vg_fatal_error( "Playermodel has too many colliders" );
-
-      u32 part_id = rd->part_count;
-      rd->part_count ++;
-
-      struct ragdoll_part *rp = &rd->parts[ part_id ];
-      rp->bone_id = i;
-      rp->parent = 0xffffffff;
-
-      player_init_ragdoll_bone_collider( bone, rp );
-      
-      /*
-       * Bones with collider and parent
-       */
-      if( !bone->parent )
-         continue;
-
-      rp->parent = ragdoll_bone_parent( rd, bone->parent );
-      
-      if( bone->orig_bone->flags & k_bone_flag_cone_constraint ){
-         u32 conid = rd->position_constraints_count;
-         rd->position_constraints_count ++;
-
-         struct rb_constr_pos *c = &rd->position_constraints[ conid ];
-
-         struct skeleton_bone *bj = &sk->bones[rp->bone_id];
-         struct ragdoll_part  *pp = &rd->parts[rp->parent];
-         struct skeleton_bone *bp = &sk->bones[pp->bone_id];
-         
-         rd->constraint_associations[conid][0] = rp->parent;
-         rd->constraint_associations[conid][1] = part_id;
-
-         /* Convention: rba -- parent, rbb -- child */
-         c->rba = &pp->rb;
-         c->rbb = &rp->rb;
-
-         v3f delta;
-         v3_sub( bj->co, bp->co, delta );
-         m4x3_mulv( rp->inv_collider_mtx, (v3f){0.0f,0.0f,0.0f}, c->lcb );
-         m4x3_mulv( pp->inv_collider_mtx, delta, c->lca );
-
-
-         mdl_bone *inf = bone->orig_bone;
-
-         struct rb_constr_swingtwist *a = 
-            &rd->cone_constraints[ rd->cone_constraints_count ++ ];
-
-         a->rba = &pp->rb;
-         a->rbb = &rp->rb;
-         a->conet = cosf( inf->conet )-0.0001f;
-         
-         /* Store constraint in local space vectors */
-         m3x3_mulv( c->rba->to_local, inf->conevx, a->conevx );
-         m3x3_mulv( c->rba->to_local, inf->conevy, a->conevy );
-         m3x3_mulv( c->rbb->to_local, inf->coneva, a->coneva );
-         v3_copy( c->lca, a->view_offset );
-         
-         v3_cross( inf->coneva, inf->conevy, a->conevxb );
-         m3x3_mulv( c->rbb->to_local, a->conevxb, a->conevxb );
-
-         v3_normalize( a->conevxb );
-         v3_normalize( a->conevx );
-         v3_normalize( a->conevy );
-         v3_normalize( a->coneva );
-
-         a->conevx[3] = v3_length( inf->conevx );
-         a->conevy[3] = v3_length( inf->conevy );
-
-         rp->use_limits = 1;
-      }
-   }
-}
-
-/*
- * Make avatar copy the ragdoll
- */
-static void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd ){
-   for( int i=0; i<rd->part_count; i++ ){
-      struct ragdoll_part *part = &rd->parts[i];
-
-      m4x3f mtx;
-
-      v4f q_int;
-      v3f co_int;
-
-      float substep = vg.time_fixed_extrapolate;
-      v3_lerp( part->prev_co, part->rb.co, substep, co_int );
-      q_nlerp( part->prev_q, part->rb.q, substep, q_int );
-
-      q_m3x3( q_int, mtx );
-      v3_copy( co_int, mtx[3] );
-
-      m4x3_mul( mtx, part->inv_collider_mtx, 
-                localplayer.final_mtx[part->bone_id] );
-   }
-
-   for( u32 i=1; i<localplayer.skeleton.bone_count; i++ ){
-      struct skeleton_bone *sb = &localplayer.skeleton.bones[i];
-
-      if( sb->parent && !sb->collider ){
-         v3f delta;
-         v3_sub( localplayer.skeleton.bones[i].co, 
-                 localplayer.skeleton.bones[sb->parent].co, delta );
-
-         m4x3f posemtx;
-         m3x3_identity( posemtx );
-         v3_copy( delta, posemtx[3] );
-
-         /* final matrix */
-         m4x3_mul( localplayer.final_mtx[sb->parent], posemtx, 
-                   localplayer.final_mtx[i] );
-      }
-   }
-
-   skeleton_apply_inverses( &localplayer.skeleton, localplayer.final_mtx );
-}
-
-/*
- * Make the ragdoll copy the player model
- */
-static void copy_localplayer_to_ragdoll( struct player_ragdoll *rd, 
-                                         enum player_die_type type ){
-   v3f centroid;
-
-   v3f *bone_mtx = localplayer.final_mtx[localplayer.id_hip];
-   m4x3_mulv( bone_mtx, 
-              localplayer.skeleton.bones[localplayer.id_hip].co, centroid );
-
-   for( int i=0; i<rd->part_count; i++ ){
-      struct ragdoll_part *part = &rd->parts[i];
-
-      v3f pos, offset;
-      u32 bone = part->bone_id;
-
-      v3f *bone_mtx = localplayer.final_mtx[bone];
-
-      m4x3_mulv( bone_mtx, localplayer.skeleton.bones[bone].co, pos );
-      m3x3_mulv( bone_mtx, part->collider_mtx[3], offset );
-      v3_add( pos, offset, part->rb.co );
-
-      m3x3f r;
-      m3x3_mul( bone_mtx, part->collider_mtx, r );
-      m3x3_q( r, part->rb.q );
-
-      v3f ra, v;
-      v3_sub( part->rb.co, centroid, ra );
-      v3_cross( localplayer.rb.w, ra, v );
-      v3_add( localplayer.rb.v, v, part->rb.v );
-
-      if( type == k_player_die_type_feet ){
-         if( (bone == localplayer.id_foot_l) || 
-             (bone == localplayer.id_foot_r) ){
-            v3_zero( part->rb.v );
-         }
-      }
-
-      v3_copy( localplayer.rb.w, part->rb.w );
-
-      v3_copy( part->rb.co, part->prev_co );
-      v4_copy( part->rb.q, part->prev_q );
-      
-      rb_update_matrices( &part->rb );
-   }
-}
-
-/*
- * Ragdoll physics step
- */
-static void player_ragdoll_iter( struct player_ragdoll *rd ){
-   world_instance *world = world_current_instance();
-
-   int run_sim = 0;
-   ragdoll_frame ++;
-
-   if( ragdoll_frame >= k_ragdoll_div ){
-      ragdoll_frame = 0;
-      run_sim = 1;
-   }
-
-   rb_solver_reset();
-   
-   float contact_velocities[256];
-
-   rigidbody _null = {0};
-   _null.inv_mass = 0.0f;
-   m3x3_zero( _null.iI );
-
-   for( int i=0; i<rd->part_count; i ++ ){
-      v4_copy( rd->parts[i].rb.q, rd->parts[i].prev_q );
-      v3_copy( rd->parts[i].rb.co, rd->parts[i].prev_co );
-
-      if( rb_global_has_space() ){
-         rb_ct *buf = rb_global_buffer();
-
-         int l;
-         
-         if( rd->parts[i].type == k_bone_collider_capsule ){
-            l = rb_capsule__scene( rd->parts[i].rb.to_world,
-                                   &rd->parts[i].inf.capsule,
-                                   NULL, world->geo_bh, buf,
-                                   k_material_flag_ghosts );
-         }
-         else if( rd->parts[i].type == k_bone_collider_box ){
-            l = rb_box__scene( rd->parts[i].rb.to_world,
-                               rd->parts[i].inf.box,
-                               NULL, world->geo_bh, buf,
-                               k_material_flag_ghosts );
-         }
-         else continue;
-
-         for( int j=0; j<l; j++ ){
-            buf[j].rba = &rd->parts[i].rb;
-            buf[j].rbb = &_null;
-         }
-
-         rb_contact_count += l;
-      }
-   }
-
-   /* 
-    * self-collision
-    */
-   for( int i=0; i<rd->part_count-1; i ++ ){
-      for( int j=i+1; j<rd->part_count; j ++ ){
-         if( rd->parts[j].parent != i ){
-            if( !rb_global_has_space() )
-               break;
-
-            if( rd->parts[j].type != k_bone_collider_capsule )
-               continue;
-
-            if( rd->parts[i].type != k_bone_collider_capsule )
-               continue;
-
-            rb_ct *buf = rb_global_buffer();
-
-            int l = rb_capsule__capsule( rd->parts[i].rb.to_world,
-                                         &rd->parts[i].inf.capsule,
-                                         rd->parts[j].rb.to_world,
-                                         &rd->parts[j].inf.capsule,
-                                         buf );
-
-            for( int k=0; k<l; k++ ){
-               buf[k].rba = &rd->parts[i].rb;
-               buf[k].rbb = &rd->parts[j].rb;
-            }
-
-            rb_contact_count += l;
-         }
-      }
-   }
-
-   if( world->water.enabled ){
-      for( int j=0; j<rd->part_count; j++ ){
-         struct ragdoll_part *pj = &rd->parts[j];
-
-         if( run_sim ){
-            rb_effect_simple_bouyency( &pj->rb, world->water.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 );
-
-   /* 
-    * DEBUG
-    */
-   if( k_ragdoll_debug_collider ){
-      for( u32 i=0; i<rd->part_count; i ++ ){
-         struct ragdoll_part *rp = &rd->parts[i];
-
-         if( rp->type == k_bone_collider_capsule ){
-            vg_line_capsule( rp->rb.to_world, 
-                             rp->inf.capsule.r, rp->inf.capsule.h, rp->colour );
-         }
-         else if( rp->type == k_bone_collider_box ){
-            vg_line_boxf_transformed( rp->rb.to_world, 
-                                      rp->inf.box, rp->colour );
-         }
-      }
-   }
-
-   if( k_ragdoll_debug_constraints ){
-      rb_debug_position_constraints( rd->position_constraints, 
-                                     rd->position_constraints_count );
-
-      rb_debug_swingtwist_constraints( rd->cone_constraints,
-                                       rd->cone_constraints_count );
-   }
-
-   /*
-    * SOLVE CONSTRAINTS  & Integrate
-    */
-   if( run_sim ){
-      /* the solver is not very quickly converging so... */
-      for( int i=0; i<40; i++ ){
-         if( i<20 ){
-            rb_solve_contacts( rb_contact_buffer, rb_contact_count );
-            rb_solve_swingtwist_constraints( rd->cone_constraints, 
-                                             rd->cone_constraints_count );
-            rb_postsolve_swingtwist_constraints( rd->cone_constraints, 
-                                                 rd->cone_constraints_count );
-         }
-         rb_solve_position_constraints( rd->position_constraints, 
-                                        rd->position_constraints_count );
-      }
-
-      rb_correct_position_constraints( rd->position_constraints,
-                                       rd->position_constraints_count, 
-                                       k_ragdoll_correction * 0.5f );
-      rb_correct_swingtwist_constraints( rd->cone_constraints, 
-                                         rd->cone_constraints_count,
-                                         k_ragdoll_correction * 0.25f );
-
-      for( int i=0; i<rd->part_count; i++ ){
-         rb_iter( &rd->parts[i].rb );
-
-         v3f w;
-         v3_copy( rd->parts[i].rb.w, w );
-         if( v3_length2( w ) > 0.00001f ){
-            v3_normalize( w );
-            v3_muladds( rd->parts[i].rb.w, w, -k_ragdoll_angular_drag,
-                        rd->parts[i].rb.w );
-         }
-      }
-
-      for( int i=0; i<rd->part_count; i++ )
-         rb_update_matrices( &rd->parts[i].rb );
-   }
-
-   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;
-
-   /* 
-    * motorized joints 
-    */
-   if( run_sim && 
-         (v3_length2(player_dead.v_lpf)>(k_ragdoll_active_threshold*
-                                         k_ragdoll_active_threshold)) ){
-      assert( rd->cone_constraints_count == rd->position_constraints_count );
-
-      mdl_keyframe anim[32];
-      skeleton_sample_anim( &localplayer.skeleton, player_dead.anim_bail,
-                            0.0f, anim );
-
-      for( u32 i=0; i<rd->cone_constraints_count; i ++ ){
-         rb_constr_swingtwist *st = &rd->cone_constraints[i];
-         rb_constr_pos *pc = &rd->position_constraints[i];
-
-         v3f va, vap;
-
-         m3x3_mulv( st->rbb->to_world, st->coneva, va );
-
-         /* calculate va as seen in rest position, from the perspective of the
-          * parent object, mapped to pose world space using the parents 
-          * transform. thats our target */
-
-         u32 id_p = rd->constraint_associations[i][0],
-             id_a = rd->constraint_associations[i][1];
-
-         struct ragdoll_part *pa = &rd->parts[ id_a ],
-                             *pp = &rd->parts[ id_p ];
-
-         mdl_keyframe *kf = &anim[ pa->bone_id-1 ];
-         m3x3_mulv( pa->collider_mtx, st->coneva, vap );
-         q_mulv( kf->q, vap, vap );
-
-         /* This could be a transfer function */
-         m3x3_mulv( pp->inv_collider_mtx, vap, vap );
-         m3x3_mulv( st->rba->to_world, vap, vap );
-
-         f32 d = v3_dot( vap, va ),
-             a = acosf( vg_clampf( d, -1.0f, 1.0f ) );
-
-         v3f axis;
-         v3_cross( vap, va, axis );
-
-         f32 Fs = -a * k_ragdoll_spring,
-             Fd = -v3_dot( st->rbb->w, axis ) * k_ragdoll_dampening,
-             F  = Fs+Fd;
-
-         v3f torque;
-         v3_muls( axis, F, torque );
-         v3_muladds( st->rbb->w, torque, k_rb_delta, st->rbb->w );
-
-         /* apply a adjustment to keep velocity at joint 0 */
-#if 0
-         v3f wcb, vcb;
-         m3x3_mulv( st->rbb->to_world, pc->lcb, wcb );
-         v3_cross( torque, wcb, vcb );
-         v3_muladds( st->rbb->v, vcb, k_rb_delta, st->rbb->v );
-#endif
-      }
-   }
-
-   if( temp_filter ){
-      temp_filter --;
-      return;
-   }
-
-   if( stress ){
-      temp_filter = 20;
-      audio_lock();
-      audio_oneshot_3d( &audio_hits[vg_randu32(&vg.rand)%5], 
-                        stress->co, 20.0f, 1.0f );
-      audio_unlock();
-   }
-}