ragdoll quality improvements
[carveJwlIkooP6JGAAIwe30JlM.git] / player_ragdoll.c
index f0a6f88c7b5de75bd31888f0fe70a699d6e7d72b..ff6a533bdebe862673e4b89cd2d0d9e264e2f52d 100644 (file)
@@ -4,12 +4,47 @@
 #include "player.h"
 #include "audio.h"
 
-static void player_ragdoll_init(void)
-{
+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_limit_scale );
    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,
@@ -226,12 +261,20 @@ static void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd ){
 /*
  * Make the ragdoll copy the player model
  */
-static void copy_localplayer_to_ragdoll( struct player_ragdoll *rd, v3f v ){
+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 );
@@ -242,8 +285,19 @@ static void copy_localplayer_to_ragdoll( struct player_ragdoll *rd, v3f v ){
       m3x3_mul( bone_mtx, part->collider_mtx, r );
       m3x3_q( r, part->obj.rb.q );
 
-      v3_copy( v, part->obj.rb.v );
-      v3_zero( part->obj.rb.w );
+      v3f ra, v;
+      v3_sub( part->obj.rb.co, centroid, ra );
+      v3_cross( localplayer.rb.w, ra, v );
+      v3_add( localplayer.rb.v, v, part->obj.rb.v );
+
+      if( type == k_player_die_type_feet ){
+         if( (bone == localplayer.id_foot_l) || 
+             (bone == localplayer.id_foot_r) ){
+            v3_zero( part->obj.rb.v );
+         }
+      }
+
+      v3_copy( localplayer.rb.w, part->obj.rb.w );
 
       v3_copy( part->obj.rb.co, part->prev_co );
       v4_copy( part->obj.rb.q, part->prev_q );
@@ -401,10 +455,10 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){
          rb_update_transform( &rd->parts[i].obj.rb );
 
       rb_correct_swingtwist_constraints( rd->cone_constraints, 
-                                         rd->cone_constraints_count, 0.25f );
+                                         rd->cone_constraints_count, 0.125f );
 
       rb_correct_position_constraints( rd->position_constraints,
-                                       rd->position_constraints_count, 0.5f );
+                                       rd->position_constraints_count, 0.25f );
    }
 
    rb_ct *stress = NULL;