}
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 );
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;
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;
}
/*
- * 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 );
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;
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;