scraped a small amount of crap
[carveJwlIkooP6JGAAIwe30JlM.git] / world.h
1 /*
2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
3 */
4
5 #include "common.h"
6
7 #ifndef WORLD_H
8 #define WORLD_H
9
10 typedef struct world_instance world_instance;
11
12 #include "vg/vg_loader.h"
13
14 #include "network.h"
15 #include "network_msg.h"
16 #include "scene.h"
17 #include "render.h"
18 #include "rigidbody.h"
19 #include "bvh.h"
20 #include "model.h"
21 #include "entity.h"
22
23 #include "shaders/scene_standard.h"
24 #include "shaders/scene_standard_alphatest.h"
25 #include "shaders/scene_vertex_blend.h"
26 #include "shaders/scene_terrain.h"
27 #include "shaders/scene_depth.h"
28 #include "shaders/scene_position.h"
29
30 #include "shaders/model_sky.h"
31
32 enum { k_max_ui_segments = 8 };
33
34 enum { k_max_ui_elements = k_max_ui_segments };
35 enum { k_max_element_verts = 10 };
36 enum { k_max_element_indices = 20 };
37
38 enum { k_route_ui_max_verts = k_max_ui_elements*k_max_element_verts };
39 enum { k_route_ui_max_indices = k_max_ui_elements*k_max_element_indices };
40
41 enum logic_type
42 {
43 k_logic_type_relay = 1,
44 k_logic_type_chance = 2,
45 k_logic_type_achievement = 3
46 };
47
48 enum geo_type
49 {
50 k_geo_type_solid = 0,
51 k_geo_type_nonsolid = 1,
52 k_geo_type_water = 2
53 };
54
55 static const float k_light_cube_size = 8.0f;
56
57 struct world_instance
58 {
59 /* Fixed items
60 * -------------------------------------------------------
61 */
62
63 char world_name[ 64 ];
64
65 struct
66 {
67 boxf depthbounds;
68 int depth_computed;
69
70 float height;
71 int enabled;
72 v4f plane;
73 }
74 water;
75
76 /* STD140 */
77 struct ub_world_lighting
78 {
79 v4f g_cube_min,
80 g_cube_inv_range;
81
82 v4f g_water_plane,
83 g_depth_bounds;
84
85 v4f g_daysky_colour;
86 v4f g_nightsky_colour;
87 v4f g_sunset_colour;
88 v4f g_ambient_colour;
89 v4f g_sunset_ambient;
90 v4f g_sun_colour;
91 v4f g_sun_dir;
92
93 float g_water_fog;
94 float g_time;
95 float g_realtime;
96 float g_shadow_length;
97 float g_shadow_spread;
98
99 float g_time_of_day;
100 float g_day_phase;
101 float g_sunset_phase;
102
103 int g_light_preview;
104 int g_shadow_samples;
105
106 int g_debug_indices;
107 int g_debug_complexity;
108 }
109 ub_lighting;
110 GLuint ubo_lighting;
111 int ubo_bind_point;
112
113 GLuint tbo_light_entities,
114 tex_light_entities,
115 tex_light_cubes;
116
117 float probabilities[3];
118
119 v3i light_cubes;
120
121 struct framebuffer heightmap;
122
123 /*
124 * Dynamically allocated when world_load is called.
125 *
126 * the following arrays index somewhere into this linear
127 * allocator
128 *
129 * (world_gen.h)
130 * --------------------------------------------------------------------------
131 */
132
133 /*
134 * Main world .mdl
135 */
136 mdl_context meta;
137
138 GLuint *textures;
139 u32 texture_count;
140
141 struct world_surface
142 {
143 mdl_material info;
144 mdl_submesh sm_geo,
145 sm_no_collide;
146 }
147 * surfaces;
148 u32 surface_count;
149
150 mdl_array_ptr ent_spawn,
151 ent_gate,
152 ent_light,
153 ent_route_node,
154 ent_path_index,
155 ent_checkpoint,
156 ent_route,
157 ent_water,
158
159 ent_audio_clip,
160 ent_audio,
161 ent_volume;
162
163 ent_gate *rendering_gate;
164
165 /* logic
166 * ----------------------------------------------------
167 */
168
169 /* world geometry */
170 scene *scene_geo,
171 *scene_no_collide,
172 *scene_lines;
173
174 /* spacial mappings */
175 bh_tree *audio_bh,
176 *volume_bh,
177 *geo_bh;
178
179 /* graphics */
180 glmesh mesh_route_lines;
181 glmesh mesh_geo,
182 mesh_no_collide,
183 mesh_water;
184
185 rigidbody rb_geo; /* todo.. ... */
186 };
187
188 VG_STATIC struct world_global
189 {
190 /*
191 * Allocated as system memory
192 * --------------------------------------------------------------------------
193 */
194 void *generic_heap;
195
196 /* rendering */
197 glmesh skydome;
198 glmesh mesh_gate;
199 mdl_submesh sm_gate_surface,
200 sm_gate_marker[4];
201
202 double sky_time, sky_rate, sky_target_rate;
203
204 u32 current_run_version;
205 double time, rewind_from, rewind_to, last_use;
206
207 /* water rendering */
208 struct
209 {
210 struct framebuffer fbreflect, fbdepth;
211 }
212 water;
213
214 /* split flap display */
215 struct
216 {
217 glmesh mesh_base, mesh_display;
218 mdl_submesh sm_base;
219 u32 active_route_board;
220
221 u32 w, h;
222 float *buffer;
223 }
224 sfd;
225
226 v3f render_gate_pos;
227 int in_volume;
228
229 int switching_to_new_world;
230
231 world_instance worlds[4];
232 u32 world_count;
233 u32 active_world;
234 }
235 world_global;
236
237 VG_STATIC world_instance *get_active_world( void )
238 {
239 return &world_global.worlds[ world_global.active_world ];
240 }
241
242 /*
243 * API
244 */
245
246 VG_STATIC
247 int ray_hit_is_ramp( world_instance *world, ray_hit *hit );
248
249 VG_STATIC
250 struct world_surface *ray_hit_surface( world_instance *world, ray_hit *hit );
251
252 VG_STATIC
253 void ray_world_get_tri( world_instance *world, ray_hit *hit, v3f tri[3] );
254
255 VG_STATIC
256 int ray_world( world_instance *world, v3f pos, v3f dir, ray_hit *hit );
257
258 /*
259 * Submodules
260 */
261
262 #include "world_routes.h"
263 #include "world_sfd.h"
264 #include "world_render.h"
265 #include "world_water.h"
266 #include "world_volumes.h"
267 #include "world_gen.h"
268 #include "world_gate.h"
269
270 /*
271 * -----------------------------------------------------------------------------
272 * Events
273 * -----------------------------------------------------------------------------
274 */
275
276 VG_STATIC int world_stop_sound( int argc, const char *argv[] )
277 {
278 world_instance *world = get_active_world();
279 return 0;
280 }
281
282 VG_STATIC void world_init(void)
283 {
284 world_global.sky_rate = 1.0;
285 world_global.sky_target_rate = 1.0;
286
287 shader_scene_standard_register();
288 shader_scene_standard_alphatest_register();
289 shader_scene_vertex_blend_register();
290 shader_scene_terrain_register();
291 shader_scene_depth_register();
292 shader_scene_position_register();
293
294 shader_model_sky_register();
295
296 vg_info( "Loading world resources\n" );
297
298 vg_linear_clear( vg_mem.scratch );
299
300 mdl_context msky;
301 mdl_open( &msky, "models/rs_skydome.mdl", vg_mem.scratch );
302 mdl_load_metadata_block( &msky, vg_mem.scratch );
303 mdl_load_mesh_block( &msky, vg_mem.scratch );
304 mdl_close( &msky );
305
306 vg_acquire_thread_sync();
307 {
308 mdl_unpack_glmesh( &msky, &world_global.skydome );
309 }
310 vg_release_thread_sync();
311
312 /* Other systems */
313 vg_info( "Loading other world systems\n" );
314
315 vg_loader_step( world_render_init, NULL );
316 vg_loader_step( world_sfd_init, NULL );
317 vg_loader_step( world_water_init, NULL );
318 vg_loader_step( world_gates_init, NULL );
319 vg_loader_step( world_routes_init, NULL );
320
321 /* Allocate dynamic world memory arena */
322 u32 max_size = 76*1024*1024;
323 world_global.generic_heap = vg_create_linear_allocator( vg_mem.rtmemory,
324 max_size,
325 VG_MEMORY_SYSTEM );
326 }
327
328 typedef struct ent_call ent_call;
329 struct ent_call{
330 ent_index ent;
331 u32 function;
332 void *data;
333 };
334
335 VG_STATIC void entity_call( world_instance *world, ent_call *call );
336
337 VG_STATIC void ent_volume_call( world_instance *world, ent_call *call )
338 {
339 ent_volume *volume = mdl_arritm( &world->ent_volume, call->ent.index );
340 if( !volume->target.type ) return;
341
342 if( call->function == k_ent_function_trigger ){
343 call->ent = volume->target;
344
345 if( volume->type == k_volume_subtype_particle ){
346 float *co = alloca( sizeof(float)*3 );
347 co[0] = vg_randf()*2.0f-1.0f;
348 co[1] = vg_randf()*2.0f-1.0f;
349 co[2] = vg_randf()*2.0f-1.0f;
350 m4x3_mulv( volume->to_world, co, co );
351
352 call->function = k_ent_function_particle_spawn;
353 call->data = co;
354 entity_call( world, call );
355 }
356 else
357 entity_call( world, call );
358 }
359 }
360
361 VG_STATIC void ent_audio_call( world_instance *world, ent_call *call )
362 {
363 ent_audio *audio = mdl_arritm( &world->ent_audio, call->ent.index );
364
365 v3f sound_co;
366
367 if( call->function == k_ent_function_particle_spawn ){
368 v3_copy( call->data, sound_co );
369 }
370 else if( call->function == k_ent_function_trigger ){
371 v3_copy( audio->transform.co, sound_co );
372 }
373 else
374 vg_fatal_exit_loop( "ent_audio_call (invalid function id)" );
375
376 float chance = vg_randf()*100.0f,
377 bar = 0.0f;
378
379 for( u32 i=0; i<audio->clip_count; i++ ){
380 ent_audio_clip *clip = mdl_arritm( &world->ent_audio_clip,
381 audio->clip_start+i );
382
383 float mod = world->probabilities[ audio->probability_curve ],
384 p = clip->probability * mod;
385
386 bar += p;
387
388 if( chance < bar ){
389
390 audio_lock();
391
392 if( audio->behaviour == k_channel_behaviour_unlimited ){
393 audio_oneshot_3d( &clip->clip, sound_co,
394 audio->transform.s[0],
395 audio->volume );
396 }
397 else if( audio->behaviour == k_channel_behaviour_discard_if_full ){
398 audio_channel *ch =
399 audio_get_group_idle_channel( audio->group,
400 audio->max_channels );
401
402 if( ch ){
403 audio_channel_init( ch, &clip->clip, audio->flags );
404 audio_channel_group( ch, audio->group );
405 audio_channel_set_spacial( ch, sound_co, audio->transform.s[0] );
406 audio_channel_edit_volume( ch, audio->volume, 1 );
407 ch = audio_relinquish_channel( ch );
408 }
409 }
410 else if( audio->behaviour == k_channel_behaviour_crossfade_if_full){
411 audio_channel *ch =
412 audio_get_group_idle_channel( audio->group,
413 audio->max_channels );
414
415 /* group is full */
416 if( !ch ){
417 audio_channel *existing =
418 audio_get_group_first_active_channel( audio->group );
419
420 if( existing ){
421 if( existing->source == &clip->clip ){
422 audio_unlock();
423 return;
424 }
425
426 existing->group = 0;
427 existing = audio_channel_fadeout(existing, audio->crossfade);
428 }
429
430 ch = audio_get_first_idle_channel();
431 }
432
433 if( ch ){
434 audio_channel_init( ch, &clip->clip, audio->flags );
435 audio_channel_group( ch, audio->group );
436 audio_channel_fadein( ch, audio->crossfade );
437 ch = audio_relinquish_channel( ch );
438 }
439 }
440
441 audio_unlock();
442 return;
443 }
444 }
445 }
446
447 VG_STATIC void entity_call( world_instance *world, ent_call *call )
448 {
449 if( call->ent.type == k_ent_volume ){
450 ent_volume_call( world, call );
451 } else if( call->ent.type == k_ent_audio ){
452 ent_audio_call( world, call );
453 }
454 }
455
456 VG_STATIC void world_update( world_instance *world, v3f pos )
457 {
458 /* TEMP!!!!!! */
459 static double g_time = 0.0;
460 g_time += vg.time_delta * (1.0/(k_day_length*60.0));
461
462
463 struct ub_world_lighting *state = &world->ub_lighting;
464
465 state->g_time = g_time;
466 state->g_realtime = vg.time;
467 state->g_debug_indices = k_debug_light_indices;
468 state->g_light_preview = k_light_preview;
469 state->g_debug_complexity = k_debug_light_complexity;
470
471 state->g_time_of_day = vg_fractf( g_time );
472 state->g_day_phase = cosf( state->g_time_of_day * VG_PIf * 2.0f );
473 state->g_sunset_phase= cosf( state->g_time_of_day * VG_PIf * 4.0f + VG_PIf );
474
475 state->g_day_phase = state->g_day_phase * 0.5f + 0.5f;
476 state->g_sunset_phase = powf( state->g_sunset_phase * 0.5f + 0.5f, 6.0f );
477
478 float a = state->g_time_of_day * VG_PIf * 2.0f;
479 state->g_sun_dir[0] = sinf( a );
480 state->g_sun_dir[1] = cosf( a );
481 state->g_sun_dir[2] = 0.2f;
482 v3_normalize( state->g_sun_dir );
483
484
485 world->probabilities[ k_probability_curve_constant ] = 1.0f;
486
487 float dp = state->g_day_phase;
488
489 world->probabilities[ k_probability_curve_wildlife_day ] =
490 (dp*dp*0.8f+state->g_sunset_phase)*0.8f;
491 world->probabilities[ k_probability_curve_wildlife_night ] =
492 1.0f-powf(fabsf((state->g_time_of_day-0.5f)*5.0f),5.0f);
493
494
495 glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
496 glBufferSubData( GL_UNIFORM_BUFFER, 0,
497 sizeof(struct ub_world_lighting), &world->ub_lighting );
498 /* TEMP!!!!!! */
499
500 world_global.sky_time += world_global.sky_rate * vg.time_delta;
501 world_global.sky_rate = vg_lerp( world_global.sky_rate,
502 world_global.sky_target_rate,
503 vg.time_delta * 5.0 );
504
505 world_routes_update( world );
506 world_routes_debug( world );
507
508 /* ---- SFD ------------ */
509
510 if( mdl_arrcount( &world->ent_route ) ){
511 u32 closest = 0;
512 float min_dist = INFINITY;
513
514 for( u32 i=0; i<mdl_arrcount( &world->ent_route ); i++ ){
515 ent_route *route = mdl_arritm( &world->ent_route, i );
516 float dist = v3_dist2( route->board_transform[3], pos );
517
518 if( dist < min_dist ){
519 min_dist = dist;
520 closest = i;
521 }
522 }
523
524 if( (world_global.sfd.active_route_board != closest)
525 || network_scores_updated )
526 {
527 network_scores_updated = 0;
528 world_global.sfd.active_route_board = closest;
529
530 ent_route *route = mdl_arritm( &world->ent_route, closest );
531 u32 id = route->official_track_id;
532
533 if( id != 0xffffffff ){
534 struct netmsg_board *local_board =
535 &scoreboard_client_data.boards[id];
536
537 for( int i=0; i<13; i++ ){
538 sfd_encode( i, &local_board->data[27*i] );
539 }
540 }else{
541 sfd_encode( 0, mdl_pstr( &world->meta, route->pstr_name ) );
542 sfd_encode( 1, "No data" );
543 }
544 }
545 }
546 sfd_update();
547
548
549
550 static float random_accum = 0.0f;
551 random_accum += vg.time_delta;
552
553 u32 random_ticks = 0;
554
555 while( random_accum > 0.1f ){
556 random_accum -= 0.1f;
557 random_ticks ++;
558 }
559
560 float radius = 25.0f;
561 boxf volume_proximity;
562 v3_add( pos, (v3f){ radius, radius, radius }, volume_proximity[1] );
563 v3_sub( pos, (v3f){ radius, radius, radius }, volume_proximity[0] );
564
565 bh_iter it;
566 bh_iter_init( 0, &it );
567 int idx;
568
569 int in_volume = 0;
570
571 while( bh_next( world->volume_bh, &it, volume_proximity, &idx ) ){
572 ent_volume *volume = mdl_arritm( &world->ent_volume, idx );
573
574 boxf cube = {{-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f}};
575
576 if( volume->type == k_volume_subtype_trigger ){
577 v3f local;
578 m4x3_mulv( volume->to_local, pos, local );
579
580 if( (fabsf(local[0]) <= 1.0f) &&
581 (fabsf(local[1]) <= 1.0f) &&
582 (fabsf(local[2]) <= 1.0f) )
583 {
584 in_volume = 1;
585 vg_line_boxf_transformed( volume->to_world, cube, 0xff00ff00 );
586
587 if( !world_global.in_volume ){
588 ent_call basecall;
589 basecall.ent.index = idx;
590 basecall.ent.type = k_ent_volume;
591 basecall.function = k_ent_function_trigger;
592 basecall.data = NULL;
593
594 entity_call( world, &basecall );
595 }
596 }
597 else
598 vg_line_boxf_transformed( volume->to_world, cube, 0xff0000ff );
599 }
600 else if( volume->type == k_volume_subtype_particle ){
601 vg_line_boxf_transformed( volume->to_world, cube, 0xff00c0ff );
602
603 for( int j=0; j<random_ticks; j++ ){
604 ent_call basecall;
605 basecall.ent.index = idx;
606 basecall.ent.type = k_ent_volume;
607 basecall.function = k_ent_function_trigger;
608 basecall.data = NULL;
609
610 entity_call( world, &basecall );
611 }
612 }
613 }
614 world_global.in_volume = in_volume;
615
616 #if 0
617 if( k_debug_light_indices )
618 {
619 for( int i=0; i<world->light_count; i++ ){
620 struct world_light *light = &world->lights[i];
621 struct classtype_world_light *inf = light->inf;
622
623 u32 colour = 0xff000000;
624 u8 r = inf->colour[0] * 255.0f,
625 g = inf->colour[1] * 255.0f,
626 b = inf->colour[2] * 255.0f;
627
628 colour |= r;
629 colour |= g << 8;
630 colour |= b << 16;
631
632 vg_line_pt3( light->node->co, 0.25f, colour );
633 }
634 }
635
636 #endif
637
638 #if 0
639
640 /* process soundscape transactions */
641 audio_lock();
642 for( int i=0; i<world->soundscape_count; i++ )
643 {
644 struct soundscape *s = &world->soundscapes[i];
645 s->usage_count = 0;
646
647 for( int j=0; j<s->max_instances; j++ )
648 {
649 if( s->channels[j] )
650 {
651 if( audio_channel_finished(s->channels[j]) )
652 s->channels[j] = audio_relinquish_channel( s->channels[j] );
653 else
654 s->usage_count ++;
655 }
656 }
657 }
658 audio_unlock();
659 #endif
660 }
661
662 /*
663 * -----------------------------------------------------------------------------
664 * API implementation
665 * -----------------------------------------------------------------------------
666 */
667
668 VG_STATIC void ray_world_get_tri( world_instance *world,
669 ray_hit *hit, v3f tri[3] )
670 {
671 for( int i=0; i<3; i++ )
672 v3_copy( world->scene_geo->arrvertices[ hit->tri[i] ].co, tri[i] );
673 }
674
675 VG_STATIC int ray_world( world_instance *world,
676 v3f pos, v3f dir, ray_hit *hit )
677 {
678 return scene_raycast( world->scene_geo, world->geo_bh, pos, dir, hit );
679 }
680
681 /*
682 * Cast a sphere from a to b and see what time it hits
683 */
684 VG_STATIC int spherecast_world( world_instance *world,
685 v3f pa, v3f pb, float r, float *t, v3f n )
686 {
687 bh_iter it;
688 bh_iter_init( 0, &it );
689
690 boxf region;
691 box_init_inf( region );
692 box_addpt( region, pa );
693 box_addpt( region, pb );
694
695 v3_add( (v3f){ r, r, r}, region[1], region[1] );
696 v3_add( (v3f){-r,-r,-r}, region[0], region[0] );
697
698 v3f dir;
699 v3_sub( pb, pa, dir );
700
701 v3f dir_inv;
702 dir_inv[0] = 1.0f/dir[0];
703 dir_inv[1] = 1.0f/dir[1];
704 dir_inv[2] = 1.0f/dir[2];
705
706 int hit = -1;
707 float min_t = 1.0f;
708
709 int idx;
710 while( bh_next( world->geo_bh, &it, region, &idx ) ){
711 u32 *ptri = &world->scene_geo->arrindices[ idx*3 ];
712 v3f tri[3];
713
714 boxf box;
715 box_init_inf( box );
716
717 for( int j=0; j<3; j++ ){
718 v3_copy( world->scene_geo->arrvertices[ptri[j]].co, tri[j] );
719 box_addpt( box, tri[j] );
720 }
721
722 v3_add( (v3f){ r, r, r}, box[1], box[1] );
723 v3_add( (v3f){-r,-r,-r}, box[0], box[0] );
724
725 if( !ray_aabb1( box, pa, dir_inv, 1.0f ) )
726 continue;
727
728 float t;
729 v3f n1;
730 if( spherecast_triangle( tri, pa, dir, r, &t, n1 ) ){
731 if( t < min_t ){
732 min_t = t;
733 hit = idx;
734 v3_copy( n1, n );
735 }
736 }
737 }
738
739 *t = min_t;
740 return hit;
741 }
742
743 VG_STATIC
744 struct world_surface *world_tri_index_surface( world_instance *world,
745 u32 index )
746 {
747 for( int i=1; i<world->surface_count; i++ ){
748 struct world_surface *surf = &world->surfaces[i];
749
750 if( (index >= surf->sm_geo.vertex_start) &&
751 (index < surf->sm_geo.vertex_start+surf->sm_geo.vertex_count ) )
752 {
753 return surf;
754 }
755 }
756
757 return &world->surfaces[0];
758 }
759
760 VG_STATIC struct world_surface *world_contact_surface( world_instance *world,
761 rb_ct *ct )
762 {
763 return world_tri_index_surface( world, ct->element_id );
764 }
765
766 VG_STATIC struct world_surface *ray_hit_surface( world_instance *world,
767 ray_hit *hit )
768 {
769 return world_tri_index_surface( world, hit->tri[0] );
770 }
771
772 #endif /* WORLD_H */