switch to entity list
authorhgn <hgodden00@gmail.com>
Wed, 19 Jul 2023 20:20:01 +0000 (21:20 +0100)
committerhgn <hgodden00@gmail.com>
Wed, 19 Jul 2023 20:20:01 +0000 (21:20 +0100)
17 files changed:
blender_export.py
ent_challenge.c [new file with mode: 0644]
entity.c
entity.h
maps_src/mp_spawn/main.mdl
player.c
rigidbody.h
scene.h
skaterift.c
world.h
world_entity.c
world_entity.h
world_gen.c
world_load.c
world_render.c
world_volumes.c
world_volumes.h

index 3f1b04f1dd00e7a91ee3afa2651ac069e5151994..820c49ac05e6f721af4ca38ab7f02e200bb5e616 100644 (file)
@@ -450,7 +450,11 @@ class ent_challenge(Structure):#{
    _fields_ = [("transform",mdl_transform),
                ("submesh_start",c_uint32), ("submesh_count",c_uint32),
                ("id_next",c_uint32),
-               ("filter",c_uint32)]
+               ("filter",c_uint32),
+               ("time_limit",c_float)]
+
+   sr_functions = { 0: 'trigger',
+                    1: 'start_challenge' }
 #}
 
 def obj_ent_type( obj ):
@@ -1723,6 +1727,7 @@ def sr_compile( collection ):
 
             if obj_data.target:#{
                volume.target = sr_entity_id( obj_data.target )
+               volume._anon.trigger.event = obj_data.event
             #}
 
             sr_ent_push(volume)
@@ -1784,6 +1789,8 @@ def sr_compile( collection ):
             challenge = ent_challenge()
             obj_data = obj.SR_data.ent_challenge[0]
             challenge.id_next = sr_entity_id( obj_data.proxima )
+            challenge.filter = 0
+            challenge.time_limit = obj_data.time_limit
 
             compile_obj_transform( obj, challenge.transform )
             challenge.submesh_start, challenge.submesh_count, _ = \
@@ -2730,8 +2737,7 @@ class SR_OBJECT_ENT_ROUTE(bpy.types.PropertyGroup):
    #}
 #}
 
-class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):
-#{
+class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):#{
    subtype: bpy.props.EnumProperty(
       name="Subtype",
       items=[('0','Trigger',''),
@@ -2741,14 +2747,33 @@ class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):
    target: bpy.props.PointerProperty( \
            type=bpy.types.Object, name="Target", \
            poll=lambda self,obj: sr_filter_ent_type(obj,\
-                                    ['ent_audio','ent_skateshop','ent_ccmd']))
+                                    ['ent_audio','ent_skateshop','ent_ccmd',\
+                                     'ent_challenge']))
+
+   event: bpy.props.IntProperty( name="Event/Method" )
 
    @staticmethod
-   def sr_inspector( layout, data ):
-   #{
-      data = data[0]
-      layout.prop( data, 'subtype' )
-      layout.prop( data, 'target' )
+   def sr_inspector( layout, data ):#{
+      layout.prop( data[0], 'subtype' )
+      layout.prop( data[0], 'target' )
+
+      row = layout.row()
+      row.prop( data[0], 'event' )
+
+      if data[0].target:#{
+         tipo = data[0].target.SR_data.ent_type
+         cls = globals()[ tipo ]
+
+         table = getattr( cls, 'sr_functions', None )
+         if table:#{
+            if data[0].event in table:#{
+               row.label( text=table[data[0].event] )
+            #}
+            else:#{
+               row.label( text="undefined function" )
+            #}
+         #}
+      #}
    #}
 #}
 
@@ -3038,6 +3063,8 @@ class SR_OBJECT_ENT_CHALLENGE(bpy.types.PropertyGroup):#{
            type=bpy.types.Object, name="Target", \
            poll=lambda self,obj: sr_filter_ent_type(obj,\
                                     ['ent_audio','ent_ccmd']))
+   event: bpy.props.IntProperty( name="Event/Method" )
+   time_limit: bpy.props.FloatProperty( name="Time Limit", default=1.0 )
 #}
 
 class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup):
@@ -3703,14 +3730,14 @@ def cv_ent_volume( obj ):
       cv_draw_ucube( obj.matrix_world, (0,1,0) )
 
       if data.target:#{
-         cv_draw_line( obj.location, data.target.location, (0,1,0) )
+         cv_draw_arrow( obj.location, data.target.location, (0,1,0) )
       #}
    #}
    elif data.subtype == '1':#{
       cv_draw_ucube( obj.matrix_world, (1,1,0) )
 
       if data.target:#{
-         cv_draw_line( obj.location, data.target.location, (1,1,0) )
+         cv_draw_arrow( obj.location, data.target.location, (1,1,0) )
       #}
    #}
 #}
@@ -3989,6 +4016,12 @@ def cv_draw():
          elif ent_type == 'ent_volume':#{
             cv_ent_volume( obj )
          #}
