X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=player_ragdoll.h;h=08ab5e75d9ff56ce37129ed4b7ed248d7c3d913e;hb=HEAD;hp=0d6d74d3f7cba96b03b2b23700585e97a1b9ba2c;hpb=deac3e6a1b3a8d28302bbc18c183c7fe64cbfb3e;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/player_ragdoll.h b/player_ragdoll.h index 0d6d74d..08ab5e7 100644 --- a/player_ragdoll.h +++ b/player_ragdoll.h @@ -1,346 +1,71 @@ -#ifndef PLAYER_RAGDOLL_H -#define PLAYER_RAGDOLL_H - -#include "player.h" - -VG_STATIC float k_ragdoll_floatyiness = 20.0f, - k_ragdoll_floatydrag = 1.0f, - k_ragdoll_limit_scale = 1.0f; - -VG_STATIC int k_ragdoll_div = 1, - ragdoll_frame = 0, - k_ragdoll_debug_collider = 1, - k_ragdoll_debug_constraints = 0; - -VG_STATIC void player_init_ragdoll_bone_collider( struct skeleton_bone *bone, - struct ragdoll_part *rp ) -{ - m4x3_identity( rp->collider_mtx ); - - if( bone->flags & k_bone_flag_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->rb.bbx[1] ); - v3_muls( delta, -1.0f, rp->rb.bbx[0] ); - - q_identity( rp->rb.q ); - rp->rb.type = k_rb_shape_box; - rp->colour = 0xffcccccc; - } - else if( bone->flags & k_bone_flag_collider_capsule ) - { - v3f v0, v1, tx, ty; - v3_sub( bone->hitbox[1], bone->hitbox[0], v0 ); - - int major_axis = 0; - float largest = -1.0f; - - for( int i=0; i<3; i ++ ) - { - if( fabsf( v0[i] ) > largest ) - { - largest = fabsf( v0[i] ); - major_axis = i; - } - } - - v3_zero( v1 ); - v1[ major_axis ] = 1.0f; - rb_tangent_basis( v1, tx, ty ); - - float r = (fabsf(v3_dot(tx,v0)) + fabsf(v3_dot(ty,v0))) * 0.25f, - l = fabsf(v0[ major_axis ]); - - /* orientation */ - v3_muls( tx, -1.0f, rp->collider_mtx[0] ); - v3_muls( v1, -1.0f, rp->collider_mtx[1] ); - v3_muls( ty, -1.0f, rp->collider_mtx[2] ); - 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->rb.type = k_rb_shape_capsule; - rp->rb.inf.capsule.height = l; - rp->rb.inf.capsule.radius = r; - - rp->colour = 0xff000000 | (0xff << (major_axis*8)); - } - else - vg_fatal_exit_loop( "Invalid bone collider type" ); - - m4x3_invert_affine( rp->collider_mtx, rp->inv_collider_mtx ); - - /* Position collider into rest */ - m3x3_q( rp->collider_mtx, rp->rb.q ); - v3_add( rp->collider_mtx[3], bone->co, rp->rb.co ); - rp->rb.is_world = 0; - rb_init( &rp->rb ); -} - -/* - * Get parent index in the ragdoll - */ -VG_STATIC u32 ragdoll_bone_parent( struct player_model *mdl, u32 bone_id ) -{ - for( u32 j=0; jragdoll_count; j++ ) - if( mdl->ragdoll[ j ].bone_id == bone_id ) - return j; - - vg_fatal_exit_loop( "Referenced parent bone does not have a rigidbody" ); - return 0; -} - -/* - * Setup ragdoll colliders - */ -VG_STATIC void player_init_ragdoll(void) -{ - struct player_model *mdl = &player.mdl; - mdl_context *src = &mdl->meta; - - if( !mdl->sk.collider_count ) - { - mdl->ragdoll_count = 0; - return; - } - - mdl->ragdoll_count = 0; - mdl->position_constraints_count = 0; - mdl->cone_constraints_count = 0; - - for( u32 i=0; isk.bone_count; i ++ ) - { - struct skeleton_bone *bone = &mdl->sk.bones[i]; - - /* - * Bones with colliders - */ - if( !(bone->flags & k_bone_flag_collider_any) ) - continue; - - if( mdl->ragdoll_count > vg_list_size(player.mdl.ragdoll) ) - vg_fatal_exit_loop( "Playermodel has too many colliders" ); - - struct ragdoll_part *rp = &mdl->ragdoll[ mdl->ragdoll_count ++ ]; - rp->bone_id = i; - rp->parent = 0xffffffff; - - player_init_ragdoll_bone_collider( bone, rp ); - - struct mdl_node *pnode = mdl_node_from_id( src, bone->orig_node ); - struct classtype_bone *inf = mdl_get_entdata( src, pnode ); - - /* - * Bones with collider and parent - */ - if( !bone->parent ) - continue; - - rp->parent = ragdoll_bone_parent( mdl, bone->parent ); - - /* Always assign a point-to-point constraint */ - struct rb_constr_pos *c = - &mdl->position_constraints[ mdl->position_constraints_count ++ ]; - - struct skeleton_bone *bj = &mdl->sk.bones[rp->bone_id]; - struct ragdoll_part *pp = &mdl->ragdoll[rp->parent]; - struct skeleton_bone *bp = &mdl->sk.bones[pp->bone_id]; - - /* Convention: rba -- parent, rbb -- child */ - c->rba = &pp->rb; - c->rbb = &rp->rb; - - v3f delta; - v3_sub( bj->co, bp->co, delta ); - m4x3_mulv( rp->inv_collider_mtx, (v3f){0.0f,0.0f,0.0f}, c->lcb ); - m4x3_mulv( pp->inv_collider_mtx, delta, c->lca ); - - if( inf->flags & k_bone_flag_cone_constraint ) - { - struct rb_constr_swingtwist *a = - &mdl->cone_constraints[ mdl->cone_constraints_count ++ ]; - a->rba = &pp->rb; - a->rbb = &rp->rb; - a->conet = cosf( inf->conet )-0.0001f; - - /* Store constraint in local space vectors */ - m3x3_mulv( c->rba->to_local, inf->conevx, a->conevx ); - m3x3_mulv( c->rba->to_local, inf->conevy, a->conevy ); - m3x3_mulv( c->rbb->to_local, inf->coneva, a->coneva ); - v3_copy( c->lca, a->view_offset ); - - v3_cross( inf->coneva, inf->conevy, a->conevxb ); - m3x3_mulv( c->rbb->to_local, a->conevxb, a->conevxb ); - - v3_normalize( a->conevxb ); - v3_normalize( a->conevx ); - v3_normalize( a->conevy ); - v3_normalize( a->coneva ); - - a->conevx[3] = v3_length( inf->conevx ); - a->conevy[3] = v3_length( inf->conevy ); - - rp->use_limits = 1; - } - } -} +#pragma once /* - * Make the player model copy the ragdoll + * Copyright (C) 2021-2024 Mt.ZERO Software - All Rights Reserved + * + * Ragdoll system */ -VG_STATIC void player_model_copy_ragdoll(void) -{ - struct player_model *mdl = &player.mdl; - for( int i=0; iragdoll_count; i++ ) - { - struct ragdoll_part *part = &mdl->ragdoll[i]; - m4x3f offset; - m3x3_identity(offset); - m4x3_mul( part->rb.to_world, part->inv_collider_mtx, - mdl->sk.final_mtx[part->bone_id] ); - } - - skeleton_apply_inverses( &mdl->sk ); -} - -/* - * Make the ragdoll copy the player model - */ -VG_STATIC void player_ragdoll_copy_model( v3f v ) -{ - struct player_model *mdl = &player.mdl; +#include "player_api.h" +#include "skeleton.h" +#include "vg/vg_rigidbody.h" +#include "vg/vg_rigidbody_constraints.h" - for( int i=0; iragdoll_count; i++ ) - { - struct ragdoll_part *part = &mdl->ragdoll[i]; - - v3f pos, offset; - u32 bone = part->bone_id; - - m4x3_mulv( mdl->sk.final_mtx[bone], mdl->sk.bones[bone].co, pos ); - m3x3_mulv( mdl->sk.final_mtx[bone], part->collider_mtx[3], offset ); - v3_add( pos, offset, part->rb.co ); - - m3x3f r; - m3x3_mul( mdl->sk.final_mtx[bone], part->collider_mtx, r ); - m3x3_q( r, part->rb.q ); - - v3_copy( v, part->rb.v ); - v3_zero( part->rb.w ); +struct player_ragdoll{ + struct ragdoll_part{ + u32 bone_id; - rb_update_transform( &part->rb ); - } -} + /* Collider transform relative to bone */ + m4x3f collider_mtx, + inv_collider_mtx; -/* - * Draw rigidbody colliders for ragdoll - */ -VG_STATIC void player_debug_ragdoll(void) -{ - struct player_model *mdl = &player.mdl; -} + v4f prev_q; + v3f prev_co; -/* - * Ragdoll physics step - */ -VG_STATIC void player_ragdoll_iter(void) -{ - struct player_model *mdl = &player.mdl; + u32 use_limits; + v3f limits[2]; - int run_sim = 0; - ragdoll_frame ++; + u32 parent; + u32 colour; - if( ragdoll_frame >= k_ragdoll_div ) - { - ragdoll_frame = 0; - run_sim = 1; - } + rigidbody rb; + enum bone_collider type; - rb_solver_reset(); - for( int i=0; iragdoll_count; i ++ ) - rb_collide( &mdl->ragdoll[i].rb, &world.rb_geo ); - - /* - * COLLISION DETECTION - */ - for( int i=0; iragdoll_count-1; i ++ ) - { - for( int j=i+1; jragdoll_count; j ++ ) - { - if( mdl->ragdoll[j].parent != i ) - rb_collide( &mdl->ragdoll[i].rb, &mdl->ragdoll[j].rb ); - } - } - - for( int j=0; jragdoll_count; j++ ) - { - struct ragdoll_part *pj = &mdl->ragdoll[j]; - struct skeleton_bone *bj = &mdl->sk.bones[pj->bone_id]; - - if( run_sim ) - { - v4f plane = {0.0f,1.0f,0.0f,0.0f}; - rb_effect_simple_bouyency( &pj->rb, plane, k_ragdoll_floatyiness, - k_ragdoll_floatydrag ); - } - } - - /* - * PRESOLVE - */ - rb_presolve_contacts( rb_contact_buffer, rb_contact_count ); - rb_presolve_swingtwist_constraints( mdl->cone_constraints, - mdl->cone_constraints_count ); - - /* - * DEBUG - */ - if( k_ragdoll_debug_collider ) - { - for( u32 i=0; iragdoll_count; i ++ ) - rb_debug( &mdl->ragdoll[i].rb, mdl->ragdoll[i].colour ); - } - - if( k_ragdoll_debug_constraints ) - { - rb_debug_position_constraints( mdl->position_constraints, - mdl->position_constraints_count ); - - rb_debug_swingtwist_constraints( mdl->cone_constraints, - mdl->cone_constraints_count ); - } - - /* - * SOLVE CONSTRAINTS - */ - if( run_sim ) - { - for( int i=0; i<25; i++ ) - { - rb_solve_contacts( rb_contact_buffer, rb_contact_count ); - rb_solve_swingtwist_constraints( mdl->cone_constraints, - mdl->cone_constraints_count ); - rb_solve_position_constraints( mdl->position_constraints, - mdl->position_constraints_count ); + union { + rb_capsule capsule; + boxf box; } - - for( int i=0; iragdoll_count; i++ ) - rb_iter( &mdl->ragdoll[i].rb ); - - for( int i=0; iragdoll_count; i++ ) - rb_update_transform( &mdl->ragdoll[i].rb ); - - rb_correct_swingtwist_constraints( mdl->cone_constraints, - mdl->cone_constraints_count, 0.25f ); - - rb_correct_position_constraints( mdl->position_constraints, - mdl->position_constraints_count, 0.5f ); + inf; } - -} - -#endif /* PLAYER_RAGDOLL_H */ + parts[32]; + u32 part_count; + + rb_constr_pos position_constraints[32]; + u32 position_constraints_count; + + rb_constr_swingtwist cone_constraints[32]; + u32 cone_constraints_count; + + /* TODO: Fix duplicated data */ + u32 constraint_associations[32][2]; + int shoes[2]; +}; + +enum player_die_type { + k_player_die_type_generic, + k_player_die_type_head, + k_player_die_type_feet +}; + +void player_ragdoll_init(void); +void player_init_ragdoll_bone_collider( struct skeleton_bone *bone, + struct ragdoll_part *rp ); +u32 ragdoll_bone_parent( struct player_ragdoll *rd, u32 bone_id ); +void setup_ragdoll_from_skeleton( struct skeleton *sk, + struct player_ragdoll *rd ); +void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd ); +void copy_localplayer_to_ragdoll( struct player_ragdoll *rd, + enum player_die_type type ); + +void player_debug_ragdoll(void); +void player_ragdoll_iter( struct player_ragdoll *rd );