#include "player.h"
#include "audio.h"
-VG_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 );
}
-VG_STATIC void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
+static void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
struct ragdoll_part *rp )
{
m4x3_identity( rp->collider_mtx );
v3_zero( v1 );
v1[ major_axis ] = 1.0f;
- rb_tangent_basis( v1, tx, ty );
+ 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 ]);
/*
* Get parent index in the ragdoll
*/
-VG_STATIC u32 ragdoll_bone_parent( struct player_ragdoll *rd,
- struct player_avatar *av, u32 bone_id )
-{
+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;
}
/*
- * Setup ragdoll colliders
+ * Setup ragdoll colliders from skeleton
*/
-VG_STATIC void player_setup_ragdoll_from_avatar( struct player_ragdoll *rd,
- struct player_avatar *av )
-{
+static void setup_ragdoll_from_skeleton( struct skeleton *sk,
+ struct player_ragdoll *rd ){
rd->part_count = 0;
- if( !av->sk.collider_count )
+ if( !sk->collider_count )
return;
rd->position_constraints_count = 0;
rd->cone_constraints_count = 0;
- for( u32 i=1; i<av->sk.bone_count; i ++ ){
- struct skeleton_bone *bone = &av->sk.bones[i];
+ for( u32 i=1; i<sk->bone_count; i ++ ){
+ struct skeleton_bone *bone = &sk->bones[i];
/*
* Bones with colliders
if( !bone->parent )
continue;
- rp->parent = ragdoll_bone_parent( rd, av, bone->parent );
-
+ 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 ++ ];
- struct skeleton_bone *bj = &av->sk.bones[rp->bone_id];
+ struct skeleton_bone *bj = &sk->bones[rp->bone_id];
struct ragdoll_part *pp = &rd->parts[rp->parent];
- struct skeleton_bone *bp = &av->sk.bones[pp->bone_id];
+ struct skeleton_bone *bp = &sk->bones[pp->bone_id];
/* Convention: rba -- parent, rbb -- child */
c->rba = &pp->obj.rb;
/*
* Make avatar copy the ragdoll
*/
-VG_STATIC void copy_ragdoll_pose_to_avatar( struct player_ragdoll *rd,
- struct player_avatar *av )
-{
+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];
q_m3x3( q_int, mtx );
v3_copy( co_int, mtx[3] );
- m4x3_mul( mtx, part->inv_collider_mtx, av->sk.final_mtx[part->bone_id] );
+ m4x3_mul( mtx, part->inv_collider_mtx,
+ localplayer.final_mtx[part->bone_id] );
}
- for( u32 i=1; i<av->sk.bone_count; i++ ){
- struct skeleton_bone *sb = &av->sk.bones[i];
+ 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( av->sk.bones[i].co, av->sk.bones[sb->parent].co, 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( av->sk.final_mtx[sb->parent], posemtx, av->sk.final_mtx[i] );
+ m4x3_mul( localplayer.final_mtx[sb->parent], posemtx,
+ localplayer.final_mtx[i] );
}
}
- skeleton_apply_inverses( &av->sk );
+ skeleton_apply_inverses( &localplayer.skeleton, localplayer.final_mtx );
}
/*
* Make the ragdoll copy the player model
*/
-VG_STATIC void copy_avatar_pose_to_ragdoll( struct player_avatar *av,
- struct player_ragdoll *rd,
- v3f velocity )
-{
+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;
- m4x3_mulv( av->sk.final_mtx[bone], av->sk.bones[bone].co, pos );
- m3x3_mulv( av->sk.final_mtx[bone], part->collider_mtx[3], offset );
+ 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->obj.rb.co );
m3x3f r;
- m3x3_mul( av->sk.final_mtx[bone], part->collider_mtx, r );
+ m3x3_mul( bone_mtx, part->collider_mtx, r );
m3x3_q( r, part->obj.rb.q );
- v3_copy( velocity, 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 );
}
}
-/*
- * Draw rigidbody colliders for ragdoll
- */
-VG_STATIC void player_debug_ragdoll(void)
-{
-}
-
/*
* Ragdoll physics step
*/
-VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd )
-{
+static void player_ragdoll_iter( struct player_ragdoll *rd ){
world_instance *world = world_current_instance();
int run_sim = 0;
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 );
+ NULL, &world->rb_geo.inf.scene, 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 );
+ NULL, &world->rb_geo.inf.scene, buf,
+ k_material_flag_ghosts );
}
else continue;
}
}
- for( int j=0; j<rd->part_count; j++ ){
- struct ragdoll_part *pj = &rd->parts[j];
+ if( world->water.enabled ){
+ for( int j=0; j<rd->part_count; j++ ){
+ struct ragdoll_part *pj = &rd->parts[j];
- if( run_sim ){
- v4f plane = {0.0f,1.0f,0.0f,0.0f};
- rb_effect_simple_bouyency( &pj->obj.rb, plane,
- k_ragdoll_floatyiness,
- k_ragdoll_floatydrag );
+ if( run_sim ){
+ rb_effect_simple_bouyency( &pj->obj.rb, world->water.plane,
+ k_ragdoll_floatyiness,
+ k_ragdoll_floatydrag );
+ }
}
}
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;
if( stress ){
temp_filter = 20;
audio_lock();
- audio_oneshot_3d( &audio_hits[vg_randu32()%5], stress->co, 20.0f, 1.0f );
+ audio_oneshot_3d( &audio_hits[vg_randu32(&vg.rand)%5],
+ stress->co, 20.0f, 1.0f );
audio_unlock();
}
}