+         elif ent_type == 'ent_challenge':#{
+            data = obj.SR_data.ent_challenge[0]
+            if data.proxima:#{
+               cv_draw_arrow( obj.location, data.proxima.location, (0,0.2,1.0) )
+            #}
+         #}
          elif ent_type == 'ent_audio':#{
             if obj.SR_data.ent_audio[0].flag_3d:
                cv_draw_sphere( obj.location, obj.scale[0], (1,1,0) )
diff --git a/ent_challenge.c b/ent_challenge.c
new file mode 100644 (file)
index 0000000..5f22eaa
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef ENT_CHALLENGE_C
+#define ENT_CHALLENGE_C
+
+#include "world.h"
+#include "world_load.h"
+#include "entity.h"
+
+VG_STATIC void ent_challenge_pass( world_instance *world, 
+                                   ent_challenge *challenge ){
+   if( challenge->id_next ){
+      world->challenge_timer += challenge->filter;
+
+      u32 index = mdl_entity_id_id( challenge->id_next );
+      ent_challenge *next = mdl_arritm( &world->ent_challenge, index );
+      world->challenge_target = next;
+
+      vg_info( "pass challenge point\n" );
+   }
+   else {
+      vg_success( "NYU Film school graduate SUCKAH\n" );
+      world->challenge_target = NULL;
+      world->challenge_timer = 0.0f;
+   }
+}
+
+VG_STATIC void ent_challenge_call( world_instance *world, ent_call *call ){
+   u32 index = mdl_entity_id_id( call->id );
+   ent_challenge *challenge = mdl_arritm( &world->ent_challenge, index );
+
+   if( call->function == 0 ){
+      if( world->challenge_target ){
+         if( world->challenge_target == challenge ){
+            ent_challenge_pass( world, challenge );
+         }
+         else {
+            vg_error( "womp womp\n" );
+            world->challenge_target = NULL;
+            world->challenge_timer = 0.0f;
+         }
+      }
+   }
+   else if( call->function == 1 ){
+      vg_info( "begin the challenge\n" );
+      world->challenge_timer = 0.0f;
+      ent_challenge_pass( world, challenge );
+   }
+   else {
+      vg_print_backtrace();
+      vg_error( "Unhandled function id: %u\n", call->function );
+   }
+}
+
+#endif /* ENT_CHALLENGE_C */
index f5e8004510d104c3eb9799b572a6e9c168cef7d6..cfc710618e60af5a26d6d1064c95ced82b4631e4 100644 (file)
--- a/entity.c
+++ b/entity.c
@@ -6,20 +6,34 @@
 #include "world_entity.h"
 
 #include "ent_skateshop.c"
+#include "ent_challenge.c"
 
