X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;ds=sidebyside;f=world_entity.c;h=cdc76f1ae23d96d5bde4957843f86ea791e7ba7a;hb=HEAD;hp=a12e071ade86fdf4a749ea840e1f61edcc434ed7;hpb=874c9d7e6ee2d826f9eb34518e8163283439c38e;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/world_entity.c b/world_entity.c deleted file mode 100644 index a12e071..0000000 --- a/world_entity.c +++ /dev/null @@ -1,647 +0,0 @@ -#ifndef WORLD_ENTITY_C -#define WORLD_ENTITY_C - -#include "model.h" -#include "entity.h" -#include "world.h" -#include "world_load.h" -#include "save.h" -#include "vg/vg_msg.h" -#include "menu.h" -#include "ent_challenge.h" -#include "ent_skateshop.h" -#include "ent_route.h" - -static void world_entity_focus( u32 entity_id ){ - localplayer.immobile = 1; - menu.disable_open = 1; - - v3_zero( localplayer.rb.v ); - v3_zero( localplayer.rb.w ); - player_walk.move_speed = 0.0f; - world_static.focused_entity = entity_id; - skaterift.activity = k_skaterift_ent_focus; -} - -static void world_entity_unfocus(void){ - localplayer.immobile = 0; - skaterift.activity = k_skaterift_default; - menu.disable_open = 0; - srinput.state = k_input_state_resume; -} - -static void world_entity_focus_camera( world_instance *world, u32 uid ){ - if( mdl_entity_id_type( uid ) == k_ent_camera ){ - u32 index = mdl_entity_id_id( uid ); - ent_camera *cam = mdl_arritm( &world->ent_camera, index ); - - v3f dir = {0.0f,-1.0f,0.0f}; - mdl_transform_vector( &cam->transform, dir, dir ); - v3_angles( dir, world_static.focus_cam.angles ); - v3_copy( cam->transform.co, world_static.focus_cam.pos ); - world_static.focus_cam.fov = cam->fov; - } - else { - camera_copy( &localplayer.cam, &world_static.focus_cam ); - - /* TODO ? */ - world_static.focus_cam.nearz = localplayer.cam.nearz; - world_static.focus_cam.farz = localplayer.cam.farz; - } -} - -/* logic preupdate */ -static void world_entity_focus_preupdate(void){ - f32 rate = vg_minf( 1.0f, vg.time_frame_delta * 2.0f ); - int active = 0; - if( skaterift.activity == k_skaterift_ent_focus ) - active = 1; - - vg_slewf( &world_static.focus_strength, active, - vg.time_frame_delta * (1.0f/0.5f) ); - - u32 type = mdl_entity_id_type( world_static.focused_entity ), - index = mdl_entity_id_id( world_static.focused_entity ); - world_instance *world = world_current_instance(); - - /* TODO: Table. */ - if( type == k_ent_skateshop ){ - ent_skateshop *skateshop = mdl_arritm( &world->ent_skateshop, index ); - ent_skateshop_preupdate( skateshop, active ); - } - else if( type == k_ent_challenge ){ - ent_challenge *challenge = mdl_arritm( &world->ent_challenge, index ); - ent_challenge_preupdate( challenge, active ); - } - else if( type == k_ent_route ){ - ent_route *route = mdl_arritm( &world->ent_route, index ); - ent_route_preupdate( route, active ); - } -} - -/* additional renderings like text etc.. */ -static void world_entity_focus_render(void){ - if( skaterift.activity != k_skaterift_ent_focus ) - return; - - u32 type = mdl_entity_id_type( world_static.focused_entity ), - index = mdl_entity_id_id( world_static.focused_entity ); - world_instance *world = world_current_instance(); - - if( type == k_ent_skateshop ){ - ent_skateshop *skateshop = mdl_arritm( &world->ent_skateshop, index ); - skateshop_render( skateshop ); - } - else if( type == k_ent_challenge ){ - } - else if( type == k_ent_route ){ - } - else { - vg_fatal_error( "Programming error\n" ); - } -} - -static void world_gen_entities_init( world_instance *world ){ - /* lights */ - for( u32 j=0; jent_light); j ++ ){ - ent_light *light = mdl_arritm( &world->ent_light, j ); - - m4x3f to_world; - q_m3x3( light->transform.q, to_world ); - v3_copy( light->transform.co, to_world[3] ); - m4x3_invert_affine( to_world, light->inverse_world ); - - light->angle_sin_cos[0] = sinf( light->angle * 0.5f ); - light->angle_sin_cos[1] = cosf( light->angle * 0.5f ); - } - - /* gates */ - for( u32 j=0; jent_gate); j ++ ){ - ent_gate *gate = mdl_arritm( &world->ent_gate, j ); - - if( !(gate->flags & k_ent_gate_nonlocal_DELETED) ) { - gate_transform_update( gate ); - } - } - - /* water */ - for( u32 j=0; jent_water); j++ ){ - ent_water *water = mdl_arritm( &world->ent_water, j ); - if( world->water.enabled ){ - vg_warn( "Multiple water surfaces in level!\n" ); - break; - } - - world->water.enabled = 1; - water_set_surface( world, water->transform.co[1] ); - } - - /* volumes */ - for( u32 j=0; jent_volume); j++ ){ - ent_volume *volume = mdl_arritm( &world->ent_volume, j ); - mdl_transform_m4x3( &volume->transform, volume->to_world ); - m4x3_invert_full( volume->to_world, volume->to_local ); - } - - /* audio packs */ - for( u32 j=0; jent_audio); j++ ){ - ent_audio *audio = mdl_arritm( &world->ent_audio, j ); - - for( u32 k=0; kclip_count; k++ ){ - ent_audio_clip *clip = mdl_arritm( &world->ent_audio_clip, - audio->clip_start+k ); - - if( clip->_.file.pack_size ){ - u32 size = clip->_.file.pack_size, - offset = clip->_.file.pack_offset; - - /* embedded files are fine to clear the scratch buffer, only - * external audio uses it */ - - vg_linear_clear( vg_mem.scratch ); - void *data = vg_linear_alloc( vg_mem.scratch, - clip->_.file.pack_size ); - - mdl_fread_pack_file( &world->meta, &clip->_.file, data ); - - clip->_.clip.path = NULL; - clip->_.clip.flags = audio->flags; - clip->_.clip.data = data; - clip->_.clip.size = size; - } - else{ - clip->_.clip.path = mdl_pstr(&world->meta,clip->_.file.pstr_path); - clip->_.clip.flags = audio->flags; - clip->_.clip.data = NULL; - clip->_.clip.size = 0; - } - - audio_clip_load( &clip->_.clip, world->heap ); - } - } - - /* create generic entity hierachy for those who need it */ - u32 indexed_count = 0; - struct { - u32 type; - mdl_array_ptr *array; - } - indexables[] = { - { k_ent_gate, &world->ent_gate }, - { k_ent_objective, &world->ent_objective }, - { k_ent_volume, &world->ent_volume }, - { k_ent_challenge, &world->ent_challenge } - }; - - for( u32 i=0; ientity_list = vg_linear_alloc( world->heap, - vg_align8(indexed_count*sizeof(u32))); - - u32 index=0; - for( u32 i=0; ientity_list[index ++] = mdl_entity_id( type, j ); - } - - world->entity_bh = bh_create( world->heap, &bh_system_entity_list, world, - indexed_count, 2 ); -} - -static -ent_spawn *world_find_closest_spawn( world_instance *world, v3f position ) -{ - ent_spawn *rp = NULL, *r; - float min_dist = INFINITY; - - for( u32 i=0; ient_spawn); i++ ){ - r = mdl_arritm( &world->ent_spawn, i ); - float d = v3_dist2( r->transform.co, position ); - - if( d < min_dist ){ - min_dist = d; - rp = r; - } - } - - if( !rp ){ - if( mdl_arrcount(&world->ent_spawn) ){ - vg_warn( "Invalid distances to spawns.. defaulting to first one.\n" ); - return mdl_arritm( &world->ent_spawn, 0 ); - } - else{ - vg_error( "There are no spawns in the level!\n" ); - } - } - - return rp; -} - -static -ent_spawn *world_find_spawn_by_name( world_instance *world, const char *name ) -{ - ent_spawn *rp = NULL, *r; - for( u32 i=0; ient_spawn); i++ ){ - r = mdl_arritm( &world->ent_spawn, i ); - if( !strcmp( mdl_pstr(&world->meta, r->pstr_name), name ) ){ - rp = r; - break; - } - } - - if( !rp ) - vg_warn( "No spawn named '%s'\n", name ); - - return rp; -} - -static void ent_volume_call( world_instance *world, ent_call *call ) -{ - u32 index = mdl_entity_id_id( call->id ); - ent_volume *volume = mdl_arritm( &world->ent_volume, index ); - if( !volume->target ) return; - - if( call->function == k_ent_function_trigger ){ - call->id = volume->target; - - if( volume->flags & k_ent_volume_flag_particles ){ - float *co = alloca( sizeof(float)*3 ); - co[0] = vg_randf64()*2.0f-1.0f; - co[1] = vg_randf64()*2.0f-1.0f; - co[2] = vg_randf64()*2.0f-1.0f; - m4x3_mulv( volume->to_world, co, co ); - - call->function = k_ent_function_particle_spawn; - call->data = co; - entity_call( world, call ); - } - else{ - call->function = volume->trigger.event; - entity_call( world, call ); - } - } - else if( call->function == k_ent_function_trigger_leave ){ - call->id = volume->target; - - if( volume->flags & k_ent_volume_flag_particles ){ - assert(0); - } - else{ - call->function = volume->trigger.event_leave; - entity_call( world, call ); - } - } -} - -static void ent_audio_call( world_instance *world, ent_call *call ){ - if( world->status == k_world_status_unloading ){ - vg_warn( "cannot modify audio while unloading world\n" ); - return; - } - - u8 world_id = (world - world_static.instances) + 1; - u32 index = mdl_entity_id_id( call->id ); - ent_audio *audio = mdl_arritm( &world->ent_audio, index ); - - v3f sound_co; - - if( call->function == k_ent_function_particle_spawn ){ - v3_copy( call->data, sound_co ); - } - else if( call->function == k_ent_function_trigger ){ - v3_copy( audio->transform.co, sound_co ); - } - else - vg_fatal_error( "ent_audio_call (invalid function id)" ); - - float chance = vg_randf64()*100.0f, - bar = 0.0f; - - for( u32 i=0; iclip_count; i++ ){ - ent_audio_clip *clip = mdl_arritm( &world->ent_audio_clip, - audio->clip_start+i ); - - float mod = world->probabilities[ audio->probability_curve ], - p = clip->probability * mod; - - bar += p; - if( chance < bar ){ - audio_lock(); - - if( audio->behaviour == k_channel_behaviour_unlimited ){ - audio_oneshot_3d( &clip->_.clip, sound_co, - audio->transform.s[0], - audio->volume ); - } - else if( audio->behaviour == k_channel_behaviour_discard_if_full ){ - audio_channel *ch = - audio_get_group_idle_channel( audio->group, - audio->max_channels ); - - if( ch ){ - audio_channel_init( ch, &clip->_.clip, audio->flags ); - audio_channel_group( ch, audio->group ); - audio_channel_world( ch, world_id ); - audio_channel_set_spacial( ch, sound_co, audio->transform.s[0] ); - audio_channel_edit_volume( ch, audio->volume, 1 ); - ch = audio_relinquish_channel( ch ); - } - } - else if( audio->behaviour == k_channel_behaviour_crossfade_if_full){ - audio_channel *ch = - audio_get_group_idle_channel( audio->group, - audio->max_channels ); - - /* group is full */ - if( !ch ){ - audio_channel *existing = - audio_get_group_first_active_channel( audio->group ); - - if( existing ){ - if( existing->source == &clip->_.clip ){ - audio_unlock(); - return; - } - - existing->group = 0; - existing = audio_channel_fadeout(existing, audio->crossfade); - } - - ch = audio_get_first_idle_channel(); - } - - if( ch ){ - audio_channel_init( ch, &clip->_.clip, audio->flags ); - audio_channel_group( ch, audio->group ); - audio_channel_world( ch, world_id ); - audio_channel_fadein( ch, audio->crossfade ); - ch = audio_relinquish_channel( ch ); - } - } - - audio_unlock(); - return; - } - } -} - - -static void ent_ccmd_call( world_instance *world, ent_call *call ){ - if( call->function == k_ent_function_trigger ){ - u32 index = mdl_entity_id_id( call->id ); - ent_ccmd *ccmd = mdl_arritm( &world->ent_ccmd, index ); - vg_execute_console_input( mdl_pstr(&world->meta, ccmd->pstr_command) ); - } -} - -/* - * BVH implementation - * ---------------------------------------------------------------------------- - */ - -static void -entity_bh_expand_bound( void *user, boxf bound, u32 item_index ){ - world_instance *world = user; - - u32 id = world->entity_list[ item_index ], - type = mdl_entity_id_type( id ), - index = mdl_entity_id_id( id ); - - if( type == k_ent_gate ){ - ent_gate *gate = mdl_arritm( &world->ent_gate, index ); - boxf box = {{ -gate->dimensions[0], -gate->dimensions[1], -0.1f }, - { gate->dimensions[0], gate->dimensions[1], 0.1f }}; - - m4x3_expand_aabb_aabb( gate->to_world, bound, box ); - } - else if( type == k_ent_objective ){ - ent_objective *objective = mdl_arritm( &world->ent_objective, index ); - - /* TODO: This might be more work than necessary. could maybe just get - * away with representing them as points */ - - boxf box; - box_init_inf( box ); - - for( u32 i=0; isubmesh_count; i++ ){ - mdl_submesh *sm = mdl_arritm( &world->meta.submeshs, - objective->submesh_start+i ); - box_concat( box, sm->bbx ); - } - - m4x3f transform; - mdl_transform_m4x3( &objective->transform, transform ); - m4x3_expand_aabb_aabb( transform, bound, box ); - } - else if( type == k_ent_volume ){ - ent_volume *volume = mdl_arritm( &world->ent_volume, index ); - m4x3_expand_aabb_aabb( volume->to_world, bound, - (boxf){{-1.0f,-1.0f,-1.0f},{ 1.0f, 1.0f, 1.0f}} ); - } - else if( type == k_ent_challenge ){ - ent_challenge *challenge = mdl_arritm( &world->ent_challenge, index ); - - boxf box = {{-1.2f*0.5f,-0.72f*0.5f,-0.01f*0.5f}, - { 1.2f*0.5f, 0.72f*0.5f, 0.01f*0.5f}}; - m4x3f transform; - mdl_transform_m4x3( &challenge->transform, transform ); - m4x3_expand_aabb_aabb( transform, bound, box ); - } - else{ - vg_fatal_error( "Programming error\n" ); - } -} - -static float entity_bh_centroid( void *user, u32 item_index, int axis ){ - world_instance *world = user; - - u32 id = world->entity_list[ item_index ], - type = mdl_entity_id_type( id ), - index = mdl_entity_id_id( id ); - - if( type == k_ent_gate ){ - ent_gate *gate = mdl_arritm( &world->ent_gate, index ); - return gate->to_world[3][axis]; - } - else if( type == k_ent_objective ){ - ent_objective *objective = mdl_arritm( &world->ent_objective, index ); - return objective->transform.co[axis]; - } - else if( type == k_ent_volume ){ - ent_volume *volume = mdl_arritm( &world->ent_volume, index ); - return volume->transform.co[axis]; - } - else if( type == k_ent_challenge ){ - ent_challenge *challenge = mdl_arritm( &world->ent_challenge, index ); - return challenge->transform.co[axis]; - } - else { - vg_fatal_error( "Programming error\n" ); - return INFINITY; - } -} - -static void entity_bh_swap( void *user, u32 ia, u32 ib ){ - world_instance *world = user; - - u32 a = world->entity_list[ ia ], - b = world->entity_list[ ib ]; - - world->entity_list[ ia ] = b; - world->entity_list[ ib ] = a; -} - -static void entity_bh_debug( void *user, u32 item_index ){ - world_instance *world = user; - - u32 id = world->entity_list[ item_index ], - type = mdl_entity_id_type( id ), - index = mdl_entity_id_id( id ); - - if( type == k_ent_gate ){ - ent_gate *gate = mdl_arritm( &world->ent_gate, index ); - boxf box = {{ -gate->dimensions[0], -gate->dimensions[1], -0.1f }, - { gate->dimensions[0], gate->dimensions[1], 0.1f }}; - vg_line_boxf_transformed( gate->to_world, box, 0xf000ff00 ); - } - else if( type == k_ent_objective ){ - ent_objective *objective = mdl_arritm( &world->ent_objective, index ); - boxf box; - box_init_inf( box ); - - for( u32 i=0; isubmesh_count; i++ ){ - mdl_submesh *sm = mdl_arritm( &world->meta.submeshs, - objective->submesh_start+i ); - box_concat( box, sm->bbx ); - } - - m4x3f transform; - mdl_transform_m4x3( &objective->transform, transform ); - vg_line_boxf_transformed( transform, box, 0xf000ff00 ); - } - else if( type == k_ent_volume ){ - ent_volume *volume = mdl_arritm( &world->ent_volume, index ); - vg_line_boxf_transformed( volume->to_world, - (boxf){{-1.0f,-1.0f,-1.0f},{ 1.0f, 1.0f, 1.0f}}, - 0xf000ff00 ); - } - else if( type == k_ent_challenge ){ - ent_challenge *challenge = mdl_arritm( &world->ent_challenge, index ); - - boxf box = {{-1.2f*0.5f,-0.72f*0.5f,-0.01f*0.5f}, - { 1.2f*0.5f, 0.72f*0.5f, 0.01f*0.5f}}; - m4x3f transform; - mdl_transform_m4x3( &challenge->transform, transform ); - vg_line_boxf_transformed( transform, box, 0xf0ff0000 ); - } - else{ - vg_fatal_error( "Programming error\n" ); - } -} - -static void entity_bh_closest( void *user, u32 item_index, v3f point, - v3f closest ){ - world_instance *world = user; - - u32 id = world->entity_list[ item_index ], - type = mdl_entity_id_type( id ), - index = mdl_entity_id_id( id ); - - if( type == k_ent_gate ){ - ent_gate *gate = mdl_arritm( &world->ent_gate, index ); - v3_copy( gate->to_world[3], closest ); - } - else if( type == k_ent_objective ){ - ent_objective *challenge = mdl_arritm( &world->ent_objective, index ); - v3_copy( challenge->transform.co, closest ); - } - else if( type == k_ent_volume ){ - ent_volume *volume = mdl_arritm( &world->ent_volume, index ); - v3_copy( volume->to_world[3], closest ); - } - else if( type == k_ent_challenge ){ - ent_challenge *challenge = mdl_arritm( &world->ent_challenge, index ); - v3_copy( challenge->transform.co, closest ); - } - else{ - vg_fatal_error( "Programming error\n" ); - } -} - -static void world_entity_start( world_instance *world, vg_msg *sav ){ - vg_info( "Start instance %p\n", world ); - - world->probabilities[ k_probability_curve_constant ] = 1.0f; - for( u32 i=0; ient_audio); i++ ){ - ent_audio *audio = mdl_arritm(&world->ent_audio,i); - if( audio->flags & AUDIO_FLAG_AUTO_START ){ - ent_call call; - call.data = NULL; - call.function = k_ent_function_trigger; - call.id = mdl_entity_id( k_ent_audio, i ); - entity_call( world, &call ); - } - } - - /* read savedata - * ----------------------------------------------------------------------- */ - - for( u32 i=0; ient_challenge); i++ ){ - ent_challenge *challenge = mdl_arritm( &world->ent_challenge, i ); - const char *alias = mdl_pstr( &world->meta, challenge->pstr_alias ); - - if( vg_msg_getkvu32( sav, alias, 0 ) ){ - ent_call call; - call.data = NULL; - call.function = 0; - call.id = mdl_entity_id( k_ent_challenge, i ); - entity_call( world, &call ); - } - } -} - -/* - * used for relinking multi-world data. ran anytime the world setup changes - */ -static void world_entity_relink( world_instance *world ){ - vg_info( "entity_relink(%d)\n", world - world_static.instances ); - for( u32 i=0; ient_miniworld); i++ ){ - ent_miniworld *miniworld = mdl_arritm( &world->ent_miniworld, i ); - miniworld->purpose = k_world_purpose_invalid; - - const char *uid = mdl_pstr( &world->meta, miniworld->pstr_world ); - addon_alias q; - addon_uid_to_alias( uid, &q ); - - u32 addon_id = addon_match( &q ); - if( addon_id != 0xffffffff ){ - addon_reg *reg = get_addon_from_index( k_addon_type_world, addon_id ); - - for( int j=0; jstatus == k_world_status_loaded) && - (world_static.instance_addons[j] == reg) ){ - miniworld->purpose = j; - break; - } - } - } - } -} - -static void world_entity_serialize( world_instance *world, vg_msg *sav ){ - for( u32 i=0; ient_challenge); i++ ){ - ent_challenge *challenge = mdl_arritm(&world->ent_challenge,i); - - const char *alias = mdl_pstr(&world->meta,challenge->pstr_alias); - vg_msg_wkvu32( sav, alias, challenge->status ); - } -} - -#endif /* WORLD_ENTITY_C */