fixe
[carveJwlIkooP6JGAAIwe30JlM.git] / world.h
diff --git a/world.h b/world.h
index 672ceb71ca35fb85bb8a49b92b24649f1aa058ba..80bf3b6bafad33620b4738fb314440cfd581a6d3 100644 (file)
--- a/world.h
+++ b/world.h
@@ -18,6 +18,7 @@ typedef struct world_instance world_instance;
 #include "rigidbody.h"
 #include "bvh.h"
 #include "model.h"
+#include "entity.h"
 
 #include "shaders/scene_standard.h"
 #include "shaders/scene_standard_alphatest.h"
@@ -28,8 +29,6 @@ typedef struct world_instance world_instance;
 
 #include "shaders/model_sky.h"
 
-typedef struct teleport_gate teleport_gate;
-
 enum { k_max_ui_segments = 8 };
 
 enum { k_max_ui_elements = k_max_ui_segments };
@@ -97,6 +96,7 @@ struct world_instance
 
       float g_water_fog;
       float g_time;
+      float g_realtime;
       float g_shadow_length;
       float g_shadow_spread;
 
@@ -134,24 +134,32 @@ struct world_instance
    /*
     * Main world .mdl 
     */
-   mdl_context *meta;
-
-   /*
-    * Materials / textures 
-    */
+   mdl_context meta;
 
    GLuint *textures;
    u32 texture_count;
 
-   struct world_material
+   struct world_surface
    {
       mdl_material info;
       mdl_submesh sm_geo,
                   sm_no_collide;
    }
-   * materials;
-   u32 material_count;
+   * surfaces;
+   u32 surface_count;
+
+   mdl_array_ptr ent_spawn,
+                 ent_gate,
+                 ent_light,
+                 ent_route_node,
+                 ent_path_index,
+                 ent_checkpoint,
+                 ent_route,
+                 ent_water;
+
+   ent_gate *rendering_gate;
 
+#if 0
    /*
     * Named safe places to respawn
     */
@@ -170,56 +178,40 @@ struct world_instance
    struct world_audio_thing
    {
       v3f pos;
-      float volume;
+      float volume, range;
       u32 flags;
-
-      audio_player player;
       audio_clip temp_embedded_clip;
    }
    * audio_things;
    u32 audio_things_count;
 
-   /*
-    * Relays
-    */
-   struct logic_relay
+   struct soundscape
    {
-      v3f pos;
-
-      struct relay_target
-      {
-         u32 sub_id;
-         enum classtype classtype;
-      }
-      targets[4];
-      u32 target_count;
+      /* locking */
+      audio_channel *channels[4];
+      
+      /* accessable without locking */
+      v3f spawn_position;
+
+      u32 usage_count;
+      u32 max_instances;
+      u32 allow_transitions;
+      float transition_duration;
+      const char *label;
    }
-   * logic_relays;
-   u32 relay_count;
+   * soundscapes;
+   u32 soundscape_count;
 
    /*
-    * Box trigger entities
+    * Box volume entities
     */
-   struct trigger_zone
+   struct world_volume
    {
       m4x3f transform, inv_transform;
-
-      struct relay_target target;
-   }
-   * triggers;
-   u32 trigger_count;
-
-   /*
-    * Achievements
-    */
-   struct logic_achievement
-   {
-      v3f pos;
-      const char *achievement_id;
-      u32 achieved;
+      mdl_node *node;
    }
-   * logic_achievements;
-   u32 achievement_count;
+   * volumes;
+   u32 volume_count;
 
    /* 
     * Lights
@@ -230,9 +222,6 @@ struct world_instance
       struct classtype_world_light *inf;
       m4x3f inverse_world;
       v2f angle_sin_cos;
-
-      /* enabled.. etc? 
-       * TODO: we should order entities in the binary by their type */
    }
    * lights;
    u32 light_count;
@@ -241,6 +230,7 @@ struct world_instance
     * Routes (world_routes.h)
     * --------------------------------------------------------------------------
     */
+
    struct route_node
    {
       v3f co, right, up, h;
@@ -310,6 +300,7 @@ struct world_instance
    }
    *collectors;
    u32 collector_count;
+#endif
 
 
    /* logic 
@@ -323,7 +314,7 @@ struct world_instance
 
    /* spacial mappings */
    bh_tree *audio_bh,
