active ragdolls
authorhgn <hgodden00@gmail.com>
Tue, 12 Dec 2023 16:02:38 +0000 (16:02 +0000)
committerhgn <hgodden00@gmail.com>
Tue, 12 Dec 2023 16:02:38 +0000 (16:02 +0000)
models_src/ch_none.mdl
player_dead.c
player_dead.h
player_ragdoll.c
player_ragdoll.h
rigidbody.h

index 34a6cc12d100d3f76afe9d5e71b6c2b38cc7ad85..e17c75934538d8d81cc7405f1b8ac6f883296ae9 100644 (file)
Binary files a/models_src/ch_none.mdl and b/models_src/ch_none.mdl differ
index 4ee223697394643f9dc1b74081e094dc38ee1928..7733c327e2b0668d9a6a7439fd7fda829cdf509b 100644 (file)
@@ -172,4 +172,9 @@ static void player__dead_animator_exchange( bitpack_ctx *ctx, void *data ){
    }
 }
 
+static void player__dead_bind(void){
+   struct skeleton *sk = &localplayer.skeleton;
+   player_dead.anim_bail = skeleton_get_anim( sk, "pose_bail_ball" );
+}
+
 #endif /* PLAYER_DEAD_C */
index e4c177e721c12dc610d83c02ea018df5fea86693..f90a3029cb393f45e0dca322c6dd60f0855994fa 100644 (file)
@@ -15,6 +15,8 @@ struct player_dead{
       transforms[ 32 ];
    }
    animator;
+
+   struct skeleton_anim *anim_bail;
 }
 static player_dead;
 
@@ -24,6 +26,7 @@ static void player__dead_animate     (void);
 static void player__dead_pose        (void *animator, player_pose *pose);
 static void player__dead_post_animate(void);
 static void player__dead_im_gui      (void);
+static void player__dead_bind        (void);
 static void player__dead_transition  ( enum player_die_type type );
 static void player__dead_animator_exchange( bitpack_ctx *ctx, void *data );
 
@@ -34,6 +37,7 @@ struct player_subsystem_interface static player_subsystem_dead = {
    .pose = player__dead_pose,
    .post_animate = player__dead_post_animate,
    .im_gui = player__dead_im_gui,
+   .bind = player__dead_bind,
 
    .animator_data = &player_dead.animator,
    .animator_size = sizeof(player_dead.animator),
index ff6a533bdebe862673e4b89cd2d0d9e264e2f52d..e3345808923f0ed5e01fe15622dc2e24dc3b16c2 100644 (file)
@@ -40,7 +40,12 @@ static int dev_ragdoll_saveload(int argc, const char *argv[]){
 }
 
 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 );
@@ -151,7 +156,10 @@ static void setup_ragdoll_from_skeleton( struct skeleton *sk,
       if( rd->part_count > vg_list_size(rd->parts) )
          vg_fatal_error( "Playermodel has too many colliders" );
 
-      struct ragdoll_part *rp = &rd->parts[ rd->part_count ++ ];
+      u32 part_id = rd->part_count;
+      rd->part_count ++;
+
+      struct ragdoll_part *rp = &rd->parts[ part_id ];
       rp->bone_id = i;
       rp->parent = 0xffffffff;
 
@@ -166,12 +174,17 @@ static void setup_ragdoll_from_skeleton( struct skeleton *sk,
       rp->parent = ragdoll_bone_parent( rd, bone->parent );
       
       if( bone->orig_bone->flags & k_bone_flag_cone_constraint ){
-         struct rb_constr_pos *c = 
-            &rd->position_constraints[ rd->position_constraints_count ++ ];
+         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->obj.rb;
@@ -437,10 +450,10 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){
    }
 
    /*
-    * SOLVE CONSTRAINTS 
+    * SOLVE CONSTRAINTS  & Integrate
     */
    if( run_sim ){
-      for( int i=0; i<16; i++ ){
+      for( int i=0; i<12; i++ ){
          rb_solve_contacts( rb_contact_buffer, rb_contact_count );
          rb_solve_swingtwist_constraints( rd->cone_constraints, 
                                           rd->cone_constraints_count );
@@ -448,17 +461,30 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){
                                         rd->position_constraints_count );
       }
 
-      for( int i=0; i<rd->part_count; i++ )
+      for( int i=0; i<rd->part_count; i++ ){
          rb_iter( &rd->parts[i].obj.rb );
 
+         v3f w;
+         v3_copy( rd->parts[i].obj.rb.w, w );
+         if( v3_length2( w ) > 0.00001f ){
+            v3_normalize( w );
+            v3_muladds( rd->parts[i].obj.rb.w, w, -k_ragdoll_angular_drag,
+                        rd->parts[i].obj.rb.w );
+         }
+      }
+
       for( int i=0; i<rd->part_count; i++ )
          rb_update_transform( &rd->parts[i].obj.rb );
 
-      rb_correct_swingtwist_constraints( rd->cone_constraints, 
-                                         rd->cone_constraints_count, 0.125f );
+      for( int i=0; i<5; i ++ ){
+         rb_correct_swingtwist_constraints( rd->cone_constraints, 
+                                            rd->cone_constraints_count,
+                                            k_ragdoll_correction * 0.25f );
 
-      rb_correct_position_constraints( rd->position_constraints,
-                                       rd->position_constraints_count, 0.25f );
+         rb_correct_position_constraints( rd->position_constraints,
+                                          rd->position_constraints_count, 
+                                          k_ragdoll_correction * 0.5f );
+      }
    }
 
    rb_ct *stress = NULL;
@@ -482,6 +508,68 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){
 
    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;
index 0afc330486d6be8e96bd82790a5b5dc9746ebff8..6f5a33137a8e5a48ef53b21da64d86b1a21555d7 100644 (file)
@@ -33,12 +33,19 @@ struct player_ragdoll{
    rb_constr_swingtwist cone_constraints[32];
    u32                  cone_constraints_count;
 
+   /* TODO: Fix duplicated data */
+   u32 constraint_associations[32][2];
    int shoes[2];
 };
 
 static float k_ragdoll_floatyiness = 20.0f,
                 k_ragdoll_floatydrag  = 1.0f,
-                k_ragdoll_limit_scale = 1.0f;
+                k_ragdoll_limit_scale = 1.0f,
+                k_ragdoll_spring = 127.0f,
+                k_ragdoll_dampening = 15.0f,
+                k_ragdoll_correction = 0.5f,
+                k_ragdoll_angular_drag = 0.08f,
+                k_ragdoll_active_threshold = 5.0f;
 
 static int   k_ragdoll_div = 1,
                 ragdoll_frame = 0,
index 2c074c47d46aea97d7b56b67d8aa70191f7c198b..a69e4afd69cb5c2b41089b65b3dbdd31f248bc70 100644 (file)
@@ -330,9 +330,11 @@ static void rb_iter( rigidbody *rb ){
       q_mul( rotation, rb->q, rb->q );
    }
 
+#if 0
    /* damping */
    v3_muls( rb->v, 1.0f/(1.0f+k_rb_delta*k_damp_linear), rb->v );
    v3_muls( rb->w, 1.0f/(1.0f+k_rb_delta*k_damp_angular), rb->w );
+#endif
 }