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