-           *trigger_bh,
+           *volume_bh,
            *geo_bh;
 
    /* graphics */
@@ -341,20 +332,17 @@ VG_STATIC struct world_global
     * Allocated as system memory
     * --------------------------------------------------------------------------
     */
-   void *generic_heap,
-        *audio_heap;  /* sub buffer of the audio buffer */
+   void *generic_heap;
 
    /* rendering */
    glmesh skydome;
-   mdl_submesh dome_upper, dome_lower;
-
-   glmesh mesh_gate_surface;
+   glmesh mesh_gate;
+   mdl_submesh sm_gate_surface,
+               sm_gate_marker[4];
 
    double sky_time, sky_rate, sky_target_rate;
 
-   /* gates, TODO: active_gate should also know which instance */
-   u32 active_gate,
-       current_run_version;
+   u32 current_run_version;
    double time, rewind_from, rewind_to, last_use;
 
    /* water rendering */
@@ -367,39 +355,17 @@ VG_STATIC struct world_global
    /* split flap display */
    struct
    {
-      mdl_submesh *sm_module, *sm_card;
       glmesh mesh_base, mesh_display;
+      mdl_submesh sm_base;
+      u32 active_route_board;
 
       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 in_volume;
 
    int switching_to_new_world;
 
@@ -422,7 +388,7 @@ 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 );
+struct world_surface *ray_hit_surface( world_instance *world, ray_hit *hit );
 
 VG_STATIC 
 void ray_world_get_tri( world_instance *world, ray_hit *hit, v3f tri[3] );
@@ -438,6 +404,7 @@ int ray_world( world_instance *world, v3f pos, v3f dir, ray_hit *hit );
 #include "world_sfd.h"
 #include "world_render.h"
 #include "world_water.h"
+#include "world_volumes.h"
 #include "world_gen.h"
 #include "world_gate.h"
 
@@ -450,74 +417,11 @@ int ray_world( world_instance *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++ )
-   {
-      struct world_audio_thing *at = &world->audio_things[i];
-
-      if( audio_player_is_playing( &at->player ) )
-      {
-         u32 cflags = audio_player_get_flags( &at->player );
-         audio_player_set_flags( &at->player, cflags | AUDIO_FLAG_KILL );
-      }
-   }
-   audio_unlock();
-
-   return 0;
-}
-
-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 );
-      return 0;
-   }
-   else
-   {
-      vg_info( "Switching world...\n" );
-      strcpy( world.world_name, argv[0] );
-      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,
-      .data_type = k_var_dtype_i32,
-      .opt_i32 = { .min=0, .max=1, .clamp=1 },
-      .persistent = 0
-   });
-#endif
-
-       vg_function_push( (struct vg_cmd)
-   {
-               .name = "world_stop_sound",
-               .function = world_stop_sound
-       });
-
-       vg_function_push( (struct vg_cmd)
-   {
-               .name = "world",
-               .function = world_change_world
-       });
-
    world_global.sky_rate = 1.0;
    world_global.sky_target_rate = 1.0;
 
@@ -533,14 +437,16 @@ VG_STATIC void world_init(void)
    vg_info( "Loading world resources\n" );
    
    vg_linear_clear( vg_mem.scratch );
-   mdl_context *msky = mdl_load_full( vg_mem.scratch, "models/rs_skydome.mdl" );
 
-   mdl_node *nupper = mdl_node_from_name( msky, "dome_complete" );
-   world_global.dome_upper = *mdl_node_submesh( msky, nupper, 0 );
+   mdl_context msky;
+   mdl_open( &msky, "models/rs_skydome.mdl", vg_mem.scratch );
+   mdl_load_metadata_block( &msky, vg_mem.scratch );
+   mdl_load_mesh_block( &msky, vg_mem.scratch );
+   mdl_close( &msky );
 
    vg_acquire_thread_sync();
    {
-      mdl_unpack_glmesh( msky, &world_global.skydome );
+      mdl_unpack_glmesh( &msky, &world_global.skydome );
    }
    vg_release_thread_sync();
 
@@ -560,81 +466,6 @@ VG_STATIC void world_init(void)
                                                            VG_MEMORY_SYSTEM );
 }
 
