null
[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 /* This is a small flag we use to changelevel.
60 * It will not be cleared until all sounds stop playing
61 */
62
63 /* Fixed items
64 * -------------------------------------------------------
65 */
66
67 char world_name[ 64 ];
68
69 struct
70 {
71 boxf depthbounds;
72 int depth_computed;
73
74 float height;
75 int enabled;
76 v4f plane;
77 }
78 water;
79
80 /* STD140 */
81 struct ub_world_lighting
82 {
83 v4f g_cube_min,
84 g_cube_inv_range;
85
86 v4f g_water_plane,
87 g_depth_bounds;
88
89 v4f g_daysky_colour;
90 v4f g_nightsky_colour;
91 v4f g_sunset_colour;
92 v4f g_ambient_colour;
93 v4f g_sunset_ambient;
94 v4f g_sun_colour;
95 v4f g_sun_dir;
96
97 float g_water_fog;
98 float g_time;
99 float g_realtime;
100 float g_shadow_length;
101 float g_shadow_spread;
102
103 float g_time_of_day;
104 float g_day_phase;
105 float g_sunset_phase;
106
107 int g_light_preview;
108 int g_shadow_samples;
109
110 int g_debug_indices;
111 int g_debug_complexity;
112 }
113 ub_lighting;
114 GLuint ubo_lighting;
115 int ubo_bind_point;
116
117 GLuint tbo_light_entities,
118 tex_light_entities,
119 tex_light_cubes;
120
121 float probabilities[3];
122
123 v3i light_cubes;
124
125 struct framebuffer heightmap;
126
127 /*
128 * Dynamically allocated when world_load is called.
129 *
130 * the following arrays index somewhere into this linear
131 * allocator
132 *
133 * (world_gen.h)
134 * --------------------------------------------------------------------------
135 */
136 /*
137 * Main world .mdl
138 */
139 mdl_context meta;
140
141 GLuint *textures;
142 u32 texture_count;
143
144 struct world_surface
145 {
146 mdl_material info;
147 mdl_submesh sm_geo,
148 sm_no_collide;
149 }
150 * surfaces;
151 u32 surface_count;
152
153 mdl_array_ptr ent_spawn,
154 ent_gate,
155 ent_light,
156 ent_route_node,
157 ent_path_index,
158 ent_checkpoint,
159 ent_route,
160 ent_water,
161
162 ent_audio_clip,
163 ent_audio,
164 ent_volume;
165
166 ent_gate *rendering_gate;
167
168 #if 0
169 /*
170 * Named safe places to respawn
171 */
172 struct respawn_point
173 {
174 v3f co;
175 v4f q;
176 const char *name;
177 }
178 * spawns;
179 u32 spawn_count;
180
181 /*
182 * Audio player entities
183 */
184 struct world_audio_thing
185 {
186 v3f pos;
187 float volume, range;
188 u32 flags;
189 audio_clip temp_embedded_clip;
190 }
191 * audio_things;
192 u32 audio_things_count;
193
194 struct soundscape
195 {
196 /* locking */
197 audio_channel *channels[4];
198
199 /* accessable without locking */
200 v3f spawn_position;
201
202 u32 usage_count;
203 u32 max_instances;
204 u32 allow_transitions;
205 float transition_duration;
206 const char *label;
207 }
208 * soundscapes;
209 u32 soundscape_count;
210
211 /*
212 * Box volume entities
213 */
214 struct world_volume
215 {
216 m4x3f transform, inv_transform;
217 mdl_node *node;
218 }
219 * volumes;
220 u32 volume_count;
221
222 /*
223 * Lights
224 */
225 struct world_light
226 {
227 mdl_node *node;
228 struct classtype_world_light *inf;
229 m4x3f inverse_world;
230 v2f angle_sin_cos;
231 }
232 * lights;
233 u32 light_count;
234
235 /*
236 * Routes (world_routes.h)
237 * --------------------------------------------------------------------------
238 */
239
240 struct route_node
241 {
242 v3f co, right, up, h;
243 u32 next[2];
244
245 u32 special_type, special_id, current_refs, ref_count;
246 u32 route_ids[4]; /* Gates can be linked into up to four routes */
247 }
248 *nodes;
249 u32 node_count;
250
251 struct route
252 {
253 u32 track_id;
254 v4f colour;
255
256 u32 start;
257 mdl_submesh sm;
258
259 int active;
260 float factive;
261
262 double best_lap, latest_pass; /* Session */
263
264 m4x3f scoreboard_transform;
265 }
266 *routes;
267 u32 route_count;
268
269 struct route_gate
270 {
271 struct teleport_gate
272 {
273 v3f co[2];
274 v4f q[2];
275 v2f dims;
276
277 m4x3f to_world, transport;
278 }
279 gate;
280
281 u32 node_id;
282
283 struct route_timing
284 {
285 u32 version; /* Incremented on every teleport */
286 double time;
287 }
288 timing;
289 }
290 *gates;
291 u32 gate_count;
292
293 struct nonlocal_gate
294 {
295 struct teleport_gate gate;
296 mdl_node *node;
297
298 u32 target_map_index, working;
299 }
300 *nonlocal_gates;
301 u32 nonlocalgate_count;
302
303 struct route_collector
304 {
305 struct route_timing timing;
306 }
307 *collectors;
308 u32 collector_count;
309 #endif
310
311
312 /* logic
313 * ----------------------------------------------------
314 */
315
316 /* world geometry */
317 scene *scene_geo,
318 *scene_no_collide,
319 *scene_lines;
320
321 /* spacial mappings */
322 bh_tree *audio_bh,
323 *volume_bh,
324 *geo_bh;
325
326 /* graphics */
327 glmesh mesh_route_lines;
328 glmesh mesh_geo,
329 mesh_no_collide,
330 mesh_water;
331
332 rigidbody rb_geo; /* todo.. ... */
333 };
334
335 VG_STATIC struct world_global
336 {
337 /*
338 * Allocated as system memory
339 * --------------------------------------------------------------------------
340 */
341 void *generic_heap;
342
343 /* rendering */
344 glmesh skydome;
345 glmesh mesh_gate;
346 mdl_submesh sm_gate_surface,
347 sm_gate_marker[4];
348
349 double sky_time, sky_rate, sky_target_rate;
350
351 u32 current_run_version;
352 double time, rewind_from, rewind_to, last_use;
353
354 /* water rendering */
355 struct
356 {
357 struct framebuffer fbreflect, fbdepth;
358 }
359 water;
360
361 /* split flap display */
362 struct
363 {
364 glmesh mesh_base, mesh_display;
365 mdl_submesh sm_base;
366 u32 active_route_board;
367
368 u32 w, h;
369 float *buffer;
370 }
371 sfd;
372
373 v3f render_gate_pos;
374 int in_volume;
375
376 int switching_to_new_world;
377
378 world_instance worlds[4];
379 u32 world_count;
380 u32 active_world;
381 }
382 world_global;
383
384 VG_STATIC world_instance *get_active_world( void )
385 {
386 return &world_global.worlds[ world_global.active_world ];
387 }
388
389 /*
390 * API
391 */
392
393 VG_STATIC
394 int ray_hit_is_ramp( world_instance *world, ray_hit *hit );
395
396 VG_STATIC
397 struct world_surface *ray_hit_surface( world_instance *world, ray_hit *hit );
398
399 VG_STATIC
400 void ray_world_get_tri( world_instance *world, ray_hit *hit, v3f tri[3] );
401
402 VG_STATIC
403 int ray_world( world_instance *world, v3f pos, v3f dir, ray_hit *hit );
404
405 /*
406 * Submodules
407 */
408
409 #include "world_routes.h"
410 #include "world_sfd.h"
411 #include "world_render.h"
412 #include "world_water.h"
413 #include "world_volumes.h"
414 #include "world_gen.h"
415 #include "world_gate.h"
416
417 /*
418 * -----------------------------------------------------------------------------
419 * Events
420 * -----------------------------------------------------------------------------
421 */
422
423 VG_STATIC int world_stop_sound( int argc, const char *argv[] )
424 {
425 world_instance *world = get_active_world();
426 return 0;
427 }
428
429 VG_STATIC void world_init(void)
430 {
431 world_global.sky_rate = 1.0;
432 world_global.sky_target_rate = 1.0;
433
434 shader_scene_standard_register();
435 shader_scene_standard_alphatest_register();
436 shader_scene_vertex_blend_register();
437 shader_scene_terrain_register();
438 shader_scene_depth_register();
439 shader_scene_position_register();
440
441 shader_model_sky_register();
442
443 vg_info( "Loading world resources\n" );
444
445 vg_linear_clear( vg_mem.scratch );
446
447 mdl_context msky;
448 mdl_open( &msky, "models/rs_skydome.mdl", vg_mem.scratch );
449 mdl_load_metadata_block( &msky, vg_mem.scratch );
450 mdl_load_mesh_block( &msky, vg_mem.scratch );
451 mdl_close( &msky );
452
453 vg_acquire_thread_sync();
454 {
455 mdl_unpack_glmesh( &msky, &world_global.skydome );
456 }
457 vg_release_thread_sync();
458
459 /* Other systems */
460 vg_info( "Loading other world systems\n" );
461
462 vg_loader_step( world_render_init, NULL );
463 vg_loader_step( world_sfd_init, NULL );
464 vg_loader_step( world_water_init, NULL );
465 vg_loader_step( world_gates_init, NULL );
466 vg_loader_step( world_routes_init, NULL );
467
468 /* Allocate dynamic world memory arena */
469 u32 max_size = 76*1024*1024;
470 world_global.generic_heap = vg_create_linear_allocator( vg_mem.rtmemory,
471 max_size,
472 VG_MEMORY_SYSTEM );
473 }
474
475 typedef struct ent_call ent_call;
476 struct ent_call{
477 ent_index ent;
478 u32 function;
479 void *data;
480 };
481
482 VG_STATIC void entity_call( world_instance *world, ent_call *call );
483
484 VG_STATIC void ent_volume_call( world_instance *world, ent_call *call )
485 {
486 ent_volume *volume = mdl_arritm( &world->ent_volume, call->ent.index );
487 if( !volume->target.type ) return;
488
489 if( call->function == k_ent_function_trigger ){
490 call->ent = volume->target;
491
492 if( volume->type == k_volume_subtype_particle ){
493 v3f co;
494 co[0] = vg_randf()*2.0f-1.0f;
495 co[1] = vg_randf()*2.0f-1.0f;
496 co[2] = vg_randf()*2.0f-1.0f;
497 m4x3_mulv( volume->to_world, co, co );
498
499 call->function = k_ent_function_particle_spawn;
500 call->data = co;
501
502 entity_call( world, call );
503 }
504 else if( volume->type == k_volume_subtype_trigger ){
505 /* TODO */
506 }
507 }
508 }
509
510 VG_STATIC void ent_audio_call( world_instance *world, ent_call *call )
511 {
512 ent_audio *audio = mdl_arritm( &world->ent_audio, call->ent.index );
513
514 if( call->function == k_ent_function_particle_spawn ){
515 float chance = vg_randf()*100.0f,
516 bar = 0.0f;
517
518 for( u32 i=0; i<audio->clip_count; i++ ){
519 ent_audio_clip *clip = mdl_arritm( &world->ent_audio_clip,
520 audio->clip_start+i );
521
522 float mod = world->probabilities[ audio->probability_curve ],
523 p = clip->probability * mod;
524
525 bar += p;
526
527 if( chance < bar ){
528 float *pos = call->data;
529
530 audio_lock();
531
532 if( audio->behaviour == k_channel_behaviour_unlimited ){
533 audio_oneshot_3d( &clip->clip, pos,
534 audio->transform.s[0],
535 audio->volume );
536 }
537 else if( audio->behaviour == k_channel_behaviour_discard_if_full ){
538 audio_channel *ch =
539 audio_get_group_idle_channel( audio->group,
540 audio->max_channels );
541
542 if( ch ){
543 audio_channel_init( ch, &clip->clip, audio->flags );
544 audio_channel_group( ch, audio->group );
545 audio_channel_set_spacial( ch, pos, audio->transform.s[0] );
546 audio_channel_edit_volume( ch, audio->volume, 1 );
547 ch = audio_relinquish_channel( ch );
548 }
549 }
550 else if( audio->behaviour == k_channel_behaviour_crossfade_if_full){
551
552 }
553
554
555
556 audio_unlock();
557 break;
558 }
559 }
560 }
561 }
562
563 VG_STATIC void entity_call( world_instance *world, ent_call *call )
564 {
565 if( call->ent.type == k_ent_volume ){
566 ent_volume_call( world, call );
567 } else if( call->ent.type == k_ent_audio ){
568 ent_audio_call( world, call );
569 }
570 }
571
572 VG_STATIC void world_update( world_instance *world, v3f pos )
573 {
574 /* TEMP!!!!!! */
575 static double g_time = 0.0;
576 g_time += vg.time_delta * (1.0/(k_day_length*60.0));
577
578
579 struct ub_world_lighting *state = &world->ub_lighting;
580
581 state->g_time = g_time;
582 state->g_realtime = vg.time;
583 state->g_debug_indices = k_debug_light_indices;
584 state->g_light_preview = k_light_preview;
585 state->g_debug_complexity = k_debug_light_complexity;
586
587 state->g_time_of_day = vg_fractf( g_time );
588 state->g_day_phase = cosf( state->g_time_of_day * VG_PIf * 2.0f );
589 state->g_sunset_phase= cosf( state->g_time_of_day * VG_PIf * 4.0f + VG_PIf );
590
591 state->g_day_phase = state->g_day_phase * 0.5f + 0.5f;
592 state->g_sunset_phase = powf( state->g_sunset_phase * 0.5f + 0.5f, 6.0f );
593
594 float a = state->g_time_of_day * VG_PIf * 2.0f;
595 state->g_sun_dir[0] = sinf( a );
596 state->g_sun_dir[1] = cosf( a );
597 state->g_sun_dir[2] = 0.2f;
598 v3_normalize( state->g_sun_dir );
599
600
601 world->probabilities[ k_probability_curve_constant ] = 1.0f;
602
603 float dp = state->g_day_phase;
604
605 world->probabilities[ k_probability_curve_wildlife_day ] =
606 (dp*dp*0.8f+state->g_sunset_phase)*0.8f;
607 world->probabilities[ k_probability_curve_wildlife_night ] =
608 1.0f-powf(fabsf((state->g_time_of_day-0.5f)*5.0f),5.0f);
609
610
611 glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
612 glBufferSubData( GL_UNIFORM_BUFFER, 0,
613 sizeof(struct ub_world_lighting), &world->ub_lighting );
614 /* TEMP!!!!!! */
615
616 world_global.sky_time += world_global.sky_rate * vg.time_delta;
617 world_global.sky_rate = vg_lerp( world_global.sky_rate,
618 world_global.sky_target_rate,
619 vg.time_delta * 5.0 );
620
621 world_routes_update( world );
622 world_routes_debug( world );
623
624 /* ---- SFD ------------ */
625
626 if( mdl_arrcount( &world->ent_route ) ){
627 u32 closest = 0;
628 float min_dist = INFINITY;
629
630 for( u32 i=0; i<mdl_arrcount( &world->ent_route ); i++ ){
631 ent_route *route = mdl_arritm( &world->ent_route, i );
632 float dist = v3_dist2( route->board_transform[3], pos );
633
634 if( dist < min_dist ){
635 min_dist = dist;
636 closest = i;
637 }
638 }
639
640 if( (world_global.sfd.active_route_board != closest)
641 || network_scores_updated )
642 {
643 network_scores_updated = 0;
644 world_global.sfd.active_route_board = closest;
645
646 ent_route *route = mdl_arritm( &world->ent_route, closest );
647 u32 id = route->official_track_id;
648
649 if( id != 0xffffffff ){
650 struct netmsg_board *local_board =
651 &scoreboard_client_data.boards[id];
652
653 for( int i=0; i<13; i++ ){
654 sfd_encode( i, &local_board->data[27*i] );
655 }
656 }else{
657 sfd_encode( 0, mdl_pstr( &world->meta, route->pstr_name ) );
658 sfd_encode( 1, "No data" );
659 }
660 }
661 }
662 sfd_update();
663
664
665
666 static float random_accum = 0.0f;
667 random_accum += vg.time_delta;
668
669 u32 random_ticks = 0;
670
671 while( random_accum > 0.1f ){
672 random_accum -= 0.1f;
673 random_ticks ++;
674 }
675
676 float radius = 25.0f;
677 boxf volume_proximity;
678 v3_add( pos, (v3f){ radius, radius, radius }, volume_proximity[1] );
679 v3_sub( pos, (v3f){ radius, radius, radius }, volume_proximity[0] );
680
681 bh_iter it;
682 bh_iter_init( 0, &it );
683 int idx;
684
685 int in_volume = 0;
686
687 while( bh_next( world->volume_bh, &it, volume_proximity, &idx ) ){
688 ent_volume *volume = mdl_arritm( &world->ent_volume, idx );
689
690 boxf cube = {{-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f}};
691
692 if( volume->type == k_volume_subtype_trigger ){
693 v3f local;
694 m4x3_mulv( volume->to_local, pos, local );
695 vg_line_boxf_transformed( volume->to_world, cube, 0xff00ff00 );
696
697 if( (fabsf(local[0]) <= 1.0f) &&
698 (fabsf(local[1]) <= 1.0f) &&
699 (fabsf(local[2]) <= 1.0f) )
700 {
701 in_volume = 1;
702
703 if( !world_global.in_volume ){
704 ent_call basecall;
705 basecall.ent.index = idx;
706 basecall.ent.type = k_ent_volume;
707 basecall.function = k_ent_function_trigger;
708 basecall.data = NULL;
709
710 entity_call( world, &basecall );
711 }
712 }
713 }
714 else if( volume->type == k_volume_subtype_particle ){
715 vg_line_boxf_transformed( volume->to_world, cube, 0xff00c0ff );
716
717 for( int j=0; j<random_ticks; j++ ){
718 ent_call basecall;
719 basecall.ent.index = idx;
720 basecall.ent.type = k_ent_volume;
721 basecall.function = k_ent_function_trigger;
722 basecall.data = NULL;
723
724 entity_call( world, &basecall );
725 }
726 }
727 }
728 world_global.in_volume = in_volume;
729
730 #if 0
731 if( k_debug_light_indices )
732 {
733 for( int i=0; i<world->light_count; i++ ){
734 struct world_light *light = &world->lights[i];
735 struct classtype_world_light *inf = light->inf;
736
737 u32 colour = 0xff000000;
738 u8 r = inf->colour[0] * 255.0f,
739 g = inf->colour[1] * 255.0f,
740 b = inf->colour[2] * 255.0f;
741
742 colour |= r;
743 colour |= g << 8;
744 colour |= b << 16;
745
746 vg_line_pt3( light->node->co, 0.25f, colour );
747 }
748 }
749
750 #endif
751
752 #if 0
753
754 /* process soundscape transactions */
755 audio_lock();
756 for( int i=0; i<world->soundscape_count; i++ )
757 {
758 struct soundscape *s = &world->soundscapes[i];
759 s->usage_count = 0;
760
761 for( int j=0; j<s->max_instances; j++ )
762 {
763 if( s->channels[j] )
764 {
765 if( audio_channel_finished(s->channels[j]) )
766 s->channels[j] = audio_relinquish_channel( s->channels[j] );
767 else
768 s->usage_count ++;
769 }
770 }
771 }
772 audio_unlock();
773 #endif
774 }
775
776 /*
777 * -----------------------------------------------------------------------------
778 * API implementation
779 * -----------------------------------------------------------------------------
780 */
781
782 VG_STATIC void ray_world_get_tri( world_instance *world,
783 ray_hit *hit, v3f tri[3] )
784 {
785 for( int i=0; i<3; i++ )
786 v3_copy( world->scene_geo->arrvertices[ hit->tri[i] ].co, tri[i] );
787 }
788
789 VG_STATIC int ray_world( world_instance *world,
790 v3f pos, v3f dir, ray_hit *hit )
791 {
792 return scene_raycast( world->scene_geo, world->geo_bh, pos, dir, hit );
793 }
794
795 /*
796 * Cast a sphere from a to b and see what time it hits
797 */
798 VG_STATIC int spherecast_world( world_instance *world,
799 v3f pa, v3f pb, float r, float *t, v3f n )
800 {
801 bh_iter it;
802 bh_iter_init( 0, &it );
803
804 boxf region;
805 box_init_inf( region );
806 box_addpt( region, pa );
807 box_addpt( region, pb );
808
809 v3_add( (v3f){ r, r, r}, region[1], region[1] );
810 v3_add( (v3f){-r,-r,-r}, region[0], region[0] );
811
812 v3f dir;
813 v3_sub( pb, pa, dir );
814
815 v3f dir_inv;
816 dir_inv[0] = 1.0f/dir[0];
817 dir_inv[1] = 1.0f/dir[1];
818 dir_inv[2] = 1.0f/dir[2];
819
820 int hit = -1;
821 float min_t = 1.0f;
822
823 int idx;
824 while( bh_next( world->geo_bh, &it, region, &idx ) ){
825 u32 *ptri = &world->scene_geo->arrindices[ idx*3 ];
826 v3f tri[3];
827
828 boxf box;
829 box_init_inf( box );
830
831 for( int j=0; j<3; j++ ){
832 v3_copy( world->scene_geo->arrvertices[ptri[j]].co, tri[j] );
833 box_addpt( box, tri[j] );
834 }
835
836 v3_add( (v3f){ r, r, r}, box[1], box[1] );
837 v3_add( (v3f){-r,-r,-r}, box[0], box[0] );
838
839 if( !ray_aabb1( box, pa, dir_inv, 1.0f ) )
840 continue;
841
842 float t;
843 v3f n1;
844 if( spherecast_triangle( tri, pa, dir, r, &t, n1 ) ){
845 if( t < min_t ){
846 min_t = t;
847 hit = idx;
848 v3_copy( n1, n );
849 }
850 }
851 }
852
853 *t = min_t;
854 return hit;
855 }
856
857 VG_STATIC
858 struct world_surface *world_tri_index_surface( world_instance *world,
859 u32 index )
860 {
861 for( int i=1; i<world->surface_count; i++ ){
862 struct world_surface *surf = &world->surfaces[i];
863
864 if( (index >= surf->sm_geo.vertex_start) &&
865 (index < surf->sm_geo.vertex_start+surf->sm_geo.vertex_count ) )
866 {
867 return surf;
868 }
869 }
870
871 return &world->surfaces[0];
872 }
873
874 VG_STATIC struct world_surface *world_contact_surface( world_instance *world,
875 rb_ct *ct )
876 {
877 return world_tri_index_surface( world, ct->element_id );
878 }
879
880 VG_STATIC struct world_surface *ray_hit_surface( world_instance *world,
881 ray_hit *hit )
882 {
883 return world_tri_index_surface( world, hit->tri[0] );
884 }
885
886 #endif /* WORLD_H */