X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=skeleton.h;h=9f715efa0e8391127df9169051b984171024d59c;hb=47941822dae18a018c985847b052e70214a3ccc6;hp=78a0b5604d5fd0facb8b903ece0631d5fcf35a15;hpb=4f96bd0040e35ecb21d353ee2b895129682d22c1;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/skeleton.h b/skeleton.h index 78a0b56..9f715ef 100644 --- a/skeleton.h +++ b/skeleton.h @@ -24,9 +24,22 @@ struct skeleton int collider; boxf hitbox; - char name[16]; + const char *name; } *bones; + u32 bone_count; + + struct skeleton_anim + { + const char *name; + u32 length; + + float rate; + mdl_keyframe *anim_data; + } + *anims; + u32 anim_count; + m4x3f *final_mtx; struct skeleton_ik @@ -35,28 +48,16 @@ struct skeleton m3x3f ia, ib; } *ik; + u32 ik_count; - struct skeleton_anim - { - float rate; - u32 length; - struct mdl_keyframe *anim_data; - char name[32]; - } - *anims; - - u32 bone_count, - ik_count, + u32 collider_count, - anim_count, - bindable_count; /* TODO: try to place IK last in the rig from export - so that we dont always upload transforms for - useless cpu IK bones. */ + bindable_count; }; -static u32 skeleton_bone_id( struct skeleton *skele, const char *name ) +VG_STATIC u32 skeleton_bone_id( struct skeleton *skele, const char *name ) { - for( u32 i=0; ibone_count; i++ ) + for( u32 i=1; ibone_count; i++ ) { if( !strcmp( skele->bones[i].name, name )) return i; @@ -65,7 +66,7 @@ static u32 skeleton_bone_id( struct skeleton *skele, const char *name ) return 0; } -static void keyframe_copy_pose( mdl_keyframe *kfa, mdl_keyframe *kfb, int num ) +VG_STATIC void keyframe_copy_pose( mdl_keyframe *kfa, mdl_keyframe *kfb, int num ) { for( int i=0; ibones[ id ], *sp = &skele->bones[ sb->parent ]; @@ -179,7 +180,7 @@ static int should_apply_bone( struct skeleton *skele, u32 id, anim_apply type ) /* * Apply block of keyframes to skeletons final pose */ -static void skeleton_apply_pose( struct skeleton *skele, mdl_keyframe *pose, +VG_STATIC void skeleton_apply_pose( struct skeleton *skele, mdl_keyframe *pose, anim_apply passtype ) { m4x3_identity( skele->final_mtx[0] ); @@ -217,7 +218,7 @@ static void skeleton_apply_pose( struct skeleton *skele, mdl_keyframe *pose, * creates the reference inverse matrix for an IK bone, as it has an initial * intrisic rotation based on the direction that the IK is setup.. */ -static void skeleton_inverse_for_ik( struct skeleton *skele, +VG_STATIC void skeleton_inverse_for_ik( struct skeleton *skele, v3f ivaxis, u32 id, m3x3f inverse ) { @@ -231,7 +232,7 @@ static void skeleton_inverse_for_ik( struct skeleton *skele, /* * Creates inverse rotation matrices which the IK system uses. */ -static void skeleton_create_inverses( struct skeleton *skele ) +VG_STATIC void skeleton_create_inverses( struct skeleton *skele ) { /* IK: inverse 'plane-bone space' axis '(^axis,^bone,...)[base] */ for( int i=0; iik_count; i++ ) @@ -241,7 +242,7 @@ static void skeleton_create_inverses( struct skeleton *skele ) m4x3f inverse; v3f iv0, iv1, ivaxis; v3_sub( skele->bones[ik->target].co, skele->bones[ik->lower].co, iv0 ); - v3_sub( skele->bones[ik->pole].co, skele->bones[ik->lower].co, iv1 ); + v3_sub( skele->bones[ik->pole].co, skele->bones[ik->lower].co, iv1 ); v3_cross( iv0, iv1, ivaxis ); v3_normalize( ivaxis ); @@ -253,7 +254,7 @@ static void skeleton_create_inverses( struct skeleton *skele ) /* * Apply a model matrix to all bones, should be done last */ -static void skeleton_apply_transform( struct skeleton *skele, m4x3f transform ) +VG_STATIC void skeleton_apply_transform( struct skeleton *skele, m4x3f transform ) { for( int i=0; ibone_count; i++ ) { @@ -266,7 +267,7 @@ static void skeleton_apply_transform( struct skeleton *skele, m4x3f transform ) * Apply an inverse matrix to all bones which maps vertices from bind space into * bone relative positions */ -static void skeleton_apply_inverses( struct skeleton *skele ) +VG_STATIC void skeleton_apply_inverses( struct skeleton *skele ) { for( int i=0; ibone_count; i++ ) { @@ -282,7 +283,7 @@ static void skeleton_apply_inverses( struct skeleton *skele ) /* * Apply all IK modifiers (2 bone ik reference from blender is supported) */ -static void skeleton_apply_ik_pass( struct skeleton *skele ) +VG_STATIC void skeleton_apply_ik_pass( struct skeleton *skele ) { for( int i=0; iik_count; i++ ) { @@ -362,7 +363,7 @@ static void skeleton_apply_ik_pass( struct skeleton *skele ) * Applies the typical operations that you want for an IK rig: * Pose, IK, Pose(deferred), Inverses, Transform */ -static void skeleton_apply_standard( struct skeleton *skele, mdl_keyframe *pose, +VG_STATIC void skeleton_apply_standard( struct skeleton *skele, mdl_keyframe *pose, m4x3f transform ) { skeleton_apply_pose( skele, pose, k_anim_apply_defer_ik ); @@ -375,7 +376,7 @@ static void skeleton_apply_standard( struct skeleton *skele, mdl_keyframe *pose, /* * Get an animation by name */ -static struct skeleton_anim *skeleton_get_anim( struct skeleton *skele, +VG_STATIC struct skeleton_anim *skeleton_get_anim( struct skeleton *skele, const char *name ) { for( int i=0; ianim_count; i++ ) @@ -389,8 +390,34 @@ static struct skeleton_anim *skeleton_get_anim( struct skeleton *skele, return NULL; } -/* Setup an animated skeleton from model */ -static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) +VG_STATIC void skeleton_alloc_from( struct skeleton *skele, + void *lin_alloc, + struct classtype_skeleton *inf ) +{ + skele->bone_count = inf->channels; + skele->ik_count = inf->ik_count; + skele->collider_count = inf->collider_count; + skele->anim_count = inf->anim_count; + + u32 bone_size = sizeof(struct skeleton_bone) * skele->bone_count, + ik_size = sizeof(struct skeleton_ik) * skele->ik_count, + mtx_size = sizeof(m4x3f) * skele->bone_count, + anim_size = sizeof(struct skeleton_anim) * skele->anim_count; + + skele->bones = vg_linear_alloc( lin_alloc, bone_size ); + skele->ik = vg_linear_alloc( lin_alloc, ik_size ); + skele->final_mtx = vg_linear_alloc( lin_alloc, mtx_size ); + skele->anims = vg_linear_alloc( lin_alloc, anim_size ); +} + +VG_STATIC void skeleton_fatal_err(void) +{ + vg_fatal_exit_loop( "Skeleton setup failed" ); +} + +/* Setup an animated skeleton from model. mdl's metadata should stick around */ +VG_STATIC void skeleton_setup( struct skeleton *skele, + void *lin_alloc, mdl_context *mdl ) { u32 bone_count = 1, skeleton_root = 0, ik_count = 0, collider_count = 0; skele->bone_count = 0; @@ -400,24 +427,14 @@ static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) struct classtype_skeleton *inf = NULL; - for( u32 i=0; inode_count; i++ ) + for( u32 i=0; iinfo.node_count; i++ ) { mdl_node *pnode = mdl_node_from_id( mdl, i ); if( pnode->classtype == k_classtype_skeleton ) { inf = mdl_get_entdata( mdl, pnode ); - if( skele->bone_count ) - { - vg_error( "Multiple skeletons in model file\n" ); - goto error_dealloc; - } - - skele->bone_count = inf->channels; - skele->ik_count = inf->ik_count; - skele->collider_count = inf->collider_count; - skele->bones =vg_alloc(sizeof(struct skeleton_bone)*skele->bone_count); - skele->ik = vg_alloc(sizeof(struct skeleton_ik)*skele->ik_count); + skeleton_alloc_from( skele, lin_alloc, inf ); skeleton_root = i; } else if( skele->bone_count ) @@ -432,7 +449,7 @@ static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) bone_count, skele->bone_count, mdl_pstr( mdl, pnode->pstr_name )); - goto error_dealloc; + skeleton_fatal_err(); } struct skeleton_bone *sb = &skele->bones[bone_count]; @@ -442,7 +459,7 @@ static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) v3_copy( pnode->co, sb->co ); v3_copy( pnode->s, sb->end ); sb->parent = pnode->parent-skeleton_root; - strncpy( sb->name, mdl_pstr(mdl,pnode->pstr_name), 15 ); + sb->name = mdl_pstr( mdl, pnode->pstr_name ); sb->deform = bone_inf->deform; if( is_ik ) @@ -453,7 +470,7 @@ static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) if( ik_count == skele->ik_count ) { vg_error( "Too many ik bones, corrupt model file\n" ); - goto error_dealloc; + skeleton_fatal_err(); } struct skeleton_ik *ik = &skele->ik[ ik_count ++ ]; @@ -476,7 +493,7 @@ static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) if( collider_count == skele->collider_count ) { vg_error( "Too many collider bones\n" ); - goto error_dealloc; + skeleton_fatal_err(); } collider_count ++; @@ -494,26 +511,27 @@ static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) if( !inf ) { vg_error( "No skeleton in model\n" ); - return 0; + skeleton_fatal_err(); } if( collider_count != skele->collider_count ) { vg_error( "Loaded %u colliders out of %u\n", collider_count, - skele->collider_count ); - goto error_dealloc; + skele->collider_count ); + skeleton_fatal_err(); } if( bone_count != skele->bone_count ) { vg_error( "Loaded %u bones out of %u\n", bone_count, skele->bone_count ); - goto error_dealloc; + vg_fatal_exit_loop( "Skeleton setup failed" ); + skeleton_fatal_err(); } if( ik_count != skele->ik_count ) { vg_error( "Loaded %u ik bones out of %u\n", ik_count, skele->ik_count ); - goto error_dealloc; + skeleton_fatal_err(); } /* fill in implicit root bone */ @@ -521,40 +539,29 @@ static int skeleton_setup( struct skeleton *skele, mdl_header *mdl ) v3_copy( (v3f){0.0f,1.0f,0.0f}, skele->bones[0].end ); skele->bones[0].parent = 0xffffffff; skele->bones[0].collider = 0; + skele->bones[0].name = "[root]"; - skele->final_mtx = vg_alloc( sizeof(m4x3f) * skele->bone_count ); - skele->anim_count = inf->anim_count; - skele->anims = vg_alloc( sizeof(struct skeleton_anim) * inf->anim_count); - - for( int i=0; ianim_count; i++ ) + /* process animation quick refs */ + for( int i=0; ianim_count; i++ ) { - mdl_animation *anim = - mdl_animation_from_id( mdl, inf->anim_start+i ); - - skele->anims[i].rate = anim->rate; - skele->anims[i].length = anim->length; - strncpy( skele->anims[i].name, mdl_pstr(mdl, anim->pstr_name), 31 ); + mdl_animation *anim = &mdl->anim_buffer[ inf->anim_start + i ]; - u32 total_keyframes = (skele->bone_count-1)*anim->length; - size_t block_size = sizeof(mdl_keyframe) * total_keyframes; - mdl_keyframe *dst = vg_alloc( block_size ); + skele->anims[i].rate = anim->rate; + skele->anims[i].length = anim->length; + skele->anims[i].name = mdl_pstr(mdl, anim->pstr_name); + skele->anims[i].anim_data = &mdl->keyframe_buffer[ anim->offset ]; - skele->anims[i].anim_data = dst; - memcpy( dst, mdl_get_animdata( mdl, anim ), block_size ); + vg_info( "animation[ %f, %u ] '%s'\n", anim->rate, + anim->length, + skele->anims[i].name ); } skeleton_create_inverses( skele ); vg_success( "Loaded skeleton with %u bones\n", skele->bone_count ); vg_success( " %u colliders\n", skele->collider_count ); - return 1; - -error_dealloc: - vg_free( skele->bones ); - vg_free( skele->ik ); - return 0; } -static void skeleton_debug( struct skeleton *skele ) +VG_STATIC void skeleton_debug( struct skeleton *skele ) { for( int i=0; ibone_count; i ++ ) {