From 56f320d8ce6e8997370ec8e02fe50ca2d07b67f0 Mon Sep 17 00:00:00 2001 From: hgn Date: Thu, 23 Feb 2023 20:12:47 +0000 Subject: [PATCH] isolate world code --- audio.h | 11 +- blender_export.py | 28 +++ maps_src/mp_home.mdl | Bin 0 -> 2720 bytes player.c | 5 +- player_ragdoll.h | 4 +- player_skate.c | 48 +++-- player_walk.c | 18 +- render.h | 123 +----------- scene.h | 4 +- skaterift.c | 59 +++--- world.h | 308 ++++++++++++++++++----------- world_gate.h | 22 ++- world_gen.h | 449 ++++++++++++++++++++++++------------------- world_render.h | 167 +++++++++++----- world_routes.h | 312 +++++++++++++++--------------- world_sfd.h | 31 +-- world_water.h | 53 ++--- 17 files changed, 886 insertions(+), 756 deletions(-) create mode 100644 maps_src/mp_home.mdl diff --git a/audio.h b/audio.h index 2d0417f..5caa759 100644 --- a/audio.h +++ b/audio.h @@ -265,6 +265,8 @@ VG_STATIC void audio_sample_occlusion( v3f origin ) v3f last; v3_zero(last); + world_instance *world = get_active_world(); + for( int i=0; iinfo.surface_prop == k_surface_prop_grass) { @@ -356,7 +359,7 @@ VG_STATIC enum audio_sprite_type audio_sample_sprite_random( v3f origin, output[1] = 0.0f; output[2] = pos[2]; - if( world.water.enabled ) + if( world->water.enabled ) return k_audio_sprite_type_water; else return k_audio_sprite_type_none; diff --git a/blender_export.py b/blender_export.py index 06d90a4..d6da9c2 100644 --- a/blender_export.py +++ b/blender_export.py @@ -798,6 +798,34 @@ class classtype_point_light(Structure): #} #} +# Classtype 201 +# +# Purpose: lighting settings for world +# +class classtype_lighting_info(Structure): +#{ + _pack_ = 1 + _fields_ = [("colours",(c_float*3)*3), + ("directions",(c_float*2)*3), + ("states",c_uint32*3), + ("shadow_spread",c_float), + ("shadow_length",c_float), + ("ambient",c_float*3)] + + def encode_obj(_, node, node_def): + #{ + node.classtype = 201 + + # TODO + #} + + @staticmethod + def editor_interface( layout, obj ): + #{ + pass + #} +#} + class classtype_spawn_link(Structure): #{ _pack_ = 1 diff --git a/maps_src/mp_home.mdl b/maps_src/mp_home.mdl new file mode 100644 index 0000000000000000000000000000000000000000..761e527bdaf05a0a161d9090521cac6659a621bd GIT binary patch literal 2720 zcmd5-zfTiU9Dl7Sic~0rf^jH=gRvsoVzt5CaiWt$7h~g~DPn=}t3n+})Ldd>&P5S| z0pdVHVwCQ#RwjqLN=O`t!7w;F_!p?3&+8rb&K`|hKk2uh?|biapMKxF@AZVR3IQR+ zN)x_-1Be`gbFD!k@DZxbMGk-+aNOoJII@qkLg?T&n|r}KFx!B3qmiq%pet~wh=29J z0ne;nF-Bf_J@YcSmr68X(E7GX-3*UuqBzG=9q4`@6nt`2;0U64=f;Q4@UT{#E2G)b@J5upmWh=`;Xl+LedZRLH-N6tNZ_?UawR|mdb zcKdL(4BoPCJMXvIA?HANFM)L-(i(ig0xWaQd!|zPpI^>7*zHsE>RP|q4hMQVeM&?9 z^NigGx?+xf!B%zU`_?Hrw{&S-%N863~# zBvY1}9GS>>b;n{AIiC$@z6bf$@mzie8eTu0&rIdPZlty4r4F7iAp2H7D}MB4-#oig zrRU{6@ak`ibl=b(dic8hZ$U5AC)NB>!|wgwt>+Btsi8+*M7jQi)UQ_am-R#E(of2I z{PozcOFs(z^49BW{-{Bor%T_1dVKVCeI6N59Vfq8^vNU0l%i(tG>o81z2<=J>nL=Q#8}`;~g{{i1%U`u&o6 zZ$F%XUZ_?3!O??>a=#sw`s)20fGQ}pW#<1)17bgd?>pvXzNQ$=5865TkR8nVn&g;# z*be6W4UWk~GlFA+IT1n}LGXI6F(-4q1;O9u8gnw&`G3axxW=5!b$Sup3v+T9F__6` za+$lMNG0x1j%1Ojj0W+mP$*b0jimM5C>Tj|)<|x5B&}#TX*ShWR$4Tyc_WBY*NmX4 z1h{wz47|0vy`wFjD!`BCd{@(Y0a>rA?pQNAY?{E MbylhD+P}}yAJs}D2mk;8 literal 0 HcmV?d00001 diff --git a/player.c b/player.c index 4c8f76a..b705d7f 100644 --- a/player.c +++ b/player.c @@ -268,7 +268,10 @@ PLAYER_API void player__render( camera *cam, player_instance *player ) shader_model_character_view_uTexMain( 0 ); shader_model_character_view_uCamera( cam->transform[3] ); shader_model_character_view_uPv( cam->mtx.pv ); - shader_link_standard_ub( _shader_model_character_view.id, 2 ); + + world_instance *world = get_active_world(); + world_link_lighting_ub( world, _shader_model_character_view.id, 2 ); + glUniformMatrix4x3fv( _uniform_model_character_view_uTransforms, player->playeravatar->sk.bone_count, 0, diff --git a/player_ragdoll.h b/player_ragdoll.h index f1f6221..e4a368e 100644 --- a/player_ragdoll.h +++ b/player_ragdoll.h @@ -269,6 +269,8 @@ VG_STATIC void player_debug_ragdoll(void) */ VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd ) { + world_instance *world = get_active_world(); + int run_sim = 0; ragdoll_frame ++; @@ -280,7 +282,7 @@ VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd ) rb_solver_reset(); for( int i=0; ipart_count; i ++ ) - rb_collide( &rd->parts[i].rb, &world.rb_geo ); + rb_collide( &rd->parts[i].rb, &world->rb_geo ); /* * COLLISION DETECTION diff --git a/player_skate.c b/player_skate.c index aae8280..098ce8a 100644 --- a/player_skate.c +++ b/player_skate.c @@ -35,8 +35,10 @@ VG_STATIC int skate_collide_smooth( player_instance *player, m4x3f mtx, rb_sphere *sphere, rb_ct *man ) { + world_instance *world = get_active_world(); + int len = 0; - len = rb_sphere__scene( mtx, sphere, NULL, &world.rb_geo.inf.scene, man ); + len = rb_sphere__scene( mtx, sphere, NULL, &world->rb_geo.inf.scene, man ); for( int i=0; ibasis[1], support_axis ); v3_normalize( support_axis ); - while( bh_next( world.geo_bh, &it, box, &idx ) ) + while( bh_next( world->geo_bh, &it, box, &idx ) ) { - u32 *ptri = &world.scene_geo->arrindices[ idx*3 ]; + u32 *ptri = &world->scene_geo->arrindices[ idx*3 ]; v3f tri[3]; - struct world_material *mat = world_tri_index_material(ptri[0]); + struct world_material *mat = world_tri_index_material(world,ptri[0]); if( !(mat->info.flags & k_material_flag_skate_surface) ) continue; for( int j=0; j<3; j++ ) - v3_copy( world.scene_geo->arrvertices[ptri[j]].co, tri[j] ); + v3_copy( world->scene_geo->arrvertices[ptri[j]].co, tri[j] ); for( int j=0; j<3; j++ ) { @@ -323,6 +327,8 @@ VG_STATIC int solve_prediction_for_target( player_instance *player, VG_STATIC void player__approximate_best_trajectory( player_instance *player ) { + world_instance *world = get_active_world(); + struct player_skate *s = &player->_skate; float k_trace_delta = k_rb_delta * 10.0f; @@ -390,7 +396,7 @@ void player__approximate_best_trajectory( player_instance *player ) if( !grind_located && (launch_vy - gravity*t < 0.0f) ) { v3f closest; - if( bh_closest_point( world.geo_bh, co1, closest, 1.0f ) != -1 ) + if( bh_closest_point( world->geo_bh, co1, closest, 1.0f ) != -1 ) { v3f ve; v3_copy( launch_v, ve ); @@ -420,7 +426,7 @@ void player__approximate_best_trajectory( player_instance *player ) float t1; v3f n; - int idx = spherecast_world( co0, co1, k_board_radius, &t1, n ); + int idx = spherecast_world( world, co0, co1, k_board_radius, &t1, n ); if( idx != -1 ) { v3f co; @@ -444,8 +450,9 @@ void player__approximate_best_trajectory( player_instance *player ) p->score = -v3_dot( ve, p->n ); p->land_dist = t + k_trace_delta * t1; - u32 vert_index = world.scene_geo->arrindices[ idx*3 ]; - struct world_material *mat = world_tri_index_material( vert_index ); + u32 vert_index = world->scene_geo->arrindices[ idx*3 ]; + struct world_material *mat = + world_tri_index_material( world, vert_index ); /* Bias prediction towords ramps */ if( !(mat->info.flags & k_material_flag_skate_surface) ) @@ -1080,6 +1087,7 @@ int skate_compute_surface_alignment( player_instance *player, v3f surface_normal, v3f axel_dir ) { struct player_skate *s = &player->_skate; + world_instance *world = get_active_world(); v3f truck, left, right; m4x3_mulv( player->rb.to_world, ra, truck ); @@ -1104,7 +1112,7 @@ int skate_compute_surface_alignment( player_instance *player, v3_muladds( left, player->rb.to_world[1], k_board_radius, left ); ray_l.dist = 2.1f * k_board_radius; - res_l = ray_world( left, dir, &ray_l ); + res_l = ray_world( world, left, dir, &ray_l ); if( res_l ) break; @@ -1117,7 +1125,7 @@ int skate_compute_surface_alignment( player_instance *player, v3_muladds( right, player->rb.to_world[1], k_board_radius, right ); ray_r.dist = 2.1f * k_board_radius; - res_r = ray_world( right, dir, &ray_r ); + res_r = ray_world( world, right, dir, &ray_r ); if( res_r ) break; @@ -1155,15 +1163,15 @@ int skate_compute_surface_alignment( player_instance *player, { /* fallback: use the closes point to the trucks */ v3f closest; - int idx = bh_closest_point( world.geo_bh, midpoint, closest, 0.1f ); + int idx = bh_closest_point( world->geo_bh, midpoint, closest, 0.1f ); if( idx != -1 ) { - u32 *tri = &world.scene_geo->arrindices[ idx * 3 ]; + u32 *tri = &world->scene_geo->arrindices[ idx * 3 ]; v3f verts[3]; for( int j=0; j<3; j++ ) - v3_copy( world.scene_geo->arrvertices[ tri[j] ].co, verts[j] ); + v3_copy( world->scene_geo->arrvertices[ tri[j] ].co, verts[j] ); v3f vert0, vert1, n; v3_sub( verts[1], verts[0], vert0 ); @@ -1302,7 +1310,7 @@ VG_STATIC int skate_point_visible( v3f origin, v3f target ) v3_muls( dir, 1.0f/ray.dist, dir ); ray.dist -= 0.025f; - if( ray_world( origin, dir, &ray ) ) + if( ray_world( get_active_world(), origin, dir, &ray ) ) return 0; return 1; @@ -1812,6 +1820,8 @@ VG_STATIC enum skate_activity skate_availible_grind( player_instance *player ) VG_STATIC void player__skate_update( player_instance *player ) { struct player_skate *s = &player->_skate; + world_instance *world = get_active_world(); + v3_copy( player->rb.co, s->state.prev_pos ); s->state.activity_prev = s->state.activity; @@ -1980,7 +1990,7 @@ begin_collision:; v3f n; float cast_radius = wheels[i].radius - k_penetration_slop * 2.0f; - if( spherecast_world( current, future, cast_radius, &t, n ) != -1) + if( spherecast_world( world, current, future, cast_radius, &t, n ) != -1) max_time = vg_minf( max_time, t * s->substep ); } @@ -2029,7 +2039,7 @@ begin_collision:; float t; v3f n; if( (v3_dist2( head_wp0, head_wp1 ) > 0.001f) && - (spherecast_world( head_wp0, head_wp1, 0.2f, &t, n ) != -1) ) + (spherecast_world( world, head_wp0, head_wp1, 0.2f, &t, n ) != -1) ) { v3_lerp( start_co, player->rb.co, t, player->rb.co ); rb_update_transform( &player->rb ); @@ -2075,7 +2085,7 @@ begin_collision:; rb_ct *cman = &manifold[manifold_len]; - int l = rb_capsule__scene( mtx, &capsule, NULL, &world.rb_geo.inf.scene, + int l = rb_capsule__scene( mtx, &capsule, NULL, &world->rb_geo.inf.scene, cman ); /* weld joints */ @@ -2212,7 +2222,7 @@ begin_collision:; vg_line_pt3( s->state.cog, 0.02f, VG__WHITE ); teleport_gate *gate; - if( (gate = world_intersect_gates( player->rb.co, s->state.prev_pos )) ) + if( (gate = world_intersect_gates(world, player->rb.co, s->state.prev_pos)) ) { m4x3_mulv( gate->transport, player->rb.co, player->rb.co ); m3x3_mulv( gate->transport, player->rb.v, player->rb.v ); diff --git a/player_walk.c b/player_walk.c index c86c9db..00ee7fb 100644 --- a/player_walk.c +++ b/player_walk.c @@ -118,6 +118,7 @@ VG_STATIC void player_walk_drop_in_overhang_transform( player_instance *player, VG_STATIC int player_walk_scan_for_drop_in( player_instance *player ) { struct player_walk *w = &player->_walk; + world_instance *world = get_active_world(); v3f dir, center; q_mulv( player->rb.q, (v3f){0.0f,0.0f,1.0f}, dir ); @@ -140,7 +141,7 @@ VG_STATIC int player_walk_scan_for_drop_in( player_instance *player ) ray_hit *ray = &samples[ sample_count ]; ray->dist = 2.0f; - if( ray_world( pos, ray_dir, ray ) ) + if( ray_world( world, pos, ray_dir, ray ) ) { vg_line( pos, ray->pos, VG__RED ); vg_line_pt3( ray->pos, 0.025f, VG__BLACK ); @@ -218,7 +219,7 @@ VG_STATIC int player_walk_scan_for_drop_in( player_instance *player ) ray_hit ray; ray.dist = k_board_length*2.0f + 0.6f; - if( ray_world( va, v0, &ray ) ) + if( ray_world( world, va, v0, &ray ) ) { vg_line( va, vb, VG__RED ); vg_line_pt3( ray.pos, 0.1f, VG__RED ); @@ -227,7 +228,7 @@ VG_STATIC int player_walk_scan_for_drop_in( player_instance *player ) } v3_muls( v0, -1.0f, v0 ); - if( ray_world( vb, v0, &ray ) ) + if( ray_world( world, vb, v0, &ray ) ) { vg_line( va, vb, VG__RED ); vg_line_pt3( ray.pos, 0.1f, VG__RED ); @@ -395,8 +396,10 @@ VG_STATIC void player__walk_update( player_instance *player ) /* * Collision detection */ + world_instance *world = get_active_world(); + len = rb_capsule__scene( mtx, &w->collider, NULL, - &world.rb_geo.inf.scene, manifold ); + &world->rb_geo.inf.scene, manifold ); rb_manifold_filter_coplanar( manifold, len, 0.01f ); len = rb_manifold_apply_filtered( manifold, len ); @@ -458,7 +461,8 @@ VG_STATIC void player__walk_update( player_instance *player ) { player_friction( player->rb.v ); - struct world_material *surface_mat = world_contact_material(manifold); + struct world_material *surface_mat = + world_contact_material( world, manifold); w->surface = surface_mat->info.surface_prop; } } @@ -565,7 +569,7 @@ VG_STATIC void player__walk_update( player_instance *player ) float t, sr = w->collider.radius-0.04f; v3f n; - if( spherecast_world( lwr_prev, lwr_now, sr, &t, n ) != -1 ) + if( spherecast_world( world, lwr_prev, lwr_now, sr, &t, n ) != -1 ) { v3_lerp( lwr_prev, lwr_now, vg_maxf(0.01f,t), player->rb.co ); player->rb.co[1] -= w->collider.radius; @@ -577,7 +581,7 @@ VG_STATIC void player__walk_update( player_instance *player ) } teleport_gate *gate; - if( (gate = world_intersect_gates( player->rb.co, w->state.prev_pos )) ) + if( (gate = world_intersect_gates(world, player->rb.co, w->state.prev_pos)) ) { m4x3_mulv( gate->transport, player->rb.co, player->rb.co ); m3x3_mulv( gate->transport, player->rb.v, player->rb.v ); diff --git a/render.h b/render.h index 7b5b473..91fe39e 100644 --- a/render.h +++ b/render.h @@ -5,6 +5,7 @@ #include "common.h" #include "model.h" #include "camera.h" +#include "world.h" #include "shaders/blit.h" #include "shaders/blitblur.h" @@ -15,11 +16,10 @@ #include "shaders/vblend.h" #endif -VG_STATIC void render_water_texture( camera *cam ); -VG_STATIC void render_water_surface( camera *cam ); -VG_STATIC void render_world( camera *cam ); -VG_STATIC void shader_link_standard_ub( GLuint shader, int texture_id ); -VG_STATIC void render_world_depth( camera *cam ); +VG_STATIC void render_water_texture( world_instance *world, camera *cam ); +VG_STATIC void render_water_surface( world_instance *world, camera *cam ); +VG_STATIC void render_world( world_instance *world, camera *cam ); +VG_STATIC void render_world_depth( world_instance *world, camera *cam ); #ifndef RENDER_H #define RENDER_H @@ -35,31 +35,9 @@ VG_STATIC struct pipeline glmesh fsquad; framebuffer *fb_main, - *fb_heightmap, *fb_water_reflection, *fb_water_beneath; - /* STD140 */ - struct ub_world_lighting - { - /* v3f (padded) */ - v4f g_light_colours[3], - g_light_directions[3], - g_ambient_colour; - - v4f g_water_plane, - g_depth_bounds; - - float g_water_fog; - int g_light_count; - int g_light_preview; - int g_shadow_samples; - - v4f g_point_light_positions[32]; - v4f g_point_light_colours[32]; - } - ub_world_lighting; - struct light_widget { int enabled; @@ -69,8 +47,6 @@ VG_STATIC struct pipeline widgets[3]; float shadow_spread, shadow_length; - GLuint ubo_world_lighting, - ubo_world; int ready; } @@ -96,11 +72,6 @@ gpipeline = }, .shadow_spread = 0.65f, .shadow_length = 9.50f, - - .ub_world_lighting = - { - .g_ambient_colour = { 0.09f, 0.03f, 0.07f } - } }; struct framebuffer @@ -179,29 +150,6 @@ framebuffers[] = } } }, - { - /* - * A ortho projection of the world, used for shadows and ocean colouring. - * Note: it does not have a render buffer attachement because it's - * intended to be drawn to in a MAX blending mode - */ - "heightmap", - .link = &gpipeline.fb_heightmap, - .fixed_w = 1024, - .fixed_h = 1024, - - .attachments = - { - { - "depth", k_framebuffer_attachment_type_colour, - - .internalformat = GL_R32F, - .format = GL_RED, - .type = GL_FLOAT, - .attachment = GL_COLOR_ATTACHMENT0 - } - } - }, { /* * Second rendered view from the perspective of the water reflection @@ -304,51 +252,6 @@ VG_STATIC void render_fb_bind_texture( framebuffer *fb, /* * Shaders */ -VG_STATIC void shader_link_standard_ub( GLuint shader, int texture_id ) -{ - GLuint idx = glGetUniformBlockIndex( shader, "ub_world_lighting" ); - glUniformBlockBinding( shader, idx, 0 ); - - render_fb_bind_texture( gpipeline.fb_heightmap, 0, texture_id ); - glUniform1i( glGetUniformLocation( shader, "g_world_depth" ), texture_id ); -} - -VG_STATIC void render_update_lighting_ub(void) -{ - struct ub_world_lighting *winf = &gpipeline.ub_world_lighting; - int c = 0; - - for( int i=0; i<3; i++ ) - { - struct light_widget *lw = &gpipeline.widgets[i]; - - if( lw->enabled ) - { - float pitch = lw->dir[0], - yaw = lw->dir[1], - xz = cosf( pitch ); - - v3_copy( (v3f){ xz*cosf(yaw), sinf(pitch), xz*sinf(yaw) }, - winf->g_light_directions[c] ); - v3_copy( lw->colour, winf->g_light_colours[c] ); - - c ++; - } - } - - winf->g_light_count = c; - winf->g_light_directions[0][3] = gpipeline.shadow_length; - winf->g_light_colours[0][3] = gpipeline.shadow_spread; - - if( vg.quality_profile == k_quality_profile_low ) - winf->g_shadow_samples = 0; - else - winf->g_shadow_samples = 8; - - glBindBuffer( GL_UNIFORM_BUFFER, gpipeline.ubo_world_lighting ); - glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting), - &gpipeline.ub_world_lighting ); -} #define FB_FORMAT_STR( E ) { E, #E }, @@ -656,21 +559,6 @@ VG_STATIC void render_init_fs_quad(void) VG_CHECK_GL_ERR(); } -VG_STATIC void render_init_uniform_buffers(void) -{ - vg_info( "[render] Allocate uniform buffer\n" ); - - glGenBuffers( 1, &gpipeline.ubo_world_lighting ); - glBindBuffer( GL_UNIFORM_BUFFER, gpipeline.ubo_world_lighting ); - glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting), - NULL, GL_DYNAMIC_DRAW ); - - render_update_lighting_ub(); - glBindBufferBase( GL_UNIFORM_BUFFER, 0, gpipeline.ubo_world_lighting ); - - VG_CHECK_GL_ERR(); -} - VG_STATIC void render_init(void) { shader_blit_register(); @@ -689,7 +577,6 @@ VG_STATIC void render_init(void) } render_init_fs_quad(); - render_init_uniform_buffers(); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); gpipeline.ready = 1; diff --git a/scene.h b/scene.h index 902aedb..7a9460b 100644 --- a/scene.h +++ b/scene.h @@ -182,13 +182,13 @@ __attribute__((warn_unused_result)) VG_STATIC scene *scene_fix( void *lin_alloc, scene *pscene ) { /* FIXME: Why is this disabled? */ - return pscene; + u32 vertex_count = pscene->vertex_count, indice_count = pscene->indice_count, vertex_length = vertex_count * sizeof(scene_vert), index_length = indice_count * sizeof(u32), - tot_size = sizeof(scene) + vertex_length + index_length; + tot_size = sizeof(scene) + vertex_length + index_length; /* copy down index data */ void *dst_indices = pscene->arrvertices + vertex_length; diff --git a/skaterift.c b/skaterift.c index 4c531a4..9e162b2 100644 --- a/skaterift.c +++ b/skaterift.c @@ -19,31 +19,18 @@ #include "audio.h" #include "world.h" -#if 0 -#include "player.h" -#else + #include "player.h" VG_STATIC player_instance localplayer; +VG_STATIC struct player_avatar localplayer_avatar; +VG_STATIC glmesh localplayer_meshes[3]; +vg_tex2d localplayer_texture = { .path = "textures/ch_gradient.qoi" }; -#if 0 -#include "player_interface.h" -#include "player_device_walk.h" -#include "player_device_skate.h" -#include "player_device_dead.h" -#include "player_model.h" -/* temp */ -VG_STATIC player_interface localplayer; -#endif -VG_STATIC struct player_avatar localplayer_avatar; -VG_STATIC glmesh localplayer_meshes[3]; -vg_tex2d localplayer_texture = { .path = "textures/ch_gradient.qoi" }; - -#endif #include "network.h" @@ -87,11 +74,13 @@ VG_STATIC int __respawn( int argc, const char *argv[] ) { struct respawn_point *rp = NULL, *r; + world_instance *world = get_active_world(); + if( argc == 1 ) { - for( int i=0; ispawn_count; i++ ) { - r = &world.spawns[i]; + r = &world->spawns[i]; if( !strcmp( r->name, argv[0] ) ) { rp = r; @@ -107,9 +96,9 @@ VG_STATIC int __respawn( int argc, const char *argv[] ) { float min_dist = INFINITY; - for( int i=0; ispawn_count; i++ ) { - r = &world.spawns[i]; + r = &world->spawns[i]; float d = v3_dist2( r->co, localplayer.rb.co ); vg_info( "Dist %s : %f\n", r->name, d ); @@ -125,10 +114,10 @@ VG_STATIC int __respawn( int argc, const char *argv[] ) { vg_error( "No spawn found\n" ); - if( !world.spawn_count ) + if( !world->spawn_count ) return 0; - rp = &world.spawns[0]; + rp = &world->spawns[0]; } player__spawn( &localplayer, rp ); @@ -268,9 +257,13 @@ VG_STATIC void vg_load(void) world_audio_init(); /* 'systems' are completely loaded now */ +#if 0 strcpy( world.world_name, "maps/mp_mtzero.mdl" ); strcpy( world.world_name, "maps/mp_gridmap.mdl" ); - world_load(); +#endif + + /* load home world */ + world_load( &world_global.worlds[0], "maps/mp_home.mdl" ); vg_console_load_autos(); } @@ -301,7 +294,7 @@ VG_STATIC void vg_update(void) #endif player__pre_update( &localplayer ); - world_update( localplayer.rb.co ); + world_update( get_active_world(), localplayer.rb.co ); } } @@ -417,9 +410,9 @@ VG_STATIC void render_scene(void) /* Draw world */ glEnable( GL_DEPTH_TEST ); - render_world( &main_camera ); - + world_instance *world = get_active_world(); + render_world( world, &main_camera ); int player_transparent = 1, player_draw = 1; @@ -433,10 +426,11 @@ VG_STATIC void render_scene(void) if( !player_transparent && player_draw ) player__render( &main_camera, &localplayer ); - render_water_texture( &main_camera ); + + render_water_texture( world, &main_camera ); render_fb_bind( gpipeline.fb_main ); - render_water_surface( &main_camera ); - render_world_gates( &main_camera ); + render_water_surface( world, &main_camera ); + render_world_gates( world, &main_camera ); if( player_transparent && player_draw ) render_player_transparent(); @@ -535,11 +529,13 @@ VG_STATIC void run_light_widget( struct light_widget *lw ); VG_STATIC void vg_ui(void) { player__im_gui( &localplayer ); + world_instance *world = get_active_world(); #if 0 menu_crap_ui(); #endif +#if 0 if( cl_light_edit ) { vg_uictx.cursor[0] = 10; @@ -574,11 +570,12 @@ VG_STATIC void vg_ui(void) render_update_lighting_ub(); } +#endif //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); if( cl_ui ) { - render_world_routes_ui(); + render_world_routes_ui( world ); } //glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); diff --git a/world.h b/world.h index 4f2c5c3..b80db37 100644 --- a/world.h +++ b/world.h @@ -4,11 +4,11 @@ #include "common.h" -VG_STATIC int ray_world( v3f pos, v3f dir, ray_hit *hit ); - #ifndef WORLD_H #define WORLD_H +typedef struct world_instance world_instance; + #include "vg/vg_loader.h" #include "network.h" @@ -52,26 +52,20 @@ enum geo_type k_geo_type_water = 2 }; -VG_STATIC struct gworld +struct world_instance { - /* - * Allocated as system memory - * -------------------------------------------------------------------------- + /* This is a small flag we use to changelevel. + * It will not be cleared until all sounds stop playing */ - /* rendering */ - glmesh skydome; - mdl_submesh dome_upper, dome_lower; - - glmesh mesh_gate_surface; + /* Fixed items + * ------------------------------------------------------- + */ - double sky_time, sky_rate, sky_target_rate; + char world_name[ 64 ]; - /* water rendering */ struct { - struct framebuffer fbreflect, fbdepth; - boxf depthbounds; int depth_computed; @@ -81,48 +75,30 @@ VG_STATIC struct gworld } water; - /* split flap display */ - struct + /* STD140 */ + struct ub_world_lighting { - mdl_submesh *sm_module, *sm_card; - glmesh mesh_base, mesh_display; + /* v3f (padded) */ + v4f g_light_colours[3], + g_light_directions[3], + g_ambient_colour; - u32 w, h; - float *buffer; - } - sfd; + v4f g_water_plane, + g_depth_bounds; - /* timing bars, fixed maximum amount */ - struct route_ui_bar - { - GLuint vao, vbo, ebo; - - u32 indices_head; - u32 vertex_head; + float g_water_fog; + int g_light_count; + int g_light_preview; + int g_shadow_samples; - struct route_ui_segment - { - float length; - u32 vertex_start, vertex_count, - index_start, index_count, notches; - } - segments[k_max_ui_segments]; - - u32 segment_start, segment_count, fade_start, fade_count; - double fade_timer_start; - float xpos; + v4f g_point_light_positions[32]; + v4f g_point_light_colours[32]; } - ui_bars[16]; - - v3f render_gate_pos; - int active_route_board; - int in_trigger; + ub_lighting; + GLuint ubo_lighting; + int ubo_bind_point; - /* This is a small flag we use to changelevel. - * It will not be cleared until all sounds stop playing - */ - int switching_to_new_world; - char world_name[ 64 ]; + struct framebuffer heightmap; /* * Dynamically allocated when world_load is called. @@ -133,9 +109,6 @@ VG_STATIC struct gworld * (world_gen.h) * -------------------------------------------------------------------------- */ - void *dynamic_vgl, - *audio_vgl; /* sub buffer of the audio buffer */ - /* * Main world .mdl */ @@ -306,10 +279,6 @@ VG_STATIC struct gworld * ---------------------------------------------------- */ - u32 active_gate, - current_run_version; - double time, rewind_from, rewind_to, last_use; - /* world geometry */ scene *scene_geo, *scene_no_collide, @@ -322,25 +291,107 @@ VG_STATIC struct gworld /* graphics */ glmesh mesh_route_lines; - glmesh mesh_geo, mesh_no_collide, mesh_water; - mdl_submesh sm_foliage_main; rigidbody rb_geo; /* todo.. ... */ +}; + +VG_STATIC struct world_global +{ + /* + * Allocated as system memory + * -------------------------------------------------------------------------- + */ + void *generic_heap, + *audio_heap; /* sub buffer of the audio buffer */ + + /* rendering */ + glmesh skydome; + mdl_submesh dome_upper, dome_lower; + + glmesh mesh_gate_surface; + + double sky_time, sky_rate, sky_target_rate; + + /* gates, TODO: active_gate should also know which instance */ + u32 active_gate, + current_run_version; + double time, rewind_from, rewind_to, last_use; + + /* water rendering */ + struct + { + struct framebuffer fbreflect, fbdepth; + } + water; + + /* split flap display */ + struct + { + mdl_submesh *sm_module, *sm_card; + glmesh mesh_base, mesh_display; + + u32 w, h; + float *buffer; + } + sfd; + + /* timing bars, fixed maximum amount */ + struct route_ui_bar + { + GLuint vao, vbo, ebo; + + u32 indices_head; + u32 vertex_head; + + struct route_ui_segment + { + float length; + u32 vertex_start, vertex_count, + index_start, index_count, notches; + } + segments[k_max_ui_segments]; + + u32 segment_start, segment_count, fade_start, fade_count; + double fade_timer_start; + float xpos; + } + ui_bars[16]; + + v3f render_gate_pos; + int active_route_board; + int in_trigger; + + int switching_to_new_world; + + world_instance worlds[4]; + u32 world_count; + u32 active_world; } -world; +world_global; +VG_STATIC world_instance *get_active_world( void ) +{ + return &world_global.worlds[ world_global.active_world ]; +} /* * API */ -VG_STATIC int ray_hit_is_ramp( ray_hit *hit ); -VG_STATIC struct world_material *ray_hit_material( ray_hit *hit ); -VG_STATIC void ray_world_get_tri( ray_hit *hit, v3f tri[3] ); -VG_STATIC int ray_world( v3f pos, v3f dir, ray_hit *hit ); +VG_STATIC +int ray_hit_is_ramp( world_instance *world, ray_hit *hit ); + +VG_STATIC +struct world_material *ray_hit_material( world_instance *world, ray_hit *hit ); + +VG_STATIC +void ray_world_get_tri( world_instance *world, ray_hit *hit, v3f tri[3] ); + +VG_STATIC +int ray_world( world_instance *world, v3f pos, v3f dir, ray_hit *hit ); /* * Submodules @@ -361,15 +412,17 @@ VG_STATIC int ray_world( v3f pos, v3f dir, ray_hit *hit ); VG_STATIC int world_stop_sound( int argc, const char *argv[] ) { + world_instance *world = get_active_world(); + /* * None of our world audio runs as one shots, they always have a player. * Therefore it is safe to delete clip data after the players are * disconnected */ audio_lock(); - for( int i=0; iaudio_things_count; i++ ) { - struct world_audio_thing *at = &world.audio_things[i]; + struct world_audio_thing *at = &world->audio_things[i]; if( audio_player_is_playing( &at->player ) ) { @@ -384,6 +437,9 @@ VG_STATIC int world_stop_sound( int argc, const char *argv[] ) VG_STATIC int world_change_world( int argc, const char *argv[] ) { +#if 0 + world_instance *world = get_active_world(); + if( argc == 0 ) { vg_info( "%s\n", world.world_name ); @@ -396,12 +452,14 @@ VG_STATIC int world_change_world( int argc, const char *argv[] ) world.switching_to_new_world = 1; world_stop_sound( 0, NULL ); } +#endif return 0; } VG_STATIC void world_init(void) { +#if 0 vg_var_push( (struct vg_var){ .name = "water_enable", .data = &world.water.enabled, @@ -409,6 +467,7 @@ VG_STATIC void world_init(void) .opt_i32 = { .min=0, .max=1, .clamp=1 }, .persistent = 0 }); +#endif vg_function_push( (struct vg_cmd) { @@ -422,8 +481,8 @@ VG_STATIC void world_init(void) .function = world_change_world }); - world.sky_rate = 1.0; - world.sky_target_rate = 1.0; + world_global.sky_rate = 1.0; + world_global.sky_target_rate = 1.0; shader_scene_standard_register(); shader_scene_standard_alphatest_register(); @@ -439,11 +498,11 @@ VG_STATIC void world_init(void) mdl_context *msky = mdl_load_full( vg_mem.scratch, "models/rs_skydome.mdl" ); mdl_node *nupper = mdl_node_from_name( msky, "dome_complete" ); - world.dome_upper = *mdl_node_submesh( msky, nupper, 0 ); + world_global.dome_upper = *mdl_node_submesh( msky, nupper, 0 ); vg_acquire_thread_sync(); { - mdl_unpack_glmesh( msky, &world.skydome ); + mdl_unpack_glmesh( msky, &world_global.skydome ); } vg_release_thread_sync(); @@ -458,8 +517,9 @@ VG_STATIC void world_init(void) /* Allocate dynamic world memory arena */ u32 max_size = 76*1024*1024; - world.dynamic_vgl = vg_create_linear_allocator( vg_mem.rtmemory, max_size, - VG_MEMORY_SYSTEM ); + world_global.generic_heap = vg_create_linear_allocator( vg_mem.rtmemory, + max_size, + VG_MEMORY_SYSTEM ); } VG_STATIC void world_audio_init(void) @@ -467,13 +527,14 @@ VG_STATIC void world_audio_init(void) u32 size = vg_linear_remaining( vg_audio.audio_pool ) - sizeof(vg_linear_allocator); - world.audio_vgl = vg_create_linear_allocator( vg_audio.audio_pool, - size, VG_MEMORY_SYSTEM ); + world_global.audio_heap = vg_create_linear_allocator( vg_audio.audio_pool, + size, + VG_MEMORY_SYSTEM ); } -VG_STATIC void world_trigger_achievement( u32 uid ) +VG_STATIC void world_trigger_achievement( world_instance *world, u32 uid ) { - struct logic_achievement *ach = &world.logic_achievements[ uid ]; + struct logic_achievement *ach = &world->logic_achievements[ uid ]; if( ach->achieved ) return; @@ -484,20 +545,22 @@ VG_STATIC void world_trigger_achievement( u32 uid ) ach->achieved = 1; } -VG_STATIC void world_run_relay( struct relay_target *rt ); -VG_STATIC void world_trigger_relay( u32 uid ) +VG_STATIC void world_run_relay( world_instance *world, + struct relay_target *rt ); + +VG_STATIC void world_trigger_relay( world_instance *world, u32 uid ) { - struct logic_relay *relay = &world.logic_relays[ uid ]; + struct logic_relay *relay = &world->logic_relays[ uid ]; for( int i=0; itarget_count; i++ ) { - world_run_relay( &relay->targets[i] ); + world_run_relay( world, &relay->targets[i] ); } } -VG_STATIC void world_trigger_audio( u32 uid ) +VG_STATIC void world_trigger_audio( world_instance *world, u32 uid ) { - struct world_audio_thing *wat = &world.audio_things[ uid ]; + struct world_audio_thing *wat = &world->audio_things[ uid ]; audio_lock(); audio_player_playclip( &wat->player, @@ -505,12 +568,13 @@ VG_STATIC void world_trigger_audio( u32 uid ) audio_unlock(); } -VG_STATIC void world_run_relay( struct relay_target *rt ) +VG_STATIC void world_run_relay( world_instance *world, + struct relay_target *rt ) { struct entity_instruction { enum classtype classtype; - void (*p_trigger)( u32 uid ); + void (*p_trigger)( world_instance *world, u32 uid ); } entity_instructions[] = { @@ -525,7 +589,7 @@ VG_STATIC void world_run_relay( struct relay_target *rt ) if( instr->classtype == rt->classtype ) { - instr->p_trigger( rt->sub_id ); + instr->p_trigger( world, rt->sub_id ); return; } } @@ -533,8 +597,9 @@ VG_STATIC void world_run_relay( struct relay_target *rt ) vg_error( "Don't know how to trigger classtype %d\n", rt->classtype ); } -VG_STATIC void world_update( v3f pos ) +VG_STATIC void world_update( world_instance *world, v3f pos ) { +#if 0 if( world.switching_to_new_world ) { int all_stopped = 1; @@ -564,20 +629,21 @@ VG_STATIC void world_update( v3f pos ) world.sky_time += world.sky_rate * vg.time_delta; world.sky_rate = vg_lerp( world.sky_rate, world.sky_target_rate, vg.time_delta * 5.0 ); +#endif - world_routes_update(); + world_routes_update( world ); #if 0 world_routes_debug(); #endif - if( world.route_count > 0 ) + if( world->route_count > 0 ) { int closest = 0; float min_dist = INFINITY; - for( int i=0; iroute_count; i++ ) { - float d = v3_dist2( world.routes[i].scoreboard_transform[3], pos ); + float d = v3_dist2( world->routes[i].scoreboard_transform[3], pos ); if( d < min_dist ) { @@ -586,12 +652,13 @@ VG_STATIC void world_update( v3f pos ) } } - if( (world.active_route_board != closest) || network_scores_updated ) + if( (world_global.active_route_board != closest) + || network_scores_updated ) { network_scores_updated = 0; - world.active_route_board = closest; + world_global.active_route_board = closest; - struct route *route = &world.routes[closest]; + struct route *route = &world->routes[closest]; u32 id = route->track_id; @@ -609,9 +676,9 @@ VG_STATIC void world_update( v3f pos ) } int in_trigger = 0; - for( int i=0; itrigger_count; i++ ) { - struct trigger_zone *zone = &world.triggers[i]; + struct trigger_zone *zone = &world->triggers[i]; v3f local; m4x3_mulv( zone->inv_transform, pos, local ); @@ -622,9 +689,9 @@ VG_STATIC void world_update( v3f pos ) { in_trigger = 1; - if( !world.in_trigger ) + if( !world_global.in_trigger ) { - world_run_relay( &zone->target ); + world_run_relay( world, &zone->target ); } } @@ -633,9 +700,9 @@ VG_STATIC void world_update( v3f pos ) 0xff00ff00 ); } - for( int i=0; ilight_count; i++ ) { - struct world_light *light = &world.lights[i]; + struct world_light *light = &world->lights[i]; u32 colour = 0xff000000; u8 r = light->colour[0] * 255.0f, @@ -649,7 +716,7 @@ VG_STATIC void world_update( v3f pos ) vg_line_pt3( light->co, 0.25f, colour ); } - world.in_trigger = in_trigger; + world_global.in_trigger = in_trigger; sfd_update(); } @@ -659,21 +726,24 @@ VG_STATIC void world_update( v3f pos ) * ----------------------------------------------------------------------------- */ -VG_STATIC void ray_world_get_tri( ray_hit *hit, v3f tri[3] ) +VG_STATIC void ray_world_get_tri( world_instance *world, + ray_hit *hit, v3f tri[3] ) { for( int i=0; i<3; i++ ) - v3_copy( world.scene_geo->arrvertices[ hit->tri[i] ].co, tri[i] ); + v3_copy( world->scene_geo->arrvertices[ hit->tri[i] ].co, tri[i] ); } -VG_STATIC int ray_world( v3f pos, v3f dir, ray_hit *hit ) +VG_STATIC int ray_world( world_instance *world, + v3f pos, v3f dir, ray_hit *hit ) { - return scene_raycast( world.scene_geo, world.geo_bh, pos, dir, hit ); + return scene_raycast( world->scene_geo, world->geo_bh, pos, dir, hit ); } /* * Cast a sphere from a to b and see what time it hits */ -VG_STATIC int spherecast_world( v3f pa, v3f pb, float r, float *t, v3f n ) +VG_STATIC int spherecast_world( world_instance *world, + v3f pa, v3f pb, float r, float *t, v3f n ) { bh_iter it; bh_iter_init( 0, &it ); @@ -698,9 +768,9 @@ VG_STATIC int spherecast_world( v3f pa, v3f pb, float r, float *t, v3f n ) float min_t = 1.0f; int idx; - while( bh_next( world.geo_bh, &it, region, &idx ) ) + while( bh_next( world->geo_bh, &it, region, &idx ) ) { - u32 *ptri = &world.scene_geo->arrindices[ idx*3 ]; + u32 *ptri = &world->scene_geo->arrindices[ idx*3 ]; v3f tri[3]; boxf box; @@ -708,7 +778,7 @@ VG_STATIC int spherecast_world( v3f pa, v3f pb, float r, float *t, v3f n ) for( int j=0; j<3; j++ ) { - v3_copy( world.scene_geo->arrvertices[ptri[j]].co, tri[j] ); + v3_copy( world->scene_geo->arrvertices[ptri[j]].co, tri[j] ); box_addpt( box, tri[j] ); } @@ -735,11 +805,13 @@ VG_STATIC int spherecast_world( v3f pa, v3f pb, float r, float *t, v3f n ) return hit; } -VG_STATIC struct world_material *world_tri_index_material( u32 index ) +VG_STATIC +struct world_material *world_tri_index_material( world_instance *world, + u32 index ) { - for( int i=1; imaterial_count; i++ ) { - struct world_material *mat = &world.materials[i]; + struct world_material *mat = &world->materials[i]; if( (index >= mat->sm_geo.vertex_start) && (index < mat->sm_geo.vertex_start+mat->sm_geo.vertex_count ) ) @@ -749,17 +821,19 @@ VG_STATIC struct world_material *world_tri_index_material( u32 index ) } /* error material */ - return &world.materials[0]; + return &world->materials[0]; } -VG_STATIC struct world_material *world_contact_material( rb_ct *ct ) +VG_STATIC struct world_material *world_contact_material( world_instance *world, + rb_ct *ct ) { - return world_tri_index_material( ct->element_id ); + return world_tri_index_material( world, ct->element_id ); } -VG_STATIC struct world_material *ray_hit_material( ray_hit *hit ) +VG_STATIC struct world_material *ray_hit_material( world_instance *world, + ray_hit *hit ) { - return world_tri_index_material( hit->tri[0] ); + return world_tri_index_material( world, hit->tri[0] ); } #endif /* WORLD_H */ diff --git a/world_gate.h b/world_gate.h index d92537e..1e8c262 100644 --- a/world_gate.h +++ b/world_gate.h @@ -38,12 +38,13 @@ VG_STATIC void world_gates_init(void) vg_acquire_thread_sync(); { - mdl_unpack_glmesh( mgate, &world.mesh_gate_surface ); + mdl_unpack_glmesh( mgate, &world_global.mesh_gate_surface ); } vg_release_thread_sync(); } -VG_STATIC int render_gate( teleport_gate *gate, camera *cam ) +VG_STATIC int render_gate( world_instance *world_inside, + teleport_gate *gate, camera *cam ) { v3f viewdir, gatedir; m3x3_mulv( cam->transform, (v3f){0.0f,0.0f,-1.0f}, viewdir ); @@ -123,25 +124,25 @@ VG_STATIC int render_gate( teleport_gate *gate, camera *cam ) glStencilFunc( GL_ALWAYS, 1, 0xFF ); glStencilMask( 0xFF ); - mesh_bind( &world.mesh_gate_surface ); - mesh_draw( &world.mesh_gate_surface ); + mesh_bind( &world_global.mesh_gate_surface ); + mesh_draw( &world_global.mesh_gate_surface ); glClear( GL_DEPTH_BUFFER_BIT ); glStencilFunc( GL_EQUAL, 1, 0xFF ); glStencilMask( 0x00 ); } - render_world( &gate_view ); + render_world( world_inside, &gate_view ); { glDisable( GL_STENCIL_TEST ); - render_water_texture( &gate_view ); + render_water_texture( world_inside, &gate_view ); render_fb_bind( gpipeline.fb_main ); glEnable( GL_STENCIL_TEST ); - render_water_surface( &gate_view ); + render_water_surface( world_inside, &gate_view ); glStencilMask( 0xFF ); glStencilFunc( GL_ALWAYS, 1, 0xFF ); @@ -213,11 +214,12 @@ VG_STATIC int gate_intersect( teleport_gate *gate, v3f pos, v3f last ) /* * Intersect all gates in the world */ -VG_STATIC teleport_gate *world_intersect_gates( v3f pos, v3f last ) +VG_STATIC teleport_gate *world_intersect_gates( world_instance *world, + v3f pos, v3f last ) { - for( int i=0; igate_count; i++ ) { - struct route_gate *rg = &world.gates[i]; + struct route_gate *rg = &world->gates[i]; teleport_gate *gate = &rg->gate; if( gate_intersect( gate, pos, last ) ) diff --git a/world_gen.h b/world_gen.h index f5e7599..3290def 100644 --- a/world_gen.h +++ b/world_gen.h @@ -7,9 +7,7 @@ #include "world.h" -/* load world TODO: Put back vg back in loading state while this happens */ -VG_STATIC void world_load(void); - +VG_STATIC void world_load( world_instance *world, const char *path ); VG_STATIC void world_add_all_if_material( m4x3f transform, scene *pscene, mdl_context *mdl, u32 id ) @@ -33,7 +31,8 @@ VG_STATIC void world_add_all_if_material( m4x3f transform, scene *pscene, } } -VG_STATIC void world_add_blob( scene *pscene, ray_hit *hit ) +VG_STATIC void world_add_blob( world_instance *world, + scene *pscene, ray_hit *hit ) { m4x3f transform; v4f qsurface, qrandom; @@ -69,7 +68,7 @@ VG_STATIC void world_add_blob( scene *pscene, ray_hit *hit ) scene_vert *dst_verts = &pscene->arrvertices[ pscene->vertex_count ]; u32 *dst_indices = &pscene->arrindices [ pscene->indice_count ]; - scene_vert *ref = &world.scene_geo->arrvertices[ hit->tri[0] ]; + scene_vert *ref = &world->scene_geo->arrvertices[ hit->tri[0] ]; for( u32 i=0; ibbx[1], world.scene_geo->bbx[0], volume ); + v3_sub( world->scene_geo->bbx[1], world->scene_geo->bbx[0], volume ); volume[1] = 1.0f; mdl_node *mblob = mdl_node_from_name( mfoliage, "blob" ); @@ -121,17 +121,17 @@ VG_STATIC void world_apply_procedural_foliage( struct world_material *mat ) v3f pos; v3_mul( volume, (v3f){ vg_randf(), 1000.0f, vg_randf() }, pos ); pos[1] = 1000.0f; - v3_add( pos, world.scene_geo->bbx[0], pos ); + v3_add( pos, world->scene_geo->bbx[0], pos ); ray_hit hit; hit.dist = INFINITY; - if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &hit )) + if( ray_world( world, pos, (v3f){0.0f,-1.0f,0.0f}, &hit )) { - struct world_material *m1 = ray_hit_material( &hit ); + struct world_material *m1 = ray_hit_material( world, &hit ); if((hit.normal[1] > 0.8f) && (m1 == mat) && (hit.pos[1] > 0.0f+10.0f)) { - world_add_blob( world.scene_no_collide, &hit ); + world_add_blob( world, world->scene_no_collide, &hit ); count ++; } } @@ -140,7 +140,7 @@ VG_STATIC void world_apply_procedural_foliage( struct world_material *mat ) vg_info( "%d foliage models added\n", count ); } -VG_STATIC void world_ents_allocate(void) +VG_STATIC void world_ents_allocate( world_instance *world ) { vg_info( "Allocating entities\n" ); @@ -160,32 +160,32 @@ VG_STATIC void world_ents_allocate(void) { { k_classtype_spawn, - (void*)&world.spawns, + (void*)&world->spawns, sizeof(struct respawn_point) }, { k_classtype_audio, - (void*)&world.audio_things, + (void*)&world->audio_things, sizeof(struct world_audio_thing) }, { k_classtype_trigger, - (void*)&world.triggers, + (void*)&world->triggers, sizeof(struct trigger_zone) }, { k_classtype_logic_relay, - (void*)&world.logic_relays, + (void*)&world->logic_relays, sizeof(struct logic_relay) }, { k_classtype_logic_achievement, - (void*)&world.logic_achievements, + (void*)&world->logic_achievements, sizeof(struct logic_achievement) }, { k_classtype_point_light, - (void*)&world.lights, + (void*)&world->lights, sizeof(struct world_light) } }; @@ -193,9 +193,9 @@ VG_STATIC void world_ents_allocate(void) for( int i=0; iinfo.node_count; i++ ) + for( int i=0; imeta->info.node_count; i++ ) { - mdl_node *pnode = mdl_node_from_id( world.meta, i ); + mdl_node *pnode = mdl_node_from_id( world->meta, i ); for( int j=0; jitem_size*counter->count; - *counter->to_allocate = vg_linear_alloc( world.dynamic_vgl, bufsize ); + *counter->to_allocate = vg_linear_alloc( world_global.generic_heap, + bufsize ); } } -VG_STATIC void world_pct_spawn( mdl_node *pnode ) +VG_STATIC void world_pct_spawn( world_instance *world, mdl_node *pnode ) { - struct respawn_point *rp = &world.spawns[ world.spawn_count ++ ]; + struct respawn_point *rp = &world->spawns[ world->spawn_count ++ ]; v3_copy( pnode->co, rp->co ); v4_copy( pnode->q, rp->q ); - rp->name = mdl_pstr( world.meta, pnode->pstr_name ); + rp->name = mdl_pstr( world->meta, pnode->pstr_name ); } -VG_STATIC void world_pct_water( mdl_node *pnode ) +VG_STATIC void world_pct_water( world_instance *world, mdl_node *pnode ) { - if( world.water.enabled ) + if( world->water.enabled ) { vg_warn( "Multiple water surfaces in level! ('%s')\n", - mdl_pstr( world.meta, pnode->pstr_name )); + mdl_pstr( world->meta, pnode->pstr_name )); return; } - world.water.enabled = 1; - water_set_surface( pnode->co[1] ); + world->water.enabled = 1; + water_set_surface( world, pnode->co[1] ); } -VG_STATIC void world_pct_audio( mdl_node *pnode ) +VG_STATIC void world_pct_audio( world_instance *world, mdl_node *pnode ) { - struct world_audio_thing *thing = &world.audio_things[ - world.audio_things_count ]; + struct world_audio_thing *thing = &world->audio_things[ + world->audio_things_count ]; memset( thing, 0, sizeof(struct world_audio_thing) ); - struct classtype_audio *aud = mdl_get_entdata( world.meta, pnode ); + struct classtype_audio *aud = mdl_get_entdata( world->meta, pnode ); v3_copy( pnode->co, thing->pos ); @@ -255,26 +256,25 @@ VG_STATIC void world_pct_audio( mdl_node *pnode ) thing->volume = aud->volume; thing->flags = aud->flags; - thing->temp_embedded_clip.path = mdl_pstr( world.meta, aud->pstr_file ); + thing->temp_embedded_clip.path = mdl_pstr( world->meta, aud->pstr_file ); thing->temp_embedded_clip.source_mode = k_audio_source_mono; - audio_clip_load( &thing->temp_embedded_clip, world.audio_vgl ); - thing->player.name = mdl_pstr( world.meta, pnode->pstr_name ); + audio_clip_load( &thing->temp_embedded_clip, world_global.audio_heap ); + thing->player.name = mdl_pstr( world->meta, pnode->pstr_name ); thing->player.enqued = 0; - pnode->sub_uid = world.audio_things_count; - world.audio_things_count ++; + pnode->sub_uid = world->audio_things_count; + world->audio_things_count ++; } - -VG_STATIC void world_pct_trigger( mdl_node *pnode ) +VG_STATIC void world_pct_trigger( world_instance *world, mdl_node *pnode ) { - struct trigger_zone *trigger = &world.triggers[ world.trigger_count ]; - struct classtype_trigger *inf = mdl_get_entdata( world.meta, pnode ); + struct trigger_zone *trigger = &world->triggers[ world->trigger_count ]; + struct classtype_trigger *inf = mdl_get_entdata( world->meta, pnode ); if( inf->target ) { - mdl_node *target_node = mdl_node_from_id( world.meta, inf->target ); + mdl_node *target_node = mdl_node_from_id( world->meta, inf->target ); trigger->target.sub_id = target_node->sub_uid; trigger->target.classtype = target_node->classtype; @@ -288,14 +288,14 @@ VG_STATIC void world_pct_trigger( mdl_node *pnode ) mdl_node_transform( pnode, trigger->transform ); m4x3_invert_full( trigger->transform, trigger->inv_transform ); - world.trigger_count ++; + world->trigger_count ++; } -VG_STATIC void world_pct_relay( mdl_node *pnode ) +VG_STATIC void world_pct_relay( world_instance *world, mdl_node *pnode ) { - struct logic_relay *relay = &world.logic_relays[ world.relay_count ]; - struct classtype_logic_relay *inf = mdl_get_entdata( world.meta, pnode ); + struct logic_relay *relay = &world->logic_relays[ world->relay_count ]; + struct classtype_logic_relay *inf = mdl_get_entdata( world->meta, pnode ); relay->target_count = 0; @@ -304,7 +304,7 @@ VG_STATIC void world_pct_relay( mdl_node *pnode ) if( inf->targets[i] ) { struct relay_target *target = &relay->targets[relay->target_count ++]; - mdl_node *other = mdl_node_from_id( world.meta, inf->targets[i] ); + mdl_node *other = mdl_node_from_id( world->meta, inf->targets[i] ); target->classtype = other->classtype; target->sub_id = other->sub_uid; @@ -312,41 +312,41 @@ VG_STATIC void world_pct_relay( mdl_node *pnode ) } v3_copy( pnode->co, relay->pos ); - world.relay_count ++; + world->relay_count ++; } -VG_STATIC void world_pct_achievement( mdl_node *pnode ) +VG_STATIC void world_pct_achievement( world_instance *world, mdl_node *pnode ) { struct logic_achievement *ach = - &world.logic_achievements[ world.achievement_count ]; + &world->logic_achievements[ world->achievement_count ]; struct classtype_logic_achievement *inf = - mdl_get_entdata( world.meta, pnode ); + mdl_get_entdata( world->meta, pnode ); v3_copy( pnode->co, ach->pos ); - ach->achievement_id = mdl_pstr( world.meta, inf->pstr_name ); + ach->achievement_id = mdl_pstr( world->meta, inf->pstr_name ); ach->achieved = 0; - world.achievement_count ++; + world->achievement_count ++; } -VG_STATIC void world_pct_point_light( mdl_node *pnode ) +VG_STATIC void world_pct_point_light( world_instance *world, mdl_node *pnode ) { - struct world_light *light = &world.lights[ world.light_count ]; + struct world_light *light = &world->lights[ world->light_count ]; v3_copy( pnode->co, light->co ); - struct classtype_point_light *inf = mdl_get_entdata( world.meta, pnode ); + struct classtype_point_light *inf = mdl_get_entdata( world->meta, pnode ); v4_copy( inf->colour, light->colour ); - world.light_count ++; + world->light_count ++; } -VG_STATIC void world_entities_process(void) +VG_STATIC void world_entities_process( world_instance *world ) { struct entity_instruction { enum classtype ct; - void (*process)( mdl_node *pnode ); + void (*process)( world_instance *world, mdl_node *pnode ); } entity_instructions[] = { @@ -359,9 +359,9 @@ VG_STATIC void world_entities_process(void) { k_classtype_point_light, world_pct_point_light } }; - for( int i=0; iinfo.node_count; i++ ) + for( int i=0; imeta->info.node_count; i++ ) { - mdl_node *pnode = mdl_node_from_id( world.meta, i ); + mdl_node *pnode = mdl_node_from_id( world->meta, i ); for( int j=0; jclasstype == instr->ct ) { - instr->process( pnode ); + instr->process( world, pnode ); break; } } } } -VG_STATIC void world_scene_compute_light_clusters( scene *sc ) +VG_STATIC void world_scene_compute_light_clusters( world_instance *world, + scene *sc ) { for( int i=0; ivertex_count; i++ ) { @@ -388,9 +389,9 @@ VG_STATIC void world_scene_compute_light_clusters( scene *sc ) float distances[4] = { INFINITY, INFINITY, INFINITY, INFINITY }; - for( int j=0; jlight_count; j ++ ) { - float dist = v3_dist2( world.lights[j].co, vert->co ); + float dist = v3_dist2( world->lights[j].co, vert->co ); int best_pos = 4; for( int k=best_pos-1; k>=0; k -- ) @@ -412,12 +413,12 @@ VG_STATIC void world_scene_compute_light_clusters( scene *sc ) } } -VG_STATIC void world_generate(void) +VG_STATIC void world_generate( world_instance *world ) { /* * Compile meshes into the world scenes */ - world.scene_geo = scene_init( world.dynamic_vgl, 320000, 1200000 ); + world->scene_geo = scene_init( world_global.generic_heap, 320000, 1200000 ); m4x3f midentity; m4x3_identity( midentity ); @@ -430,36 +431,37 @@ VG_STATIC void world_generate(void) vg_info( "Generating collidable geometry\n" ); - for( int i=0; imaterial_count; i++ ) { - struct world_material *mat = &world.materials[ i ]; + struct world_material *mat = &world->materials[ i ]; if( mat->info.flags & k_material_flag_collision ) - world_add_all_if_material( midentity, world.scene_geo, world.meta, i ); + world_add_all_if_material( midentity, world->scene_geo, world->meta, i ); - scene_copy_slice( world.scene_geo, &mat->sm_geo ); + scene_copy_slice( world->scene_geo, &mat->sm_geo ); } - world_scene_compute_light_clusters( world.scene_geo ); + world_scene_compute_light_clusters( world, world->scene_geo ); /* compress that bad boy */ - world.scene_geo = scene_fix( world.dynamic_vgl, world.scene_geo ); + world->scene_geo = scene_fix( world_global.generic_heap, world->scene_geo ); vg_acquire_thread_sync(); { - scene_upload( world.scene_geo, &world.mesh_geo ); + scene_upload( world->scene_geo, &world->mesh_geo ); } vg_release_thread_sync(); /* setup spacial mapping and rigidbody */ - world.geo_bh = scene_bh_create( world.dynamic_vgl, world.scene_geo ); + world->geo_bh = scene_bh_create( world_global.generic_heap, + world->scene_geo ); - v3_zero( world.rb_geo.co ); - q_identity( world.rb_geo.q ); + v3_zero( world->rb_geo.co ); + q_identity( world->rb_geo.q ); - world.rb_geo.type = k_rb_shape_scene; - world.rb_geo.inf.scene.bh_scene = world.geo_bh; - world.rb_geo.is_world = 1; - rb_init( &world.rb_geo ); + world->rb_geo.type = k_rb_shape_scene; + world->rb_geo.inf.scene.bh_scene = world->geo_bh; + world->rb_geo.is_world = 1; + rb_init( &world->rb_geo ); /* * Generate scene: non-collidable geometry @@ -467,44 +469,45 @@ VG_STATIC void world_generate(void) */ vg_info( "Generating non-collidable geometry\n" ); - world.scene_no_collide = scene_init( world.dynamic_vgl, 200000, 500000 ); + world->scene_no_collide = scene_init( world_global.generic_heap, + 200000, 500000 ); - for( int i=0; imaterial_count; i++ ) { - struct world_material *mat = &world.materials[ i ]; + struct world_material *mat = &world->materials[ i ]; if( !(mat->info.flags & k_material_flag_collision) ) { - world_add_all_if_material( midentity, world.scene_no_collide, - world.meta, i ); + world_add_all_if_material( midentity, world->scene_no_collide, + world->meta, i ); } if( mat->info.flags & k_material_flag_grow_grass ) - world_apply_procedural_foliage( mat ); + world_apply_procedural_foliage( world, mat ); - scene_copy_slice( world.scene_no_collide, &mat->sm_no_collide ); + scene_copy_slice( world->scene_no_collide, &mat->sm_no_collide ); } - world_scene_compute_light_clusters( world.scene_no_collide ); + world_scene_compute_light_clusters( world, world->scene_no_collide ); /* upload and free that */ vg_acquire_thread_sync(); { - scene_upload( world.scene_no_collide, &world.mesh_no_collide ); + scene_upload( world->scene_no_collide, &world->mesh_no_collide ); } vg_release_thread_sync(); - vg_linear_del( world.dynamic_vgl, world.scene_no_collide ); - world.scene_no_collide = NULL; + vg_linear_del( world_global.generic_heap, world->scene_no_collide ); + world->scene_no_collide = NULL; } VG_STATIC int reset_player( int argc, char const *argv[] ); -VG_STATIC void world_post_process(void) +VG_STATIC void world_post_process( world_instance *world ) { /* initialize audio if need be */ audio_lock(); - for( int i=0; iaudio_things_count; i++ ) { - struct world_audio_thing *thingy = &world.audio_things[ i ]; + struct world_audio_thing *thingy = &world->audio_things[ i ]; audio_player_init( &thingy->player ); audio_player_set_flags( &thingy->player, thingy->flags ); @@ -527,12 +530,12 @@ VG_STATIC void world_post_process(void) camera ortho; v3f extent; - v3_sub( world.scene_geo->bbx[1], world.scene_geo->bbx[0], extent ); + v3_sub( world->scene_geo->bbx[1], world->scene_geo->bbx[0], extent ); - float fl = world.scene_geo->bbx[0][0], - fr = world.scene_geo->bbx[1][0], - fb = world.scene_geo->bbx[0][2], - ft = world.scene_geo->bbx[1][2], + float fl = world->scene_geo->bbx[0][0], + fr = world->scene_geo->bbx[1][0], + fb = world->scene_geo->bbx[0][2], + ft = world->scene_geo->bbx[1][2], rl = 1.0f / (fr-fl), tb = 1.0f / (ft-fb); @@ -549,7 +552,7 @@ VG_STATIC void world_post_process(void) glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); - render_fb_bind( gpipeline.fb_heightmap ); + render_fb_bind( &world->heightmap ); shader_blitcolour_use(); shader_blitcolour_uColour( (v4f){-9999.0f,-9999.0f,-9999.0f,-9999.0f} ); render_fsquad(); @@ -559,41 +562,39 @@ VG_STATIC void world_post_process(void) glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_MAX); - render_world_depth( &ortho ); + render_world_depth( world, &ortho ); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); - /* - * TODO: World settings entity - */ - struct ub_world_lighting *winfo = &gpipeline.ub_world_lighting; - - if( world.water.enabled ) - v4_copy( world.water.plane, winfo->g_water_plane ); + /* Upload lighting uniform buffer */ + if( world->water.enabled ) + v4_copy( world->water.plane, world->ub_lighting.g_water_plane ); v4f info_vec; - v3f *bounds = world.scene_geo->bbx; + v3f *bounds = world->scene_geo->bbx; info_vec[0] = bounds[0][0]; info_vec[1] = bounds[0][2]; info_vec[2] = 1.0f/ (bounds[1][0]-bounds[0][0]); info_vec[3] = 1.0f/ (bounds[1][2]-bounds[0][2]); - v4_copy( info_vec, winfo->g_depth_bounds ); - - winfo->g_water_fog = 0.04f; + v4_copy( info_vec, world->ub_lighting.g_depth_bounds ); - for( int i=0; ilight_count; i++ ) { - struct world_light *light = &world.lights[i]; + struct world_light *light = &world->lights[i]; v3_muls( light->colour, light->colour[3] * 2.0f, - gpipeline.ub_world_lighting.g_point_light_colours[i] ); + world->ub_lighting.g_point_light_colours[i] ); v3_copy( light->co, - gpipeline.ub_world_lighting.g_point_light_positions[i] ); + world->ub_lighting.g_point_light_positions[i] ); } - render_update_lighting_ub(); + /* upload full buffer */ + glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting ); + glBufferSubData( GL_UNIFORM_BUFFER, 0, + sizeof(struct ub_world_lighting), &world->ub_lighting ); } vg_release_thread_sync(); @@ -606,24 +607,24 @@ VG_STATIC void world_post_process(void) #endif } -VG_STATIC void world_process_resources(void) +VG_STATIC void world_process_resources( world_instance *world ) { vg_info( "Loading textures\n" ); - world.texture_count = world.meta->info.texture_count; - world.textures = - vg_linear_alloc( world.dynamic_vgl, sizeof(GLuint)*world.texture_count ); + world->texture_count = world->meta->info.texture_count; + world->textures = vg_linear_alloc( world_global.generic_heap, + sizeof(GLuint)*world->texture_count ); vg_acquire_thread_sync(); { /* error texture */ - world.textures[0] = vg_tex2d_new(); + world->textures[0] = vg_tex2d_new(); vg_tex2d_set_error(); vg_tex2d_nearest(); vg_tex2d_repeat(); - for( int i=1; itexture_count; i++ ) { - mdl_texture *tex = &world.meta->texture_buffer[i]; + mdl_texture *tex = &world->meta->texture_buffer[i]; if( !tex->pack_offset ) { @@ -632,10 +633,10 @@ VG_STATIC void world_process_resources(void) } vg_linear_clear( vg_mem.scratch ); - world.textures[i] = vg_tex2d_new(); + world->textures[i] = vg_tex2d_new(); vg_tex2d_set_error(); - vg_tex2d_qoi( world.meta->pack + tex->pack_offset, tex->pack_length, - mdl_pstr( world.meta, tex->pstr_name )); + vg_tex2d_qoi( world->meta->pack + tex->pack_offset, tex->pack_length, + mdl_pstr( world->meta, tex->pstr_name )); vg_tex2d_nearest(); vg_tex2d_repeat(); } @@ -644,17 +645,17 @@ VG_STATIC void world_process_resources(void) vg_info( "Loading materials\n" ); - u32 size = sizeof(struct world_material) * world.meta->info.material_count; - world.materials = vg_linear_alloc( world.dynamic_vgl, size ); + u32 size = sizeof(struct world_material) * world->meta->info.material_count; + world->materials = vg_linear_alloc( world_global.generic_heap, size ); - world.material_count = world.meta->info.material_count; - memset( world.materials, 0, size ); + world->material_count = world->meta->info.material_count; + memset( world->materials, 0, size ); - for( int i=1; imaterial_buffer[i]; + for( int i=1; imaterial_count; i++ ) + world->materials[i].info = world->meta->material_buffer[i]; /* error material */ - struct world_material *errmat = &world.materials[0]; + struct world_material *errmat = &world->materials[0]; v4_copy( (v4f){ 1.0f,0.0f,0.0f,1.0f }, errmat->info.colour ); v4_copy( (v4f){ 1.0f,0.0f,0.0f,1.0f }, errmat->info.colour1 ); errmat->info.flags = 0x00; @@ -665,27 +666,27 @@ VG_STATIC void world_process_resources(void) errmat->info.tex_normal = 0; } -VG_STATIC void world_unload(void) +VG_STATIC void world_unload( world_instance *world ) { vg_acquire_thread_sync(); /* free meshes */ - mesh_free( &world.mesh_route_lines ); - mesh_free( &world.mesh_geo ); - mesh_free( &world.mesh_no_collide ); - - world.time = 0.0; - world.rewind_from = 0.0; - world.rewind_to = 0.0; - world.last_use = 0.0; - world.active_gate = 0; - world.current_run_version = 2; - world.active_route_board = 0; - v3_zero( world.render_gate_pos ); - - for( int i=0; imesh_route_lines ); + mesh_free( &world->mesh_geo ); + mesh_free( &world->mesh_no_collide ); + + /* FIXME: CANT DO THIS HERE */ + world_global.time = 0.0; + world_global.rewind_from = 0.0; + world_global.rewind_to = 0.0; + world_global.last_use = 0.0; + world_global.active_gate = 0; + world_global.current_run_version = 2; + world_global.active_route_board = 0; + + for( int i=0; isegment_start = 0; uib->segment_count = 0; uib->fade_start = 0; @@ -695,85 +696,133 @@ VG_STATIC void world_unload(void) } /* delete textures and meshes */ - glDeleteTextures( world.texture_count, world.textures ); + glDeleteTextures( world->texture_count, world->textures ); /* delete the entire block of memory */ - vg_linear_clear( world.dynamic_vgl ); - vg_linear_clear( world.audio_vgl ); + /* FIXME: WE CANT DO THIS SHIT ANYMORE, NEED TO DEALLOC FROM ABOVE */ +#if 0 + vg_linear_clear( world->dynamic_vgl ); + vg_linear_clear( world->audio_vgl ); +#endif + + + vg_release_thread_sync(); +} + +VG_STATIC void world_add_global_light( world_instance *world, + v2f dir, v3f colour ) +{ + int id = world->ub_lighting.g_light_count; + + v3_copy( colour, world->ub_lighting.g_light_colours[id] ); + v3_copy( (v3f){ cosf(dir[1]) * cosf(dir[0]), + sinf(dir[0]), + sinf(dir[1]) * cosf(dir[0]) }, + world->ub_lighting.g_light_directions[id] ); + + world->ub_lighting.g_light_count ++; +} +VG_STATIC void world_clean( world_instance *world ) +{ /* clean dangling pointers */ - world.meta = NULL; + world->meta = NULL; - world.textures = NULL; - world.texture_count = 0; - world.materials = NULL; - world.material_count = 0; + world->textures = NULL; + world->texture_count = 0; + world->materials = NULL; + world->material_count = 0; - world.scene_geo = NULL; - world.scene_no_collide = NULL; - world.scene_lines = NULL; + world->scene_geo = NULL; + world->scene_no_collide = NULL; + world->scene_lines = NULL; - world.geo_bh = NULL; - world.trigger_bh = NULL; - world.audio_bh = NULL; + world->geo_bh = NULL; + world->trigger_bh = NULL; + world->audio_bh = NULL; - world.spawns = NULL; - world.spawn_count = 0; + world->spawns = NULL; + world->spawn_count = 0; - world.audio_things = NULL; - world.audio_things_count = 0; + world->audio_things = NULL; + world->audio_things_count = 0; - world.triggers = NULL; - world.trigger_count = 0; + world->triggers = NULL; + world->trigger_count = 0; - world.lights = NULL; - world.light_count = 0; + world->lights = NULL; + world->light_count = 0; - world.logic_relays = NULL; - world.relay_count = 0; + world->logic_relays = NULL; + world->relay_count = 0; - world.logic_achievements = NULL; - world.achievement_count = 0; + world->logic_achievements = NULL; + world->achievement_count = 0; - world.nodes = NULL; - world.node_count = 0; + world->nodes = NULL; + world->node_count = 0; - world.routes = NULL; - world.route_count = 0; + world->routes = NULL; + world->route_count = 0; - world.gates = NULL; - world.gate_count = 0; + world->gates = NULL; + world->gate_count = 0; - world.collectors = NULL; - world.collector_count = 0; + world->collectors = NULL; + world->collector_count = 0; - world.water.enabled = 0; + world->water.enabled = 0; - vg_release_thread_sync(); + + /* default lighting conditions + * -------------------------------------------------------------*/ + world->ub_lighting.g_light_count = 0; + world->ub_lighting.g_light_preview = 0; + world->ub_lighting.g_shadow_samples = 8; + world->ub_lighting.g_water_fog = 0.04f; + + v4_zero( world->ub_lighting.g_water_plane ); + v4_zero( world->ub_lighting.g_depth_bounds ); + v4_zero( world->ub_lighting.g_ambient_colour ); + + v3_copy( (v3f){ 0.09f, 0.03f, 0.07f }, world->ub_lighting.g_ambient_colour ); + + world_add_global_light( world, (v2f){ 0.63f, -0.08f }, + (v3f){ 1.36f, 1.35f, 1.01f } ); + + world_add_global_light( world, (v2f){ -2.60f, -0.13f }, + (v3f){ 0.33f, 0.56f, 0.64f } ); + + world_add_global_light( world, (v2f){ 2.60f, -0.84f }, + (v3f){ 0.05f, 0.05f, 0.23f } ); + + world->ub_lighting.g_light_directions[0][3] = 9.50f; + world->ub_lighting.g_light_colours[0][3] = 0.65f; } -VG_STATIC void world_load(void) +VG_STATIC void world_load( world_instance *world, const char *path ) { - world_unload(); + world_unload( world ); + world_clean( world ); - world.meta = mdl_load_full( world.dynamic_vgl, world.world_name ); - vg_info( "Loading world: %s\n", world.world_name ); + world->meta = mdl_load_full( world_global.generic_heap, path ); + vg_info( "Loading world: %s\n", path ); /* process resources from pack */ - world_process_resources(); + world_process_resources( world ); /* dynamic allocations */ - world_ents_allocate(); - world_routes_allocate(); + world_ents_allocate( world ); + world_routes_allocate( world ); /* meta processing */ - world_routes_process(); - world_entities_process(); + world_routes_process( world ); + world_entities_process( world ); /* main bulk */ - world_generate(); - world_routes_generate(); - world_post_process(); + world_generate( world ); + world_routes_generate( world ); + world_post_process( world ); } #endif /* WORLD_GEN_H */ diff --git a/world_render.h b/world_render.h index e738d37..fd0b39f 100644 --- a/world_render.h +++ b/world_render.h @@ -19,11 +19,67 @@ VG_STATIC void world_render_init(void) vg_acquire_thread_sync(); { vg_tex2d_init( (vg_tex2d *[]){ &tex_terrain_noise }, 1 ); + + + vg_info( "Allocate uniform buffers\n" ); + for( int i=0; i<4; i++ ) + { + world_instance *world = &world_global.worlds[i]; + world->ubo_bind_point = i; + + glGenBuffers( 1, &world->ubo_lighting ); + glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting ); + glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting), + NULL, GL_DYNAMIC_DRAW ); + + glBindBufferBase( GL_UNIFORM_BUFFER, i, world->ubo_lighting ); + VG_CHECK_GL_ERR(); + } + + vg_info( "Allocate frame buffers\n" ); + for( int i=0; i<4; i++ ) + { + world_instance *world = &world_global.worlds[i]; + struct framebuffer *fb = &world->heightmap; + + fb->display_name = NULL; + fb->link = NULL; + fb->fixed_w = 1024; + fb->fixed_h = 1024; + fb->resolution_div = 0; + + /* TODO: We could get away with this being R16u, and just have it be + * a normed value between min and max of the bounding box Y */ + + fb->attachments[0].display_name = NULL; + fb->attachments[0].purpose = k_framebuffer_attachment_type_colour; + fb->attachments[0].internalformat = GL_R16F; + fb->attachments[0].format = GL_RED; + fb->attachments[0].type = GL_FLOAT; + fb->attachments[0].attachment = GL_COLOR_ATTACHMENT0; + + fb->attachments[1].purpose = k_framebuffer_attachment_type_none; + fb->attachments[2].purpose = k_framebuffer_attachment_type_none; + fb->attachments[3].purpose = k_framebuffer_attachment_type_none; + fb->attachments[4].purpose = k_framebuffer_attachment_type_none; + + render_fb_allocate( fb ); + } } vg_release_thread_sync(); } -VG_STATIC void render_world_depth( camera *cam ); +VG_STATIC void world_link_lighting_ub( world_instance *world, + GLuint shader, int texture_id ) +{ + GLuint idx = glGetUniformBlockIndex( shader, "ub_world_lighting" ); + glUniformBlockBinding( shader, idx, world->ubo_bind_point ); + + render_fb_bind_texture( &world->heightmap, 0, texture_id ); + glUniform1i( glGetUniformLocation( shader, "g_world_depth" ), texture_id ); +} + +VG_STATIC void render_world_depth( world_instance *world, camera *cam ); /* * Rendering @@ -34,14 +90,18 @@ VG_STATIC void bind_terrain_noise(void) vg_tex2d_bind( &tex_terrain_noise, 0 ); } -VG_STATIC void world_render_if( enum mdl_shader shader, +typedef void (*func_bind_point)( world_instance *world, + struct world_material *mat ); + +VG_STATIC void world_render_if( world_instance *world, + enum mdl_shader shader, enum geo_type geo_type, - void (*bind_point)(struct world_material *mat)) + func_bind_point bind_point ) { - for( int i=0; imaterial_count; i++ ) { - struct world_material *mat = &world.materials[i]; + struct world_material *mat = &world->materials[i]; if( mat->info.shader == shader ) { @@ -55,31 +115,34 @@ VG_STATIC void world_render_if( enum mdl_shader shader, if( !sm->indice_count ) continue; - bind_point( mat ); + bind_point( world, mat ); mdl_draw_submesh( sm ); } } } -VG_STATIC void world_render_both_stages( enum mdl_shader shader, - void (*bind_point)(struct world_material *mat)) +VG_STATIC +void world_render_both_stages( world_instance *world, + enum mdl_shader shader, + func_bind_point bind_point ) { - mesh_bind( &world.mesh_geo ); - world_render_if( shader, k_geo_type_solid, bind_point ); + mesh_bind( &world->mesh_geo ); + world_render_if( world, shader, k_geo_type_solid, bind_point ); glDisable( GL_CULL_FACE ); - mesh_bind( &world.mesh_no_collide ); - world_render_if( shader, k_geo_type_nonsolid, bind_point ); + mesh_bind( &world->mesh_no_collide ); + world_render_if( world, shader, k_geo_type_nonsolid, bind_point ); glEnable( GL_CULL_FACE ); } -VG_STATIC void bindpoint_diffuse_texture1( struct world_material *mat ) +VG_STATIC void bindpoint_diffuse_texture1( world_instance *world, + struct world_material *mat ) { glActiveTexture( GL_TEXTURE1 ); - glBindTexture( GL_TEXTURE_2D, world.textures[ mat->info.tex_diffuse ] ); + glBindTexture( GL_TEXTURE_2D, world->textures[ mat->info.tex_diffuse ] ); } -VG_STATIC void render_world_vb( camera *cam ) +VG_STATIC void render_world_vb( world_instance *world, camera *cam ) { m4x3f identity_matrix; m4x3_identity( identity_matrix ); @@ -87,7 +150,7 @@ VG_STATIC void render_world_vb( camera *cam ) shader_scene_vertex_blend_use(); shader_scene_vertex_blend_uTexGarbage(0); shader_scene_vertex_blend_uTexGradients(1); - shader_link_standard_ub( _shader_scene_vertex_blend.id, 2 ); + world_link_lighting_ub( world, _shader_scene_vertex_blend.id, 2 ); vg_tex2d_bind( &tex_terrain_noise, 0 ); shader_scene_vertex_blend_uPv( cam->mtx.pv ); @@ -97,11 +160,11 @@ VG_STATIC void render_world_vb( camera *cam ) shader_scene_vertex_blend_uBoard0( TEMP_BOARD_0 ); shader_scene_vertex_blend_uBoard1( TEMP_BOARD_1 ); - world_render_both_stages( k_shader_standard_vertex_blend, + world_render_both_stages( world, k_shader_standard_vertex_blend, bindpoint_diffuse_texture1 ); } -VG_STATIC void render_world_standard( camera *cam ) +VG_STATIC void render_world_standard( world_instance *world, camera *cam ) { m4x3f identity_matrix; m4x3_identity( identity_matrix ); @@ -111,7 +174,7 @@ VG_STATIC void render_world_standard( camera *cam ) shader_scene_standard_uTexMain(1); shader_scene_standard_uPv( cam->mtx.pv ); shader_scene_standard_uPvmPrev( cam->mtx_prev.pv ); - shader_link_standard_ub( _shader_scene_standard.id, 2 ); + world_link_lighting_ub( world, _shader_scene_standard.id, 2 ); bind_terrain_noise(); shader_scene_standard_uMdl( identity_matrix ); @@ -119,11 +182,11 @@ VG_STATIC void render_world_standard( camera *cam ) shader_scene_standard_uBoard0( TEMP_BOARD_0 ); shader_scene_standard_uBoard1( TEMP_BOARD_1 ); - world_render_both_stages( k_shader_standard, + world_render_both_stages( world, k_shader_standard, bindpoint_diffuse_texture1 ); } -VG_STATIC void render_world_alphatest( camera *cam ) +VG_STATIC void render_world_alphatest( world_instance *world, camera *cam ) { m4x3f identity_matrix; m4x3_identity( identity_matrix ); @@ -133,7 +196,7 @@ VG_STATIC void render_world_alphatest( camera *cam ) shader_scene_standard_alphatest_uTexMain(1); shader_scene_standard_alphatest_uPv( cam->mtx.pv ); shader_scene_standard_alphatest_uPvmPrev( cam->mtx_prev.pv ); - shader_link_standard_ub( _shader_scene_standard_alphatest.id, 2 ); + world_link_lighting_ub( world, _shader_scene_standard_alphatest.id, 2 ); bind_terrain_noise(); shader_scene_standard_alphatest_uMdl( identity_matrix ); @@ -143,22 +206,23 @@ VG_STATIC void render_world_alphatest( camera *cam ) glDisable(GL_CULL_FACE); - world_render_both_stages( k_shader_standard_cutout, + world_render_both_stages( world, k_shader_standard_cutout, bindpoint_diffuse_texture1 ); glEnable(GL_CULL_FACE); } -VG_STATIC void bindpoint_terrain( struct world_material *mat ) +VG_STATIC void bindpoint_terrain( world_instance *world, + struct world_material *mat ) { glActiveTexture( GL_TEXTURE1 ); - glBindTexture( GL_TEXTURE_2D, world.textures[ mat->info.tex_diffuse ] ); + glBindTexture( GL_TEXTURE_2D, world->textures[ mat->info.tex_diffuse ] ); shader_scene_terrain_uSandColour( mat->info.colour ); shader_scene_terrain_uBlendOffset( mat->info.colour1 ); } -VG_STATIC void render_terrain( camera *cam ) +VG_STATIC void render_terrain( world_instance *world, camera *cam ) { m4x3f identity_matrix; m4x3_identity( identity_matrix ); @@ -166,7 +230,7 @@ VG_STATIC void render_terrain( camera *cam ) shader_scene_terrain_use(); shader_scene_terrain_uTexGarbage(0); shader_scene_terrain_uTexGradients(1); - shader_link_standard_ub( _shader_scene_terrain.id, 2 ); + world_link_lighting_ub( world, _shader_scene_terrain.id, 2 ); vg_tex2d_bind( &tex_terrain_noise, 0 ); @@ -178,7 +242,7 @@ VG_STATIC void render_terrain( camera *cam ) shader_scene_terrain_uBoard0( TEMP_BOARD_0 ); shader_scene_terrain_uBoard1( TEMP_BOARD_1 ); - world_render_both_stages( k_shader_terrain_blend, bindpoint_terrain ); + world_render_both_stages( world, k_shader_terrain_blend, bindpoint_terrain ); } VG_STATIC void render_sky( camera *cam ) @@ -215,31 +279,31 @@ VG_STATIC void render_sky( camera *cam ) shader_model_sky_uPv( pv ); shader_model_sky_uPvmPrev( pv_prev ); shader_model_sky_uTexGarbage(0); - shader_model_sky_uTime( world.sky_time ); + shader_model_sky_uTime( world_global.sky_time ); vg_tex2d_bind( &tex_terrain_noise, 0 ); glDepthMask( GL_FALSE ); glDisable( GL_DEPTH_TEST ); - mesh_bind( &world.skydome ); - mdl_draw_submesh( &world.dome_upper ); + mesh_bind( &world_global.skydome ); + mdl_draw_submesh( &world_global.dome_upper ); glEnable( GL_DEPTH_TEST ); glDepthMask( GL_TRUE ); } -VG_STATIC void render_world_gates( camera *cam ) +VG_STATIC void render_world_gates( world_instance *world, camera *cam ) { - if( !world.gate_count ) + if( !world->gate_count ) return; float closest = INFINITY; int id = 0; - for( int i=0; igate_count; i++ ) { - struct route_gate *rg = &world.gates[i]; + struct route_gate *rg = &world->gates[i]; float dist = v3_dist2( rg->gate.co[0], cam->transform[3] ); if( dist < closest ) @@ -249,33 +313,30 @@ VG_STATIC void render_world_gates( camera *cam ) } } - render_gate( &world.gates[id].gate, cam ); - v3_lerp( world.render_gate_pos, - world.gates[id].gate.co[0], - 1.0f, - world.render_gate_pos ); + /* TODO: non-local portals! :D */ + render_gate( world, &world->gates[id].gate, cam ); } -VG_STATIC void render_world( camera *cam ) +VG_STATIC void render_world( world_instance *world, camera *cam ) { render_sky( cam ); - render_world_routes( cam ); - render_world_standard( cam ); - render_world_vb( cam ); - render_world_alphatest( cam ); - render_terrain( cam ); + render_world_routes( world, cam ); + render_world_standard( world, cam ); + render_world_vb( world, cam ); + render_world_alphatest( world, cam ); + render_terrain( world, cam ); /* Render SFD's */ int closest = 0; float min_dist = INFINITY; - if( !world.route_count ) + if( !world->route_count ) return; - for( int i=0; iroute_count; i++ ) { - float dist = v3_dist2(world.routes[i].scoreboard_transform[3], cam->pos); + float dist = v3_dist2(world->routes[i].scoreboard_transform[3], cam->pos); if( dist < min_dist ) { @@ -284,10 +345,10 @@ VG_STATIC void render_world( camera *cam ) } } - sfd_render( cam, world.routes[closest].scoreboard_transform ); + sfd_render( cam, world->routes[closest].scoreboard_transform ); } -VG_STATIC void render_world_depth( camera *cam ) +VG_STATIC void render_world_depth( world_instance *world, camera *cam ) { m4x3f identity_matrix; m4x3_identity( identity_matrix ); @@ -298,8 +359,8 @@ VG_STATIC void render_world_depth( camera *cam ) shader_scene_depth_uPvmPrev( cam->mtx_prev.pv ); shader_scene_depth_uMdl( identity_matrix ); - mesh_bind( &world.mesh_geo ); - mesh_draw( &world.mesh_geo ); + mesh_bind( &world->mesh_geo ); + mesh_draw( &world->mesh_geo ); #if 0 glDisable(GL_CULL_FACE); diff --git a/world_routes.h b/world_routes.h index 35f38f0..121f447 100644 --- a/world_routes.h +++ b/world_routes.h @@ -53,7 +53,8 @@ VG_STATIC void debug_sbpath( struct route_node *rna, struct route_node *rnb, /* * Get a list of node ids in stack, and return how many there is */ -VG_STATIC u32 world_routes_get_path( u32 starter, u32 stack[64] ) +VG_STATIC u32 world_routes_get_path( world_instance *world, + u32 starter, u32 stack[64] ) { u32 stack_i[64]; @@ -71,7 +72,7 @@ VG_STATIC u32 world_routes_get_path( u32 starter, u32 stack[64] ) continue; } - struct route_node *rn = &world.nodes[stack[si-1]]; + struct route_node *rn = &world->nodes[stack[si-1]]; u32 nextid = rn->next[stack_i[si-1]]; stack_i[si-1] ++; @@ -224,7 +225,7 @@ VG_STATIC struct route_ui_segment *world_routes_ui_curseg( */ VG_STATIC void world_routes_ui_newseg( u32 route ) { - struct route_ui_bar *pui = &world.ui_bars[route]; + struct route_ui_bar *pui = &world_global.ui_bars[route]; glBindVertexArray( pui->vao ); if( pui->segment_count ) @@ -279,7 +280,7 @@ VG_STATIC void world_routes_ui_newseg( u32 route ) */ VG_STATIC void world_routes_ui_updatetime( u32 route, float time ) { - struct route_ui_bar *pui = &world.ui_bars[route]; + struct route_ui_bar *pui = &world_global.ui_bars[route]; v2f verts[2]; verts[0][0] = time; @@ -311,20 +312,22 @@ VG_STATIC void world_routes_ui_draw_segment( struct route_ui_segment *segment ) /* * Draws full bar at Y offset(offset). */ -VG_STATIC void world_routes_ui_draw( u32 route, v4f colour, float offset ) +VG_STATIC void world_routes_ui_draw( world_instance *world, + u32 route, v4f colour, float offset ) { float const k_bar_height = 0.05f, k_bar_scale_x = 0.005f; - struct route *pr = &world.routes[route]; - struct route_ui_bar *pui = &world.ui_bars[route]; + /* FIXME(10) ID mishmatch */ + struct route *pr = &world->routes[route]; + struct route_ui_bar *pui = &world_global.ui_bars[route]; float cx = pui->xpos; shader_routeui_use(); glBindVertexArray( pui->vao ); - float fade_amt = world.time - pui->fade_timer_start; + float fade_amt = world_global.time - pui->fade_timer_start; fade_amt = vg_clampf( fade_amt / 1.0f, 0.0f, 1.0f ); float fade_block_size = 0.0f, @@ -345,7 +348,7 @@ VG_STATIC void world_routes_ui_draw( u32 route, v4f colour, float offset ) fade_colour[3] *= 1.0f-fade_amt; /* 1 minute timer */ - float timer_delta = (world.time - world.last_use) * (1.0/45.0), + float timer_delta = (world_global.time - world_global.last_use) * (1.0/45.0), timer_scale = 1.0f - vg_minf( timer_delta, 1.0f ); /* @@ -389,11 +392,13 @@ VG_STATIC void world_routes_ui_draw( u32 route, v4f colour, float offset ) pui->xpos = vg_lerpf( pui->xpos, -main_block_size * 0.5f, 0.03f ); } -VG_STATIC void world_routes_local_set_record( u32 route, double lap_time ) +VG_STATIC void world_routes_local_set_record( world_instance *world, + u32 route, double lap_time ) { vg_success( " NEW LAP TIME: %f\n", lap_time ); - struct route *pr = &world.routes[route]; + /* FIXME(10): ID mishmatch */ + struct route *pr = &world->routes[route]; if( pr->track_id != 0xffffffff ) { @@ -431,13 +436,14 @@ VG_STATIC void world_routes_local_set_record( u32 route, double lap_time ) * 2: the time of each segment will be recorded into the data buffer * (not implemented: TODO) */ -VG_STATIC void world_routes_verify_run( u32 route ) +VG_STATIC void world_routes_verify_run( world_instance *world, u32 route ) { - struct route *pr = &world.routes[route]; - struct route_ui_bar *pui = &world.ui_bars[route]; + /* FIXME(10): ID mishmatch */ + struct route *pr = &world->routes[route]; + struct route_ui_bar *pui = &world_global.ui_bars[route]; u32 stack[64]; - u32 si = world_routes_get_path( world.routes[route].start, stack ); + u32 si = world_routes_get_path( world, world->routes[route].start, stack ); /* * we only care about gates that ref gates, so shuffle down the array @@ -446,15 +452,15 @@ VG_STATIC void world_routes_verify_run( u32 route ) u32 sj = 0, maxv = 0, begin = 0; for( u32 i=0; inodes[stack[i]]; if( inode->special_type == k_route_special_type_collector ) { - timings[sj ++] = &world.collectors[ inode->special_id ].timing; + timings[sj ++] = &world->collectors[ inode->special_id ].timing; } else if( inode->special_type == k_route_special_type_gate ) { - timings[sj ++] = &world.gates[inode->special_id].timing; + timings[sj ++] = &world->gates[inode->special_id].timing; } } @@ -468,10 +474,10 @@ VG_STATIC void world_routes_verify_run( u32 route ) } vg_info( "== begin verification (%u) ==\n", route ); - vg_info( " current version: %u\n", world.current_run_version ); + vg_info( " current version: %u\n", world_global.current_run_version ); int verified = 0; - if( timings[begin]->version == world.current_run_version ) + if( timings[begin]->version == world_global.current_run_version ) verified = 1; int valid_segment_count = 0; @@ -508,7 +514,7 @@ VG_STATIC void world_routes_verify_run( u32 route ) pui->fade_start = pui->segment_start; pui->fade_count = 0; - pui->fade_timer_start = world.time; + pui->fade_timer_start = world_global.time; int orig_seg_count = pui->segment_count; @@ -516,7 +522,7 @@ VG_STATIC void world_routes_verify_run( u32 route ) if( verified ) { - world_routes_local_set_record( route, lap_time ); + world_routes_local_set_record( world, route, lap_time ); world_routes_ui_popfirst( pui ); pui->fade_count ++; } @@ -531,40 +537,40 @@ VG_STATIC void world_routes_verify_run( u32 route ) pui->fade_count ++; } - world.routes[route].latest_pass = world.time; + world->routes[route].latest_pass = world_global.time; } -VG_STATIC void world_routes_clear(void) +VG_STATIC void world_routes_clear( world_instance *world ) { - for( u32 i=0; iroute_count; i++ ) { - struct route *route = &world.routes[i]; + struct route *route = &world->routes[i]; route->active = 0; } - world.current_run_version += 4; - world.last_use = 0.0; + world_global.current_run_version += 4; + world_global.last_use = 0.0; } /* * When going through a gate this is called for bookkeeping purposes */ -VG_STATIC void world_routes_activate_gate( u32 id ) +VG_STATIC void world_routes_activate_gate( world_instance *world, u32 id ) { - struct route_gate *rg = &world.gates[id]; - struct route_node *pnode = &world.nodes[rg->node_id], - *pdest = &world.nodes[pnode->next[0]]; + struct route_gate *rg = &world->gates[id]; + struct route_node *pnode = &world->nodes[rg->node_id], + *pdest = &world->nodes[pnode->next[0]]; - world.last_use = world.time; + world_global.last_use = world_global.time; - struct route_collector *rc = &world.collectors[ pdest->special_id ]; + struct route_collector *rc = &world->collectors[ pdest->special_id ]; - world.active_gate = id; - rg->timing.version = world.current_run_version; - rg->timing.time = world.time; + world_global.active_gate = id; + rg->timing.version = world_global.current_run_version; + rg->timing.time = world_global.time; - for( u32 i=0; iroute_count; i++ ) { - struct route *route = &world.routes[i]; + struct route *route = &world->routes[i]; int was_active = route->active; @@ -573,7 +579,7 @@ VG_STATIC void world_routes_activate_gate( u32 id ) { if( pdest->route_ids[j] == i ) { - world_routes_verify_run( i ); + world_routes_verify_run( world, i ); route->active = 1; break; } @@ -581,10 +587,10 @@ VG_STATIC void world_routes_activate_gate( u32 id ) if( was_active && !route->active ) { - struct route_ui_bar *pui = &world.ui_bars[i]; + struct route_ui_bar *pui = &world_global.ui_bars[i]; pui->fade_start = pui->segment_start; pui->fade_count = pui->segment_count; - pui->fade_timer_start = world.time; + pui->fade_timer_start = world_global.time; world_routes_ui_clear( pui ); vg_success( "CLEARING -> %u %u \n", pui->fade_start, @@ -592,11 +598,11 @@ VG_STATIC void world_routes_activate_gate( u32 id ) } } - world.current_run_version ++; + world_global.current_run_version ++; - rc->timing.version = world.current_run_version; - rc->timing.time = world.time; - world.current_run_version ++; + rc->timing.version = world_global.current_run_version; + rc->timing.time = world_global.time; + world_global.current_run_version ++; } /* @@ -604,41 +610,32 @@ VG_STATIC void world_routes_activate_gate( u32 id ) */ VG_STATIC void world_routes_notify_reset(void) { - world.rewind_from = world.time; - world.rewind_to = world.last_use; - -#if 0 - for( int i=0; iroute_count; i++ ) - { - struct route *route = &r->routes[i]; - - if( route->active ) - world_routes_ui_notch( i, r->time - route->latest_pass ); - } -#endif + world_global.rewind_from = world_global.time; + world_global.rewind_to = world_global.last_use; } /* Rewind between the saved points in time */ VG_STATIC void world_routes_rollback_time( double t ) { - world.time = vg_lerp( world.rewind_to, world.rewind_from, t ); + world_global.time = vg_lerp( world_global.rewind_to, + world_global.rewind_from, t ); } /* draw lines along the paths */ -VG_STATIC void world_routes_debug(void) +VG_STATIC void world_routes_debug( world_instance *world ) { - for( int i=0; inode_count; i++ ) { - struct route_node *rn = &world.nodes[i]; + struct route_node *rn = &world->nodes[i]; vg_line_pt3( rn->co, 1.0f, rn->special_type? 0xffffff00: 0xff00b2ff ); } - for( int i=0; iroute_count; i++ ) { - struct route *route = &world.routes[i]; + struct route *route = &world->routes[i]; u32 stack[64]; - u32 si = world_routes_get_path( route->start, stack ); + u32 si = world_routes_get_path( world, route->start, stack ); u32 colours[] = { 0xfff58142, 0xff42cbf5, 0xff42f56c, 0xfff542b3, 0xff5442f5 }; @@ -649,34 +646,34 @@ VG_STATIC void world_routes_debug(void) { int sk = (sj+1)%si; - struct route_node *pj = &world.nodes[stack[sj]], - *pk = &world.nodes[stack[sk]]; + struct route_node *pj = &world->nodes[stack[sj]], + *pk = &world->nodes[stack[sk]]; debug_sbpath( pj, pk, cc, (float)i ); } } - for( int i=0; inode_count; i++ ) { - struct route_node *ri = &world.nodes[i], + struct route_node *ri = &world->nodes[i], *rj = NULL; for( int j=0; j<2; j++ ) { if( ri->next[j] != 0xffffffff ) { - rj = &world.nodes[ri->next[j]]; + rj = &world->nodes[ri->next[j]]; vg_line( ri->co, rj->co, 0x20ffffff ); } } } } -VG_STATIC void world_routes_create_mesh( u32 route_id ) +VG_STATIC void world_routes_create_mesh( world_instance *world, u32 route_id ) { - struct route *route = &world.routes[ route_id ]; + struct route *route = &world->routes[ route_id ]; u32 stack[64]; - u32 si = world_routes_get_path( route->start, stack ); + u32 si = world_routes_get_path( world, route->start, stack ); u32 last_valid = 0; @@ -684,8 +681,8 @@ VG_STATIC void world_routes_create_mesh( u32 route_id ) { int sk=(sj+1)%si; - struct route_node *rnj = &world.nodes[ stack[sj] ], - *rnk = &world.nodes[ stack[sk] ], + struct route_node *rnj = &world->nodes[ stack[sj] ], + *rnk = &world->nodes[ stack[sk] ], *rnl; if( rnj->special_type && rnk->special_type ) @@ -699,7 +696,7 @@ VG_STATIC void world_routes_create_mesh( u32 route_id ) if( rnk->special_type ) { - rnl = &world.nodes[ rnk->next[0] ]; + rnl = &world->nodes[ rnk->next[0] ]; base_x1 = (float)rnl->ref_count*-0.5f + (float)rnl->current_refs; } @@ -746,8 +743,8 @@ VG_STATIC void world_routes_create_mesh( u32 route_id ) ray_hit ha, hb; ha.dist = 8.0f; hb.dist = 8.0f; - if( ray_world( sa, down, &ha ) && - ray_world( sb, down, &hb )) + if( ray_world( world, sa, down, &ha ) && + ray_world( world, sb, down, &hb )) { scene_vert va, vb; @@ -759,19 +756,19 @@ VG_STATIC void world_routes_create_mesh( u32 route_id ) v2_zero( va.uv ); v2_zero( vb.uv ); - scene_push_vert( world.scene_lines, &va ); - scene_push_vert( world.scene_lines, &vb ); + scene_push_vert( world->scene_lines, &va ); + scene_push_vert( world->scene_lines, &vb ); if( last_valid ) { /* Connect them with triangles */ - scene_push_tri( world.scene_lines, (u32[3]){ + scene_push_tri( world->scene_lines, (u32[3]){ last_valid+0-2, last_valid+1-2, last_valid+2-2} ); - scene_push_tri( world.scene_lines, (u32[3]){ + scene_push_tri( world->scene_lines, (u32[3]){ last_valid+1-2, last_valid+3-2, last_valid+2-2} ); } - last_valid = world.scene_lines->vertex_count; + last_valid = world->scene_lines->vertex_count; } else last_valid = 0; @@ -789,38 +786,43 @@ VG_STATIC void world_routes_create_mesh( u32 route_id ) rnj->current_refs ++; } - scene_copy_slice( world.scene_lines, &route->sm ); + scene_copy_slice( world->scene_lines, &route->sm ); } +VG_STATIC void world_scene_compute_light_clusters( world_instance *world, + scene *sc ); /* * Create the strips of colour that run through the world along course paths */ -VG_STATIC void world_routes_generate(void) +VG_STATIC void world_routes_generate( world_instance *world ) { vg_info( "Generating route meshes\n" ); - world.scene_lines = scene_init( world.dynamic_vgl, 200000, 300000 ); + world->scene_lines = scene_init( world_global.generic_heap, 200000, 300000 ); - for( u32 i=0; iroute_count; i++ ) + world_routes_create_mesh( world, i ); + + world_scene_compute_light_clusters( world, world->scene_lines ); vg_acquire_thread_sync(); { - scene_upload( world.scene_lines, &world.mesh_route_lines ); + scene_upload( world->scene_lines, &world->mesh_route_lines ); } vg_release_thread_sync(); - vg_linear_del( world.dynamic_vgl, world.scene_lines ); + vg_linear_del( world_global.generic_heap, world->scene_lines ); } /* determine if special type is required for this gate */ -VG_STATIC enum route_special_type world_route_node_type( mdl_node *pnode ) +VG_STATIC enum route_special_type world_route_node_type( world_instance *world, + mdl_node *pnode ) { if( pnode->classtype == k_classtype_gate ) { - struct classtype_gate *inf = mdl_get_entdata( world.meta, pnode ); + struct classtype_gate *inf = mdl_get_entdata( world->meta, pnode ); if( inf->target ) { - mdl_node *pother = mdl_node_from_id( world.meta, inf->target ); + mdl_node *pother = mdl_node_from_id( world->meta, inf->target ); if( pother->classtype == k_classtype_gate ) { @@ -835,7 +837,7 @@ VG_STATIC enum route_special_type world_route_node_type( mdl_node *pnode ) } /* count entities and allocate correct amount of memory in advance */ -VG_STATIC void world_routes_allocate(void) +VG_STATIC void world_routes_allocate( world_instance *world ) { vg_info( "Allocating routes\n" ); @@ -845,16 +847,16 @@ VG_STATIC void world_routes_allocate(void) gate_count = 0, collector_count = 0; - for( int i=0; iinfo.node_count; i++ ) + for( int i=0; imeta->info.node_count; i++ ) { - mdl_node *pnode = mdl_node_from_id( world.meta, i ); + mdl_node *pnode = mdl_node_from_id( world->meta, i ); if( pnode->classtype == k_classtype_route_node || pnode->classtype == k_classtype_gate ) { pnode->sub_uid = node_count; - enum route_special_type type = world_route_node_type( pnode ); + enum route_special_type type = world_route_node_type( world, pnode ); if( type == k_route_special_type_gate ) gate_count ++; @@ -875,16 +877,18 @@ VG_STATIC void world_routes_allocate(void) gate_size = gate_count * sizeof(struct route_gate), collector_size = collector_count * sizeof(struct route_collector); - world.nodes = vg_linear_alloc( world.dynamic_vgl, node_size ); - world.routes = vg_linear_alloc( world.dynamic_vgl, route_size ); - world.gates = vg_linear_alloc( world.dynamic_vgl, gate_size ); - world.collectors = vg_linear_alloc( world.dynamic_vgl, collector_size ); + world->nodes = vg_linear_alloc( world_global.generic_heap, node_size ); + world->routes = vg_linear_alloc( world_global.generic_heap, route_size ); + world->gates = vg_linear_alloc( world_global.generic_heap, gate_size ); + world->collectors = vg_linear_alloc( world_global.generic_heap, + collector_size ); } /* create node from mdl node */ -VG_STATIC struct route_node *world_routes_create_node( mdl_node *pnode ) +VG_STATIC struct route_node *world_routes_create_node( world_instance *world, + mdl_node *pnode ) { - struct route_node *rn = &world.nodes[ world.node_count ++ ]; + struct route_node *rn = &world->nodes[ world->node_count ++ ]; m4x3f transform; mdl_node_transform( pnode, transform ); @@ -908,12 +912,12 @@ VG_STATIC struct route_node *world_routes_create_node( mdl_node *pnode ) } /* retrieve the correct node id from mdl subuid */ -VG_STATIC u32 world_routes_get_subuid( u32 target ) +VG_STATIC u32 world_routes_get_subuid( world_instance *world, u32 target ) { if( target == 0 ) return 0xffffffff; else - return mdl_node_from_id( world.meta, target )->sub_uid; + return mdl_node_from_id( world->meta, target )->sub_uid; } #if 0 @@ -927,26 +931,27 @@ VG_STATIC void world_id_fixup( u32 *uid, mdl_context *mdl ) #endif /* process gate attachement onto node */ -VG_STATIC void world_routes_process_gate( struct route_node *rn, +VG_STATIC void world_routes_process_gate( world_instance *world, + struct route_node *rn, mdl_node *pnode ) { - struct classtype_gate *inf = mdl_get_entdata( world.meta, pnode ); + struct classtype_gate *inf = mdl_get_entdata( world->meta, pnode ); /* H is later scaled based on link distance */ v3_normalize( rn->h ); - rn->next[0] = world_routes_get_subuid( inf->target ); + rn->next[0] = world_routes_get_subuid( world, inf->target ); rn->next[1] = 0xffffffff; - rn->special_type = world_route_node_type( pnode ); + rn->special_type = world_route_node_type( world, pnode ); /* process gate type */ if( rn->special_type == k_route_special_type_gate ) { - mdl_node *pother = mdl_node_from_id( world.meta, inf->target ); + mdl_node *pother = mdl_node_from_id( world->meta, inf->target ); - struct route_gate *rg = &world.gates[ world.gate_count ]; + struct route_gate *rg = &world->gates[ world->gate_count ]; - rg->node_id = world.node_count-1; + rg->node_id = world->node_count-1; rg->timing.time = 0.0; rg->timing.version = 0; @@ -957,34 +962,35 @@ VG_STATIC void world_routes_process_gate( struct route_node *rn, v2_copy( inf->dims, rg->gate.dims ); gate_transform_update( &rg->gate ); - rn->special_id = world.gate_count; + rn->special_id = world->gate_count; - world.gate_count ++; + world->gate_count ++; } /* process collector type */ else if( rn->special_type == k_route_special_type_collector ) { struct route_collector *rc = - &world.collectors[ world.collector_count ]; + &world->collectors[ world->collector_count ]; rc->timing.time = 0.0; rc->timing.version = 0; - rn->special_id = world.collector_count; - world.collector_count ++; + rn->special_id = world->collector_count; + world->collector_count ++; } else vg_fatal_exit_loop( "Invalid state" ); } /* create route from node description */ -VG_STATIC void world_routes_create_route( mdl_node *pnode ) +VG_STATIC void world_routes_create_route( world_instance *world, + mdl_node *pnode ) { - mdl_context *mdl = world.meta; + mdl_context *mdl = world->meta; struct classtype_route *inf = mdl_get_entdata( mdl, pnode ); - struct route *route = &world.routes[ world.route_count ]; + struct route *route = &world->routes[ world->route_count ]; memset( route, 0, sizeof(struct route) ); v3_copy( inf->colour, route->colour ); @@ -1000,12 +1006,12 @@ VG_STATIC void world_routes_create_route( mdl_node *pnode ) } } - route->start = world_routes_get_subuid( inf->id_start ); + route->start = world_routes_get_subuid( world, inf->id_start ); route->active = 0; route->factive = 0.0f; mdl_node_transform( pnode, route->scoreboard_transform ); - struct route_ui_bar *pui = &world.ui_bars[ world.route_count ]; + struct route_ui_bar *pui = &world_global.ui_bars[ world->route_count ]; pui->indices_head = k_route_ui_max_indices - 9; pui->vertex_head = k_route_ui_max_verts - 200; pui->segment_start = 0; @@ -1014,14 +1020,14 @@ VG_STATIC void world_routes_create_route( mdl_node *pnode ) pui->fade_count = 0; pui->fade_timer_start = 0.0; - world.route_count ++; + world->route_count ++; } /* load all routes from model header */ -VG_STATIC void world_routes_process(void) +VG_STATIC void world_routes_process( world_instance *world ) { vg_info( "Initializing routes\n" ); - mdl_context *mdl = world.meta; + mdl_context *mdl = world->meta; for( int i=0; iinfo.node_count; i++ ) { @@ -1030,38 +1036,38 @@ VG_STATIC void world_routes_process(void) if( pnode->classtype == k_classtype_route_node || pnode->classtype == k_classtype_gate ) { - struct route_node *rn = world_routes_create_node( pnode ); + struct route_node *rn = world_routes_create_node( world, pnode ); if( pnode->classtype == k_classtype_gate ) { - world_routes_process_gate( rn, pnode ); + world_routes_process_gate( world, rn, pnode ); } else { struct classtype_route_node *inf = mdl_get_entdata( mdl, pnode ); - rn->next[0] = world_routes_get_subuid( inf->target ); - rn->next[1] = world_routes_get_subuid( inf->target1 ); + rn->next[0] = world_routes_get_subuid( world, inf->target ); + rn->next[1] = world_routes_get_subuid( world, inf->target1 ); } } else if( pnode->classtype == k_classtype_route ) { - world_routes_create_route( pnode ); + world_routes_create_route( world, pnode ); } } /* * Gather references */ - for( int i=0; iroute_count; i++ ) { - struct route *route = &world.routes[i]; + struct route *route = &world->routes[i]; u32 stack[64]; - u32 si = world_routes_get_path( route->start, stack ); + u32 si = world_routes_get_path( world, route->start, stack ); for( int sj=0; sjnodes[ stack[sj] ]; rn->route_ids[ rn->ref_count ++ ] = i; if( rn->ref_count > 4 ) @@ -1078,9 +1084,9 @@ VG_STATIC void world_routes_process(void) VG_STATIC void world_routes_init(void) { - world.current_run_version = 2; - world.time = RESET_MAX_TIME*2.0; - world.last_use = 0.0; + world_global.current_run_version = 2; + world_global.time = RESET_MAX_TIME*2.0; + world_global.last_use = 0.0; shader_scene_route_register(); shader_routeui_register(); @@ -1088,10 +1094,10 @@ VG_STATIC void world_routes_init(void) vg_acquire_thread_sync(); { /* UI buffers */ - for( int i=0; ivao ); glGenBuffers( 1, &pui->vbo ); @@ -1118,32 +1124,32 @@ VG_STATIC void world_routes_init(void) vg_release_thread_sync(); } -VG_STATIC void world_routes_update(void) +VG_STATIC void world_routes_update( world_instance *world ) { - world.time += vg.time_delta; + world_global.time += vg.time_delta; - for( int i=0; iroute_count; i++ ) { - struct route *route = &world.routes[i]; + struct route *route = &world->routes[i]; route->factive = vg_lerpf( route->factive, route->active, 0.6f*vg.time_delta ); if( route->active ) { - world_routes_ui_updatetime(i, world.time - route->latest_pass ); + world_routes_ui_updatetime(i, world_global.time - route->latest_pass ); } } } VG_STATIC void bind_terrain_noise(void); -VG_STATIC void render_world_routes( camera *cam ) +VG_STATIC void render_world_routes( world_instance *world, camera *cam ) { m4x3f identity_matrix; m4x3_identity( identity_matrix ); shader_scene_route_use(); shader_scene_route_uTexGarbage(0); - shader_link_standard_ub( _shader_scene_route.id, 2 ); + world_link_lighting_ub( world, _shader_scene_route.id, 2 ); bind_terrain_noise(); shader_scene_route_uPv( cam->mtx.pv ); @@ -1153,11 +1159,11 @@ VG_STATIC void render_world_routes( camera *cam ) shader_scene_route_uBoard0( TEMP_BOARD_0 ); shader_scene_route_uBoard1( TEMP_BOARD_1 ); - mesh_bind( &world.mesh_route_lines ); + mesh_bind( &world->mesh_route_lines ); - for( int i=0; iroute_count; i++ ) { - struct route *route = &world.routes[i]; + struct route *route = &world->routes[i]; v4f colour; v3_lerp( (v3f){0.7f,0.7f,0.7f}, route->colour, route->factive, colour ); @@ -1168,17 +1174,17 @@ VG_STATIC void render_world_routes( camera *cam ) } } -VG_STATIC void render_world_routes_ui(void) +VG_STATIC void render_world_routes_ui( world_instance *world ) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); float active_offset = 0.0f; - for( int i=0; iroute_count; i++ ) { - struct route *route = &world.routes[i]; - world_routes_ui_draw( i, route->colour, active_offset ); + struct route *route = &world->routes[i]; + world_routes_ui_draw( world, i, route->colour, active_offset ); active_offset += route->factive; } diff --git a/world_sfd.h b/world_sfd.h index 3fbbe94..1b59e5a 100644 --- a/world_sfd.h +++ b/world_sfd.h @@ -58,22 +58,22 @@ float sfd_encode_glyph( char c ) VG_STATIC void sfd_encode( u32 row, const char *str ) { int end=0; - u32 row_h = world.sfd.h -1 -row; + u32 row_h = world_global.sfd.h -1 -row; - for( int i=0; iwater.height = height; + v4_copy( (v4f){ 0.0f, 1.0f, 0.0f, height }, world->water.plane ); } +VG_STATIC void world_link_lighting_ub( world_instance *world, + GLuint shader, int texture_id ); + /* * Does not write motion vectors */ -VG_STATIC void render_water_texture( camera *cam ) +VG_STATIC void render_water_texture( world_instance *world, camera *cam ) { - if( !world.water.enabled || (vg.quality_profile == k_quality_profile_low) ) + if( !world->water.enabled || (vg.quality_profile == k_quality_profile_low) ) return; /* Draw reflection buffa */ @@ -49,7 +52,7 @@ VG_STATIC void render_water_texture( camera *cam ) /* * Create flipped view matrix. Don't care about motion vectors */ - float cam_height = cam->transform[3][1] - world.water.height; + float cam_height = cam->transform[3][1] - world->water.height; camera water_cam; water_cam.farz = cam->farz; @@ -67,7 +70,7 @@ VG_STATIC void render_water_texture( camera *cam ) /* * Create clipped projection */ - v4f clippa = { 0.0f, 1.0f, 0.0f, world.water.height-0.1f }; + v4f clippa = { 0.0f, 1.0f, 0.0f, world->water.height-0.1f }; m4x3_mulp( water_cam.transform_inverse, clippa, clippa ); clippa[3] *= -1.0f; @@ -80,7 +83,7 @@ VG_STATIC void render_water_texture( camera *cam ) * Draw world */ glCullFace( GL_FRONT ); - render_world( &water_cam ); + render_world( world, &water_cam ); glCullFace( GL_BACK ); /* @@ -93,9 +96,9 @@ VG_STATIC void render_water_texture( camera *cam ) m4x3_copy( cam->transform, beneath_cam.transform ); camera_update_view( &beneath_cam ); - float bias = -(cam->transform[3][1]-world.water.height)*0.1f; + float bias = -(cam->transform[3][1]-world->water.height)*0.1f; - v4f clippb = { 0.0f, -1.0f, 0.0f, -(world.water.height) + bias }; + v4f clippb = { 0.0f, -1.0f, 0.0f, -(world->water.height) + bias }; m4x3_mulp( beneath_cam.transform_inverse, clippb, clippb ); clippb[3] *= -1.0f; @@ -103,13 +106,13 @@ VG_STATIC void render_water_texture( camera *cam ) m4x4_clip_projection( beneath_cam.mtx.p, clippb ); camera_finalize( &beneath_cam ); - render_world_depth( &beneath_cam ); + render_world_depth( world, &beneath_cam ); glViewport( 0, 0, vg.window_x, vg.window_y ); } -VG_STATIC void render_water_surface( camera *cam ) +VG_STATIC void render_water_surface( world_instance *world, camera *cam ) { - if( !world.water.enabled ) + if( !world->water.enabled ) return; if( vg.quality_profile == k_quality_profile_high ) @@ -126,13 +129,13 @@ VG_STATIC void render_water_surface( camera *cam ) 1.0f / (float)vg.window_x, 1.0f / (float)vg.window_y }); - shader_link_standard_ub( _shader_model_water.id, 2 ); + world_link_lighting_ub( world, _shader_model_water.id, 2 ); render_fb_bind_texture( gpipeline.fb_water_beneath, 0, 3 ); shader_model_water_uTexBack( 3 ); - shader_model_water_uTime( world.time ); + shader_model_water_uTime( world_global.time ); shader_model_water_uCamera( cam->transform[3] ); - shader_model_water_uSurfaceY( world.water.height ); + shader_model_water_uSurfaceY( world->water.height ); shader_model_water_uPv( cam->mtx.pv ); shader_model_water_uPvmPrev( cam->mtx_prev.pv ); @@ -145,11 +148,11 @@ VG_STATIC void render_water_surface( camera *cam ) glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); - mesh_bind( &world.mesh_no_collide ); + mesh_bind( &world->mesh_no_collide ); - for( int i=0; imaterial_count; i++ ) { - struct world_material *mat = &world.materials[i]; + struct world_material *mat = &world->materials[i]; if( mat->info.shader == k_shader_water ) { @@ -168,10 +171,10 @@ VG_STATIC void render_water_surface( camera *cam ) vg_tex2d_bind( &tex_water_surf, 1 ); shader_model_water_fast_uTexDudv( 1 ); - shader_model_water_fast_uTime( world.time ); + shader_model_water_fast_uTime( world_global.time ); shader_model_water_fast_uCamera( cam->transform[3] ); - shader_model_water_fast_uSurfaceY( world.water.height ); - shader_link_standard_ub( _shader_model_water_fast.id, 2 ); + shader_model_water_fast_uSurfaceY( world->water.height ); + world_link_lighting_ub( world, _shader_model_water_fast.id, 2 ); m4x3f full; m4x3_identity( full ); @@ -183,11 +186,11 @@ VG_STATIC void render_water_surface( camera *cam ) glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); - mesh_bind( &world.mesh_no_collide ); + mesh_bind( &world->mesh_no_collide ); - for( int i=0; imaterial_count; i++ ) { - struct world_material *mat = &world.materials[i]; + struct world_material *mat = &world->materials[i]; if( mat->info.shader == k_shader_water ) { -- 2.25.1