isolate world code
authorhgn <hgodden00@gmail.com>
Thu, 23 Feb 2023 20:12:47 +0000 (20:12 +0000)
committerhgn <hgodden00@gmail.com>
Thu, 23 Feb 2023 20:12:47 +0000 (20:12 +0000)
17 files changed:
audio.h
blender_export.py
maps_src/mp_home.mdl [new file with mode: 0644]
player.c
player_ragdoll.h
player_skate.c
player_walk.c
render.h
scene.h
skaterift.c
world.h
world_gate.h
world_gen.h
world_render.h
world_routes.h
world_sfd.h
world_water.h

diff --git a/audio.h b/audio.h
index 2d0417fd3293a9b8902f282ab4e1fd6ec69b5ca8..5caa759e01fdc7b00182f025eb36d03950520e5d 100644 (file)
--- 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; i<sample_count; i++ )
    {
       v3f dir;
@@ -273,7 +275,7 @@ VG_STATIC void audio_sample_occlusion( v3f origin )
       ray_hit contact;
       contact.dist = 15.0f;
       
-      if( ray_world( origin, dir, &contact ) )
+      if( ray_world( world, origin, dir, &contact ) )
       {
          d += contact.dist;
 
@@ -332,10 +334,11 @@ VG_STATIC enum audio_sprite_type audio_sample_sprite_random( v3f origin,
    ray_hit contact;
    contact.dist = vg_minf( 16.0f, pos[1] );
 
+   world_instance *world = get_active_world();
    
-   if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &contact ) )
+   if( ray_world( world, pos, (v3f){0.0f,-1.0f,0.0f}, &contact ) )
    {
-      struct world_material *mat = ray_hit_material( &contact );
+      struct world_material *mat = ray_hit_material( world, &contact );
 
       if( mat->info.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;
index 06d90a4b11d4cb69654c547958f28e6d134a695d..d6da9c2864f358c8be0ee5f51dc7473ac9d4c114 100644 (file)
@@ -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 (file)
index 0000000..761e527
Binary files /dev/null and b/maps_src/mp_home.mdl differ
index 4c8f76a755bc2e2f9f31d374085a7f8b199dafc9..b705d7fe75d92929918d679f7162c819479b7fdd 100644 (file)
--- 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,
index f1f62218d5de6adf9429df26e18bf7b701eb151d..e4a368ebfad8ed50bc60350057aa359eba502b9d 100644 (file)
@@ -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; i<rd->part_count; i ++ )
-      rb_collide( &rd->parts[i].rb, &world.rb_geo );
+      rb_collide( &rd->parts[i].rb, &world->rb_geo );
 
    /* 
     * COLLISION DETECTION
index aae8280f5b30a006fe00172717bf01a7e8d8dce6..098ce8ad42d1fe26e1bc138e3b193b5318f53278 100644 (file)
@@ -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; i<len; i++ )
    {
@@ -70,6 +72,8 @@ VG_STATIC int skate_grind_scansq( player_instance *player,
                                   v3f pos, v3f dir, float r,
                                   struct grind_info *inf )
 {
+   world_instance *world = get_active_world();
+
    v4f plane;
    v3_copy( dir, plane );
    v3_normalize( plane );
@@ -100,17 +104,17 @@ VG_STATIC int skate_grind_scansq( player_instance *player,
    v3_cross( plane, player->basis[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 );
index c86c9dba385d28ac8f3da4b0a22ad0013659c59b..00ee7fb4807cf27d197331f941c4018ce4278c57 100644 (file)
@@ -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 );
index 7b5b473739f7ec6c6b01083bd3448f6e73d43697..91fe39ea0516585ee37cafecea6ba710e53aca6a 100644 (file)
--- 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"
 #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 902aedbff9924a8e4f2b7301d3e85bf6014dff4b..7a9460b4dbfe1a7f463b401f61718dc0c3eea5b0 100644 (file)
--- 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;
index 4c531a4736f66dee33740b3cb13905db8e9777c9..9e162b2c322af6695a7857e08275c1c726910744 100644 (file)
 #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; i<world.spawn_count; i++ )
+      for( int i=0; i<world->spawn_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; i<world.spawn_count; i++ )
+      for( int i=0; i<world->spawn_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 4f2c5c3a383df91819f794380c64feaf8fa0ff84..b80db3776879f2b1dfb760b64ef432c2010ce6f1 100644 (file)
--- 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; i<world.audio_things_count; i++ )
+   for( int i=0; i<world->audio_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; i<relay->target_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; i<world.route_count; i++ )
+      for( int i=0; i<world->route_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; i<world.trigger_count; i++ )
+   for( int i=0; i<world->trigger_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; i<world.light_count; i++ )
+   for( int i=0; i<world->light_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; i<world.material_count; i++ )
+   for( int i=1; i<world->material_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 */
index d92537eb1566fada932ddb4c4dc121828f776eaf..1e8c26247a718ef270e27dc71951883ab871efd3 100644 (file)
@@ -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; i<world.gate_count; i++ )
+   for( int i=0; i<world->gate_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 ) )
index f5e7599c7fe260f17439259f3ea1e0e49ac16e85..3290def58a7f7e2010fc602aa74640242cf0131a 100644 (file)
@@ -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; i<vg_list_size(verts); i++ )
    {
@@ -90,7 +89,8 @@ VG_STATIC void world_add_blob( scene *pscene, ray_hit *hit )
 }
 
 /* Sprinkle foliage models over the map on terrain material */
