2 * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
11 static world_instance
*world_current_instance(void){
12 return &world_static
.worlds
[ world_static
.active_world
];
15 static void world_init(void)
17 VG_VAR_F32( k_day_length
);
18 VG_VAR_I32( k_debug_light_indices
);
19 VG_VAR_I32( k_debug_light_complexity
);
20 VG_VAR_I32( k_light_preview
);
22 world_render
.sky_rate
= 1.0;
23 world_render
.sky_target_rate
= 1.0;
25 shader_scene_standard_register();
26 shader_scene_standard_alphatest_register();
27 shader_scene_vertex_blend_register();
28 shader_scene_terrain_register();
29 shader_scene_depth_register();
30 shader_scene_position_register();
32 shader_model_sky_register();
34 vg_info( "Loading world resources\n" );
36 vg_linear_clear( vg_mem
.scratch
);
39 mdl_open( &msky
, "models/rs_skydome.mdl", vg_mem
.scratch
);
40 mdl_load_metadata_block( &msky
, vg_mem
.scratch
);
41 mdl_async_load_glmesh( &msky
, &world_render
.skydome
);
45 vg_info( "Loading other world systems\n" );
47 vg_loader_step( world_render_init
, NULL
);
48 vg_loader_step( world_sfd_init
, NULL
);
49 vg_loader_step( world_water_init
, NULL
);
50 vg_loader_step( world_gates_init
, NULL
);
51 vg_loader_step( world_routes_init
, NULL
);
53 /* Allocate dynamic world memory arena */
54 u32 max_size
= 76*1024*1024;
55 world_static
.heap
= vg_create_linear_allocator( vg_mem
.rtmemory
, max_size
,
59 #include "world_entity.c"
60 #include "world_gate.c"
61 #include "world_gen.c"
62 #include "world_load.c"
63 #include "world_physics.c"
64 #include "world_render.c"
65 #include "world_sfd.c"
66 #include "world_volumes.c"
67 #include "world_water.c"
68 #include "world_audio.c"
69 #include "world_routes.c"
71 VG_STATIC
void world_update( world_instance
*world
, v3f pos
)
73 world_render
.sky_time
+= world_render
.sky_rate
* vg
.time_delta
;
74 world_render
.sky_rate
= vg_lerp( world_render
.sky_rate
,
75 world_render
.sky_target_rate
,
76 vg
.time_delta
* 5.0 );
78 world_routes_update_timer_texts( world
);
79 world_routes_update( world
);
80 //world_routes_debug( world );
82 /* ---- traffic -------- */
84 for( u32 i
=0; i
<mdl_arrcount( &world
->ent_traffic
); i
++ ){
85 ent_traffic
*traffic
= mdl_arritm( &world
->ent_traffic
, i
);
87 u32 i1
= traffic
->index
,
91 if( i1
== 0 ) i0
= traffic
->node_count
-1;
94 if( i2
>= traffic
->node_count
) i2
= 0;
96 i0
+= traffic
->start_node
;
97 i1
+= traffic
->start_node
;
98 i2
+= traffic
->start_node
;
102 ent_route_node
*rn0
= mdl_arritm( &world
->ent_route_node
, i0
),
103 *rn1
= mdl_arritm( &world
->ent_route_node
, i1
),
104 *rn2
= mdl_arritm( &world
->ent_route_node
, i2
);
106 v3_copy( rn1
->co
, h
[1] );
107 v3_lerp( rn0
->co
, rn1
->co
, 0.5f
, h
[0] );
108 v3_lerp( rn1
->co
, rn2
->co
, 0.5f
, h
[2] );
110 float const k_sample_dist
= 0.0025f
;
112 eval_bezier3( h
[0], h
[1], h
[2], traffic
->t
, pc
);
113 eval_bezier3( h
[0], h
[1], h
[2], traffic
->t
+k_sample_dist
, pd
);
116 v3_sub( pd
, pc
, v0
);
117 float length
= vg_maxf( 0.0001f
, v3_length( v0
) );
118 v3_muls( v0
, 1.0f
/length
, v0
);
120 float mod
= k_sample_dist
/ length
;
122 traffic
->t
+= traffic
->speed
* vg
.time_delta
* mod
;
124 if( traffic
->t
> 1.0f
){
127 if( traffic
->t
> 1.0f
) traffic
->t
= 0.0f
;
131 if( traffic
->index
>= traffic
->node_count
)
135 v3_copy( pc
, traffic
->transform
.co
);
137 float a
= atan2f( -v0
[0], v0
[2] );
138 q_axis_angle( traffic
->transform
.q
, (v3f
){0.0f
,1.0f
,0.0f
}, -a
);
140 vg_line_pt3( traffic
->transform
.co
, 0.3f
, VG__BLUE
);
143 /* ---- SFD ------------ */
145 if( mdl_arrcount( &world
->ent_route
) ){
147 float min_dist
= INFINITY
;
149 for( u32 i
=0; i
<mdl_arrcount( &world
->ent_route
); i
++ ){
150 ent_route
*route
= mdl_arritm( &world
->ent_route
, i
);
151 float dist
= v3_dist2( route
->board_transform
[3], pos
);
153 if( dist
< min_dist
){
159 if( (world_sfd
.active_route_board
!= closest
) || network_scores_updated
)
161 network_scores_updated
= 0;
162 world_sfd
.active_route_board
= closest
;
164 ent_route
*route
= mdl_arritm( &world
->ent_route
, closest
);
165 u32 id
= route
->official_track_id
;
167 if( id
!= 0xffffffff ){
168 struct netmsg_board
*local_board
=
169 &scoreboard_client_data
.boards
[id
];
171 for( int i
=0; i
<13; i
++ ){
172 sfd_encode( i
, &local_board
->data
[27*i
] );
175 sfd_encode( 0, mdl_pstr( &world
->meta
, route
->pstr_name
) );
176 sfd_encode( 1, "No data" );
183 * -------------------------------------------------------------------------
186 /* filter and check the existing ones
187 * TODO: on change world, clear volumes list */
189 for( u32 i
=0; i
<world_static
.active_trigger_volume_count
; i
++ ){
190 i32 idx
= world_static
.active_trigger_volumes
[i
];
191 ent_volume
*volume
= mdl_arritm( &world
->ent_volume
, idx
);
194 m4x3_mulv( volume
->to_local
, pos
, local
);
195 if( (fabsf(local
[0]) <= 1.0f
) &&
196 (fabsf(local
[1]) <= 1.0f
) &&
197 (fabsf(local
[2]) <= 1.0f
) )
199 world_static
.active_trigger_volumes
[ j
++ ] = idx
;
200 boxf cube
= {{-1.0f
,-1.0f
,-1.0f
},{1.0f
,1.0f
,1.0f
}};
201 vg_line_boxf_transformed( volume
->to_world
, cube
, 0xff00ccff );
202 /* triggr on stay ..... */
205 /* trigger on exit...... */
208 world_static
.active_trigger_volume_count
= j
;
210 static float random_accum
= 0.0f
;
211 random_accum
+= vg
.time_delta
;
213 u32 random_ticks
= 0;
215 while( random_accum
> 0.1f
){
216 random_accum
-= 0.1f
;
220 float radius
= 25.0f
;
221 boxf volume_proximity
;
222 v3_add( pos
, (v3f
){ radius
, radius
, radius
}, volume_proximity
[1] );
223 v3_sub( pos
, (v3f
){ radius
, radius
, radius
}, volume_proximity
[0] );
226 bh_iter_init_box( 0, &it
, volume_proximity
);
229 while( bh_next( world
->volume_bh
, &it
, &idx
) ){
230 ent_volume
*volume
= mdl_arritm( &world
->ent_volume
, idx
);
232 boxf cube
= {{-1.0f
,-1.0f
,-1.0f
},{1.0f
,1.0f
,1.0f
}};
234 if( volume
->type
== k_volume_subtype_trigger
){
235 for( u32 i
=0; i
<world_static
.active_trigger_volume_count
; i
++ )
236 if( world_static
.active_trigger_volumes
[i
] == idx
)
239 if( world_static
.active_trigger_volume_count
>
240 vg_list_size(world_static
.active_trigger_volumes
) ) continue;
243 m4x3_mulv( volume
->to_local
, pos
, local
);
245 if( (fabsf(local
[0]) <= 1.0f
) &&
246 (fabsf(local
[1]) <= 1.0f
) &&
247 (fabsf(local
[2]) <= 1.0f
) )
250 basecall
.function
= k_ent_function_trigger
;
251 basecall
.id
= mdl_entity_id( k_ent_volume
, idx
);
252 basecall
.data
= NULL
;
254 entity_call( world
, &basecall
);
255 world_static
.active_trigger_volumes
[
256 world_static
.active_trigger_volume_count
++ ] = idx
;
259 vg_line_boxf_transformed( volume
->to_world
, cube
, 0xffcccccc );
261 else if( volume
->type
== k_volume_subtype_particle
){
262 vg_line_boxf_transformed( volume
->to_world
, cube
, 0xff00c0ff );
264 for( int j
=0; j
<random_ticks
; j
++ ){
266 basecall
.id
= mdl_entity_id( k_ent_volume
, idx
);
267 basecall
.data
= NULL
;
269 entity_call( world
, &basecall
);
276 if( k_debug_light_indices
)
278 for( int i
=0; i
<world
->light_count
; i
++ ){
279 struct world_light
*light
= &world
->lights
[i
];
280 struct classtype_world_light
*inf
= light
->inf
;
282 u32 colour
= 0xff000000;
283 u8 r
= inf
->colour
[0] * 255.0f
,
284 g
= inf
->colour
[1] * 255.0f
,
285 b
= inf
->colour
[2] * 255.0f
;
291 vg_line_pt3( light
->node
->co
, 0.25f
, colour
);