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