X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=skeleton.h;h=79e80171b2acc49935c11ac5ad973122b3bf54e1;hb=badfa88dd109bbae5628f58504402f4707569f73;hp=4f35d58e25d50681b462cfac7596f3a8b02991da;hpb=2a238d32da833812e837cf38e16a7685c98db5c3;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/skeleton.h b/skeleton.h index 4f35d58..79e8017 100644 --- a/skeleton.h +++ b/skeleton.h @@ -18,9 +18,9 @@ struct skeleton int defer; mdl_keyframe kf; + mdl_bone *orig_bone; - u32 orig_node; - + u32 collider; boxf hitbox; const char *name; } @@ -55,53 +55,76 @@ struct skeleton VG_STATIC u32 skeleton_bone_id( struct skeleton *skele, const char *name ) { - for( u32 i=1; ibone_count; i++ ) - { + for( u32 i=1; ibone_count; i++ ){ if( !strcmp( skele->bones[i].name, name )) return i; } + vg_error( "skeleton_bone_id( *, \"%s\" );\n", name ); + vg_fatal_error( "Bone does not exist\n" ); + return 0; } -VG_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; ico, offset, co ); + v3_sub( co, origin, v0 ); + q_mulv( q, v0, v0 ); + v3_add( v0, origin, co ); + v3_sub( co, offset, kf->co ); + + q_mul( q, kf->q, kf->q ); + q_normalize( kf->q ); +} + /* * Lerp between two sets of keyframes and store in dest. Rotations use Nlerp. */ -VG_STATIC void keyframe_lerp_pose( mdl_keyframe *kfa, mdl_keyframe *kfb, float t, - mdl_keyframe *kfd, int count ) +VG_STATIC void keyframe_lerp_pose( mdl_keyframe *kfa, mdl_keyframe *kfb, + float t, mdl_keyframe *kfd, int count ) { - if( t <= 0.01f ) - { + if( t <= 0.0001f ){ keyframe_copy_pose( kfa, kfd, count ); return; } - else if( t >= 0.99f ) - { + else if( t >= 0.9999f ){ keyframe_copy_pose( kfb, kfd, count ); return; } - for( int i=0; ibone_count-1 ); } +VG_STATIC void skeleton_copy_pose( struct skeleton *skele, + mdl_keyframe *kfa, mdl_keyframe *kfd ) +{ + keyframe_copy_pose( kfa, kfd, skele->bone_count-1 ); +} + /* * Sample animation between 2 closest frames using time value. Output is a * keyframe buffer that is allocated with an appropriate size @@ -146,27 +169,25 @@ typedef enum anim_apply } anim_apply; -VG_STATIC int should_apply_bone( struct skeleton *skele, u32 id, anim_apply type ) +VG_STATIC +int should_apply_bone( struct skeleton *skele, u32 id, anim_apply type ) { struct skeleton_bone *sb = &skele->bones[ id ], *sp = &skele->bones[ sb->parent ]; - if( type == k_anim_apply_defer_ik ) - { + if( type == k_anim_apply_defer_ik ){ if( ((sp->flags & k_bone_flag_ik) && !(sb->flags & k_bone_flag_ik)) || sp->defer ) { sb->defer = 1; return 0; } - else - { + else{ sb->defer = 0; return 1; } } - else if( type == k_anim_apply_deffered_only ) - { + else if( type == k_anim_apply_deffered_only ){ if( sb->defer ) return 1; else @@ -180,16 +201,15 @@ VG_STATIC int should_apply_bone( struct skeleton *skele, u32 id, anim_apply type * Apply block of keyframes to skeletons final pose */ VG_STATIC void skeleton_apply_pose( struct skeleton *skele, mdl_keyframe *pose, - anim_apply passtype ) + anim_apply passtype ) { m4x3_identity( skele->final_mtx[0] ); skele->bones[0].defer = 0; skele->bones[0].flags &= ~k_bone_flag_ik; - for( int i=1; ibone_count; i++ ) - { + for( u32 i=1; ibone_count; i++ ){ struct skeleton_bone *sb = &skele->bones[i], - *sp = &skele->bones[ sb->parent ]; + *sp = &skele->bones[sb->parent]; if( !should_apply_bone( skele, i, passtype ) ) continue; @@ -234,8 +254,7 @@ VG_STATIC void skeleton_inverse_for_ik( 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++ ) - { + for( u32 i=0; iik_count; i++ ){ struct skeleton_ik *ik = &skele->ik[i]; m4x3f inverse; @@ -253,10 +272,10 @@ VG_STATIC void skeleton_create_inverses( struct skeleton *skele ) /* * Apply a model matrix to all bones, should be done last */ -VG_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++ ) - { + for( u32 i=0; ibone_count; i++ ){ struct skeleton_bone *sb = &skele->bones[i]; m4x3_mul( transform, skele->final_mtx[i], skele->final_mtx[i] ); } @@ -268,8 +287,7 @@ VG_STATIC void skeleton_apply_transform( struct skeleton *skele, m4x3f transform */ VG_STATIC void skeleton_apply_inverses( struct skeleton *skele ) { - for( int i=0; ibone_count; i++ ) - { + for( u32 i=0; ibone_count; i++ ){ struct skeleton_bone *sb = &skele->bones[i]; m4x3f inverse; m3x3_identity( inverse ); @@ -284,8 +302,7 @@ VG_STATIC void skeleton_apply_inverses( struct skeleton *skele ) */ VG_STATIC void skeleton_apply_ik_pass( struct skeleton *skele ) { - for( int i=0; iik_count; i++ ) - { + for( u32 i=0; iik_count; i++ ){ struct skeleton_ik *ik = &skele->ik[i]; v3f v0, /* base -> target */ @@ -376,27 +393,40 @@ VG_STATIC void skeleton_apply_standard( struct skeleton *skele, mdl_keyframe *po * Get an animation by name */ VG_STATIC struct skeleton_anim *skeleton_get_anim( struct skeleton *skele, - const char *name ) + const char *name ) { - for( int i=0; ianim_count; i++ ) - { + for( u32 i=0; ianim_count; i++ ){ struct skeleton_anim *anim = &skele->anims[i]; if( !strcmp( anim->name, name ) ) return anim; } + vg_error( "skeleton_get_anim( *, \"%s\" )\n", name ); + vg_fatal_error( "Invalid animation name\n" ); + return NULL; } VG_STATIC void skeleton_alloc_from( struct skeleton *skele, - void *lin_alloc, - struct classtype_skeleton *inf ) + void *lin_alloc, + mdl_context *mdl, + mdl_armature *armature ) { - skele->bone_count = inf->channels; - skele->ik_count = inf->ik_count; - skele->collider_count = inf->collider_count; - skele->anim_count = inf->anim_count; + skele->bone_count = armature->bone_count+1; + skele->anim_count = armature->anim_count; + skele->ik_count = 0; + skele->collider_count = 0; + + for( u32 i=0; ibone_count; i++ ){ + mdl_bone *bone = mdl_arritm( &mdl->bones, armature->bone_start+i ); + + if( bone->flags & k_bone_flag_ik ) + skele->ik_count ++; + + if( bone->collider ) + skele->collider_count ++; + } u32 bone_size = sizeof(struct skeleton_bone) * skele->bone_count, ik_size = sizeof(struct skeleton_ik) * skele->ik_count, @@ -411,119 +441,65 @@ VG_STATIC void skeleton_alloc_from( struct skeleton *skele, VG_STATIC void skeleton_fatal_err(void) { - vg_fatal_exit_loop( "Skeleton setup failed" ); + vg_fatal_error( "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; + u32 ik_count = 0, collider_count = 0; skele->bone_count = 0; skele->bones = NULL; skele->final_mtx = NULL; skele->anims = NULL; - struct classtype_skeleton *inf = NULL; + if( !mdl->armatures.count ){ + vg_error( "No skeleton in model\n" ); + skeleton_fatal_err(); + } - for( u32 i=0; iinfo.node_count; i++ ) - { - mdl_node *pnode = mdl_node_from_id( mdl, i ); + mdl_armature *armature = mdl_arritm( &mdl->armatures, 0 ); + skeleton_alloc_from( skele, lin_alloc, mdl, armature ); - if( pnode->classtype == k_classtype_skeleton ) - { - inf = mdl_get_entdata( mdl, pnode ); - skeleton_alloc_from( skele, lin_alloc, inf ); - skeleton_root = i; - } - else if( skele->bone_count ) - { - int is_bone = pnode->classtype == k_classtype_bone; - - if( is_bone ) - { - if( bone_count == skele->bone_count ) - { - vg_error( "too many bones (%u/%u) @%s!\n", - bone_count, skele->bone_count, - mdl_pstr( mdl, pnode->pstr_name )); - - skeleton_fatal_err(); - } - - struct skeleton_bone *sb = &skele->bones[bone_count]; - struct classtype_bone *bone_inf = mdl_get_entdata( mdl, pnode ); - - v3_copy( pnode->co, sb->co ); - v3_copy( pnode->s, sb->end ); - sb->parent = pnode->parent-skeleton_root; - sb->name = mdl_pstr( mdl, pnode->pstr_name ); - sb->flags = bone_inf->flags; - - if( sb->flags & k_bone_flag_ik ) - { - skele->bones[ sb->parent ].flags |= k_bone_flag_ik; - - if( ik_count == skele->ik_count ) - { - vg_error( "Too many ik bones, corrupt model file\n" ); - skeleton_fatal_err(); - } - - struct skeleton_ik *ik = &skele->ik[ ik_count ++ ]; - ik->upper = bone_count; - ik->lower = sb->parent; - ik->target = bone_inf->ik_target; - ik->pole = bone_inf->ik_pole; - } - - sb->orig_node = i; - box_copy( bone_inf->hitbox, sb->hitbox ); - - if( bone_inf->flags & k_bone_flag_collider_any ) - { - if( collider_count == skele->collider_count ) - { - vg_error( "Too many collider bones\n" ); - skeleton_fatal_err(); - } - - collider_count ++; - } - - bone_count ++; - } - else - { - break; + for( u32 i=0; ibone_count; i++ ){ + mdl_bone *bone = mdl_arritm( &mdl->bones, armature->bone_start+i ); + struct skeleton_bone *sb = &skele->bones[i+1]; + + v3_copy( bone->co, sb->co ); + v3_copy( bone->end, sb->end ); + + sb->parent = bone->parent; + sb->name = mdl_pstr( mdl, bone->pstr_name ); + sb->flags = bone->flags; + sb->collider = bone->collider; + sb->orig_bone = bone; + + if( sb->flags & k_bone_flag_ik ){ + skele->bones[ sb->parent ].flags |= k_bone_flag_ik; + + if( ik_count == skele->ik_count ){ + vg_error( "Too many ik bones, corrupt model file\n" ); + skeleton_fatal_err(); } - } - } - if( !inf ) - { - vg_error( "No skeleton in model\n" ); - skeleton_fatal_err(); - } + struct skeleton_ik *ik = &skele->ik[ ik_count ++ ]; + ik->upper = i+1; + ik->lower = bone->parent; + ik->target = bone->ik_target; + ik->pole = bone->ik_pole; + } - if( collider_count != skele->collider_count ) - { - vg_error( "Loaded %u colliders out of %u\n", collider_count, - skele->collider_count ); - skeleton_fatal_err(); - } + box_copy( bone->hitbox, sb->hitbox ); - if( bone_count != skele->bone_count ) - { - vg_error( "Loaded %u bones out of %u\n", bone_count, skele->bone_count ); - vg_fatal_exit_loop( "Skeleton setup failed" ); - skeleton_fatal_err(); - } + if( bone->collider ){ + if( collider_count == skele->collider_count ){ + vg_error( "Too many collider bones\n" ); + skeleton_fatal_err(); + } - if( ik_count != skele->ik_count ) - { - vg_error( "Loaded %u ik bones out of %u\n", ik_count, skele->ik_count ); - skeleton_fatal_err(); + collider_count ++; + } } /* fill in implicit root bone */ @@ -534,14 +510,15 @@ VG_STATIC void skeleton_setup( struct skeleton *skele, skele->bones[0].name = "[root]"; /* process animation quick refs */ - for( int i=0; ianim_count; i++ ) - { - mdl_animation *anim = &mdl->anim_buffer[ inf->anim_start + i ]; + for( u32 i=0; ianim_count; i++ ){ + mdl_animation *anim = + mdl_arritm( &mdl->animations, armature->anim_start+i ); 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 = + mdl_arritm( &mdl->keyframes, anim->offset ); vg_info( "animation[ %f, %u ] '%s'\n", anim->rate, anim->length, @@ -555,26 +532,21 @@ VG_STATIC void skeleton_setup( struct skeleton *skele, VG_STATIC void skeleton_debug( struct skeleton *skele ) { - for( int i=0; ibone_count; i ++ ) - { + for( u32 i=1; ibone_count; i ++ ){ struct skeleton_bone *sb = &skele->bones[i]; v3f p0, p1; v3_copy( sb->co, p0 ); v3_add( p0, sb->end, p1 ); - //vg_line( p0, p1, 0xffffffff ); m4x3_mulv( skele->final_mtx[i], p0, p0 ); m4x3_mulv( skele->final_mtx[i], p1, p1 ); - if( sb->flags & k_bone_flag_deform ) - { - if( sb->flags & k_bone_flag_ik ) - { + if( sb->flags & k_bone_flag_deform ){ + if( sb->flags & k_bone_flag_ik ){ vg_line( p0, p1, 0xff0000ff ); } - else - { + else{ vg_line( p0, p1, 0xffcccccc ); } }