From: hgn Date: Sun, 22 Sep 2024 13:40:18 +0000 (+0100) Subject: basic cutscene player (armatures only) X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;h=2f83f15bbd26ebc277a02f7fc3de197a2b89b1bd;p=carveJwlIkooP6JGAAIwe30JlM.git basic cutscene player (armatures only) --- diff --git a/content_skaterift/maps/mp_hq/main.mdl b/content_skaterift/maps/mp_hq/main.mdl new file mode 100644 index 0000000..e64efab Binary files /dev/null and b/content_skaterift/maps/mp_hq/main.mdl differ diff --git a/content_skaterift/metascenes/test_scene.ms b/content_skaterift/metascenes/test_scene.ms new file mode 100644 index 0000000..a112cfa Binary files /dev/null and b/content_skaterift/metascenes/test_scene.ms differ diff --git a/content_skaterift/playermodels/skaterift_john/ch_john.mdl b/content_skaterift/playermodels/skaterift_john/ch_john.mdl index f5f3239..717ce52 100644 Binary files a/content_skaterift/playermodels/skaterift_john/ch_john.mdl and b/content_skaterift/playermodels/skaterift_john/ch_john.mdl differ diff --git a/playermodels/skaterift_john/ch_john.mdl b/playermodels/skaterift_john/ch_john.mdl new file mode 100644 index 0000000..3a313d6 Binary files /dev/null and b/playermodels/skaterift_john/ch_john.mdl differ diff --git a/skaterift_blender/sr_main.py b/skaterift_blender/sr_main.py index 1ec554f..289bf1e 100644 --- a/skaterift_blender/sr_main.py +++ b/skaterift_blender/sr_main.py @@ -31,12 +31,14 @@ sr_entity_list = [ ('ent_objective', 'Objective', '', 18 ), ('ent_challenge', 'Challenge', '', 19 ), ('ent_relay', 'Relay', '', 20 ), + # reserved 21.. cubemap. ('ent_miniworld', 'Mini World', '', 22 ), ('ent_prop', 'Prop', '', 23 ), ('ent_list', 'Entity List', '', 24 ), ('ent_region', 'Region', '', 25 ), ('ent_glider', 'Glider', '', 26 ), - ('ent_npc', 'npc', '', 27 ) + ('ent_npc', 'npc', '', 27 ), + # reserved 28.. armature ] MDL_VERSION_NR = 107 @@ -54,6 +56,7 @@ def get_entity_enum_id( alias ): #} if alias == 'ent_cubemap': return 21 + if alias == 'mdl_armature': return 28 return 0 #} @@ -745,7 +748,7 @@ def sr_compile_mesh_internal( obj ): armature = mod.object rig_weight_groups = \ ['0 [ROOT]']+[_.name for _ in sr_armature_bones(mod.object)] - armature_id = sr_compile.entity_ids[armature.name] + armature_id = sr_entity_id( armature ) POSE_OR_REST_CACHE = armature.data.pose_position armature.data.pose_position = 'REST' diff --git a/skaterift_blender/sr_metascene.py b/skaterift_blender/sr_metascene.py index 73d3b91..cf076bf 100644 --- a/skaterift_blender/sr_metascene.py +++ b/skaterift_blender/sr_metascene.py @@ -90,7 +90,7 @@ class ms_instance(Structure): class ms_override(Structure): #{ - _fields_ = [("pstr_name",c_uint32), + _fields_ = [("entity_type",c_uint32), ("pstr_name",c_uint32), ("transform",mdl_transform)] #} @@ -138,7 +138,11 @@ def _metascene_armature_anims( obj, instance_id, override_id ): out_strip.instance_id = instance_id out_strip.object_id = override_id - if _metascene_action_cache( out_strip, action ): continue + if _metascene_action_cache( out_strip, action ): + #{ + _ms_compiler.strips.append( out_strip ) + continue + #} out_strip.data_mode = 0 out_strip.data_start = len( _ms_compiler.keyframes ) @@ -209,6 +213,7 @@ def _metascene_armature_anims( obj, instance_id, override_id ): # _ms_compiler.strips.append( out_strip ) print( F"[MS] | anim( {NLAStrip.action.name} )" ) + _ms_compiler.action_cache[ action.name ] = out_strip #} #} @@ -277,6 +282,8 @@ def _metascene_camera_anims( obj, entity_id ): out_strip = ms_strip() _metascene_compile_action_curves( out_strip, NLAStrip.action ) + out_strip.instance_id = 0xffffffff + out_strip.object_id = 0 # TODO out_strip.offset = math.floor( NLAStrip.frame_start ) out_strip.length = math.ceil( NLAStrip.frame_end - out_strip.offset ) out_strip.pstr_name = \ @@ -292,6 +299,15 @@ def _metascene_camera_anims( obj, entity_id ): for NLAStrip in NLALayer.strips: #{ print( F" have strip {NLAStrip.name}" ) + out_strip = ms_strip() + _metascene_compile_action_curves( out_strip, NLAStrip.action ) + out_strip.instance_id = 0xffffffff + out_strip.object_id = 0 # TODO + out_strip.offset = math.floor( NLAStrip.frame_start ) + out_strip.length = math.ceil( NLAStrip.frame_end - out_strip.offset ) + out_strip.pstr_name = \ + pack_string( _ms_compiler.strings, NLAStrip.name ) + _ms_compiler.strips.append( out_strip ) #} #} #} @@ -354,6 +370,7 @@ def _sr_export_metascene( path ): override_id = instance.override_count init = ms_override() + init.entity_type = get_entity_enum_id( obj_ent_type( o ) ) init.pstr_name = pack_string( _ms_compiler.strings, obj_name ) compile_obj_transform( o, init.transform ) @@ -382,7 +399,7 @@ def _sr_export_metascene( path ): return False #} - _metascene_camera_anims( o ) + _metascene_camera_anims( o, 0 ) #} #} @@ -412,6 +429,8 @@ def _sr_export_metascene( path ): print( F"Marker {marker.name}: {marker.camera}" ) #} + _ms_compiler.strips.sort( key=lambda s: s.offset ) + arrays = { 'strings': _ms_compiler.strings.buffer, 'ms_strip': _ms_compiler.strips, diff --git a/src/array_file.c b/src/array_file.c index 080b85c..6a50eb9 100644 --- a/src/array_file.c +++ b/src/array_file.c @@ -35,8 +35,8 @@ static void af_load_array_file_buffer( FILE *fp, array_file_meta *arr, } else { - vg_warn( "Applying alignment fixup to array @%p [%u -> %u] x %u\n", - buffer, arr->item_size, stride, arr->item_count ); + vg_warn( "Applying alignment fixup to array '%s' [%u -> %u] x %u\n", + arr->name, arr->item_size, stride, arr->item_count ); if( stride > arr->item_size ) memset( buffer, 0, stride*arr->item_count ); diff --git a/src/ent_npc.c b/src/ent_npc.c index ce0ac3d..dac28f6 100644 --- a/src/ent_npc.c +++ b/src/ent_npc.c @@ -21,7 +21,7 @@ void npc_load_model( struct npc *npc, const char *path ) mdl_load_metadata_block( meta, vg_mem.rtmemory ); struct skeleton *sk = &npc->skeleton; - skeleton_setup( sk, vg_mem.rtmemory, meta ); + skeleton_setup( sk, meta, 0, vg_mem.rtmemory ); u32 mtx_size = sizeof(m4x3f)*sk->bone_count; npc->final_mtx = vg_linear_alloc( vg_mem.rtmemory, mtx_size ); diff --git a/src/entity.h b/src/entity.h index 5120052..d7d7360 100644 --- a/src/entity.h +++ b/src/entity.h @@ -66,7 +66,9 @@ enum entity_alias{ k_ent_list = 24, k_ent_region = 25, k_ent_glider = 26, - k_ent_npc = 27 + k_ent_npc = 27, + k_ent_armature = 28, + k_ent_max }; typedef struct ent_call ent_call; diff --git a/src/metascene.c b/src/metascene.c index 4bb0ca1..7c7c92c 100644 --- a/src/metascene.c +++ b/src/metascene.c @@ -43,3 +43,569 @@ void metascene_load( ms_context *ms, const char *path, void *alloc ) alloc, sizeof(ms_curve_keyframe) ); fclose( fp ); } + +struct +{ + ms_context meta; + void *arena; + + bool ready; + + struct model_ref + { + const char *name; + u32 name_hash; + + mdl_context mdl; + + struct cs_skeleton + { + struct skeleton sk; + u32 skinning_offset; + } + *skeletons; + u32 total_skinning_bones; + } + * refs; + u32 unique_refs; + + struct cs_instance + { + u32 ref_id; + m4x3f *skinning_data; + } + * instances; + u32 instance_count; + + struct cs_sampler + { + ms_strip *strip; + ms_override *override; + union + { + struct + { + ms_track *track; + f32 *target; + } + curves; + + struct + { + struct skeleton *ref_sk; + m4x3f *skinning_data; + } + skeleton; + }; + } + samplers[32]; + u32 active_samplers; + + u32 strip; + f32 time; +} +_cutscene; + +void cutscene_debug_ui( ui_context *ctx ) +{ + ms_strip *usage[8]; + for( u32 i=0; ioffset + usage[k]->length < strip->offset ) + { + usage[k] = NULL; + } + } + + if( !usage[k] ) + { + usage[k] = strip; + layer = k; + break; + } + } + + ui_rect box = { strip->offset, layer*32, strip->length, 30 }; + u32 ps = strip->pstr_name, + colour = *((u32 *)af_arritm( &_cutscene.meta.strings, ps )); + + ui_fill( ctx, box, colour | 0xff000000 ); + ui_text( ctx, box, ps_get( &_cutscene.meta.strings, ps ), 1, + k_ui_align_middle_center, 0 ); + } + + ui_fill( ctx, (ui_rect){ (f32)_cutscene.time*_cutscene.meta.info.framerate, + 0, 1, VG_ARRAY_LEN(usage)*32 }, 0xffffffff ); +} + +/* + * Find associated entity data. We should also probably do this on the world + * thingy + */ +struct cs_asoc +{ + mdl_context *orig_data; + u16 entity_type, + entity_index; + ms_override *override; +}; + +static void _cutscene_override_asoc( u32 instance_id, u32 override_index, + struct cs_asoc *out_asoc ) +{ + struct cs_instance *instance = &_cutscene.instances[ instance_id ]; + mdl_context *mdl = &_cutscene.refs[ instance->ref_id ].mdl; + + ms_instance *oins = af_arritm( &_cutscene.meta.instances, instance_id ); + ms_override *override = + af_arritm( &_cutscene.meta.overrides, + oins->override_start + override_index ); + + out_asoc->orig_data = mdl; + out_asoc->entity_type = override->entity_type; + out_asoc->override = override; + const char *name = ps_get( &_cutscene.meta.strings, override->pstr_name ); + + if( out_asoc->entity_type != 28 ) + goto NOT_IMPLEMENTED; + + u32 name_hash = vg_strdjb2( name ); + for( u32 j=0; jarmatures ); j ++ ) + { + mdl_armature *armature = af_arritm( &mdl->armatures, j ); + if( ps_consteq( &mdl->strings, armature->pstr_name, + name, name_hash ) ) + { + out_asoc->entity_index = j; + return; + } + } + +NOT_IMPLEMENTED: + + vg_fatal_condition(); + vg_warn( "The data association was not found.\n" + " Entity Type: %u\n" + " Entity name: %s\n", override->entity_type, name ); + vg_fatal_exit(); +} + +static void _cutscene_get_strip_asoc( ms_strip *strip, + struct cs_asoc *out_asoc ) +{ + if( strip->instance_id == 0xffffffff ) + { + out_asoc->orig_data = NULL;// &_cutscene.meta; + out_asoc->entity_type = mdl_entity_id_type( strip->object_id ); + out_asoc->entity_index = mdl_entity_id_id( strip->object_id ); + out_asoc->override = NULL; + } + else + { + _cutscene_override_asoc( strip->instance_id, strip->object_id, out_asoc ); + } +} + +static void sync_cutscene_loaded( void *payload, u32 size ) +{ + vg_info( "Cutscene ready\n" ); + _cutscene.ready = 1; +} + +static void cutscene_load_thread( void *data ) +{ + const char *path = data; + vg_info( "Loading cutscene: %s\n", path ); + + u32 size = 20*1024*1024; + _cutscene.arena = + _vg_create_linear_allocator( NULL, size, VG_MEMORY_SYSTEM, "Cutscene" ); + + metascene_load( &_cutscene.meta, path, _cutscene.arena ); + + _cutscene.instance_count = af_arrcount( &_cutscene.meta.instances ); + _cutscene.instances = vg_linear_alloc( _cutscene.arena, + sizeof(struct cs_instance) * _cutscene.instance_count ); + + _cutscene.refs = NULL; + _cutscene.unique_refs = 0; + for( u32 i=0; i < _cutscene.instance_count; i ++ ) + { + ms_instance *instance = af_arritm( &_cutscene.meta.instances, i ); + const char *name = ps_get( &_cutscene.meta.strings, instance->pstr_name ); + + struct model_ref *ref = NULL; + u32 ref_id = 0; + + for( u32 j=0; j<_cutscene.unique_refs; j ++ ) + { + struct model_ref *ref_j = &_cutscene.refs[ j ]; + + if( ps_consteq( &_cutscene.meta.strings, instance->pstr_name, + ref_j->name, ref_j->name_hash ) ) + { + ref = ref_j; + ref_id = j; + break; + } + } + + if( !ref ) + { + _cutscene.refs = vg_linear_extend( _cutscene.arena, _cutscene.refs, + sizeof( struct model_ref ) ); + ref_id = _cutscene.unique_refs; + ref = &_cutscene.refs[ ref_id ]; + ref->name = name; + ref->name_hash = vg_strdjb2( name ); + vg_info( "Indexed reference '%s'\n", name ); + _cutscene.unique_refs ++; + } + + _cutscene.instances[ i ].ref_id = ref_id; + _cutscene.instances[ i ].skinning_data = NULL; + } + + /* load model data */ + for( u32 i=0; i<_cutscene.unique_refs; i ++ ) + { + struct model_ref *ref = &_cutscene.refs[ i ]; + char mdl_path_buf[ 512 ]; + vg_str mdl_path; + vg_strnull( &mdl_path, mdl_path_buf, sizeof(mdl_path_buf) ); + vg_strcat( &mdl_path, ref->name ); + vg_strcat( &mdl_path, ".mdl" ); + + vg_info( "Loading instance model: %s\n", mdl_path.buffer ); + mdl_open( &ref->mdl, mdl_path.buffer, _cutscene.arena ); + mdl_load_metadata_block( &ref->mdl, _cutscene.arena ); + mdl_async_full_load_std( &ref->mdl ); + mdl_close( &ref->mdl ); + + u32 skeleton_count = af_arrcount( &ref->mdl.armatures ); + if( skeleton_count ) + { + ref->skeletons = vg_linear_alloc( _cutscene.arena, + sizeof(struct cs_skeleton) * skeleton_count ); + + ref->total_skinning_bones = 0; + for( u32 j=0; jskeletons[ j ]; + skeleton_setup( &skele->sk, &ref->mdl, j, _cutscene.arena ); + skele->skinning_offset = ref->total_skinning_bones; + ref->total_skinning_bones += skele->sk.bone_count; + } + } + else + { + ref->skeletons = NULL; + ref->total_skinning_bones = 0; + } + } + + /* allocate skinning memory per-instance */ + for( u32 i=0; i<_cutscene.instance_count; i ++ ) + { + struct cs_instance *ins = &_cutscene.instances[ i ]; + struct model_ref *ref = &_cutscene.refs[ ins->ref_id ]; + + ins->skinning_data = vg_linear_alloc( _cutscene.arena, + sizeof(m4x3f) * ref->total_skinning_bones ); + + for( u32 j=0; jtotal_skinning_bones; j ++ ) + { + m4x3_identity( ins->skinning_data[ j ] ); + } + + /* load overrides */ + ms_instance *oins = af_arritm( &_cutscene.meta.instances, i ); + for( u32 j=0; joverride_count; j ++ ) + { + ms_override *override = + af_arritm( &_cutscene.meta.overrides, oins->override_start + j ); + + struct cs_asoc asoc; + _cutscene_override_asoc( i, j, &asoc ); + + VG_ASSERT( asoc.entity_type == 28 ); + + struct cs_skeleton *skele = &ref->skeletons[ asoc.entity_index ]; + + m4x3f mmdl; + mdl_transform_m4x3( &override->transform, mmdl ); + + for( u32 l=0; lsk.bone_count; l ++ ) + { + m4x3_copy( mmdl, ins->skinning_data[skele->skinning_offset+l] ); + } + } + } + + vg_async_call( sync_cutscene_loaded, NULL, 0 ); +} + +static int ccmd_cutscene_play( int argc, const char *argv[] ) +{ + if( argc == 1 ) + { + if( _cutscene.ready ) + { + vg_info( "Resetting cutscene..\n" ); + _cutscene.time = 0.0f; + _cutscene.strip = 0; + _cutscene.active_samplers = 0; + return 1; + } + + if( vg_loader_availible() ) + { + _cutscene.ready = 0; + _cutscene.time = 0.0f; + _cutscene.strip = 0; + _cutscene.active_samplers = 0; + + vg_linear_clear( vg_async.buffer ); + u32 len = strlen( argv[0] ) +1; + char *path_buf = vg_linear_alloc( vg_async.buffer, len ); + strcpy( path_buf, argv[0] ); + vg_loader_start( cutscene_load_thread, path_buf ); + return 1; + } + else + { + vg_error( "The loading thread is currently occupied.\n" ); + return 0; + } + } + else + { + vg_error( "Usage: cutscene path/to/cutscene.ms\n" ); + return 0; + } +} + +void cutscene_init(void) +{ + vg_console_reg_cmd( "cutscene", ccmd_cutscene_play, NULL ); +} + +/* + * Currently draws everything as skinned meshes. + */ +void cutscene_render_instance( struct cs_instance *ins, + world_instance *world, vg_camera *cam ) +{ + struct model_ref *ref = &_cutscene.refs[ ins->ref_id ]; + mdl_context *mdl = &ref->mdl; + mesh_bind( &mdl->mesh ); + + shader_model_character_view_use(); + shader_model_character_view_uCamera( cam->transform[3] ); + shader_model_character_view_uPv( cam->mtx.pv ); + shader_model_character_view_uDepthMode( 0 ); + + WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_character_view ); + + glActiveTexture( GL_TEXTURE0 ); + shader_model_character_view_uTexMain( 0 ); + + u32 armature_id = 0x00; + u32 material_id = 0x00; + + for( u32 i=0; imeshs ); i ++ ) + { + mdl_mesh *mesh = af_arritm( &mdl->meshs, i ); + VG_ASSERT( mesh->armature_id ); + + if( mesh->armature_id != armature_id ) + { + armature_id = mesh->armature_id; + u32 sk_index = mdl_entity_id_id( armature_id ); + + struct cs_skeleton *skele = &ref->skeletons[ sk_index ]; + + m4x3f *skinning_data = ins->skinning_data + skele->skinning_offset; + glUniformMatrix4x3fv( _uniform_model_character_view_uTransforms, + skele->sk.bone_count, + 0, + (const GLfloat *)skinning_data ); + } + + for( u32 j=0; jsubmesh_count; j ++ ) + { + mdl_submesh *sm = af_arritm( &mdl->submeshs, mesh->submesh_start+j ); + VG_ASSERT( sm->material_id ); + + if( sm->material_id != material_id ) + { + mdl_material *m = af_arritm( &mdl->materials, sm->material_id-1 ); + VG_ASSERT( m->shader == k_shader_standard ); + + struct shader_props_standard *props = m->props.compiled; + VG_ASSERT( props->tex_diffuse ); + + mdl_texture *tex = af_arritm( &mdl->textures, props->tex_diffuse-1); + glBindTexture( GL_TEXTURE_2D, tex->glname ); + } + + mdl_draw_submesh( sm ); + } + } +} + +void cutscene_update( f32 delta ) +{ + _cutscene.time += delta; + u32 frame = _cutscene.time * _cutscene.meta.info.framerate; + + /* clear out finished samplers */ + bool move = 0; + u32 j = 0; + for( u32 i=0; i<_cutscene.active_samplers; i ++ ) + { + struct cs_sampler *si = &_cutscene.samplers[i]; + + if( frame > (si->strip->offset + si->strip->length) ) + { + move = 1; + } + else + { + if( move ) + { + struct cs_sampler *sj = &_cutscene.samplers[j]; + *sj = *si; + } + + j ++; + } + } + _cutscene.active_samplers = j; + + /* add new samplers as we get to them */ + for( u32 i=_cutscene.strip; ioffset ) + { + break; + } + + if( frame > strip->offset + strip->length ) + { + vg_warn( "Skipping?\n" ); + _cutscene.strip ++; + continue; + } + + if( strip->instance_id == 0xffffffff ) + { + // TODO + _cutscene.strip ++; + continue; + } + + struct cs_instance *ins = &_cutscene.instances[ strip->instance_id ]; + + struct cs_asoc asoc; + _cutscene_get_strip_asoc( strip, &asoc ); + VG_ASSERT( asoc.entity_type == 28 ); + + if( strip->data_mode == 1 ) + { + for( u32 j=0; jdata_count; j ++ ) + { + ms_track *track = af_arritm( &_cutscene.meta.tracks, + strip->data_start + j ); + + VG_ASSERT( _cutscene.active_samplers < + VG_ARRAY_LEN(_cutscene.samplers) ); + + struct cs_sampler *samp = + &_cutscene.samplers[ _cutscene.active_samplers ++ ]; + samp->strip = strip; + samp->curves.track = track; + samp->curves.target = NULL; /* DOTO */ + samp->override = asoc.override; + } + } + else + { + VG_ASSERT( _cutscene.active_samplers < + VG_ARRAY_LEN(_cutscene.samplers) ); + + struct cs_sampler *samp = + &_cutscene.samplers[ _cutscene.active_samplers ++ ]; + + struct model_ref *ref = &_cutscene.refs[ ins->ref_id ]; + struct cs_skeleton *skele = &ref->skeletons[ asoc.entity_index ]; + + samp->strip = strip; + samp->skeleton.skinning_data = + &ins->skinning_data[ skele->skinning_offset ]; + samp->skeleton.ref_sk = &skele->sk; + samp->override = asoc.override; + } + + _cutscene.strip ++; + } + + /* sample da samplers */ + for( u32 i=0; i<_cutscene.active_samplers; i ++ ) + { + struct cs_sampler *samp = &_cutscene.samplers[ i ]; + + struct skeleton_anim temp_anim = + { + .strip = samp->strip, + .framerate = _cutscene.meta.info.framerate, + .keyframes_base = af_arritm( &_cutscene.meta.keyframes, + samp->strip->data_start ) + }; + + f32 t = _cutscene.time; + t -= (f32)samp->strip->offset / _cutscene.meta.info.framerate; + + struct skeleton *ref_sk = samp->skeleton.ref_sk; + m4x3f *final_mtx = samp->skeleton.skinning_data; + + ms_keyframe pose[32]; + skeleton_sample_anim( ref_sk, &temp_anim, t, pose ); + + skeleton_apply_pose( ref_sk, pose, + k_anim_apply_defer_ik, final_mtx ); + skeleton_apply_ik_pass( ref_sk, final_mtx ); + skeleton_apply_pose( ref_sk, pose, + k_anim_apply_deffered_only, final_mtx ); + skeleton_apply_inverses( ref_sk, final_mtx ); + + if( samp->override ) + { + m4x3f mmdl; + mdl_transform_m4x3( &samp->override->transform, mmdl ); + skeleton_apply_transform( ref_sk, mmdl, final_mtx ); + } + } +} + +void cutscene_render( world_instance *world, vg_camera *cam ) +{ + if( _cutscene.ready ) + { + for( u32 i=0; i<_cutscene.instance_count; i ++ ) + { + cutscene_render_instance( &_cutscene.instances[i], world, cam ); + } + } +} diff --git a/src/metascene.h b/src/metascene.h index 6b7685d..f95eedc 100644 --- a/src/metascene.h +++ b/src/metascene.h @@ -1,5 +1,6 @@ #pragma once #include "model.h" +#include "world.h" #define MS_VERSION_NR 1 #define MS_VERSION_MIN 1 @@ -43,7 +44,7 @@ struct ms_instance struct ms_override { - u32 pstr_name; + u32 entity_type, pstr_name; mdl_transform transform; }; @@ -74,3 +75,7 @@ struct ms_curve_keyframe }; void metascene_load( ms_context *ms, const char *path, void *alloc ); +void cutscene_init(void); +void cutscene_render( world_instance *world, vg_camera *cam ); +void cutscene_debug_ui( ui_context *ctx ); +void cutscene_update( f32 delta ); diff --git a/src/model.c b/src/model.c index fc7e387..e493096 100644 --- a/src/model.c +++ b/src/model.c @@ -528,4 +528,5 @@ void mdl_async_full_load_std( mdl_context *mdl ) VG_TEX2D_CLAMP|VG_TEX2D_NEAREST, &tex->glname ); } } + #endif diff --git a/src/player_render.c b/src/player_render.c index 1531c34..31346d7 100644 --- a/src/player_render.c +++ b/src/player_render.c @@ -54,7 +54,7 @@ void player_load_animation_reference( const char *path ) mdl_close( meta ); struct skeleton *sk = &localplayer.skeleton; - skeleton_setup( sk, vg_mem.rtmemory, meta ); + skeleton_setup( sk, meta, 0, vg_mem.rtmemory ); localplayer.id_world = skeleton_bone_id( sk, "world" ); localplayer.id_hip = skeleton_bone_id( sk, "hips" ); diff --git a/src/skaterift.c b/src/skaterift.c index b28ee45..1137548 100644 --- a/src/skaterift.c +++ b/src/skaterift.c @@ -163,6 +163,7 @@ void game_load(void) vg_loader_step( player_init, NULL ); vg_loader_step( player_ragdoll_init, NULL ); vg_loader_step( npc_init, NULL ); + vg_loader_step( cutscene_init, NULL ); /* content stuff */ vg_loader_step( addon_system_init, NULL ); @@ -240,6 +241,8 @@ void vg_pre_update(void) vg_slewf( &skaterift.time_rate, target, vg.time_frame_delta * (1.0f/0.3f) ); vg.time_rate = vg_smoothstepf( skaterift.time_rate ); + + cutscene_update( vg.time_rate * vg.time_frame_delta ); /* TODO: how can we compress this? */ ent_miniworld_preupdate(); @@ -607,6 +610,7 @@ void vg_gui( ui_context *ctx ) skaterift_replay_imgui( ctx ); workshop_form_gui( ctx ); remote_player_network_imgui( ctx, vg.pv ); + cutscene_debug_ui( ctx ); if( menu_viewing_map() ) { diff --git a/src/skeleton.h b/src/skeleton.h index 9a3be61..a62c3e3 100644 --- a/src/skeleton.h +++ b/src/skeleton.h @@ -16,7 +16,7 @@ struct skeleton u32 flags; int defer; - ms_keyframe kf; + //ms_keyframe kf; mdl_bone *orig_bone; u32 collider; @@ -34,8 +34,7 @@ struct skeleton *ik; u32 ik_count; - u32 - collider_count, + u32 collider_count, bindable_count; }; @@ -442,8 +441,7 @@ static void skeleton_alloc_from( struct skeleton *skele, } 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; + ik_size = sizeof(struct skeleton_ik) * skele->ik_count; skele->bones = vg_linear_alloc( lin_alloc, bone_size ); skele->ik = vg_linear_alloc( lin_alloc, ik_size ); @@ -457,18 +455,20 @@ static void skeleton_fatal_err(void){ } /* Setup a skeleton from model. mdl's metadata should stick around */ -static void skeleton_setup( struct skeleton *skele, - void *lin_alloc, mdl_context *mdl ){ +void skeleton_setup( struct skeleton *skele, mdl_context *mdl, u32 index, + void *lin_alloc ) +{ u32 ik_count = 0, collider_count = 0; skele->bone_count = 0; skele->bones = NULL; - if( !mdl->armatures.count ){ + if( !mdl->armatures.count ) + { vg_error( "No skeleton in model\n" ); skeleton_fatal_err(); } - mdl_armature *armature = af_arritm( &mdl->armatures, 0 ); + mdl_armature *armature = af_arritm( &mdl->armatures, index ); skeleton_alloc_from( skele, lin_alloc, mdl, armature ); for( u32 i=0; ibone_count; i++ ) @@ -520,22 +520,6 @@ static void skeleton_setup( struct skeleton *skele, skele->bones[0].parent = 0xffffffff; skele->bones[0].flags = 0; skele->bones[0].name = "[root]"; - - /* process animation quick refs */ - // for( u32 i=0; ianim_count; i++ ){ - // mdl_animation *anim = - // af_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 = - // af_arritm( &mdl->keyframes, anim->offset ); - - // 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 ); diff --git a/src/world_render.c b/src/world_render.c index b7a6732..4075981 100644 --- a/src/world_render.c +++ b/src/world_render.c @@ -1018,6 +1018,8 @@ static void render_other_entities( world_instance *world, vg_camera *cam ) npc_update( npc ); npc_render( npc, world, cam ); } + + cutscene_render( world, cam ); } void render_world( world_instance *world, vg_camera *cam,