switch to entity list
[carveJwlIkooP6JGAAIwe30JlM.git] / world_entity.c
index 61d014d6ea38806dcecfef8ab4066ba72aba89cd..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 );
       }
    }
@@ -194,12 +226,11 @@ VG_STATIC void ent_audio_call( world_instance *world, ent_call *call ){
             p   = clip->probability * mod;
 
       bar += p;
-
       if( chance < bar ){
          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 );
          }
@@ -209,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] );
@@ -228,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;
                   }
@@ -241,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 );
@@ -264,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 */