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