X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=player_ragdoll.c;h=6f9d430c56cefff23fe7ca69ed577f8e0597327b;hb=refs%2Fheads%2Fmaster;hp=e1231bcbd6956ba83e47b70d7697d1059bf15ebb;hpb=f0ba02684dbf4722afa2dcfd491d56921162182a;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/player_ragdoll.c b/player_ragdoll.c index e1231bc..6f9d430 100644 --- a/player_ragdoll.c +++ b/player_ragdoll.c @@ -1,9 +1,27 @@ -#ifndef PLAYER_RAGDOLL_C -#define PLAYER_RAGDOLL_C +#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 "player_dead.h" #include "audio.h" +static float k_ragdoll_floatyiness = 20.0f, + k_ragdoll_floatydrag = 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, + k_ragdoll_debug_collider = 1, + k_ragdoll_debug_constraints = 0; + static int dev_ragdoll_saveload(int argc, const char *argv[]){ if( argc != 2 ){ vg_info( "Usage: ragdoll load/save filepath\n" ); @@ -39,7 +57,8 @@ static int dev_ragdoll_saveload(int argc, const char *argv[]){ return 0; } -static void player_ragdoll_init(void){ +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 ); @@ -52,23 +71,27 @@ static void player_ragdoll_init(void){ vg_console_reg_cmd( "ragdoll", dev_ragdoll_saveload, NULL ); } -static void player_init_ragdoll_bone_collider( struct skeleton_bone *bone, - struct ragdoll_part *rp ) +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_copy( delta, rp->obj.rb.bbx[1] ); - v3_muls( delta, -1.0f, rp->obj.rb.bbx[0] ); + v3_muls( delta, -1.0f, rp->inf.box[0] ); + v3_copy( delta, rp->inf.box[1] ); - q_identity( rp->obj.rb.q ); - rp->obj.type = k_rb_shape_box; 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; @@ -88,9 +111,9 @@ static void player_init_ragdoll_bone_collider( struct skeleton_bone *bone, v1[ major_axis ] = 1.0f; v3_tangent_basis( v1, tx, ty ); - float r = (fabsf(v3_dot(tx,v0)) + fabsf(v3_dot(ty,v0))) * 0.25f, - l = fabsf(v0[ major_axis ]); - + 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] ); @@ -98,11 +121,10 @@ 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->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)); + + 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 ); @@ -112,17 +134,18 @@ static void player_init_ragdoll_bone_collider( struct skeleton_bone *bone, m4x3_invert_affine( rp->collider_mtx, rp->inv_collider_mtx ); /* Position collider into rest */ - 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, 4.0f ); + 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 ){ +u32 ragdoll_bone_parent( struct player_ragdoll *rd, u32 bone_id ) +{ for( u32 j=0; jpart_count; j++ ) if( rd->parts[ j ].bone_id == bone_id ) return j; @@ -134,8 +157,9 @@ static u32 ragdoll_bone_parent( struct player_ragdoll *rd, u32 bone_id ){ /* * Setup ragdoll colliders from skeleton */ -static void setup_ragdoll_from_skeleton( struct skeleton *sk, - struct player_ragdoll *rd ){ +void setup_ragdoll_from_skeleton( struct skeleton *sk, + struct player_ragdoll *rd ) +{ rd->part_count = 0; if( !sk->collider_count ) @@ -187,8 +211,8 @@ static void setup_ragdoll_from_skeleton( struct skeleton *sk, rd->constraint_associations[conid][1] = part_id; /* Convention: rba -- parent, rbb -- child */ - c->rba = &pp->obj.rb; - c->rbb = &rp->obj.rb; + c->rba = &pp->rb; + c->rbb = &rp->rb; v3f delta; v3_sub( bj->co, bp->co, delta ); @@ -201,8 +225,8 @@ static void setup_ragdoll_from_skeleton( struct skeleton *sk, struct rb_constr_swingtwist *a = &rd->cone_constraints[ rd->cone_constraints_count ++ ]; - a->rba = &pp->obj.rb; - a->rbb = &rp->obj.rb; + a->rba = &pp->rb; + a->rbb = &rp->rb; a->conet = cosf( inf->conet )-0.0001f; /* Store constraint in local space vectors */ @@ -230,7 +254,8 @@ static void setup_ragdoll_from_skeleton( struct skeleton *sk, /* * Make avatar copy the ragdoll */ -static void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd ){ +void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd ) +{ for( int i=0; ipart_count; i++ ){ struct ragdoll_part *part = &rd->parts[i]; @@ -240,8 +265,8 @@ static void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd ){ v3f co_int; float substep = vg.time_fixed_extrapolate; - v3_lerp( part->prev_co, part->obj.rb.co, substep, co_int ); - q_nlerp( part->prev_q, part->obj.rb.q, substep, q_int ); + 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] ); @@ -274,8 +299,9 @@ 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, - enum player_die_type type ){ +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]; @@ -292,37 +318,38 @@ static void copy_localplayer_to_ragdoll( struct player_ragdoll *rd, m4x3_mulv( bone_mtx, localplayer.skeleton.bones[bone].co, pos ); m3x3_mulv( bone_mtx, part->collider_mtx[3], offset ); - v3_add( pos, offset, part->obj.rb.co ); + v3_add( pos, offset, part->rb.co ); m3x3f r; m3x3_mul( bone_mtx, part->collider_mtx, r ); - m3x3_q( r, part->obj.rb.q ); + m3x3_q( r, part->rb.q ); v3f ra, v; - v3_sub( part->obj.rb.co, centroid, ra ); + v3_sub( part->rb.co, centroid, ra ); v3_cross( localplayer.rb.w, ra, v ); - v3_add( localplayer.rb.v, v, part->obj.rb.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->obj.rb.v ); + v3_zero( part->rb.v ); } } - v3_copy( localplayer.rb.w, part->obj.rb.w ); + v3_copy( localplayer.rb.w, part->rb.w ); - v3_copy( part->obj.rb.co, part->prev_co ); - v4_copy( part->obj.rb.q, part->prev_q ); + v3_copy( part->rb.co, part->prev_co ); + v4_copy( part->rb.q, part->prev_q ); - rb_update_transform( &part->obj.rb ); + rb_update_matrices( &part->rb ); } } /* * Ragdoll physics step */ -static void player_ragdoll_iter( struct player_ragdoll *rd ){ +void player_ragdoll_iter( struct player_ragdoll *rd ) +{ world_instance *world = world_current_instance(); int run_sim = 0; @@ -337,32 +364,36 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){ float contact_velocities[256]; + rigidbody _null = {0}; + _null.inv_mass = 0.0f; + m3x3_zero( _null.iI ); + for( int i=0; ipart_count; i ++ ){ - v4_copy( rd->parts[i].obj.rb.q, rd->parts[i].prev_q ); - v3_copy( rd->parts[i].obj.rb.co, rd->parts[i].prev_co ); + 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].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, + 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].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 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; jparts[i].obj.rb; - buf[j].rbb = &world->rb_geo.rb; + buf[j].rba = &rd->parts[i].rb; + buf[j].rbb = &_null; } rb_contact_count += l; @@ -378,23 +409,23 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){ if( !rb_global_has_space() ) break; - if( rd->parts[j].obj.type != k_rb_shape_capsule ) + if( rd->parts[j].type != k_bone_collider_capsule ) continue; - if( rd->parts[i].obj.type != k_rb_shape_capsule ) + if( rd->parts[i].type != k_bone_collider_capsule ) continue; rb_ct *buf = rb_global_buffer(); - 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, + 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; kparts[i].obj.rb; - buf[k].rbb = &rd->parts[j].obj.rb; + buf[k].rba = &rd->parts[i].rb; + buf[k].rbb = &rd->parts[j].rb; } rb_contact_count += l; @@ -402,12 +433,15 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){ } } - if( world->water.enabled ){ - for( int j=0; jpart_count; j++ ){ + if( localplayer.drowned ) + { + for( int j=0; jpart_count; j++ ) + { struct ragdoll_part *pj = &rd->parts[j]; - if( run_sim ){ - rb_effect_simple_bouyency( &pj->obj.rb, world->water.plane, + if( run_sim ) + { + rb_effect_simple_bouyency( &pj->rb, world->water.plane, k_ragdoll_floatyiness, k_ragdoll_floatydrag ); } @@ -429,7 +463,8 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){ contact_velocities[i] = vn; } - rb_presolve_contacts( rb_contact_buffer, rb_contact_count ); + rb_presolve_contacts( rb_contact_buffer, vg.time_fixed_delta, + rb_contact_count ); rb_presolve_swingtwist_constraints( rd->cone_constraints, rd->cone_constraints_count ); @@ -437,8 +472,18 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){ * DEBUG */ if( k_ragdoll_debug_collider ){ - for( u32 i=0; ipart_count; i ++ ) - rb_object_debug( &rd->parts[i].obj, rd->parts[i].colour ); + for( u32 i=0; ipart_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 ){ @@ -474,19 +519,19 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){ k_ragdoll_correction * 0.25f ); for( int i=0; ipart_count; i++ ){ - rb_iter( &rd->parts[i].obj.rb ); + rb_iter( &rd->parts[i].rb ); v3f w; - v3_copy( rd->parts[i].obj.rb.w, w ); + v3_copy( rd->parts[i].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 ); + v3_muladds( rd->parts[i].rb.w, w, -k_ragdoll_angular_drag, + rd->parts[i].rb.w ); } } for( int i=0; ipart_count; i++ ) - rb_update_transform( &rd->parts[i].obj.rb ); + rb_update_matrices( &rd->parts[i].rb ); } rb_ct *stress = NULL; @@ -516,8 +561,6 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){ 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 ); @@ -560,14 +603,14 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){ v3f torque; v3_muls( axis, F, torque ); - v3_muladds( st->rbb->w, torque, k_rb_delta, st->rbb->w ); + v3_muladds( st->rbb->w, torque, vg.time_fixed_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 ); + v3_muladds( st->rbb->v, vcb, vg.time_fixed_delta, st->rbb->v ); #endif } } @@ -585,5 +628,3 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){ audio_unlock(); } } - -#endif /* PLAYER_RAGDOLL_C */