fix long standing grind bug
[carveJwlIkooP6JGAAIwe30JlM.git] / world.c
1 /*
2 * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
3 */
4
5 #ifndef WORLD_C
6 #define WORLD_C
7
8 #include "world.h"
9 #include "network.h"
10
11 static world_instance *world_current_instance(void){
12 return &world_static.worlds[ world_static.active_world ];
13 }
14
15 static void world_init(void)
16 {
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 );
21
22 world_render.sky_rate = 1.0;
23 world_render.sky_target_rate = 1.0;
24
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();
31
32 shader_model_sky_register();
33
34 vg_info( "Loading world resources\n" );
35
36 vg_linear_clear( vg_mem.scratch );
37
38 mdl_context msky;
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 );
42 mdl_close( &msky );
43
44 /* Other systems */
45 vg_info( "Loading other world systems\n" );
46
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 );
52
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,
56 VG_MEMORY_SYSTEM );
57 }
58
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"
70
71 VG_STATIC void world_update( world_instance *world, v3f pos )
72 {
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 );
77
78 world_routes_update_timer_texts( world );
79 world_routes_update( world );
80 //world_routes_debug( world );
81
82 /* ---- traffic -------- */
83
84 for( u32 i=0; i<mdl_arrcount( &world->ent_traffic ); i++ ){
85 ent_traffic *traffic = mdl_arritm( &world->ent_traffic, i );
86
87 u32 i1 = traffic->index,
88 i0,
89 i2 = i1+1;
90
91 if( i1 == 0 ) i0 = traffic->node_count-1;
92 else i0 = i1-1;
93
94 if( i2 >= traffic->node_count ) i2 = 0;
95
96 i0 += traffic->start_node;
97 i1 += traffic->start_node;
98 i2 += traffic->start_node;
99
100 v3f h[3];
101
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 );
105
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] );
109
110 float const k_sample_dist = 0.0025f;
111 v3f pc, pd;
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 );
114
115 v3f v0;
116 v3_sub( pd, pc, v0 );
117 float length = vg_maxf( 0.0001f, v3_length( v0 ) );
118 v3_muls( v0, 1.0f/length, v0 );
119
120 float mod = k_sample_dist / length;
121
122 traffic->t += traffic->speed * vg.time_delta * mod;
123
124 if( traffic->t > 1.0f ){
125 traffic->t -= 1.0f;
126
127 if( traffic->t > 1.0f ) traffic->t = 0.0f;
128
129 traffic->index ++;
130
131 if( traffic->index >= traffic->node_count )
132 traffic->index = 0;
133 }
134
135 v3_copy( pc, traffic->transform.co );
136
137 float a = atan2f( -v0[0], v0[2] );
138 q_axis_angle( traffic->transform.q, (v3f){0.0f,1.0f,0.0f}, -a );
139
140 vg_line_pt3( traffic->transform.co, 0.3f, VG__BLUE );
141 }
142
143 /* ---- SFD ------------ */
144
145 if( mdl_arrcount( &world->ent_route ) ){
146 u32 closest = 0;
147 float min_dist = INFINITY;
148
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 );
152
153 if( dist < min_dist ){
154 min_dist = dist;
155 closest = i;
156 }
157 }
158
159 if( (world_sfd.active_route_board != closest) || network_scores_updated )
160 {
161 network_scores_updated = 0;
162 world_sfd.active_route_board = closest;
163
164 ent_route *route = mdl_arritm( &world->ent_route, closest );
165 u32 id = route->official_track_id;
166
167 if( id != 0xffffffff ){
168 struct netmsg_board *local_board =
169 &scoreboard_client_data.boards[id];
170
171 for( int i=0; i<13; i++ ){
172 sfd_encode( i, &local_board->data[27*i] );
173 }
174 }else{
175 sfd_encode( 0, mdl_pstr( &world->meta, route->pstr_name ) );
176 sfd_encode( 1, "No data" );
177 }
178 }
179 }
180 sfd_update();
181
182 static float random_accum = 0.0f;
183 random_accum += vg.time_delta;
184
185 u32 random_ticks = 0;
186
187 while( random_accum > 0.1f ){
188 random_accum -= 0.1f;
189 random_ticks ++;
190 }
191
192 float radius = 25.0f;
193 boxf volume_proximity;
194 v3_add( pos, (v3f){ radius, radius, radius }, volume_proximity[1] );
195 v3_sub( pos, (v3f){ radius, radius, radius }, volume_proximity[0] );
196
197 bh_iter it;
198 bh_iter_init_box( 0, &it, volume_proximity );
199 i32 idx;
200
201 int in_volume = 0;
202
203 while( bh_next( world->volume_bh, &it, &idx ) ){
204 ent_volume *volume = mdl_arritm( &world->ent_volume, idx );
205
206 boxf cube = {{-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f}};
207
208 if( volume->type == k_volume_subtype_trigger ){
209 v3f local;
210 m4x3_mulv( volume->to_local, pos, local );
211
212 if( (fabsf(local[0]) <= 1.0f) &&
213 (fabsf(local[1]) <= 1.0f) &&
214 (fabsf(local[2]) <= 1.0f) )
215 {
216 in_volume = 1;
217 vg_line_boxf_transformed( volume->to_world, cube, 0xff00ff00 );
218
219 if( !world_static.in_volume ){
220 ent_call basecall;
221 basecall.function = k_ent_function_trigger;
222 basecall.id = mdl_entity_id( k_ent_volume, idx );
223 basecall.data = NULL;
224
225 entity_call( world, &basecall );
226 }
227 }
228 else
229 vg_line_boxf_transformed( volume->to_world, cube, 0xff0000ff );
230 }
231 else if( volume->type == k_volume_subtype_particle ){
232 vg_line_boxf_transformed( volume->to_world, cube, 0xff00c0ff );
233
234 for( int j=0; j<random_ticks; j++ ){
235 ent_call basecall;
236 basecall.id = mdl_entity_id( k_ent_volume, idx );
237 basecall.data = NULL;
238
239 entity_call( world, &basecall );
240 }
241 }
242 }
243 world_static.in_volume = in_volume;
244
245 #if 0
246 if( k_debug_light_indices )
247 {
248 for( int i=0; i<world->light_count; i++ ){
249 struct world_light *light = &world->lights[i];
250 struct classtype_world_light *inf = light->inf;
251
252 u32 colour = 0xff000000;
253 u8 r = inf->colour[0] * 255.0f,
254 g = inf->colour[1] * 255.0f,
255 b = inf->colour[2] * 255.0f;
256
257 colour |= r;
258 colour |= g << 8;
259 colour |= b << 16;
260
261 vg_line_pt3( light->node->co, 0.25f, colour );
262 }
263 }
264
265 #endif
266 }
267
268 #endif /* WORLD_C */