large reduction, redoing things
[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
22 #include "shaders/scene_standard.h"
23 #include "shaders/scene_standard_alphatest.h"
24 #include "shaders/scene_vertex_blend.h"
25 #include "shaders/scene_terrain.h"
26 #include "shaders/scene_depth.h"
27 #include "shaders/scene_position.h"
28
29 #include "shaders/model_sky.h"
30
31 typedef struct teleport_gate teleport_gate;
32
33 enum { k_max_ui_segments = 8 };
34
35 enum { k_max_ui_elements = k_max_ui_segments };
36 enum { k_max_element_verts = 10 };
37 enum { k_max_element_indices = 20 };
38
39 enum { k_route_ui_max_verts = k_max_ui_elements*k_max_element_verts };
40 enum { k_route_ui_max_indices = k_max_ui_elements*k_max_element_indices };
41
42 enum logic_type
43 {
44 k_logic_type_relay = 1,
45 k_logic_type_chance = 2,
46 k_logic_type_achievement = 3
47 };
48
49 enum geo_type
50 {
51 k_geo_type_solid = 0,
52 k_geo_type_nonsolid = 1,
53 k_geo_type_water = 2
54 };
55
56 static const float k_light_cube_size = 8.0f;
57
58 struct world_instance
59 {
60 /* This is a small flag we use to changelevel.
61 * It will not be cleared until all sounds stop playing
62 */
63
64 /* Fixed items
65 * -------------------------------------------------------
66 */
67
68 char world_name[ 64 ];
69
70 struct
71 {
72 boxf depthbounds;
73 int depth_computed;
74
75 float height;
76 int enabled;
77 v4f plane;
78 }
79 water;
80
81 /* STD140 */
82 struct ub_world_lighting
83 {
84 v4f g_cube_min,
85 g_cube_inv_range;
86
87 v4f g_water_plane,
88 g_depth_bounds;
89
90 v4f g_daysky_colour;
91 v4f g_nightsky_colour;
92 v4f g_sunset_colour;
93 v4f g_ambient_colour;
94 v4f g_sunset_ambient;
95 v4f g_sun_colour;
96 v4f g_sun_dir;
97
98 float g_water_fog;
99 float g_time;
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 /*
140 * Materials / textures
141 */
142
143 GLuint *textures;
144 u32 texture_count;
145
146 struct world_material
147 {
148 mdl_material info;
149 mdl_submesh sm_geo,
150 sm_no_collide;
151 }
152 * materials;
153 u32 material_count;
154
155 /*
156 * Named safe places to respawn
157 */
158 struct respawn_point
159 {
160 v3f co;
161 v4f q;
162 const char *name;
163 }
164 * spawns;
165 u32 spawn_count;
166
167 /*
168 * Audio player entities
169 */
170 struct world_audio_thing
171 {
172 v3f pos;
173 float volume, range;
174 u32 flags;
175 audio_clip temp_embedded_clip;
176 }
177 * audio_things;
178 u32 audio_things_count;
179
180 struct soundscape
181 {
182 /* locking */
183 audio_channel *channels[4];
184
185 /* accessable without locking */
186 v3f spawn_position;
187
188 u32 usage_count;
189 u32 max_instances;
190 u32 allow_transitions;
191 float transition_duration;
192 const char *label;
193 }
194 * soundscapes;
195 u32 soundscape_count;
196
197 /*
198 * Box volume entities
199 */
200 struct world_volume
201 {
202 m4x3f transform, inv_transform;
203 mdl_node *node;
204 }
205 * volumes;
206 u32 volume_count;
207
208 /*
209 * Lights
210 */
211 struct world_light
212 {
213 mdl_node *node;
214 struct classtype_world_light *inf;
215 m4x3f inverse_world;
216 v2f angle_sin_cos;
217
218 /* enabled.. etc?
219 * TODO: we should order entities in the binary by their type */
220 }
221 * lights;
222 u32 light_count;
223
224 /*
225 * Routes (world_routes.h)
226 * --------------------------------------------------------------------------
227 */
228 struct route_node
229 {
230 v3f co, right, up, h;
231 u32 next[2];
232
233 u32 special_type, special_id, current_refs, ref_count;
234 u32 route_ids[4]; /* Gates can be linked into up to four routes */
235 }
236 *nodes;
237 u32 node_count;
238
239 struct route
240 {
241 u32 track_id;
242 v4f colour;
243
244 u32 start;
245 mdl_submesh sm;
246
247 int active;
248 float factive;
249
250 double best_lap, latest_pass; /* Session */
251
252 m4x3f scoreboard_transform;
253 }
254 *routes;
255 u32 route_count;
256
257 struct route_gate
258 {
259 struct teleport_gate
260 {
261 v3f co[2];
262 v4f q[2];
263 v2f dims;
264
265 m4x3f to_world, transport;
266 }
267 gate;
268
269 u32 node_id;
270
271 struct route_timing
272 {
273 u32 version; /* Incremented on every teleport */
274 double time;
275 }
276 timing;
277 }
278 *gates;
279 u32 gate_count;
280
281 struct nonlocal_gate
282 {
283 struct teleport_gate gate;
284 mdl_node *node;
285
286 u32 target_map_index, working;
287 }
288 *nonlocal_gates;
289 u32 nonlocalgate_count;
290
291 struct route_collector
292 {
293 struct route_timing timing;
294 }
295 *collectors;
296 u32 collector_count;
297
298
299 /* logic
300 * ----------------------------------------------------
301 */
302
303 /* world geometry */
304 scene *scene_geo,
305 *scene_no_collide,
306 *scene_lines;
307
308 /* spacial mappings */
309 bh_tree *audio_bh,
310 *volume_bh,
311 *geo_bh;
312
313 /* graphics */
314 glmesh mesh_route_lines;
315 glmesh mesh_geo,
316 mesh_no_collide,
317 mesh_water;
318
319 rigidbody rb_geo; /* todo.. ... */
320 };
321
322 VG_STATIC struct world_global
323 {
324 /*
325 * Allocated as system memory
326 * --------------------------------------------------------------------------
327 */
328 void *generic_heap;
329
330 /* rendering */
331 glmesh skydome;
332 mdl_submesh dome_upper, dome_lower;
333
334 glmesh mesh_gate_surface;
335
336 double sky_time, sky_rate, sky_target_rate;
337
338 /* gates, TODO: active_gate should also know which instance */
339 u32 active_gate,
340 current_run_version;
341 double time, rewind_from, rewind_to, last_use;
342
343 /* water rendering */
344 struct
345 {
346 struct framebuffer fbreflect, fbdepth;
347 }
348 water;
349
350 /* split flap display */
351 struct
352 {
353 mdl_submesh *sm_module, *sm_card;
354 glmesh mesh_base, mesh_display;
355
356 u32 w, h;
357 float *buffer;
358 }
359 sfd;
360
361 /* timing bars, fixed maximum amount */
362 struct route_ui_bar
363 {
364 GLuint vao, vbo, ebo;
365
366 u32 indices_head;
367 u32 vertex_head;
368
369 struct route_ui_segment
370 {
371 float length;
372 u32 vertex_start, vertex_count,
373 index_start, index_count, notches;
374 }
375 segments[k_max_ui_segments];
376
377 u32 segment_start, segment_count, fade_start, fade_count;
378 double fade_timer_start;
379 float xpos;
380 }
381 ui_bars[16];
382
383 v3f render_gate_pos;
384 int active_route_board;
385 int in_volume;
386
387 int switching_to_new_world;
388
389 world_instance worlds[4];
390 u32 world_count;
391 u32 active_world;
392 }
393 world_global;
394
395 VG_STATIC world_instance *get_active_world( void )
396 {
397 return &world_global.worlds[ world_global.active_world ];
398 }
399
400 /*
401 * API
402 */
403
404 VG_STATIC
405 int ray_hit_is_ramp( world_instance *world, ray_hit *hit );
406
407 VG_STATIC
408 struct world_material *ray_hit_material( world_instance *world, ray_hit *hit );
409
410 VG_STATIC
411 void ray_world_get_tri( world_instance *world, ray_hit *hit, v3f tri[3] );
412
413 VG_STATIC
414 int ray_world( world_instance *world, v3f pos, v3f dir, ray_hit *hit );
415
416 /*
417 * Submodules
418 */
419
420 #include "world_routes.h"
421 #include "world_sfd.h"
422 #include "world_render.h"
423 #include "world_water.h"
424 #include "world_volumes.h"
425 #include "world_gen.h"
426 #include "world_gate.h"
427
428 /*
429 * -----------------------------------------------------------------------------
430 * Events
431 * -----------------------------------------------------------------------------
432 */
433
434 VG_STATIC int world_stop_sound( int argc, const char *argv[] )
435 {
436 world_instance *world = get_active_world();
437 return 0;
438 }
439
440 VG_STATIC void world_init(void)
441 {
442 world_global.sky_rate = 1.0;
443 world_global.sky_target_rate = 1.0;
444
445 shader_scene_standard_register();
446 shader_scene_standard_alphatest_register();
447 shader_scene_vertex_blend_register();
448 shader_scene_terrain_register();
449 shader_scene_depth_register();
450 shader_scene_position_register();
451
452 shader_model_sky_register();
453
454 vg_info( "Loading world resources\n" );
455
456 vg_linear_clear( vg_mem.scratch );
457 mdl_context *msky = mdl_load_full( vg_mem.scratch, "models/rs_skydome.mdl" );
458
459 mdl_node *nupper = mdl_node_from_name( msky, "dome_complete" );
460 world_global.dome_upper = *mdl_node_submesh( msky, nupper, 0 );
461
462 vg_acquire_thread_sync();
463 {
464 mdl_unpack_glmesh( msky, &world_global.skydome );
465 }
466 vg_release_thread_sync();
467
468 /* Other systems */
469 vg_info( "Loading other world systems\n" );
470
471 vg_loader_step( world_render_init, NULL );
472 vg_loader_step( world_sfd_init, NULL );
473 vg_loader_step( world_water_init, NULL );
474 vg_loader_step( world_gates_init, NULL );
475 vg_loader_step( world_routes_init, NULL );
476
477 /* Allocate dynamic world memory arena */
478 u32 max_size = 76*1024*1024;
479 world_global.generic_heap = vg_create_linear_allocator( vg_mem.rtmemory,
480 max_size,
481 VG_MEMORY_SYSTEM );
482 }
483
484 VG_STATIC void world_update( world_instance *world, v3f pos )
485 {
486 /* TEMP!!!!!! */
487 static double g_time = 0.0;
488 g_time += vg.time_delta * (1.0/(k_day_length*60.0));
489
490
491 struct ub_world_lighting *state = &world->ub_lighting;
492
493 state->g_time = g_time;
494 state->g_debug_indices = k_debug_light_indices;
495 state->g_light_preview = k_light_preview;
496 state->g_debug_complexity = k_debug_light_complexity;
497
498 state->g_time_of_day = vg_fractf( g_time );
499 state->g_day_phase = cosf( state->g_time_of_day * VG_PIf * 2.0f );
500 state->g_sunset_phase= cosf( state->g_time_of_day * VG_PIf * 4.0f + VG_PIf );
501
502 state->g_day_phase = state->g_day_phase * 0.5f + 0.5f;
503 state->g_sunset_phase = powf( state->g_sunset_phase * 0.5f + 0.5f, 6.0f );
504
505 float a = state->g_time_of_day * VG_PIf * 2.0f;
506 state->g_sun_dir[0] = sinf( a );
507 state->g_sun_dir[1] = cosf( a );
508 state->g_sun_dir[2] = 0.2f;
509 v3_normalize( state->g_sun_dir );
510
511
512
513 glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
514 glBufferSubData( GL_UNIFORM_BUFFER, 0,
515 sizeof(struct ub_world_lighting), &world->ub_lighting );
516 /* TEMP!!!!!! */
517
518 world_global.sky_time += world_global.sky_rate * vg.time_delta;
519 world_global.sky_rate = vg_lerp( world_global.sky_rate,
520 world_global.sky_target_rate,
521 vg.time_delta * 5.0 );
522
523 world_routes_update( world );
524 #if 0
525 world_routes_debug();
526 #endif
527
528 if( world->route_count > 0 )
529 {
530 int closest = 0;
531 float min_dist = INFINITY;
532
533 for( int i=0; i<world->route_count; i++ )
534 {
535 float d = v3_dist2( world->routes[i].scoreboard_transform[3], pos );
536
537 if( d < min_dist )
538 {
539 min_dist = d;
540 closest = i;
541 }
542 }
543
544 if( (world_global.active_route_board != closest)
545 || network_scores_updated )
546 {
547 network_scores_updated = 0;
548 world_global.active_route_board = closest;
549
550 struct route *route = &world->routes[closest];
551
552 u32 id = route->track_id;
553
554 if( id != 0xffffffff )
555 {
556 struct netmsg_board *local_board =
557 &scoreboard_client_data.boards[id];
558
559 for( int i=0; i<13; i++ )
560 {
561 sfd_encode( i, &local_board->data[27*i] );
562 }
563 }
564 }
565 }
566
567 /* TODO: Bvh */
568
569 static float random_accum = 0.0f;
570 random_accum += vg.time_delta;
571
572 u32 random_ticks = 0;
573
574 while( random_accum > 0.1f )
575 {
576 random_accum -= 0.1f;
577 random_ticks ++;
578 }
579
580 float radius = 25.0f;
581 boxf volume_proximity;
582 v3_add( pos, (v3f){ radius, radius, radius }, volume_proximity[1] );
583 v3_sub( pos, (v3f){ radius, radius, radius }, volume_proximity[0] );
584
585 bh_iter it;
586 bh_iter_init( 0, &it );
587 int idx;
588
589 int in_volume = 0;
590
591 while( bh_next( world->volume_bh, &it, volume_proximity, &idx ) )
592 {
593 struct world_volume *zone = &world->volumes[idx];
594
595 if( zone->node->classtype == k_classtype_volume_audio )
596 {
597 vg_line_boxf_transformed( zone->transform, (boxf){{-1.0f,-1.0f,-1.0f},
598 { 1.0f, 1.0f, 1.0f}},
599 0xff00c0ff );
600 #if 0
601 for( int j=0; j<random_ticks; j++ )
602 {
603 logic_packet packet;
604 packet.location = zone->target_logic_brick;
605 packet.function = 0;
606
607 packet.type = k_mdl_128bit_datatype_vec3;
608 packet.data._v4f[0] = vg_randf()*2.0f-1.0f;
609 packet.data._v4f[1] = vg_randf()*2.0f-1.0f;
610 packet.data._v4f[2] = vg_randf()*2.0f-1.0f;
611 m4x3_mulv( zone->transform, packet.data._v4f, packet.data._v4f );
612
613 logic_bricks_send_packet( world, &packet );
614 }
615 #endif
616 continue;
617 }
618
619 v3f local;
620 m4x3_mulv( zone->inv_transform, pos, local );
621
622 if( (fabsf(local[0]) <= 1.0f) &&
623 (fabsf(local[1]) <= 1.0f) &&
624 (fabsf(local[2]) <= 1.0f) )
625 {
626 in_volume = 1;
627
628 if( !world_global.in_volume )
629 {
630 #if 0
631 logic_packet packet;
632 packet.location = zone->target_logic_brick;
633 packet.function = 0;
634
635 packet.type = k_mdl_128bit_datatype_vec3;
636 v3_copy( pos, packet.data._v4f );
637
638 logic_bricks_send_packet( world, &packet );
639 #endif
640 }
641
642 vg_line_boxf_transformed( zone->transform, (boxf){{-1.0f,-1.0f,-1.0f},
643 { 1.0f, 1.0f, 1.0f}},
644 0xff00ff00 );
645 }
646 else
647 {
648 vg_line_boxf_transformed( zone->transform, (boxf){{-1.0f,-1.0f,-1.0f},
649 { 1.0f, 1.0f, 1.0f}},
650 0xff0000ff );
651 }
652 }
653
654 if( k_debug_light_indices )
655 {
656 for( int i=0; i<world->light_count; i++ )
657 {
658 struct world_light *light = &world->lights[i];
659 struct classtype_world_light *inf = light->inf;
660
661 u32 colour = 0xff000000;
662 u8 r = inf->colour[0] * 255.0f,
663 g = inf->colour[1] * 255.0f,
664 b = inf->colour[2] * 255.0f;
665
666 colour |= r;
667 colour |= g << 8;
668 colour |= b << 16;
669
670 vg_line_pt3( light->node->co, 0.25f, colour );
671 }
672 }
673
674 world_global.in_volume = in_volume;
675 sfd_update();
676
677 /* process soundscape transactions */
678 audio_lock();
679 for( int i=0; i<world->soundscape_count; i++ )
680 {
681 struct soundscape *s = &world->soundscapes[i];
682 s->usage_count = 0;
683
684 for( int j=0; j<s->max_instances; j++ )
685 {
686 if( s->channels[j] )
687 {
688 if( audio_channel_finished(s->channels[j]) )
689 s->channels[j] = audio_relinquish_channel( s->channels[j] );
690 else
691 s->usage_count ++;
692 }
693 }
694 }
695 audio_unlock();
696 }
697
698 /*
699 * -----------------------------------------------------------------------------
700 * API implementation
701 * -----------------------------------------------------------------------------
702 */
703
704 VG_STATIC void ray_world_get_tri( world_instance *world,
705 ray_hit *hit, v3f tri[3] )
706 {
707 for( int i=0; i<3; i++ )
708 v3_copy( world->scene_geo->arrvertices[ hit->tri[i] ].co, tri[i] );
709 }
710
711 VG_STATIC int ray_world( world_instance *world,
712 v3f pos, v3f dir, ray_hit *hit )
713 {
714 return scene_raycast( world->scene_geo, world->geo_bh, pos, dir, hit );
715 }
716
717 /*
718 * Cast a sphere from a to b and see what time it hits
719 */
720 VG_STATIC int spherecast_world( world_instance *world,
721 v3f pa, v3f pb, float r, float *t, v3f n )
722 {
723 bh_iter it;
724 bh_iter_init( 0, &it );
725
726 boxf region;
727 box_init_inf( region );
728 box_addpt( region, pa );
729 box_addpt( region, pb );
730
731 v3_add( (v3f){ r, r, r}, region[1], region[1] );
732 v3_add( (v3f){-r,-r,-r}, region[0], region[0] );
733
734 v3f dir;
735 v3_sub( pb, pa, dir );
736
737 v3f dir_inv;
738 dir_inv[0] = 1.0f/dir[0];
739 dir_inv[1] = 1.0f/dir[1];
740 dir_inv[2] = 1.0f/dir[2];
741
742 int hit = -1;
743 float min_t = 1.0f;
744
745 int idx;
746 while( bh_next( world->geo_bh, &it, region, &idx ) )
747 {
748 u32 *ptri = &world->scene_geo->arrindices[ idx*3 ];
749 v3f tri[3];
750
751 boxf box;
752 box_init_inf( box );
753
754 for( int j=0; j<3; j++ )
755 {
756 v3_copy( world->scene_geo->arrvertices[ptri[j]].co, tri[j] );
757 box_addpt( box, tri[j] );
758 }
759
760 v3_add( (v3f){ r, r, r}, box[1], box[1] );
761 v3_add( (v3f){-r,-r,-r}, box[0], box[0] );
762
763 if( !ray_aabb1( box, pa, dir_inv, 1.0f ) )
764 continue;
765
766 float t;
767 v3f n1;
768 if( spherecast_triangle( tri, pa, dir, r, &t, n1 ) )
769 {
770 if( t < min_t )
771 {
772 min_t = t;
773 hit = idx;
774 v3_copy( n1, n );
775 }
776 }
777 }
778
779 *t = min_t;
780 return hit;
781 }
782
783 VG_STATIC
784 struct world_material *world_tri_index_material( world_instance *world,
785 u32 index )
786 {
787 for( int i=1; i<world->material_count; i++ )
788 {
789 struct world_material *mat = &world->materials[i];
790
791 if( (index >= mat->sm_geo.vertex_start) &&
792 (index < mat->sm_geo.vertex_start+mat->sm_geo.vertex_count ) )
793 {
794 return mat;
795 }
796 }
797
798 /* error material */
799 return &world->materials[0];
800 }
801
802 VG_STATIC struct world_material *world_contact_material( world_instance *world,
803 rb_ct *ct )
804 {
805 return world_tri_index_material( world, ct->element_id );
806 }
807
808 VG_STATIC struct world_material *ray_hit_material( world_instance *world,
809 ray_hit *hit )
810 {
811 return world_tri_index_material( world, hit->tri[0] );
812 }
813
814 #endif /* WORLD_H */