From 08b11851edbca3f8951b6023554169cc67aa4f22 Mon Sep 17 00:00:00 2001 From: hgn Date: Mon, 11 Dec 2023 16:03:09 +0000 Subject: [PATCH] ragdoll quality improvements --- models_src/ch_none.mdl | Bin 854840 -> 854840 bytes player.h | 2 ++ player_dead.c | 4 +-- player_dead.h | 2 +- player_ragdoll.c | 68 ++++++++++++++++++++++++++++++++++++----- player_ragdoll.h | 10 +++++- player_render.c | 2 ++ player_replay.c | 2 +- player_skate.c | 8 ++--- player_walk.c | 2 +- rigidbody.h | 66 ++++++++++++++++++++++++++++----------- scene.h | 2 +- 12 files changed, 132 insertions(+), 36 deletions(-) diff --git a/models_src/ch_none.mdl b/models_src/ch_none.mdl index fb3b9eaa3700251d89a674f34d793079f7ef636d..34a6cc12d100d3f76afe9d5e71b6c2b38cc7ad85 100644 GIT binary patch delta 15760 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 delta 15430 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 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; diff --git a/player_ragdoll.h b/player_ragdoll.h index 2ea5727..0afc330 100644 --- a/player_ragdoll.h +++ b/player_ragdoll.h @@ -45,6 +45,12 @@ static int k_ragdoll_div = 1, k_ragdoll_debug_collider = 1, k_ragdoll_debug_constraints = 0; +enum player_die_type { + k_player_die_type_generic, + k_player_die_type_head, + k_player_die_type_feet +}; + static void player_ragdoll_init(void); static void player_init_ragdoll_bone_collider( struct skeleton_bone *bone, struct ragdoll_part *rp ); @@ -52,7 +58,9 @@ static u32 ragdoll_bone_parent( struct player_ragdoll *rd, u32 bone_id ); static void setup_ragdoll_from_skeleton( struct skeleton *sk, struct player_ragdoll *rd ); static void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd ); -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 ); + static void player_debug_ragdoll(void); static void player_ragdoll_iter( struct player_ragdoll *rd ); diff --git a/player_render.c b/player_render.c index aed6caf..44ab25b 100644 --- a/player_render.c +++ b/player_render.c @@ -35,6 +35,8 @@ static void player_load_animation_reference( const char *path ){ localplayer.id_ik_elbow_l = skeleton_bone_id( sk, "elbow.L" ); localplayer.id_ik_elbow_r = skeleton_bone_id( sk, "elbow.R" ); localplayer.id_head = skeleton_bone_id( sk, "head" ); + localplayer.id_foot_l = skeleton_bone_id( sk, "foot.L" ); + localplayer.id_foot_r = skeleton_bone_id( sk, "foot.R" ); localplayer.id_ik_foot_l = skeleton_bone_id( sk, "foot.IK.L" ); localplayer.id_ik_foot_r = skeleton_bone_id( sk, "foot.IK.R" ); localplayer.id_board = skeleton_bone_id( sk, "board" ); diff --git a/player_replay.c b/player_replay.c index 12f7f6b..c1bf7b4 100644 --- a/player_replay.c +++ b/player_replay.c @@ -333,7 +333,7 @@ void skaterift_restore_frame( replay_frame *frame ){ memcpy( &player_skate.state, src, src_size ); } else if( frame->system == k_player_subsystem_dead ){ - player__dead_transition(); + player__dead_transition(0); struct replay_rb *arr = src; for( u32 i=0; itrick_time > 0.2f) { player__skate_kill_audio(); - player__dead_transition(); + player__dead_transition( k_player_die_type_feet ); } state->trick_euler[0] = roundf( state->trick_euler[0] ); @@ -2048,7 +2048,7 @@ static void player__skate_update(void){ k_player_walk_soundeffect_splash, localplayer.rb.co, 1.0f ); player__skate_kill_audio(); - player__dead_transition(); + player__dead_transition( k_player_die_type_generic ); return; } } @@ -2323,7 +2323,7 @@ begin_collision:; rb_update_transform( &localplayer.rb ); player__skate_kill_audio(); - player__dead_transition(); + player__dead_transition( k_player_die_type_head ); return; } @@ -2491,7 +2491,7 @@ begin_collision:; if( nforce > 4.0f ){ if( nforce > 17.6f ){ v3_muladds( localplayer.rb.v, normal_total, -1.0f, localplayer.rb.v ); - player__dead_transition(); + player__dead_transition( k_player_die_type_feet ); player__skate_kill_audio(); return; } diff --git a/player_walk.c b/player_walk.c index 34ad072..ec863b6 100644 --- a/player_walk.c +++ b/player_walk.c @@ -435,7 +435,7 @@ static void player__walk_update(void){ player__networked_sfx( k_player_subsystem_walk, 32, k_player_walk_soundeffect_splash, localplayer.rb.co, 1.0f ); - player__dead_transition(); + player__dead_transition( k_player_die_type_generic ); return; } } diff --git a/rigidbody.h b/rigidbody.h index 7d878e9..2c074c4 100644 --- a/rigidbody.h +++ b/rigidbody.h @@ -1076,6 +1076,48 @@ static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, capsule_manifold manifold; rb_capsule_manifold_init( &manifold ); + + v3f v0, v1, n; + v3_sub( tri[1], tri[0], v0 ); + v3_sub( tri[2], tri[0], v1 ); + v3_cross( v0, v1, n ); + + if( v3_length2( n ) <= 0.00001f ){ +#ifdef RIGIDBODY_CRY_ABOUT_EVERYTHING + vg_error( "Zero area triangle!\n" ); +#endif + return 0; + } + + v3_normalize( n ); + +#if 1 + /* deep penetration recovery. for when we clip through the triangles. so its + * not very 'correct' */ + f32 dist; + if( ray_tri( tri, p0w, mtxA[1], &dist, 1 ) ){ + f32 l = c->height - c->radius*2.0f; + if( (dist >= 0.0f) && (dist < l) ){ + v3f co; + v3_muladds( p0w, mtxA[1], dist, co ); + vg_line_point( co, 0.02f, 0xffffff00 ); + + v3f d0, d1; + v3_sub( p0w, co, d0 ); + v3_sub( p1w, co, d1 ); + + f32 p = vg_minf( v3_dot( n, d0 ), v3_dot( n, d1 ) ) - c->radius; + + rb_ct *ct = buf; + ct->p = -p; + ct->type = k_contact_type_default; + v3_copy( n, ct->n ); + v3_muladds( co, n, p, ct->co ); + + return 1; + } + } +#endif v3f c0, c1; closest_on_triangle_1( p0w, tri, c0 ); @@ -1090,12 +1132,13 @@ static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, v3_normalize(d1); v3_normalize(da); + /* the two balls at the ends */ if( v3_dot( da, d0 ) <= 0.01f ) rb_capsule_manifold( p0w, c0, 0.0f, c->radius, &manifold ); - if( v3_dot( da, d1 ) >= -0.01f ) rb_capsule_manifold( p1w, c1, 1.0f, c->radius, &manifold ); + /* the edges to edges */ for( int i=0; i<3; i++ ){ int i0 = i, i1 = (i+1)%3; @@ -1106,20 +1149,6 @@ static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, rb_capsule_manifold( ca, cb, ta, c->radius, &manifold ); } - v3f v0, v1, n; - v3_sub( tri[1], tri[0], v0 ); - v3_sub( tri[2], tri[0], v1 ); - v3_cross( v0, v1, n ); - - if( v3_length2( n ) <= 0.00001f ){ -#ifdef RIGIDBODY_CRY_ABOUT_EVERYTHING - vg_error( "Zero area triangle!\n" ); -#endif - return 0; - } - - v3_normalize( n ); - int count = rb_capsule__manifold_done( mtxA, c, &manifold, buf ); for( int i=0; irba, *rbb = ct->rbb; - float mass_total = 1.0f / (rba->inv_mass + rbb->inv_mass); + f32 mass_total = 1.0f / (rba->inv_mass + rbb->inv_mass), + d = ct->p*mass_total*amt; - v3_muladds( rba->co, ct->n, -mass_total * rba->inv_mass, rba->co ); - v3_muladds( rbb->co, ct->n, mass_total * rbb->inv_mass, rbb->co ); + v3_muladds( rba->co, ct->n, -d * rba->inv_mass, rba->co ); + v3_muladds( rbb->co, ct->n, d * rbb->inv_mass, rbb->co ); } } diff --git a/scene.h b/scene.h index ba23ffb..d8fac1a 100644 --- a/scene.h +++ b/scene.h @@ -414,7 +414,7 @@ static int scene_raycast( scene_context *s, bh_tree *bh, v3_copy( s->arrvertices[tri[i]].co, vs[i] ); f32 t; - if( ray_tri( vs, co, dir, &t ) ){ + if( ray_tri( vs, co, dir, &t, 0 ) ){ if( t < hit->dist ){ hit->dist = t; hit->tri = tri; -- 2.25.1