From c2ee05fe23699fd1de7e1d8259b9bc272b232058 Mon Sep 17 00:00:00 2001 From: hgn Date: Sun, 11 Jun 2023 07:00:58 +0100 Subject: [PATCH] organize world modules --- world.c | 249 +----------------------------------------------- world_render.c | 32 ++++++- world_sfd.c | 39 +++++++- world_traffic.c | 67 +++++++++++++ world_volumes.c | 90 +++++++++++++++++ 5 files changed, 229 insertions(+), 248 deletions(-) create mode 100644 world_traffic.c diff --git a/world.c b/world.c index 5cc7841..0183acb 100644 --- a/world.c +++ b/world.c @@ -14,36 +14,6 @@ static world_instance *world_current_instance(void){ static void world_init(void) { - VG_VAR_F32( k_day_length ); - VG_VAR_I32( k_debug_light_indices ); - VG_VAR_I32( k_debug_light_complexity ); - VG_VAR_I32( k_light_preview ); - - world_render.sky_rate = 1.0; - world_render.sky_target_rate = 1.0; - - shader_scene_standard_register(); - shader_scene_standard_alphatest_register(); - shader_scene_vertex_blend_register(); - shader_scene_terrain_register(); - shader_scene_depth_register(); - shader_scene_position_register(); - - shader_model_sky_register(); - - vg_info( "Loading world resources\n" ); - - vg_linear_clear( vg_mem.scratch ); - - mdl_context msky; - mdl_open( &msky, "models/rs_skydome.mdl", vg_mem.scratch ); - mdl_load_metadata_block( &msky, vg_mem.scratch ); - mdl_async_load_glmesh( &msky, &world_render.skydome ); - mdl_close( &msky ); - - /* Other systems */ - vg_info( "Loading other world systems\n" ); - vg_loader_step( world_render_init, NULL ); vg_loader_step( world_sfd_init, NULL ); vg_loader_step( world_water_init, NULL ); @@ -67,6 +37,7 @@ static void world_init(void) #include "world_water.c" #include "world_audio.c" #include "world_routes.c" +#include "world_traffic.c" VG_STATIC void world_update( world_instance *world, v3f pos ) { @@ -77,221 +48,9 @@ VG_STATIC void world_update( world_instance *world, v3f pos ) world_routes_update_timer_texts( world ); world_routes_update( world ); - //world_routes_debug( world ); - - /* ---- traffic -------- */ - - for( u32 i=0; ient_traffic ); i++ ){ - ent_traffic *traffic = mdl_arritm( &world->ent_traffic, i ); - - u32 i1 = traffic->index, - i0, - i2 = i1+1; - - if( i1 == 0 ) i0 = traffic->node_count-1; - else i0 = i1-1; - - if( i2 >= traffic->node_count ) i2 = 0; - - i0 += traffic->start_node; - i1 += traffic->start_node; - i2 += traffic->start_node; - - v3f h[3]; - - ent_route_node *rn0 = mdl_arritm( &world->ent_route_node, i0 ), - *rn1 = mdl_arritm( &world->ent_route_node, i1 ), - *rn2 = mdl_arritm( &world->ent_route_node, i2 ); - - v3_copy( rn1->co, h[1] ); - v3_lerp( rn0->co, rn1->co, 0.5f, h[0] ); - v3_lerp( rn1->co, rn2->co, 0.5f, h[2] ); - - float const k_sample_dist = 0.0025f; - v3f pc, pd; - eval_bezier3( h[0], h[1], h[2], traffic->t, pc ); - eval_bezier3( h[0], h[1], h[2], traffic->t+k_sample_dist, pd ); - - v3f v0; - v3_sub( pd, pc, v0 ); - float length = vg_maxf( 0.0001f, v3_length( v0 ) ); - v3_muls( v0, 1.0f/length, v0 ); - - float mod = k_sample_dist / length; - - traffic->t += traffic->speed * vg.time_delta * mod; - - if( traffic->t > 1.0f ){ - traffic->t -= 1.0f; - - if( traffic->t > 1.0f ) traffic->t = 0.0f; - - traffic->index ++; - - if( traffic->index >= traffic->node_count ) - traffic->index = 0; - } - - v3_copy( pc, traffic->transform.co ); - - float a = atan2f( -v0[0], v0[2] ); - q_axis_angle( traffic->transform.q, (v3f){0.0f,1.0f,0.0f}, -a ); - - vg_line_pt3( traffic->transform.co, 0.3f, VG__BLUE ); - } - - /* ---- SFD ------------ */ - - if( mdl_arrcount( &world->ent_route ) ){ - u32 closest = 0; - float min_dist = INFINITY; - - for( u32 i=0; ient_route ); i++ ){ - ent_route *route = mdl_arritm( &world->ent_route, i ); - float dist = v3_dist2( route->board_transform[3], pos ); - - if( dist < min_dist ){ - min_dist = dist; - closest = i; - } - } - - if( (world_sfd.active_route_board != closest) || network_scores_updated ) - { - network_scores_updated = 0; - world_sfd.active_route_board = closest; - - ent_route *route = mdl_arritm( &world->ent_route, closest ); - u32 id = route->official_track_id; - - if( id != 0xffffffff ){ - struct netmsg_board *local_board = - &scoreboard_client_data.boards[id]; - - for( int i=0; i<13; i++ ){ - sfd_encode( i, &local_board->data[27*i] ); - } - }else{ - sfd_encode( 0, mdl_pstr( &world->meta, route->pstr_name ) ); - sfd_encode( 1, "No data" ); - } - } - } - sfd_update(); - - /* volumes - * ------------------------------------------------------------------------- - */ - - /* filter and check the existing ones - * TODO: on change world, clear volumes list */ - u32 j=0; - for( u32 i=0; ient_volume, idx ); - - v3f local; - m4x3_mulv( volume->to_local, pos, local ); - if( (fabsf(local[0]) <= 1.0f) && - (fabsf(local[1]) <= 1.0f) && - (fabsf(local[2]) <= 1.0f) ) - { - world_static.active_trigger_volumes[ j ++ ] = idx; - boxf cube = {{-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f}}; - vg_line_boxf_transformed( volume->to_world, cube, 0xff00ccff ); - /* triggr on stay ..... */ - } - else{ - /* trigger on exit...... */ - } - } - world_static.active_trigger_volume_count = j; - - static float random_accum = 0.0f; - random_accum += vg.time_delta; - - u32 random_ticks = 0; - - while( random_accum > 0.1f ){ - random_accum -= 0.1f; - random_ticks ++; - } - - float radius = 25.0f; - boxf volume_proximity; - v3_add( pos, (v3f){ radius, radius, radius }, volume_proximity[1] ); - v3_sub( pos, (v3f){ radius, radius, radius }, volume_proximity[0] ); - - bh_iter it; - bh_iter_init_box( 0, &it, volume_proximity ); - i32 idx; - - while( bh_next( world->volume_bh, &it, &idx ) ){ - ent_volume *volume = mdl_arritm( &world->ent_volume, idx ); - - boxf cube = {{-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f}}; - - if( volume->type == k_volume_subtype_trigger ){ - for( u32 i=0; i - vg_list_size(world_static.active_trigger_volumes) ) continue; - - v3f local; - m4x3_mulv( volume->to_local, pos, local ); - - if( (fabsf(local[0]) <= 1.0f) && - (fabsf(local[1]) <= 1.0f) && - (fabsf(local[2]) <= 1.0f) ) - { - ent_call basecall; - basecall.function = k_ent_function_trigger; - basecall.id = mdl_entity_id( k_ent_volume, idx ); - basecall.data = NULL; - - entity_call( world, &basecall ); - world_static.active_trigger_volumes[ - world_static.active_trigger_volume_count ++ ] = idx; - } - else - vg_line_boxf_transformed( volume->to_world, cube, 0xffcccccc ); - } - else if( volume->type == k_volume_subtype_particle ){ - vg_line_boxf_transformed( volume->to_world, cube, 0xff00c0ff ); - - for( int j=0; jlight_count; i++ ){ - struct world_light *light = &world->lights[i]; - struct classtype_world_light *inf = light->inf; - - u32 colour = 0xff000000; - u8 r = inf->colour[0] * 255.0f, - g = inf->colour[1] * 255.0f, - b = inf->colour[2] * 255.0f; - - colour |= r; - colour |= g << 8; - colour |= b << 16; - - vg_line_pt3( light->node->co, 0.25f, colour ); - } - } -#endif + world_traffic_update( world, pos ); + world_sfd_update( world, pos ); + world_volumes_update( world, pos ); } #endif /* WORLD_C */ diff --git a/world_render.c b/world_render.c index 8255d53..1c030a6 100644 --- a/world_render.c +++ b/world_render.c @@ -8,6 +8,17 @@ #include "world.h" #include "world_render.h" +static int ccmd_set_time( int argc, const char *argv[] ){ + if( argc == 1 ){ + world_instance *world = world_current_instance(); + world->time = atof( argv[0] ); + } + else { + vg_error( "Usage set_time <0-1.0>\n" ); + } + return 0; +} + VG_STATIC void async_world_render_init( void *payload, u32 size ) { vg_info( "Allocate uniform buffers\n" ); @@ -53,6 +64,15 @@ VG_STATIC void async_world_render_init( void *payload, u32 size ) VG_STATIC void world_render_init(void) { + VG_VAR_F32( k_day_length ); + VG_VAR_I32( k_debug_light_indices ); + VG_VAR_I32( k_debug_light_complexity ); + VG_VAR_I32( k_light_preview ); + vg_console_reg_cmd( "set_time", ccmd_set_time, NULL ); + + world_render.sky_rate = 1.0; + world_render.sky_target_rate = 1.0; + shader_scene_standard_register(); shader_scene_standard_alphatest_register(); shader_scene_vertex_blend_register(); @@ -61,6 +81,15 @@ VG_STATIC void world_render_init(void) shader_scene_position_register(); shader_model_sky_register(); + vg_info( "Loading world resources\n" ); + vg_linear_clear( vg_mem.scratch ); + + mdl_context msky; + mdl_open( &msky, "models/rs_skydome.mdl", vg_mem.scratch ); + mdl_load_metadata_block( &msky, vg_mem.scratch ); + mdl_async_load_glmesh( &msky, &world_render.skydome ); + mdl_close( &msky ); + vg_info( "Loading default world textures\n" ); vg_tex2d_load_qoi_async_file( "textures/garbage.qoi", VG_TEX2D_NEAREST|VG_TEX2D_REPEAT, @@ -423,7 +452,8 @@ VG_STATIC void render_world_gates( world_instance *world, camera *cam, VG_STATIC void world_prerender( world_instance *world ) { - world->time += vg.time_delta * (1.0/(k_day_length*60.0)); + f32 day_length = vg_maxf(0.1f, fabsf(k_day_length)) * vg_signf(k_day_length); + world->time += vg.time_delta * (1.0/(day_length*60.0)); struct ub_world_lighting *state = &world->ub_lighting; diff --git a/world_sfd.c b/world_sfd.c index 9fe2d68..a5ba3f6 100644 --- a/world_sfd.c +++ b/world_sfd.c @@ -59,8 +59,43 @@ VG_STATIC void sfd_encode( u32 row, const char *str ) } } -VG_STATIC void sfd_update(void) -{ +VG_STATIC void world_sfd_update( world_instance *world, v3f pos ){ + if( mdl_arrcount( &world->ent_route ) ){ + u32 closest = 0; + float min_dist = INFINITY; + + for( u32 i=0; ient_route ); i++ ){ + ent_route *route = mdl_arritm( &world->ent_route, i ); + float dist = v3_dist2( route->board_transform[3], pos ); + + if( dist < min_dist ){ + min_dist = dist; + closest = i; + } + } + + if( (world_sfd.active_route_board != closest) || network_scores_updated ) + { + network_scores_updated = 0; + world_sfd.active_route_board = closest; + + ent_route *route = mdl_arritm( &world->ent_route, closest ); + u32 id = route->official_track_id; + + if( id != 0xffffffff ){ + struct netmsg_board *local_board = + &scoreboard_client_data.boards[id]; + + for( int i=0; i<13; i++ ){ + sfd_encode( i, &local_board->data[27*i] ); + } + }else{ + sfd_encode( 0, mdl_pstr( &world->meta, route->pstr_name ) ); + sfd_encode( 1, "No data" ); + } + } + } + for( int i=0; ient_traffic ); i++ ){ + ent_traffic *traffic = mdl_arritm( &world->ent_traffic, i ); + + u32 i1 = traffic->index, + i0, + i2 = i1+1; + + if( i1 == 0 ) i0 = traffic->node_count-1; + else i0 = i1-1; + + if( i2 >= traffic->node_count ) i2 = 0; + + i0 += traffic->start_node; + i1 += traffic->start_node; + i2 += traffic->start_node; + + v3f h[3]; + + ent_route_node *rn0 = mdl_arritm( &world->ent_route_node, i0 ), + *rn1 = mdl_arritm( &world->ent_route_node, i1 ), + *rn2 = mdl_arritm( &world->ent_route_node, i2 ); + + v3_copy( rn1->co, h[1] ); + v3_lerp( rn0->co, rn1->co, 0.5f, h[0] ); + v3_lerp( rn1->co, rn2->co, 0.5f, h[2] ); + + float const k_sample_dist = 0.0025f; + v3f pc, pd; + eval_bezier3( h[0], h[1], h[2], traffic->t, pc ); + eval_bezier3( h[0], h[1], h[2], traffic->t+k_sample_dist, pd ); + + v3f v0; + v3_sub( pd, pc, v0 ); + float length = vg_maxf( 0.0001f, v3_length( v0 ) ); + v3_muls( v0, 1.0f/length, v0 ); + + float mod = k_sample_dist / length; + + traffic->t += traffic->speed * vg.time_delta * mod; + + if( traffic->t > 1.0f ){ + traffic->t -= 1.0f; + + if( traffic->t > 1.0f ) traffic->t = 0.0f; + + traffic->index ++; + + if( traffic->index >= traffic->node_count ) + traffic->index = 0; + } + + v3_copy( pc, traffic->transform.co ); + + float a = atan2f( -v0[0], v0[2] ); + q_axis_angle( traffic->transform.q, (v3f){0.0f,1.0f,0.0f}, -a ); + + vg_line_pt3( traffic->transform.co, 0.3f, VG__BLUE ); + } +} + +#endif /* WORLD_TRAFFIC_C */ diff --git a/world_volumes.c b/world_volumes.c index c08fe43..0cc1ed6 100644 --- a/world_volumes.c +++ b/world_volumes.c @@ -3,6 +3,96 @@ #include "world_volumes.h" +static void world_volumes_update( world_instance *world, v3f pos ){ + /* filter and check the existing ones */ + u32 j=0; + for( u32 i=0; ient_volume, idx ); + + v3f local; + m4x3_mulv( volume->to_local, pos, local ); + if( (fabsf(local[0]) <= 1.0f) && + (fabsf(local[1]) <= 1.0f) && + (fabsf(local[2]) <= 1.0f) ) + { + world_static.active_trigger_volumes[ j ++ ] = idx; + boxf cube = {{-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f}}; + vg_line_boxf_transformed( volume->to_world, cube, 0xff00ccff ); + /* triggr on stay ..... */ + } + else{ + /* trigger on exit...... */ + } + } + world_static.active_trigger_volume_count = j; + + static float random_accum = 0.0f; + random_accum += vg.time_delta; + + u32 random_ticks = 0; + + while( random_accum > 0.1f ){ + random_accum -= 0.1f; + random_ticks ++; + } + + float radius = 25.0f; + boxf volume_proximity; + v3_add( pos, (v3f){ radius, radius, radius }, volume_proximity[1] ); + v3_sub( pos, (v3f){ radius, radius, radius }, volume_proximity[0] ); + + bh_iter it; + bh_iter_init_box( 0, &it, volume_proximity ); + i32 idx; + + while( bh_next( world->volume_bh, &it, &idx ) ){ + ent_volume *volume = mdl_arritm( &world->ent_volume, idx ); + + boxf cube = {{-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f}}; + + if( volume->type == k_volume_subtype_trigger ){ + for( u32 i=0; i + vg_list_size(world_static.active_trigger_volumes) ) continue; + + v3f local; + m4x3_mulv( volume->to_local, pos, local ); + + if( (fabsf(local[0]) <= 1.0f) && + (fabsf(local[1]) <= 1.0f) && + (fabsf(local[2]) <= 1.0f) ) + { + ent_call basecall; + basecall.function = k_ent_function_trigger; + basecall.id = mdl_entity_id( k_ent_volume, idx ); + basecall.data = NULL; + + entity_call( world, &basecall ); + world_static.active_trigger_volumes[ + world_static.active_trigger_volume_count ++ ] = idx; + } + else + vg_line_boxf_transformed( volume->to_world, cube, 0xffcccccc ); + } + else if( volume->type == k_volume_subtype_particle ){ + vg_line_boxf_transformed( volume->to_world, cube, 0xff00c0ff ); + + for( int j=0; j