-VG_STATIC void entity_call( world_instance *world, ent_call *call )
-{
+typedef void (*fn_entity_call_handler)( world_instance *, ent_call *);
+
+VG_STATIC void entity_call( world_instance *world, ent_call *call ){
    u32 type = mdl_entity_id_type( call->id );
 
-   if( type == k_ent_volume ){
-      ent_volume_call( world, call );
-   } else if( type == k_ent_audio ){
-      ent_audio_call( world, call );
-   } else if( type == k_ent_skateshop ){
-      ent_skateshop_call( world, call );
-   } else if( type == k_ent_ccmd ){
-      ent_ccmd_call( world, call );
+   fn_entity_call_handler table[] = {
+      [k_ent_volume]    = ent_volume_call,
+      [k_ent_audio]     = ent_audio_call,
+      [k_ent_skateshop] = ent_skateshop_call,
+      [k_ent_challenge] = ent_challenge_call,
+      [k_ent_ccmd]      = ent_ccmd_call
+   };
+
+   if( type > vg_list_size(table) ){
+      vg_error( "call to entity type: %u is out of range\n", type );
+      return;
+   }
+
+   fn_entity_call_handler fn = table[ type ];
+
+   if( !fn ){
+      vg_error( "call to entity type: %u is undefined\n", type );
+      return;
    }
+
+   fn( world, call );
 }
 
 #endif /* ENTITY_C */
index 487c4d390042104ca7fa133922fd7419c9840ee7..05294f3b58809d3c800f7af03623d849370487c8 100644 (file)
--- a/entity.h
+++ b/entity.h
@@ -47,7 +47,8 @@ enum entity_alias{
    k_ent_menuitem    = 15,
    k_ent_worldinfo   = 16,
    k_ent_ccmd        = 17,
-   k_ent_challenge   = 18
+   k_ent_challenge   = 18,
+   k_ent_relay       = 19
 };
 
 static u32 mdl_entity_id_type( u32 entity_id ){
@@ -171,7 +172,7 @@ struct ent_audio_clip{
    union{
       mdl_file file;
       audio_clip clip;
-   };
+   }_;
 
    float probability;
 };
@@ -184,18 +185,17 @@ struct volume_trigger{
    u32 event, blank;
 };
 
-enum volume_subtype{
-   k_volume_subtype_trigger,
-   k_volume_subtype_particle
+enum ent_volume_flag {
+   k_ent_volume_flag_particles = 0x1,
+   k_ent_volume_flag_disabled  = 0x2
 };
 
 struct ent_volume{
    mdl_transform transform;
    m4x3f to_world, to_local;
-   u32 type;
+   u32 flags;
 
    u32 target;
-
    union{
       volume_trigger trigger;
       volume_particles particles;
@@ -386,6 +386,7 @@ struct ent_challenge{
        submesh_count,
        id_next,
        filter;
+   f32 time_limit;
 };
 
 typedef struct ent_call ent_call;
index f54719a991f9a0a29885410f10feb5ee5b6000a2..5df1a39b3706c460754163a903c43bcb8e51874b 100644 (file)
Binary files a/maps_src/mp_spawn/main.mdl and b/maps_src/mp_spawn/main.mdl differ
index 52949ecaa41824a139ee4a4b5dcd8fa759c22c78..b67e050abd8807c832b1cc4fa0cd86f5025acc7a 100644 (file)
--- a/player.c
+++ b/player.c
@@ -167,8 +167,6 @@ void player__pass_gate( player_instance *player, ent_gate *gate )
    if( gate->type == k_gate_type_nonlocel )
       world_static.active_world = gate->target;
 
-   world_volumes.inside = 0;
-
    audio_lock();
    audio_oneshot( &audio_gate_pass, 1.0f, 0.0f );
    audio_unlock();
index 8489dbccf830ed1a527d1b17906e27bbe5a63f6d..92419991f7b0e6f21c5659a63a2db9f5bfb9700c 100644 (file)
@@ -191,10 +191,9 @@ VG_STATIC void rb_object_debug( rb_object *obj, u32 colour ){
 /*
  * Update world space bounding box based on local one
  */
-VG_STATIC void rb_update_bounds( rigidbody *rb )
-{
-   box_copy( rb->bbx, rb->bbx_world );
-   m4x3_transform_aabb( rb->to_world, rb->bbx_world );
+VG_STATIC void rb_update_bounds( rigidbody *rb ){
+   box_init_inf( rb->bbx_world );
+   m4x3_expand_aabb_aabb( rb->to_world, rb->bbx_world, rb->bbx );
 }
 
 /*
diff --git a/scene.h b/scene.h
index 027f4bded5c3bd6b8dc9f2b9f1ed038a15b3ab2b..c53c7b3c3c383f8198a1877a3c19965d3fce3c9c 100644 (file)
--- a/scene.h
+++ b/scene.h
@@ -110,8 +110,8 @@ VG_STATIC void scene_add_mdl_submesh( scene_context *ctx, mdl_context *mdl,
    
    /* Transform and place vertices */
    boxf bbxnew;
-   box_copy( sm->bbx, bbxnew );
-   m4x3_transform_aabb( transform, bbxnew );
+   box_init_inf( bbxnew );
+   m4x3_expand_aabb_aabb( transform, bbxnew, sm->bbx );
    box_concat( ctx->bbx, bbxnew );
 
    m3x3f normal_matrix;
index 357c59375710d67a9285b9e2c8ef250884935f99..f790aefc2cd9373e828f0536c39a1f1b2029d9f8 100644 (file)
@@ -508,7 +508,7 @@ VG_STATIC void render_main_game(void){
                                    it up with the oblique rendering inside the
                                    portals */
 
-   world_render_challenges( localplayer.viewable_world );
+   //world_render_challenges( localplayer.viewable_world );
 
    /* continue with variable rate */
    render_scene_gate_subview();
diff --git a/world.h b/world.h
index 7d513f9d0a768043cc7d3a63531614ab83cbb5b3..49c030ea37260f7945311ee69e4a9db447882f9d 100644 (file)
--- a/world.h
+++ b/world.h
@@ -170,9 +170,9 @@ struct world_instance {
                  scene_lines;
 
    /* spacial mappings */
-   bh_tree *audio_bh,
-           *volume_bh,
-           *geo_bh;
+   bh_tree *geo_bh,
+           *entity_bh;
+   u32 *entity_list;
 
    /* graphics */
    glmesh mesh_route_lines;
@@ -181,6 +181,9 @@ struct world_instance {
           mesh_water;
 
    rb_object rb_geo;
+
+   ent_challenge *challenge_target;
+   f32 challenge_timer;
 };
 
 struct world_static {
index 006ef9faa5e27edf2d35cd8da76759c8ec749ad8..d431bedc20f88dfd0cb1043bf16143bbc21841d5 100644 (file)
@@ -1,12 +1,12 @@
 #ifndef WORLD_ENTITY_C
 #define WORLD_ENTITY_C
 
+#include "model.h"
+#include "entity.h"
 #include "world.h"
 #include "world_load.h"
-#include "entity.h"
 
-VG_STATIC void world_gen_entities_init(void)
-{
+VG_STATIC void world_gen_entities_init(void){
    world_instance *world = world_loading_instance();
 
    /* lights */
@@ -59,34 +59,65 @@ VG_STATIC void world_gen_entities_init(void)
          ent_audio_clip *clip = mdl_arritm( &world->ent_audio_clip,  
                                              audio->clip_start+k );
 
-         if( clip->file.pack_size ){
-            u32 size = clip->file.pack_size,
-                offset = clip->file.pack_offset;
+         if( clip->_.file.pack_size ){
+            u32 size = clip->_.file.pack_size,
+                offset = clip->_.file.pack_offset;
 
             /* embedded files are fine to clear the scratch buffer, only
              * external audio uses it */
 
             vg_linear_clear( vg_mem.scratch );
             void *data = vg_linear_alloc( vg_mem.scratch, 
-                                          clip->file.pack_size );
+                                          clip->_.file.pack_size );
 
-            mdl_fread_pack_file( &world->meta, &clip->file, data );
+            mdl_fread_pack_file( &world->meta, &clip->_.file, data );
 
-            clip->clip.path = NULL;
-            clip->clip.flags = audio->flags;
-            clip->clip.data = data;
-            clip->clip.size = size;
+            clip->_.clip.path = NULL;
+            clip->_.clip.flags = audio->flags;
+            clip->_.clip.data = data;
+            clip->_.clip.size = size;
          }
          else{
-            clip->clip.path = mdl_pstr( &world->meta, clip->file.pstr_path );
-            clip->clip.flags = audio->flags;
-            clip->clip.data = NULL;
-            clip->clip.size = 0;
+            clip->_.clip.path = mdl_pstr(&world->meta,clip->_.file.pstr_path);
+            clip->_.clip.flags = audio->flags;
+            clip->_.clip.data = NULL;
+            clip->_.clip.size = 0;
          }
 
-         audio_clip_load( &clip->clip, world->heap );
+         audio_clip_load( &clip->_.clip, world->heap );
       }
    }
+
+   /* create generic entity hierachy for those who need it */
+   u32 indexed_count = 0;
+   struct {
+      u32 type;
+      mdl_array_ptr *array;
+   }
+   indexables[] = {
+      { k_ent_gate, &world->ent_gate },
+      { k_ent_challenge, &world->ent_challenge },
+      { k_ent_volume, &world->ent_volume }
+   };
+
+   for( u32 i=0; i<vg_list_size(indexables); i++ )
+      indexed_count += mdl_arrcount( indexables[i].array );
+   vg_info( "indexing %u entities\n", indexed_count );
+
+   world->entity_list = vg_linear_alloc( world->heap, 
+                                         vg_align8(indexed_count*sizeof(u32)));
+
+   u32 index=0;
+   for( u32 i=0; i<vg_list_size(indexables); i++ ){
+      u32 type  = indexables[i].type,
+          count = mdl_arrcount( indexables[i].array );
+      
+      for( u32 j=0; j<count; j ++ )
+         world->entity_list[index ++] = mdl_entity_id( type, j );
+   }
+
+   world->entity_bh = bh_create( world->heap, &bh_system_entity_list, world,
+                                 indexed_count, 2 );
 }
 
 VG_STATIC
@@ -145,7 +176,7 @@ VG_STATIC void ent_volume_call( world_instance *world, ent_call *call )
    if( call->function == k_ent_function_trigger ){
       call->id = volume->target;
 
-      if( volume->type == k_volume_subtype_particle ){
+      if( volume->flags & k_ent_volume_flag_particles ){
          float *co = alloca( sizeof(float)*3 );
          co[0] = vg_randf64()*2.0f-1.0f;
          co[1] = vg_randf64()*2.0f-1.0f;
@@ -157,6 +188,7 @@ VG_STATIC void ent_volume_call( world_instance *world, ent_call *call )
          entity_call( world, call );
       }
       else{
+         call->function = volume->trigger.event;
          entity_call( world, call );
       }
    }
@@ -198,7 +230,7 @@ VG_STATIC void ent_audio_call( world_instance *world, ent_call *call ){
          audio_lock();
 
          if( audio->behaviour == k_channel_behaviour_unlimited ){
-            audio_oneshot_3d( &clip->clip, sound_co,
+            audio_oneshot_3d( &clip->_.clip, sound_co,
                               audio->transform.s[0],
                               audio->volume );
          }
@@ -208,7 +240,7 @@ VG_STATIC void ent_audio_call( world_instance *world, ent_call *call ){
                                              audio->max_channels );
 
             if( ch ){
-               audio_channel_init( ch, &clip->clip, audio->flags );
+               audio_channel_init( ch, &clip->_.clip, audio->flags );
                audio_channel_group( ch, audio->group );
                audio_channel_world( ch, world_id );
                audio_channel_set_spacial( ch, sound_co, audio->transform.s[0] );
@@ -227,7 +259,7 @@ VG_STATIC void ent_audio_call( world_instance *world, ent_call *call ){
                   audio_get_group_first_active_channel( audio->group );
 
                if( existing ){
-                  if( existing->source == &clip->clip ){
+                  if( existing->source == &clip->_.clip ){
                      audio_unlock();
                      return;
                   }
@@ -240,7 +272,7 @@ VG_STATIC void ent_audio_call( world_instance *world, ent_call *call ){
             }
 
             if( ch ){
-               audio_channel_init( ch, &clip->clip, audio->flags );
+               audio_channel_init( ch, &clip->_.clip, audio->flags );
                audio_channel_group( ch, audio->group );
                audio_channel_world( ch, world_id );
                audio_channel_fadein( ch, audio->crossfade );
@@ -263,4 +295,124 @@ VG_STATIC void ent_ccmd_call( world_instance *world, ent_call *call ){
    }
 }
 
+/*
+ * BVH implementation
+ * ----------------------------------------------------------------------------
+ */
+
+VG_STATIC void 
+entity_bh_expand_bound( void *user, boxf bound, u32 item_index ){
+   world_instance *world = user;
+
+   u32 id    = world->entity_list[ item_index ],
+       type  = mdl_entity_id_type( id ),
+       index = mdl_entity_id_id( id );
+
+   if( type == k_ent_gate ){
+      ent_gate *gate = mdl_arritm( &world->ent_gate, index );
+      boxf box = {{ -gate->dimensions[0], -gate->dimensions[1], -0.1f },
+                  {  gate->dimensions[0],  gate->dimensions[1],  0.1f }};
+
+      m4x3_expand_aabb_aabb( gate->to_world, bound, box );
+   }
+   else if( type == k_ent_challenge ){
+      ent_challenge *challenge = mdl_arritm( &world->ent_challenge, index );
+      
+      /* TODO: This might be more work than necessary. could maybe just get
+       *       away with representing them as points */
+
+      boxf box;
+      box_init_inf( box );
+
+      for( u32 i=0; i<challenge->submesh_count; i++ ){
+         mdl_submesh *sm = mdl_arritm( &world->meta.submeshs,
+                                       challenge->submesh_start+i );
+         box_concat( box, sm->bbx );
+      }
+
+      m4x3f transform;
+      mdl_transform_m4x3( &challenge->transform, transform );
+      m4x3_expand_aabb_aabb( transform, bound, box );
+   }
+   else if( type == k_ent_volume ){
+      ent_volume *volume = mdl_arritm( &world->ent_volume, index );
+      m4x3_expand_aabb_aabb( volume->to_world, bound,
+                              (boxf){{-1.0f,-1.0f,-1.0f},{ 1.0f, 1.0f, 1.0f}} );
+   }
+}
+
+VG_STATIC float entity_bh_centroid( void *user, u32 item_index, int axis ){
+   world_instance *world = user;
+
+   u32 id    = world->entity_list[ item_index ],
+       type  = mdl_entity_id_type( id ),
+       index = mdl_entity_id_id( id );
+
+   if( type == k_ent_gate ){
+      ent_gate *gate = mdl_arritm( &world->ent_gate, index );
+      return gate->to_world[3][axis];
+   }
+   else if( type == k_ent_challenge ){
+      ent_challenge *challenge = mdl_arritm( &world->ent_challenge, index );
+      return challenge->transform.co[axis];
+   }
+   else if( type == k_ent_volume ){
+      ent_volume *volume = mdl_arritm( &world->ent_volume, index );
+      return volume->transform.co[axis];
+   }
+   else {
+      vg_fatal_error( "Programming error\n" );
+      return INFINITY;
+   }
+}
+
+VG_STATIC void entity_bh_swap( void *user, u32 ia, u32 ib ){
+   world_instance *world = user;
+
+   u32 a = world->entity_list[ ia ],
+       b = world->entity_list[ ib ];
+
+   world->entity_list[ ia ] = b;
+   world->entity_list[ ib ] = a;
+}
+
+VG_STATIC void entity_bh_debug( void *user, u32 item_index ){
+   world_instance *world = user;
+
+   u32 id    = world->entity_list[ item_index ],
+       type  = mdl_entity_id_type( id ),
+       index = mdl_entity_id_id( id );
+
+   if( type == k_ent_gate ){
+      ent_gate *gate = mdl_arritm( &world->ent_gate, index );
+      boxf box = {{ -gate->dimensions[0], -gate->dimensions[1], -0.1f },
+                  {  gate->dimensions[0],  gate->dimensions[1],  0.1f }};
+      vg_line_boxf_transformed( gate->to_world, box, 0xf000ff00 );
+   }
+   else if( type == k_ent_challenge ){
+      ent_challenge *challenge = mdl_arritm( &world->ent_challenge, index );
+      boxf box;
+      box_init_inf( box );
+
+      for( u32 i=0; i<challenge->submesh_count; i++ ){
+         mdl_submesh *sm = mdl_arritm( &world->meta.submeshs,
+                                       challenge->submesh_start+i );
+         box_concat( box, sm->bbx );
+      }
+
+      m4x3f transform;
+      mdl_transform_m4x3( &challenge->transform, transform );
+      vg_line_boxf_transformed( transform, box, 0xf000ff00 );
+   }
+   else if( type == k_ent_volume ){
+      ent_volume *volume = mdl_arritm( &world->ent_volume, index );
+      vg_line_boxf_transformed( volume->to_world,
+                                (boxf){{-1.0f,-1.0f,-1.0f},{ 1.0f, 1.0f, 1.0f}},
+                                0xf000ff00 );
+   }
+   else{
+      vg_fatal_error( "Programming error\n" );
+   }
+}
+
 #endif /* WORLD_ENTITY_C */
index 3c6d10de95407f3b1a1ad8df25efc982754d9a1f..3baaa2385a591aac82a822e3ff719af234ee4e59 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "world.h"
 #include "entity.h"
+#include "bvh.h"
 
 VG_STATIC void world_gen_entities_init(void);
 VG_STATIC ent_spawn *world_find_spawn_by_name( world_instance *world, 
@@ -14,4 +15,18 @@ VG_STATIC void ent_volume_call( world_instance *world, ent_call *call );
 VG_STATIC void ent_audio_call( world_instance *world, ent_call *call );
 VG_STATIC void ent_ccmd_call( world_instance *world, ent_call *call );
 
+VG_STATIC void entity_bh_expand_bound( void *user, boxf bound, u32 item_index );
+VG_STATIC float entity_bh_centroid( void *user, u32 item_index, int axis );
+VG_STATIC void entity_bh_swap( void *user, u32 ia, u32 ib );
+VG_STATIC void entity_bh_debug( void *user, u32 item_index );
+
+static bh_system bh_system_entity_list = {
+   .expand_bound = entity_bh_expand_bound,
+   .item_centroid = entity_bh_centroid,
+   .item_closest = NULL,
+   .item_swap = entity_bh_swap,
+   .item_debug = entity_bh_debug,
+   .cast_ray = NULL
+};
+
 #endif /* WORLD_ENTITY_H */
index a454d02509b6baac826cd00b74b7662e3a5985da..c31c2c2dd904955be10e8c7fde126cdfd2b2438e 100644 (file)
@@ -148,6 +148,19 @@ VG_STATIC void world_apply_procedural_foliage( scene_context *scene,
    vg_info( "%d foliage models added\n", count );
 }
 
+VG_STATIC 
+void world_unpack_submesh_dynamic( world_instance *world,
+                                   scene_context *scene, mdl_submesh *sm ){
+   if( sm->flags & k_submesh_flag_consumed ) return;
+
+   m4x3f identity;
+   m4x3_identity( identity );
+   scene_add_mdl_submesh( scene, &world->meta, sm, identity );
+
+   scene_copy_slice( scene, sm );
+   sm->flags |= k_submesh_flag_consumed;
+}
+
 /*
  * Create the main meshes for the world
  */
@@ -243,24 +256,29 @@ VG_STATIC void world_gen_generate_meshes(void)
       scene_copy_slice( &world->scene_no_collide, &surf->sm_no_collide );
    }
 
+   /* unpack traffic models.. TODO: should we just put all these submeshes in a
+    * dynamic models list? and then the actual entitities point to the 
+    * models. we only have 2 types at the moment which need dynamic models but
+    * would make sense to do this when/if we have more.
+    */
    for( u32 i=0; i<mdl_arrcount( &world->ent_traffic ); i++ ){
       ent_traffic *vehc = mdl_arritm( &world->ent_traffic, i );
 
       for( u32 j=0; j<vehc->submesh_count; j++ ){
          mdl_submesh *sm = mdl_arritm( &world->meta.submeshs, 
                                        vehc->submesh_start+j );
+         world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+      }
+   }
 
-         if( sm->flags & k_submesh_flag_consumed ){
-            continue;
-         }
-
-         m4x3f identity;
-         m4x3_identity( identity );
-         scene_add_mdl_submesh( &world->scene_no_collide, 
-                                &world->meta, sm, identity );
+   /* unpack challenge models */
+   for( u32 i=0; i<mdl_arrcount( &world->ent_challenge ); i++ ){
+      ent_challenge *challenge = mdl_arritm( &world->ent_challenge, i );
 
-         scene_copy_slice( &world->scene_no_collide, sm );
-         sm->flags |= k_submesh_flag_consumed;
+      for( u32 j=0; j<challenge->submesh_count; j ++ ){
+         mdl_submesh *sm = mdl_arritm( &world->meta.submeshs, 
+                                       challenge->submesh_start+j );
+         world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
       }
    }
 
index 9ca847c85d191f09707a7bd6a2fca92e38307b0f..01fa9cc6da2a6796b11f2d5a9bf4e048b69e3112 100644 (file)
@@ -84,8 +84,6 @@ VG_STATIC void world_load_mdl( const char *path )
    world_gen_load_surfaces();
    world_gen_routes_ent_init();
    world_gen_entities_init();
-   world->volume_bh = bh_create( heap, &bh_system_volumes, world,
-                                 mdl_arrcount( &world->ent_volume ), 1 );
    
    /* main bulk */
    world_gen_generate_meshes();
@@ -338,8 +336,8 @@ VG_STATIC void world_init_blank( world_instance *world )
    world->surface_count = 0;
 
    world->geo_bh = NULL;
-   world->volume_bh = NULL;
-   world->audio_bh = NULL;
+   world->entity_bh = NULL;
+   world->entity_list = NULL;
    world->rendering_gate = NULL;
 
    world->water.enabled = 0;
index ac0df1a1001754bf04f894c09c558c9dc0ed3dd6..3693a28920108f5978b1080b323a131a4fa19682 100644 (file)
@@ -222,20 +222,6 @@ void world_render_pass( world_instance *world, struct world_pass *pass ){
    }
 }
 
-VG_STATIC
-void world_render_challenges( world_instance *world ){
-   if( !world ) return;
-
-   shader_scene_fxglow_use();
-   for( u32 i=0; i<mdl_arrcount(&world->ent_challenge); i++ ){
-      ent_challenge *challenge = mdl_arritm(&world->ent_challenge,i);
-      
-      m4x3f mmdl;
-      mdl_transform_m4x3( &challenge->transform, mmdl );
-      shader_scene_fxglow_uMdl( mmdl );
-   }
-}
-
 VG_STATIC 
 void world_render_both_stages( world_instance *world, struct world_pass *pass )
 {
@@ -353,6 +339,37 @@ VG_STATIC void render_world_alphatest( world_instance *world, camera *cam )
    glEnable(GL_CULL_FACE);
 }
 
+VG_STATIC
+void world_render_challenges( world_instance *world, struct world_pass *pass ){
+   if( !world ) return;
+
+   glDisable( GL_CULL_FACE );
+   mesh_bind( &world->mesh_no_collide );
+
+   u32 last_material = 0;
+
+   for( u32 i=0; i<mdl_arrcount(&world->ent_challenge); i++ ){
+      ent_challenge *challenge = mdl_arritm(&world->ent_challenge,i);
+      
+      m4x3f mmdl;
+      mdl_transform_m4x3( &challenge->transform, mmdl );
+      shader_scene_fxglow_uMdl( mmdl );
+
+      for( u32 j=0; j<challenge->submesh_count; j++ ){
+         mdl_submesh *sm = mdl_arritm( &world->meta.submeshs, 
+                                       challenge->submesh_start + j );
+
+         if( sm->material_id != last_material ){
+            last_material = sm->material_id;
+
+            pass->fn_bind_textures( world, &world->surfaces[sm->material_id] );
+         }
+
+         mdl_draw_submesh( sm );
+      }
+   }
+}
+
 VG_STATIC void render_world_fxglow( world_instance *world, camera *cam ){
    //glDrawBuffers( 1, (GLenum[]){ GL_COLOR_ATTACHMENT0 } );
 
@@ -380,6 +397,7 @@ VG_STATIC void render_world_fxglow( world_instance *world, camera *cam ){
    };
 
    world_render_both_stages( world, &pass );
+   world_render_challenges( world, &pass );
 
    glEnable(GL_CULL_FACE);
    //glDrawBuffers( 2, (GLenum[]){ GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 } );
index 0cc1ed608929b03aaf094afd49ff4e4cba7cb5ac..2f0569df364df22a93eedbc3a2797c2887bc79e4 100644 (file)
@@ -46,14 +46,31 @@ static void world_volumes_update( world_instance *world, v3f pos ){
    bh_iter_init_box( 0, &it, volume_proximity );
    i32 idx;
 
-   while( bh_next( world->volume_bh, &it, &idx ) ){
-      ent_volume *volume = mdl_arritm( &world->ent_volume, idx );
+   while( bh_next( world->entity_bh, &it, &idx ) ){
+      u32 id    = world->entity_list[ idx ],
+          type  = mdl_entity_id_type( id ),
+          index = mdl_entity_id_id( id );
+
+      if( type != k_ent_volume ) continue;
 
+      ent_volume *volume = mdl_arritm( &world->ent_volume, index );
       boxf cube = {{-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f}};
       
-      if( volume->type == k_volume_subtype_trigger ){
+      if( volume->flags & k_ent_volume_flag_particles ){
+         vg_line_boxf_transformed( volume->to_world, cube, 0xff00c0ff );
+
+         for( int j=0; j<random_ticks; j++ ){
+            ent_call basecall;
+            basecall.id = id;
+            basecall.data = NULL;
+            basecall.function = 0;
+
+            entity_call( world, &basecall );
+         }
+      }
+      else{
          for( u32 i=0; i<world_static.active_trigger_volume_count; i++ )
-            if( world_static.active_trigger_volumes[i] == idx )
+            if( world_static.active_trigger_volumes[i] == index )
                goto next_volume;
 
          if( world_static.active_trigger_volume_count > 
@@ -64,82 +81,21 @@ static void world_volumes_update( world_instance *world, v3f pos ){
 
          if( (fabsf(local[0]) <= 1.0f) &&
              (fabsf(local[1]) <= 1.0f) &&
-             (fabsf(local[2]) <= 1.0f) )
-         {
+             (fabsf(local[2]) <= 1.0f) ){
             ent_call basecall;
-            basecall.function = k_ent_function_trigger;
-            basecall.id = mdl_entity_id( k_ent_volume, idx );
+            basecall.function = 0;
+            basecall.id = id;
             basecall.data = NULL;
 
             entity_call( world, &basecall );
             world_static.active_trigger_volumes[ 
-               world_static.active_trigger_volume_count ++ ] = idx;
+               world_static.active_trigger_volume_count ++ ] = index;
          }
          else
             vg_line_boxf_transformed( volume->to_world, cube, 0xffcccccc );
       }
-      else if( volume->type == k_volume_subtype_particle ){
-         vg_line_boxf_transformed( volume->to_world, cube, 0xff00c0ff );
-
-         for( int j=0; j<random_ticks; j++ ){
-            ent_call basecall;
-            basecall.id = mdl_entity_id( k_ent_volume, idx );
-            basecall.data = NULL;
-
-            entity_call( world, &basecall );
-         }
-      }
 next_volume:;
    }
 }
 
-/*
- * BVH implementation
- * ----------------------------------------------------------------------------
- */
-
-VG_STATIC void volume_vg_expand_bound( void *user, boxf bound, u32 item_index )
-{
-   world_instance *world = user;
-
-   ent_volume *volume = mdl_arritm( &world->ent_volume, item_index );
-
-   m4x3_expand_aabb_point( volume->to_world, bound, (v3f){ 1.0f, 1.0f, 1.0f} );
-   m4x3_expand_aabb_point( volume->to_world, bound, (v3f){ 1.0f, 1.0f,-1.0f} );
-   m4x3_expand_aabb_point( volume->to_world, bound, (v3f){ 1.0f,-1.0f, 1.0f} );
-   m4x3_expand_aabb_point( volume->to_world, bound, (v3f){ 1.0f,-1.0f,-1.0f} );
-   m4x3_expand_aabb_point( volume->to_world, bound, (v3f){-1.0f, 1.0f, 1.0f} );
-   m4x3_expand_aabb_point( volume->to_world, bound, (v3f){-1.0f, 1.0f,-1.0f} );
-   m4x3_expand_aabb_point( volume->to_world, bound, (v3f){-1.0f,-1.0f, 1.0f} );
-   m4x3_expand_aabb_point( volume->to_world, bound, (v3f){-1.0f,-1.0f,-1.0f} );
-}
-
-VG_STATIC float volume_vg_centroid( void *user, u32 item_index, int axis )
-{
-   world_instance *world = user;
-   ent_volume *volume = mdl_arritm( &world->ent_volume, item_index );
-   return volume->to_world[3][axis];
-}
-
-VG_STATIC void volume_vg_swap( void *user, u32 ia, u32 ib )
-{
-   world_instance *world = user;
-   ent_volume *a = mdl_arritm( &world->ent_volume, ia ),
-              *b = mdl_arritm( &world->ent_volume, ib ),
-              temp;
-
-   temp = *a;
-   *a = *b;
-   *b = temp;
-}
-
-VG_STATIC void volume_vg_debug( void *user, u32 item_index )
-{
-   world_instance *world = user;
-   ent_volume *volume = mdl_arritm( &world->ent_volume, item_index );
-   vg_line_boxf_transformed( volume->to_world, (boxf){{-1.0f,-1.0f,-1.0f},
-                                                      { 1.0f, 1.0f, 1.0f}}, 
-                                                      0xff00ff00 );
-}
-
 #endif /* WORLD_VOLUMES_H */
index 5bdc2d9ffdc5e52a01fb46536d2e3fde0c1bb012..199a09679558fe0da1aa3d25ff0e656aea0c0cf3 100644 (file)
@@ -4,24 +4,4 @@
 #include "world.h"
 #include "bvh.h"
 
-struct {
-   int inside;
-}
-static world_volumes;
-
-VG_STATIC void volume_vg_expand_bound( void *user, boxf bound, u32 item_index );
-VG_STATIC float volume_vg_centroid( void *user, u32 item_index, int axis );
-VG_STATIC void volume_vg_swap( void *user, u32 ia, u32 ib );
-VG_STATIC void volume_vg_debug( void *user, u32 item_index );
-
-static bh_system bh_system_volumes = 
-{
-   .expand_bound = volume_vg_expand_bound,
-   .item_centroid = volume_vg_centroid,
-   .item_closest = NULL,
-   .item_swap = volume_vg_swap,
-   .item_debug = volume_vg_debug,
-   .cast_ray = NULL
-};
-
 #endif /* WORLD_VOLUMES_H */