id_ik_elbow_l,
id_ik_elbow_r,
id_head,
+ id_foot_l,
+ id_foot_r,
id_ik_foot_l,
id_ik_foot_r,
id_ik_knee_l,
static void player__dead_im_gui(void){
}
-static void player__dead_transition(void){
+static void player__dead_transition( enum player_die_type type ){
localplayer.subsystem = k_player_subsystem_dead;
- copy_localplayer_to_ragdoll( &localplayer.ragdoll, localplayer.rb.v );
+ copy_localplayer_to_ragdoll( &localplayer.ragdoll, type );
struct ragdoll_part *part =
&localplayer.ragdoll.parts[ localplayer.id_hip-1 ];
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_transition (void);
+static void player__dead_transition ( enum player_die_type type );
static void player__dead_animator_exchange( bitpack_ctx *ctx, void *data );
struct player_subsystem_interface static player_subsystem_dead = {
#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,
/*
* 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 );
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 );
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;
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 );
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 );
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" );
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; i<localplayer.ragdoll.part_count; i ++ ){
state->trick_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] );
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;
}
}
rb_update_transform( &localplayer.rb );
player__skate_kill_audio();
- player__dead_transition();
+ player__dead_transition( k_player_die_type_head );
return;
}
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;
}
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;
}
}
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 );
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;
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; i<count; i++ )
v3_copy( n, buf[i].n );
rigidbody *rba = ct->rba,
*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 );
}
}
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;