-VG_STATIC void world_audio_init(void)
-{
-   u32 size = vg_linear_remaining( vg_audio.audio_pool ) 
-               - sizeof(vg_linear_allocator);
-
-   world_global.audio_heap = vg_create_linear_allocator( vg_audio.audio_pool, 
-                                                         size, 
-                                                         VG_MEMORY_SYSTEM );
-}
-
-VG_STATIC void world_trigger_achievement( world_instance *world, u32 uid )
-{
-   struct logic_achievement *ach = &world->logic_achievements[ uid ];
-
-   if( ach->achieved )
-      return;
-
-   steam_set_achievement( ach->achievement_id );
-   steam_store_achievements();
-
-   ach->achieved = 1;
-}
-
-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 ];
-
-   for( int i=0; i<relay->target_count; i++ )
-   {
-      world_run_relay( world, &relay->targets[i] );
-   }
-}
-
-VG_STATIC void world_trigger_audio( world_instance *world, u32 uid )
-{
-   struct world_audio_thing *wat = &world->audio_things[ uid ];
-
-   audio_lock();
-   audio_player_playclip( &wat->player, 
-                          &wat->temp_embedded_clip );
-   audio_unlock();
-}
-
-VG_STATIC void world_run_relay( world_instance *world,
-                                struct relay_target *rt )
-{
-   struct entity_instruction
-   {
-      enum classtype classtype;
-      void (*p_trigger)( world_instance *world, u32 uid );
-   }
-   entity_instructions[] =
-   {
-      { k_classtype_logic_achievement, world_trigger_achievement },
-      { k_classtype_logic_relay, world_trigger_relay },
-      { k_classtype_audio, world_trigger_audio }
-   };
-
-   for( int i=0; i<vg_list_size(entity_instructions); i++ )
-   {
-      struct entity_instruction *instr = &entity_instructions[i];
-
-      if( instr->classtype == rt->classtype )
-      {
-         instr->p_trigger( world, rt->sub_id );
-         return;
-      }
-   }
-
-   vg_error( "Don't know how to trigger classtype %d\n", rt->classtype );
-}
-
 VG_STATIC void world_update( world_instance *world, v3f pos )
 {
    /* TEMP!!!!!! */
@@ -645,6 +476,7 @@ VG_STATIC void world_update( world_instance *world, v3f pos )
    struct ub_world_lighting *state = &world->ub_lighting;
 
    state->g_time = g_time;
+   state->g_realtime = vg.time;
    state->g_debug_indices = k_debug_light_indices;
    state->g_light_preview = k_light_preview;
    state->g_debug_complexity = k_debug_light_complexity;
@@ -669,88 +501,105 @@ VG_STATIC void world_update( world_instance *world, v3f pos )
                     sizeof(struct ub_world_lighting), &world->ub_lighting );
    /* TEMP!!!!!! */
 
-
-#if 0
-   if( world.switching_to_new_world )
-   {
-      int all_stopped = 1;
-
-      audio_lock();
-      for( int i=0; i<world.audio_things_count; i++ )
-      {
-         struct world_audio_thing *at = &world.audio_things[i];
-
-         if( audio_player_is_playing( &at->player ) )
-         {
-            all_stopped = 0;
-            break;
-         }
-      }
-      audio_unlock();
-
-      if( all_stopped )
-      {
-         world.switching_to_new_world = 0;
-         world_unload();
-         vg_loader_start( world_load );
-         return;
-      }
-   }
-
-#endif
    world_global.sky_time += world_global.sky_rate * vg.time_delta;
    world_global.sky_rate = vg_lerp( world_global.sky_rate, 
                                     world_global.sky_target_rate, 
                                     vg.time_delta * 5.0 );
 
    world_routes_update( world );
-#if 0
-   world_routes_debug();
-#endif
+   world_routes_debug( world );
+
+   /* ---- SFD ------------ */
    