-VG_STATIC void world_apply_procedural_foliage( struct world_material *mat )
+VG_STATIC void world_apply_procedural_foliage( world_instance *world,
+                                               struct world_material *mat )
 {
    if( vg.quality_profile == k_quality_profile_low )
       return;
@@ -103,7 +103,7 @@ VG_STATIC void world_apply_procedural_foliage( struct world_material *mat )
       mdl_load_full( vg_mem.scratch, "models/rs_foliage.mdl");
 
    v3f volume;
-   v3_sub( world.scene_geo->bbx[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; i<vg_list_size(entity_counts); i++ )
       entity_counts[i].count = 0;
 
-   for( int i=0; i<world.meta->info.node_count; i++ )
+   for( int i=0; i<world->meta->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; j<vg_list_size(entity_counts); j ++ )
       {
@@ -213,39 +213,40 @@ VG_STATIC void world_ents_allocate(void)
       struct countable *counter = &entity_counts[i];
       
       u32 bufsize = counter->item_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; i<world.meta->info.node_count; i++ )
+   for( int i=0; i<world->meta->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; j<vg_list_size(entity_instructions); j++ )
       {
@@ -369,14 +369,15 @@ VG_STATIC void world_entities_process(void)
 
          if( pnode->classtype == 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; i<sc->vertex_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; j<world.light_count; j ++ )
+      for( int j=0; j<world->light_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; i<world.material_count; i++ )
+   for( int i=0; i<world->material_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; i<world.material_count; i++ )
+   for( int i=0; i<world->material_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; i<world.audio_things_count; i++ )
+   for( int i=0; i<world->audio_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; i<world.light_count; i++ )
+      /* add scene lights */
+      for( int i=0; i<world->light_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; i<world.texture_count; i++ )
+      for( int i=1; i<world->texture_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; i<world.material_count; i++ )
-      world.materials[i].info = world.meta->material_buffer[i];
+   for( int i=1; i<world->material_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; i<vg_list_size(world.ui_bars); i++ )
+   mesh_free( &world->mesh_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; i<vg_list_size(world_global.ui_bars); i++ )
    {
-      struct route_ui_bar *uib = &world.ui_bars[i];
+      struct route_ui_bar *uib = &world_global.ui_bars[i];
       uib->segment_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 */
index e738d372dd59d019011595e32f80829f85ac7146..fd0b39f214a34e9785de222f5c19c6e6b79d052b 100644 (file)
@@ -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; i<world.material_count; i++ )
+   for( int i=0; i<world->material_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; i<world.gate_count; i++ )
+   for( int i=0; i<world->gate_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; i<world.route_count; i++ )
+   for( int i=0; i<world->route_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);
index 35f38f0f04a094394f80ab15a6d6f5563abafa42..121f447fd5113d7536e55fdccec2530cabb473a7 100644 (file)
@@ -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; i<si; i++ )
    {
-      struct route_node *inode = &world.nodes[stack[i]];
+      struct route_node *inode = &world->nodes[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; i<world.route_count; i++ )
+   for( u32 i=0; i<world->route_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; i<world.route_count; i++ )
+   for( u32 i=0; i<world->route_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; i<r->route_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; i<world.node_count; i++ )
+   for( int i=0; i<world->node_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; i<world.route_count; i++ )
+   for( int i=0; i<world->route_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; i<world.node_count; i++ )
+   for( int i=0; i<world->node_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; i<world.route_count; i++ )
-      world_routes_create_mesh( i );
+   for( u32 i=0; i<world->route_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; i<world.meta->info.node_count; i++ )
+   for( int i=0; i<world->meta->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; i<mdl->info.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; i<world.route_count; i++ )
+   for( int i=0; i<world->route_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; sj<si; sj++ )
       {
-         struct route_node *rn = &world.nodes[ stack[sj] ];
+         struct route_node *rn = &world->nodes[ 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; i<vg_list_size(world.ui_bars); i++ )
+      for( int i=0; i<vg_list_size(world_global.ui_bars); i++ )
       {
          /* OpenGL strips */
-         struct route_ui_bar *pui = &world.ui_bars[i];
+         struct route_ui_bar *pui = &world_global.ui_bars[i];
 
          glGenVertexArrays( 1, &pui->vao );
          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; i<world.route_count; i++ )
+   for( int i=0; i<world->route_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; i<world.route_count; i++ )
+   for( int i=0; i<world->route_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; i<world.route_count; i++ )
+   for( int i=0; i<world->route_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;
    }
 
index 3fbbe949482a775ebba620a53b71e25b36f86c50..1b59e5a8c509cb477968473298b327b9d19def2d 100644 (file)
@@ -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; i<world.sfd.w; i++ )
+   for( int i=0; i<world_global.sfd.w; i++ )
    {
-      u32 idx = (world.sfd.w*row_h + i) * 2;
+      u32 idx = (world_global.sfd.w*row_h + i) * 2;
 
       if( end )
       {
-         world.sfd.buffer[idx] = 0.0f;
+         world_global.sfd.buffer[idx] = 0.0f;
       }
       else
       {
          if( !str[i] )
             end = 1;
 
-         world.sfd.buffer[idx] = sfd_encode_glyph( str[i] );
+         world_global.sfd.buffer[idx] = sfd_encode_glyph( str[i] );
       }
    }
 }
@@ -84,10 +84,10 @@ VG_STATIC void sfd_init( u32 w, u32 h )
 
 VG_STATIC void sfd_update(void)
 {
-   for( int i=0; i<world.sfd.w*world.sfd.h; i++ )
+   for( int i=0; i<world_global.sfd.w*world_global.sfd.h; i++ )
    {
-      float *target = &world.sfd.buffer[i*2+0],
-            *cur =    &world.sfd.buffer[i*2+1];
+      float *target = &world_global.sfd.buffer[i*2+0],
+            *cur =    &world_global.sfd.buffer[i*2+1];
       
       float const rate = vg.time_delta * 15.2313131414f;
       float d1 = *target-*cur;
@@ -156,7 +156,7 @@ VG_STATIC int world_sfd_test( int argc, const char *argv[] )
 {
    if( argc == 2 )
    {
-      int row = vg_min( vg_max(atoi(argv[0]),0), world.sfd.h);
+      int row = vg_min( vg_max(atoi(argv[0]),0), world_global.sfd.h);
       sfd_encode( row, argv[1] );
    }
 
@@ -211,8 +211,8 @@ VG_STATIC void world_sfd_init(void)
 
    vg_acquire_thread_sync();
    {
-      scene_upload( sc, &world.sfd.mesh_display );
-      mdl_unpack_submesh( mboard, &world.sfd.mesh_base, backer );
+      scene_upload( sc, &world_global.sfd.mesh_display );
+      mdl_unpack_submesh( mboard, &world_global.sfd.mesh_base, backer );
 
       vg_tex2d_init( (vg_tex2d *[]){ &tex_scoretext }, 1 );
    }
@@ -221,12 +221,13 @@ VG_STATIC void world_sfd_init(void)
    int w = 27,
        h = 13;
 
-   world.sfd.w = w;
-   world.sfd.h = h;
-   world.sfd.buffer = vg_linear_alloc( vg_mem.rtmemory, 2*w*h*sizeof(float) );
+   world_global.sfd.w = w;
+   world_global.sfd.h = h;
+   world_global.sfd.buffer = 
+                     vg_linear_alloc( vg_mem.rtmemory, 2*w*h*sizeof(float) );
 
    for( int i=0; i<w*h*2; i++ )
-      world.sfd.buffer[i] = 0.0f;
+      world_global.sfd.buffer[i] = 0.0f;
 }
 
 #endif /* SFD_H */
index d2447b513e22be1e6cd1503084b989d4f7205ff0..382a775b892a89363f41c9dc562975d402e4fb51 100644 (file)
@@ -28,18 +28,21 @@ VG_STATIC void world_water_init(void)
    vg_success( "done\n" );
 }
 
-VG_STATIC void water_set_surface( float height )
+VG_STATIC void water_set_surface( world_instance *world, float height )
 {
-   world.water.height = height;
-   v4_copy( (v4f){ 0.0f, 1.0f, 0.0f, height }, world.water.plane );
+   world->water.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; i<world.material_count; i++ )
+      for( int i=0; i<world->material_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; i<world.material_count; i++ )
+      for( int i=0; i<world->material_count; i++ )
       {
-         struct world_material *mat = &world.materials[i];
+         struct world_material *mat = &world->materials[i];
 
          if( mat->info.shader == k_shader_water )
          {