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 );
#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 )
{
world_routes_update_timer_texts( world );
world_routes_update( world );
- //world_routes_debug( world );
-
- /* ---- traffic -------- */
-
- for( u32 i=0; i<mdl_arrcount( &world->ent_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; i<mdl_arrcount( &world->ent_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; i<world_static.active_trigger_volume_count; i++ ){
- i32 idx = world_static.active_trigger_volumes[i];
- ent_volume *volume = mdl_arritm( &world->ent_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<world_static.active_trigger_volume_count; i++ )
- if( world_static.active_trigger_volumes[i] == idx )
- goto next_volume;
-
- if( world_static.active_trigger_volume_count >
- 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<random_ticks; j++ ){
- ent_call basecall;
- basecall.id = mdl_entity_id( k_ent_volume, idx );
- basecall.data = NULL;
-
- entity_call( world, &basecall );
- }
- }
-next_volume:;
- }
-
-#if 0
- if( k_debug_light_indices )
- {
- for( int i=0; i<world->light_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 */
#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" );
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();
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,
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;
--- /dev/null
+#ifndef WORLD_TRAFFIC_C
+#define WORLD_TRAFFIC_C
+
+#include "world.h"
+
+static void world_traffic_update( world_instance *world, v3f pos ){
+ for( u32 i=0; i<mdl_arrcount( &world->ent_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 */
#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; i<world_static.active_trigger_volume_count; i++ ){
+ i32 idx = world_static.active_trigger_volumes[i];
+ ent_volume *volume = mdl_arritm( &world->ent_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<world_static.active_trigger_volume_count; i++ )
+ if( world_static.active_trigger_volumes[i] == idx )
+ goto next_volume;
+
+ if( world_static.active_trigger_volume_count >
+ 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<random_ticks; j++ ){
+ ent_call basecall;
+ basecall.id = mdl_entity_id( k_ent_volume, idx );
+ basecall.data = NULL;
+
+ entity_call( world, &basecall );
+ }
+ }
+next_volume:;
+ }
+}
+
/*
* BVH implementation
* ----------------------------------------------------------------------------