- struct instance_cache
- {
- mdl_context *mdl;
- u32 pstr_file;
- }
- instance_cache[32];
- u32 instance_cache_count;
-}
-world;
-
-
-/*
- * API
- */
-
-VG_STATIC int ray_hit_is_ramp( ray_hit *hit );
-VG_STATIC int ray_hit_is_terrain( ray_hit *hit );
-VG_STATIC void ray_world_get_tri( ray_hit *hit, v3f tri[3] );
-VG_STATIC int ray_world( v3f pos, v3f dir, ray_hit *hit );
-
-/*
- * Submodules
- */
-
-#include "world_routes.h"
-#include "world_sfd.h"
-#include "world_render.h"
-#include "world_water.h"
-#include "world_gen.h"
-#include "world_gate.h"
-
-/*
- * -----------------------------------------------------------------------------
- * Events
- * -----------------------------------------------------------------------------
- */
-
-VG_STATIC int world_stop_sound( int argc, const char *argv[] )
-{
- /*
- * None of our world audio runs as one shots, they always have a player.
- * Therefore it is safe to delete clip data after the players are
- * disconnected
- */
- audio_lock();
- for( int i=0; i<world.audio_things_count; i++ )
- {
- struct world_audio_thing *at = &world.audio_things[i];
-
- if( audio_player_is_playing( &at->player ) )
- {
- u32 cflags = audio_player_get_flags( &at->player );
- audio_player_set_flags( &at->player, cflags | AUDIO_FLAG_KILL );
- }
- }
- audio_unlock();
-
- return 0;
-}
-
-VG_STATIC int world_change_world( int argc, const char *argv[] )
-{
- if( argc == 0 )
- {
- vg_info( "%s\n", world.world_name );
- return 0;
- }
- else
- {
- vg_info( "Switching world...\n" );
- strcpy( world.world_name, argv[0] );
- world.switching_to_new_world = 1;
- world_stop_sound( 0, NULL );
- }
-
- return 0;
-}
-
-VG_STATIC void world_init(void)
-{
- vg_convar_push( (struct vg_convar){
- .name = "water_enable",
- .data = &world.water.enabled,
- .data_type = k_convar_dtype_i32,
- .opt_i32 = { .min=0, .max=1, .clamp=1 },
- .persistent = 0
- });
-
- vg_function_push( (struct vg_cmd)
- {
- .name = "world_stop_sound",
- .function = world_stop_sound
- });
-
- vg_function_push( (struct vg_cmd)
- {
- .name = "world",
- .function = world_change_world
- });
-
- world.sky_rate = 1.0;
- world.sky_target_rate = 1.0;
-
- shader_terrain_register();
- shader_sky_register();
- shader_planeinf_register();
- shader_gpos_register();
- shader_fscolour_register();
- shader_alphatest_register();
-
- vg_info( "Loading world resources\n" );
-
- vg_linear_clear( vg_mem.scratch );
- mdl_context *msky = mdl_load_full( vg_mem.scratch, "models/rs_skydome.mdl" );
-
- mdl_node *nlower = mdl_node_from_name( msky, "dome_lower" ),
- *nupper = mdl_node_from_name( msky, "dome_upper" );
-
- world.dome_lower = *mdl_node_submesh( msky, nlower, 0 );
- world.dome_upper = *mdl_node_submesh( msky, nupper, 0 );
-
- vg_acquire_thread_sync();
- {
- mdl_unpack_glmesh( msky, &world.skydome );
- }
- vg_release_thread_sync();
-
- /* Other systems */
- vg_info( "Loading other world systems\n" );
-
- vg_loader_highwater( world_render_init, NULL, NULL );
- vg_loader_highwater( world_sfd_init, NULL, NULL );
- vg_loader_highwater( world_water_init, NULL, NULL );
- vg_loader_highwater( world_gates_init, NULL, NULL );
- vg_loader_highwater( world_routes_init, NULL, NULL );
-
- /* Allocate dynamic world memory arena */
- u32 max_size = 72*1024*1024;
- world.dynamic_vgl = vg_create_linear_allocator( vg_mem.rtmemory, max_size );
- for( u32 i=0; i<72*1024*1024; i++ )
- ((u8 *)world.dynamic_vgl)[i] = 0xfe;
-}
-
-VG_STATIC void world_update( v3f pos )
-{
- if( world.switching_to_new_world )
- {
- int all_stopped = 1;
-
- audio_lock();
- for( int i=0; i<world.audio_things_count; i++ )
- {
- struct world_audio_thing *at = &world.audio_things[i];
-
- if( audio_player_is_playing( &at->player ) )
- {
- all_stopped = 0;
- break;
- }
- }
- audio_unlock();
-
- if( all_stopped )
- {
- world.switching_to_new_world = 0;
- world_unload();
- world_load();
- }
- }
-
-
- world.sky_time += world.sky_rate * vg.time_delta;
- world.sky_rate = vg_lerp( world.sky_rate, world.sky_target_rate,
- vg.time_delta * 5.0 );
-
- world_routes_update();
-#if 0
- world_routes_debug();
-#endif
-
- int closest = 0;
- float min_dist = INFINITY;
-
- for( int i=0; i<world.route_count; i++ )
- {
- float d = v3_dist2( world.routes[i].scoreboard_transform[3], pos );
-
- if( d < min_dist )
- {
- min_dist = d;
- closest = i;
- }
- }