-   if( world->route_count > 0 )
-   {
-      int closest = 0;
+   if( mdl_arrcount( &world->ent_route ) ){
+      u32 closest = 0;
       float min_dist = INFINITY;
 
-      for( int i=0; i<world->route_count; i++ )
-      {
-         float d = v3_dist2( world->routes[i].scoreboard_transform[3], pos );
+      for( u32 i=0; i<mdl_arrcount( &world->ent_route ); i++ ){
+         ent_route *route = mdl_arritm( &world->ent_route, i );
+         float dist = v3_dist2( route->board_transform[3], pos );
 
-         if( d < min_dist )
-         {
-            min_dist = d;
+         if( dist < min_dist ){
+            min_dist = dist;
             closest = i;
          }
       }
 
-      if( (world_global.active_route_board != closest) 
+      if( (world_global.sfd.active_route_board != closest) 
           || network_scores_updated )
       {
          network_scores_updated = 0;
-         world_global.active_route_board = closest;
+         world_global.sfd.active_route_board = closest;
 
-         struct route *route = &world->routes[closest];
+         ent_route *route = mdl_arritm( &world->ent_route, closest );
+         u32 id = route->official_track_id;
 
-         u32 id = route->track_id;
-
-         if( id != 0xffffffff )
-         {
+         if( id != 0xffffffff ){
             struct netmsg_board *local_board = 
                &scoreboard_client_data.boards[id];
 
-            for( int i=0; i<13; i++ )
-            {
+            for( int i=0; i<13; i++ ){
                sfd_encode( i, &local_board->data[27*i] );
             }
+         }else{
+            sfd_encode( 0, mdl_pstr( &world->meta, route->pstr_name ) );
+            sfd_encode( 1, "No data" );
          }
       }
    }
+   sfd_update();
+   
+#if 0
+   /* TODO: Bvh */
+
+   static float random_accum = 0.0f;
+   random_accum += vg.time_delta;
 
-   int in_trigger = 0;
-   for( int i=0; i<world->trigger_count; i++ )
+   u32 random_ticks = 0;
+
+   while( random_accum > 0.1f ){
+      random_accum -= 0.1f;
+      random_ticks ++;
+   }
+
+   float radius = 25.0f;
+   boxf volume_proximity;
+   v3_add( pos, (v3f){ radius, radius, radius }, volume_proximity[1] );
+   v3_sub( pos, (v3f){ radius, radius, radius }, volume_proximity[0] );
+
+   bh_iter it;
+   bh_iter_init( 0, &it );
+   int idx;
+
+   int in_volume = 0;
+
+   while( bh_next( world->volume_bh, &it, volume_proximity, &idx ) )
    {
-      struct trigger_zone *zone = &world->triggers[i];
+      struct world_volume *zone = &world->volumes[idx];
+
+      if( zone->node->classtype == k_classtype_volume_audio )
+      {
+         vg_line_boxf_transformed( zone->transform, (boxf){{-1.0f,-1.0f,-1.0f},
+                                                           { 1.0f, 1.0f, 1.0f}}, 
+                                                           0xff00c0ff );
+#if 0
+         for( int j=0; j<random_ticks; j++ )
+         {
+            logic_packet packet;
+            packet.location = zone->target_logic_brick;
+            packet.function = 0;
+
+            packet.type = k_mdl_128bit_datatype_vec3;
+            packet.data._v4f[0] = vg_randf()*2.0f-1.0f;
+            packet.data._v4f[1] = vg_randf()*2.0f-1.0f;
+            packet.data._v4f[2] = vg_randf()*2.0f-1.0f;
+            m4x3_mulv( zone->transform, packet.data._v4f, packet.data._v4f );
+
+            logic_bricks_send_packet( world, &packet );
+         }
+#endif
+         continue;
+      }
 
       v3f local;
       m4x3_mulv( zone->inv_transform, pos, local );
@@ -759,23 +608,39 @@ VG_STATIC void world_update( world_instance *world, v3f pos )
           (fabsf(local[1]) <= 1.0f) &&
           (fabsf(local[2]) <= 1.0f) )
       {
-         in_trigger = 1;
+         in_volume = 1;
 
-         if( !world_global.in_trigger )
+         if( !world_global.in_volume )
          {
-            world_run_relay( world, &zone->target );
+#if 0
+            logic_packet packet;
+            packet.location = zone->target_logic_brick;
+            packet.function = 0;
+
+            packet.type = k_mdl_128bit_datatype_vec3;
+            v3_copy( pos, packet.data._v4f );
+
+            logic_bricks_send_packet( world, &packet );
+#endif
          }
+         
+         vg_line_boxf_transformed( zone->transform, (boxf){{-1.0f,-1.0f,-1.0f},
+                                                           { 1.0f, 1.0f, 1.0f}}, 
+                                                           0xff00ff00 );
+      }
+      else
+      {
+         vg_line_boxf_transformed( zone->transform, (boxf){{-1.0f,-1.0f,-1.0f},
+                                                           { 1.0f, 1.0f, 1.0f}}, 
+                                                           0xff0000ff );
       }
-
-      vg_line_boxf_transformed( zone->transform, (boxf){{-1.0f,-1.0f,-1.0f},
-                                                        { 1.0f, 1.0f, 1.0f}}, 
-                                                        0xff00ff00 );
    }
+#endif
 
+#if 0
    if( k_debug_light_indices )
    {
-      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 classtype_world_light *inf = light->inf;
 
@@ -792,8 +657,31 @@ VG_STATIC void world_update( world_instance *world, v3f pos )
       }
    }
 
-   world_global.in_trigger = in_trigger;
-   sfd_update();
+   world_global.in_volume = in_volume;
+#endif
+
+#if 0
+
+   /* process soundscape transactions */
+   audio_lock();
+   for( int i=0; i<world->soundscape_count; i++ )
+   {
+      struct soundscape *s = &world->soundscapes[i];
+      s->usage_count = 0;
+
+      for( int j=0; j<s->max_instances; j++ )
+      {
+         if( s->channels[j] )
+         {
+            if( audio_channel_finished(s->channels[j]) )
+               s->channels[j] = audio_relinquish_channel( s->channels[j] );
+            else
+               s->usage_count ++;
+         }
+      }
+   }
+   audio_unlock();
+#endif
 }
 
 /* 
@@ -844,16 +732,14 @@ VG_STATIC int spherecast_world( world_instance *world,
    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 ];
       v3f tri[3];
 
       boxf box;
       box_init_inf( box );
 
-      for( int j=0; j<3; j++ )
-      {
+      for( int j=0; j<3; j++ ){
          v3_copy( world->scene_geo->arrvertices[ptri[j]].co, tri[j] );
          box_addpt( box, tri[j] );
       }
@@ -866,10 +752,8 @@ VG_STATIC int spherecast_world( world_instance *world,
       
       float t;
       v3f n1;
-      if( spherecast_triangle( tri, pa, dir, r, &t, n1 ) )
-      {
-         if( t < min_t )
-         {
+      if( spherecast_triangle( tri, pa, dir, r, &t, n1 ) ){
+         if( t < min_t ){
             min_t = t;
             hit = idx;
             v3_copy( n1, n );
@@ -882,34 +766,32 @@ VG_STATIC int spherecast_world( world_instance *world,
 }
 
 VG_STATIC 
-struct world_material *world_tri_index_material( world_instance *world, 
+struct world_surface *world_tri_index_surface( world_instance *world, 
                                                  u32 index )
 {
-   for( int i=1; i<world->material_count; i++ )
-   {
-      struct world_material *mat = &world->materials[i];
+   for( int i=1; i<world->surface_count; i++ ){
+      struct world_surface *surf = &world->surfaces[i];
 
-      if( (index >= mat->sm_geo.vertex_start) &&
-          (index  < mat->sm_geo.vertex_start+mat->sm_geo.vertex_count ) )
+      if( (index >= surf->sm_geo.vertex_start) &&
+          (index  < surf->sm_geo.vertex_start+surf->sm_geo.vertex_count ) )
       {
-         return mat;
+         return surf;
       }
    }
 
-   /* error material */
-   return &world->materials[0];
+   return &world->surfaces[0];
 }
 
-VG_STATIC struct world_material *world_contact_material( world_instance *world,
+VG_STATIC struct world_surface *world_contact_surface( world_instance *world,
                                                          rb_ct *ct )
 {
-   return world_tri_index_material( world, ct->element_id );
+   return world_tri_index_surface( world, ct->element_id );
 }
 
-VG_STATIC struct world_material *ray_hit_material( world_instance *world,
-                                                   ray_hit *hit )
+VG_STATIC struct world_surface *ray_hit_surface( world_instance *world,
+                                                 ray_hit *hit )
 {
-   return world_tri_index_material( world, hit->tri[0] );
+   return world_tri_index_surface( world, hit->tri[0] );
 }
 
 #endif /* WORLD_H */