entities zones
authorhgn <hgodden00@gmail.com>
Sat, 1 Apr 2023 02:51:55 +0000 (03:51 +0100)
committerhgn <hgodden00@gmail.com>
Sat, 1 Apr 2023 02:51:55 +0000 (03:51 +0100)
blender_export.py
entity.h
maps_src/mp_gridmap.mdl
player_skate.c
world.h
world_gen.h
world_volumes.h

index 07179e71b7c5bc5b684d1b0d82f95a62869feddd..a367cc169a6863b09db6445269a5da7b9e798566 100644 (file)
@@ -16,6 +16,16 @@ bl_info = {
    "category":"Import/Export",
 }
 
+sr_entity_alias = {
+   'ent_gate': 1,
+   'ent_spawn': 2,
+   'ent_route_node': 3,
+   'ent_route': 4,
+   'ent_water': 5,
+   'ent_volume': 6,
+   'ent_audio': 7
+}
+
 class mdl_vert(Structure):              # 48 bytes. Quite large. Could compress
 #{                                      # the normals and uvs to i16s. Not an
    _pack_ = 1                           # real issue, yet.
@@ -175,6 +185,26 @@ class ent_path_index(Structure):
    _fields_ = [("index",c_uint16)]
 #}
 
+class vg_audio_clip(Structure):
+#{
+   _fields_ = [("path",c_uint64),
+               ("flags",c_uint32),
+               ("size",c_uint32),
+               ("data",c_uint64)]
+#}
+
+class union_file_audio_clip(Union):
+#{
+   _fields_ = [("file",mdl_file),
+               ("reserved",vg_audio_clip)]
+#}
+
+class ent_audio_clip(Structure):
+#{
+   _fields_ = [("_anon",union_file_audio_clip),
+               ("probability",c_float)]
+#}
+
 class ent_checkpoint(Structure):
 #{
    _fields_ = [("gate_index",c_uint16),
@@ -182,7 +212,7 @@ class ent_checkpoint(Structure):
                ("path_count",c_uint16)]
 #}
 
-class ent_route(Structure):
+class ent_route(Structure): 
 #{
    _fields_ = [("transform",mdl_transform),
                ("pstr_name",c_uint32),
@@ -204,6 +234,54 @@ class ent_water(Structure):
                ("reserved1",c_uint32)]
 #}
 
+class volume_trigger(Structure):
+#{
+   _fields_ = [("event",c_uint32),
+               ("blank",c_uint32)]
+#}
+
+class volume_particles(Structure):
+#{
+   _fields_ = [("blank",c_uint32),
+               ("blank2",c_uint32)]
+#}
+
+class volume_union(Union):
+#{
+   _fields_ = [("trigger",volume_trigger),
+               ("particles",volume_particles)]
+#}
+
+class ent_index(Structure):
+#{
+   _fields_ = [("type",c_uint32),
+               ("index",c_uint32)]
+#}
+
+class ent_volume(Structure):
+#{
+   _fields_ = [("transform",mdl_transform),
+               ("to_world",(c_float*3)*4),
+               ("to_local",(c_float*3)*4),
+               ("type",c_uint32),
+               ("target",ent_index),
+               ("_anon",volume_union)]
+#}
+
+class ent_audio(Structure):
+#{
+   _fields_ = [("transform",mdl_transform),
+               ("flags",c_uint32),
+               ("clip_start",c_uint32),
+               ("clip_count",c_uint32),
+               ("volume",c_float),
+               ("crossfade",c_float),
+               ("channel_behaviour",c_uint32),
+               ("group",c_uint32),
+               ("probability_curve",c_uint32),
+               ("max_channels",c_uint32)]
+#}
+
 def obj_ent_type( obj ):
 #{
    if obj.type == 'ARMATURE': return 'mdl_armature'
@@ -211,14 +289,14 @@ def obj_ent_type( obj ):
    else: return obj.SR_data.ent_type
 #}
 
-def sr_filter_ent_type( obj, ent_type ):
+def sr_filter_ent_type( obj, ent_types ):
 #{
    if obj == bpy.context.active_object: return False
 
    for c0 in obj.users_collection:#{
       for c1 in bpy.context.active_object.users_collection:#{
          if c0 == c1:#{
-            return ent_type == obj_ent_type( obj )
+            return  obj_ent_type( obj ) in ent_types
          #}
       #}
    #}
@@ -393,6 +471,17 @@ def material_info(mat):
    return info
 #}
 
+def vg_str_bin( s ):
+#{
+   decoded = bytearray()
+   for i in range(len(s)//2):#{
+      c  = (ord(s[i*2+0])-0x41)
+      c |= (ord(s[i*2+1])-0x41)<<4
+      decoded.extend(bytearray(c_uint8(c))) #??
+   #}
+   return decoded
+#}
+
 def sr_pack_file( file, path, data ):
 #{
    file.path = sr_compile_string( path )
@@ -1010,6 +1099,7 @@ def sr_compile( collection ):
 
    checkpoint_count = 0
    pathindice_count = 0
+   audio_clip_count = 0
 
    for ent_type, arr in sr_compile.entities.items():#{
       print(F"[SR] Compiling {len(arr)} {ent_type}{'s' if len(arr)>1 else ''}")
@@ -1153,6 +1243,58 @@ def sr_compile( collection ):
             water.max_dist = 0.0
             sr_ent_push( water )
          #}
+         elif ent_type == 'ent_audio':#{
+            obj_data = obj.SR_data.ent_audio[0]
+            audio = ent_audio()
+            compile_obj_transform( obj, audio.transform )
+            audio.clip_start = audio_clip_count
+            audio.clip_count = len(obj_data.files)
+            audio.max_channels = obj_data.max_channels
+            audio.volume = obj_data.volume
+
+            # TODO flags: 
+            #   - allow/disable doppler
+            #   - channel group tags with random colours
+            #   - transition properties
+
+            if obj_data.flag_loop: audio.flags |= 0x1
+            if obj_data.flag_nodoppler: audio.flags |= 0x2
+            if obj_data.flag_3d: audio.flags |= 0x4
+            if obj_data.flag_auto: audio.flags |= 0x8
+            if   obj_data.formato == '0': audio.flags |= 0x000
+            elif obj_data.formato == '1': audio.flags |= 0x400
+            elif obj_data.formato == '2': audio.flags |= 0x1000
+
+            for ci in range(audio.clip_count):#{
+               entry = obj_data.files[ci]
+               clip = ent_audio_clip()
+               clip.probability = entry.probability
+               if obj_data.formato == '2':#{
+                  sr_pack_file( clip._anon.file, '', vg_str_bin(entry.path) ) 
+               #}
+               else:#{
+                  clip._anon.file.path = sr_compile_string( entry.path )
+                  clip._anon.file.pack_offset = 0
+                  clip._anon.file.pack_size = 0
+               #}
+               sr_ent_push( clip )
+            #}
+            sr_ent_push( audio )
+         #}
+         elif ent_type == 'ent_volume':#{
+            obj_data = obj.SR_data.ent_volume[0]
+            volume = ent_volume()
+            volume.type = int(obj_data.subtype)
+            compile_obj_transform( obj, volume.transform )
+
+            if obj_data.target:#{
+               target = obj_data.target
+               volume.target.type = sr_entity_alias[obj_ent_type(target)]
+               volume.target.index = sr_compile.entity_ids[ target.name ]
+            #}
+
+            sr_ent_push(volume)
+         #}
       #}
    #}
    
@@ -1567,7 +1709,7 @@ class SR_OBJECT_ENT_GATE(bpy.types.PropertyGroup):
 #{
    target: bpy.props.PointerProperty( \
                type=bpy.types.Object, name="destination", \
-               poll=lambda self,obj: sr_filter_ent_type(obj,'ent_gate'))
+               poll=lambda self,obj: sr_filter_ent_type(obj,['ent_gate']))
 #}
 
 class SR_MESH_ENT_GATE(bpy.types.PropertyGroup):
@@ -1579,7 +1721,7 @@ class SR_OBJECT_ENT_ROUTE_ENTRY(bpy.types.PropertyGroup):
 #{
    target: bpy.props.PointerProperty( \
                type=bpy.types.Object, name='target', \
-               poll=lambda self,obj: sr_filter_ent_type(obj,'ent_gate'))
+               poll=lambda self,obj: sr_filter_ent_type(obj,['ent_gate']))
 #}
 
 class SR_UL_ROUTE_NODE_LIST(bpy.types.UIList):
@@ -1612,7 +1754,7 @@ class SR_OT_ROUTE_LIST_DEL_ITEM(bpy.types.Operator):
    @classmethod 
    def poll(cls, context):#{
       active_object = context.active_object
-      if obj_ent_type == 'ent_gate':#{
+      if obj_ent_type(active_object) == 'ent_gate':#{
          return active_object.SR_data.ent_route[0].gates
       #}
       else: return False
@@ -1629,6 +1771,64 @@ class SR_OT_ROUTE_LIST_DEL_ITEM(bpy.types.Operator):
    #}
 #}
 
+class SR_OT_AUDIO_LIST_NEW_ITEM(bpy.types.Operator):
+#{
+   bl_idname = "skaterift.al_new_entry"
+   bl_label = "Add file"
+   
+   def execute(self, context):#{
+      active_object = context.active_object
+      active_object.SR_data.ent_audio[0].files.add()
+      return{'FINISHED'}
+   #}
+#}
+
+class SR_OT_AUDIO_LIST_DEL_ITEM(bpy.types.Operator):
+#{
+   bl_idname = "skaterift.al_del_entry"
+   bl_label = "Remove file"
+
+   @classmethod 
+   def poll(cls, context):#{
+      active_object = context.active_object
+      if obj_ent_type(active_object) == 'ent_audio':#{
+         return active_object.SR_data.ent_audio[0].files
+      #}
+      else: return False
+   #}
+   
+   def execute(self, context):#{
+      active_object = context.active_object
+      lista = active_object.SR_data.ent_audio[0].files
+      index = active_object.SR_data.ent_audio[0].file_index
+      lista.remove(index) 
+      active_object.SR_data.ent_audio[0].file_index = \
+            min(max(0, index-1), len(lista) - 1)
+      return{'FINISHED'}
+   #}
+#}
+
+class SR_OBJECT_ENT_AUDIO_FILE_ENTRY(bpy.types.PropertyGroup):
+#{
+   path: bpy.props.StringProperty( name="Path" )
+   probability: bpy.props.FloatProperty( name="Probability",default=100.0 )
+#}
+
+class SR_UL_AUDIO_LIST(bpy.types.UIList):
+#{
+   bl_idname = 'SR_UL_AUDIO_LIST'
+
+   def draw_item(_,context,layout,data,item,icon,active_data,active_propname):
+   #{
+      split = layout.split(factor=0.7)
+      c = split.column()
+      c.prop( item, 'path', text='', emboss=False )
+      c = split.column()
+      c.prop( item, 'probability', text='%', emboss=True )
+   #}
+#}
+
+
 class SR_OBJECT_ENT_ROUTE(bpy.types.PropertyGroup):
 #{
    gates: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_ROUTE_ENTRY)
@@ -1662,11 +1862,107 @@ class SR_OBJECT_ENT_ROUTE(bpy.types.PropertyGroup):
    #}
 #}
 
+class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):
+#{
+   subtype: bpy.props.EnumProperty(
+      name="Subtype",
+      items=[('0','Trigger',''),
+             ('1','Particles (0.1s)','')]
+   )
+
+   target: bpy.props.PointerProperty( \
+           type=bpy.types.Object, name="Target", \
+           poll=lambda self,obj: sr_filter_ent_type(obj,['ent_audio']))
+
+   @staticmethod
+   def sr_inspector( layout, data ):
+   #{
+      data = data[0]
+      layout.prop( data, 'subtype' )
+      layout.prop( data, 'target' )
+   #}
+#}
+
+class SR_OBJECT_ENT_AUDIO(bpy.types.PropertyGroup):
+#{
+   files: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_AUDIO_FILE_ENTRY)
+   file_index: bpy.props.IntProperty()
+
+   flag_3d: bpy.props.BoolProperty( name="3D audio",default=True )
+   flag_loop: bpy.props.BoolProperty( name="Loop",default=False )
+   flag_auto: bpy.props.BoolProperty( name="Play at start",default=False )
+   flag_nodoppler: bpy.props.BoolProperty( name="No Doppler",default=False )
+   formato: bpy.props.EnumProperty(
+      name="Format",
+      items=[('0','Uncompressed Mono',''),
+             ('1','Compressed Vorbis',''),
+             ('2','[vg] Bird Synthesis','')]
+   )
+   probability_curve: bpy.props.EnumProperty(
+      name="Probability Curve",
+      items=[('0','Constant',''),
+             ('1','Wildlife Daytime',''),
+             ('2','Wildlife Nighttime','')])
+   channel_behaviour: bpy.props.EnumProperty(
+      name="Channel Behaviour",
+      items=[('0','Unlimited',''),
+             ('1','Discard if group full', ''),
+             ('2','Crossfade if group full','')])
+
+   transition_duration: bpy.props.FloatProperty(name="Transition Time",\
+                                                default=0.2)
+   
+   max_channels: bpy.props.IntProperty( name="Max Channels", default=1 )
+   volume: bpy.props.FloatProperty( name="Volume",default=1.0 )
+
+   @staticmethod
+   def sr_inspector( layout, data ):
+   #{
+      layout.prop( data[0], 'formato' )
+      layout.prop( data[0], 'volume' )
+
+      box = layout.box()
+      box.label( text='Channels' )
+      split = box.split(factor=0.3)
+      c = split.column()
+      c.prop( data[0], 'max_channels' )
+      c = split.column()
+      c.prop( data[0], 'channel_behaviour', text='Behaviour' )
+      if data[0].channel_behaviour == '2': 
+         box.prop( data[0], 'transition_duration' )
+
+      box = layout.box()
+      box.label( text='Flags' )
+      box.prop( data[0], 'flag_3d' )
+      if data[0].flag_3d: box.prop( data[0], 'flag_nodoppler' )
+
+      box.prop( data[0], 'flag_loop' )
+      box.prop( data[0], 'flag_auto' )
+
+      split = layout.split(factor=0.7)
+      c = split.column()
+      c.label( text='Filepath' )
+      c = split.column()
+      c.label( text='Chance (0.1s)' )
+
+      layout.prop( data[0], 'probability_curve' )
+
+      layout.template_list('SR_UL_AUDIO_LIST', 'Files', \
+                            data[0], 'files', data[0], 'file_index', rows=5)
+
+      row = layout.row()
+      row.operator( 'skaterift.al_new_entry', text='Add' )
+      row.operator( 'skaterift.al_del_entry', text='Remove' )
+   #}
+#}
+
 class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup):
 #{
    ent_gate: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_GATE)
    ent_spawn: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_SPAWN)
    ent_route: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_ROUTE)
+   ent_volume: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_VOLUME)
+   ent_audio: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_AUDIO)
 
    ent_type: bpy.props.EnumProperty(
       name="Type",
@@ -1675,7 +1971,9 @@ class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup):
              ('ent_spawn','Spawn','', 2),
              ('ent_route_node', 'Route Node', '', 3 ),
              ('ent_route', 'Route', '', 4),
-             ('ent_water', 'Water Surface', '', 5)],
+             ('ent_water', 'Water Surface', '', 5),
+             ('ent_volume', 'Volume', '', 6 ),
+             ('ent_audio', 'Audio Files', '', 7)],
       update=sr_on_type_change
    )
 #}
@@ -2295,6 +2593,28 @@ def cv_ent_gate( obj ):
       cv_draw_arrow( obj.location, data.target.location, sw )
 #}
 
+def cv_ent_volume( obj ):
+#{
+   global cv_view_verts, cv_view_colours
+
+   data = obj.SR_data.ent_volume[0]
+
+   if data.subtype == '0':#{
+      cv_draw_ucube( obj.matrix_world, (0,1,0) )
+
+      if data.target:#{
+         cv_draw_line( 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) )
+      #}
+   #}
+#}
+
 def dijkstra( graph, start_node, target_node ):
 #{
    unvisited = [_ for _ in graph]
@@ -2464,6 +2784,12 @@ def cv_draw():
             route_nodes += [obj]
          elif ent_type == 'ent_route':
             routes += [obj]
+         elif ent_type == 'ent_volume':#{
+            cv_ent_volume( obj )
+         #}
+         elif ent_type == 'ent_audio':#{
+            cv_draw_sphere( obj.location, obj.scale[0], (1,1,0) )
+         #}
       #}
    #}
    
@@ -2482,8 +2808,12 @@ classes = [ SR_INTERFACE, SR_MATERIAL_PANEL,\
             \
             SR_OBJECT_ENT_GATE, SR_MESH_ENT_GATE, SR_OBJECT_ENT_SPAWN, \
             SR_OBJECT_ENT_ROUTE_ENTRY, SR_UL_ROUTE_NODE_LIST, \
-            SR_OBJECT_ENT_ROUTE, SR_OT_ROUTE_LIST_NEW_ITEM,
+            SR_OBJECT_ENT_ROUTE, SR_OT_ROUTE_LIST_NEW_ITEM,\
+            SR_OT_AUDIO_LIST_NEW_ITEM,SR_OT_AUDIO_LIST_DEL_ITEM,\
+            SR_OBJECT_ENT_VOLUME, 
+            SR_UL_AUDIO_LIST, SR_OBJECT_ENT_AUDIO_FILE_ENTRY,\
             SR_OT_ROUTE_LIST_DEL_ITEM,\
+            SR_OBJECT_ENT_AUDIO,\
             \
             SR_OBJECT_PROPERTIES, SR_LIGHT_PROPERTIES, SR_BONE_PROPERTIES, 
             SR_MESH_PROPERTIES, SR_MATERIAL_PROPERTIES \
index 2c70b82988375ed3e6814869c1e6b8481ea5d97d..490737d5322737ab15cc839270bf38e236b1f65c 100644 (file)
--- a/entity.h
+++ b/entity.h
@@ -11,6 +11,32 @@ typedef struct ent_path_index ent_path_index;
 typedef struct ent_checkpoint ent_checkpoint;
 typedef struct ent_route ent_route;
 typedef struct ent_water ent_water;
+typedef struct ent_audio_clip ent_audio_clip;
+typedef struct volume_particles volume_particles;
+typedef struct volume_trigger volume_trigger;
+typedef struct ent_volume ent_volume;
+typedef struct ent_audio ent_audio;
+typedef struct ent_index ent_index;
+
+enum entity_alias{
+   k_ent_gate = 1,
+   k_ent_spawn = 2,
+   k_ent_route_node = 3,
+   k_ent_route = 4,
+   k_ent_water = 5,
+   k_ent_volume = 6,
+   k_ent_audio = 7
+};
+
+struct ent_index{
+   u32 type,
+       index;
+};
+
+enum entity_function{
+   k_ent_function_trigger,
+   k_ent_function_particle_spawn
+};
 
 struct ent_spawn{
    mdl_transform transform;
@@ -109,4 +135,51 @@ struct ent_water{
    u32 reserved0, reserved1;
 };
 
+struct ent_audio_clip{
+   union{
+      mdl_file file;
+      audio_clip clip;
+   };
+
+   float probability;
+};
+
+struct volume_particles{
+   u32 blank, blank2;
+};
+
+struct volume_trigger{
+   u32 event, blank;
+};
+
+enum volume_subtype{
+   k_volume_subtype_trigger,
+   k_volume_subtype_particle
+};
+
+struct ent_volume{
+   mdl_transform transform;
+   m4x3f to_world, to_local;
+   u32 type;
+
+   ent_index target;
+
+   union{
+      volume_trigger trigger;
+      volume_particles particles;
+   };
+};
+
+struct ent_audio{
+   mdl_transform transform;
+   u32 flags,
+       clip_start,
+       clip_count;
+   float volume, crossfade;
+   u32 channel_behaviour,
+       group,
+       probability_curve,
+       max_channels;
+};
+
 #endif /* ENTITY_H */
index 726aaa877c4142926691c5b4701ff79d4f644f02..ceb3721c51f0b0173603e197c56301a2d30c137a 100644 (file)
Binary files a/maps_src/mp_gridmap.mdl and b/maps_src/mp_gridmap.mdl differ
index bfccb61a2930b5c146544182eb5d3327b379858f..0362386289b361901505252bf19f8f37e16b39a3 100644 (file)
@@ -1198,11 +1198,17 @@ VG_STATIC void player__skate_post_update( player_instance *player )
 
    const u32 flags = AUDIO_FLAG_SPACIAL_3D|AUDIO_FLAG_LOOP;
 
-   if( !s->aud_air )
-      s->aud_air = audio_request_channel( &audio_board[1], flags );
+   if( !s->aud_air ){
+      s->aud_air = audio_get_first_idle_channel();
+      if( s->aud_air )
+         audio_channel_init( s->aud_air, &audio_board[1], flags );
+   }
 
-   if( !s->aud_slide )
-      s->aud_slide = audio_request_channel( &audio_board[2], flags );
+   if( !s->aud_slide ){
+      s->aud_slide = audio_get_first_idle_channel();
+      if( s->aud_slide ) 
+         audio_channel_init( s->aud_slide, &audio_board[2], flags );
+   }
 
 
    /* brrrrrrrrrrrt sound for tiles and stuff 
diff --git a/world.h b/world.h
index 80bf3b6bafad33620b4738fb314440cfd581a6d3..08d3ca09123d253651cc89fecc653e36f1468718 100644 (file)
--- a/world.h
+++ b/world.h
@@ -155,7 +155,11 @@ struct world_instance
                  ent_path_index,
                  ent_checkpoint,
                  ent_route,
-                 ent_water;
+                 ent_water,
+
+                 ent_audio_clip,
+                 ent_audio,
+                 ent_volume;
 
    ent_gate *rendering_gate;
 
@@ -466,6 +470,78 @@ VG_STATIC void world_init(void)
                                                            VG_MEMORY_SYSTEM );
 }
 
+typedef struct ent_call ent_call;
+struct ent_call{
+   ent_index ent;
+   u32 function;
+   void *data;
+};
+
+VG_STATIC void entity_call( world_instance *world, ent_call *call );
+
+VG_STATIC void ent_volume_call( world_instance *world, ent_call *call )
+{
+   ent_volume *volume = mdl_arritm( &world->ent_volume, call->ent.index );
+   if( !volume->target.type ) return;
+
+   if( call->function == k_ent_function_trigger ){
+      call->ent = volume->target;
+
+      if( volume->type == k_volume_subtype_particle ){
+         v3f co;
+         co[0] = vg_randf()*2.0f-1.0f;
+         co[1] = vg_randf()*2.0f-1.0f;
+         co[2] = vg_randf()*2.0f-1.0f;
+         m4x3_mulv( volume->to_world, co, co );
+
+         call->function = k_ent_function_particle_spawn;
+         call->data = co;
+         
+         entity_call( world, call );
+      }
+      else if( volume->type == k_volume_subtype_trigger ){
+         /* TODO */
+      }
+   }
+}
+
+VG_STATIC void ent_audio_call( world_instance *world, ent_call *call )
+{
+   ent_audio *audio = mdl_arritm( &world->ent_audio, call->ent.index );
+
+   if( call->function == k_ent_function_particle_spawn ){
+      float chance = vg_randf()*100.0f,
+            bar = 0.0f;
+
+      for( u32 i=0; i<audio->clip_count; i++ ){
+         ent_audio_clip *clip = mdl_arritm( &world->ent_audio_clip, 
+                                             audio->clip_start+i );
+
+         bar += clip->probability;
+
+         if( chance < bar ){
+            float *pos = call->data;
+
+            audio_lock();
+            audio_oneshot_3d( &clip->clip, pos,
+                              audio->transform.s[0],
+                              audio->volume );
+            audio_unlock();
+            break;
+         }
+      }
+   }
+}
+
+VG_STATIC void entity_call( world_instance *world, ent_call *call )
+{
+   if( call->ent.type == k_ent_volume ){
+      ent_volume_call( world, call );
+   } else if( call->ent.type == k_ent_audio ){
+      ent_audio_call( world, call );
+   }
+}
+
 VG_STATIC void world_update( world_instance *world, v3f pos )
 {
    /* TEMP!!!!!! */
@@ -549,8 +625,7 @@ VG_STATIC void world_update( world_instance *world, v3f pos )
    }
    sfd_update();
    
-#if 0
-   /* TODO: Bvh */
+
 
    static float random_accum = 0.0f;
    random_accum += vg.time_delta;
@@ -573,69 +648,48 @@ VG_STATIC void world_update( world_instance *world, v3f pos )
 
    int in_volume = 0;
 
-   while( bh_next( world->volume_bh, &it, volume_proximity, &idx ) )
-   {
-      struct world_volume *zone = &world->volumes[idx];
+   while( bh_next( world->volume_bh, &it, volume_proximity, &idx ) ){
+      ent_volume *volume = mdl_arritm( &world->ent_volume, 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++ )
+      boxf cube = {{-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f}};
+      
+      if( volume->type == k_volume_subtype_trigger ){
+         v3f local;
+         m4x3_mulv( volume->to_local, pos, local );
+         vg_line_boxf_transformed( volume->to_world, cube, 0xff00ff00 );
+
+         if( (fabsf(local[0]) <= 1.0f) &&
+             (fabsf(local[1]) <= 1.0f) &&
+             (fabsf(local[2]) <= 1.0f) )
          {
-            logic_packet packet;
-            packet.location = zone->target_logic_brick;
-            packet.function = 0;
+            in_volume = 1;
 
-            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 );
+            if( !world_global.in_volume ){
+               ent_call basecall;
+               basecall.ent.index = idx;
+               basecall.ent.type = k_ent_volume;
+               basecall.function = k_ent_function_trigger;
+               basecall.data = NULL;
 
-            logic_bricks_send_packet( world, &packet );
+               entity_call( world, &basecall );
+            }
          }
-#endif
-         continue;
       }
+      else if( volume->type == k_volume_subtype_particle ){
+         vg_line_boxf_transformed( volume->to_world, cube, 0xff00c0ff );
 
-      v3f local;
-      m4x3_mulv( zone->inv_transform, pos, local );
-      
-      if( (fabsf(local[0]) <= 1.0f) &&
-          (fabsf(local[1]) <= 1.0f) &&
-          (fabsf(local[2]) <= 1.0f) )
-      {
-         in_volume = 1;
-
-         if( !world_global.in_volume )
-         {
-#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 );
+         for( int j=0; j<random_ticks; j++ ){
+            ent_call basecall;
+            basecall.ent.index = idx;
+            basecall.ent.type = k_ent_volume;
+            basecall.function = k_ent_function_trigger;
+            basecall.data = NULL;
 
-            logic_bricks_send_packet( world, &packet );
-#endif
+            entity_call( world, &basecall );
          }
-         
-         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 );
       }
    }
-#endif
+   world_global.in_volume = in_volume;
 
 #if 0
    if( k_debug_light_indices )
@@ -657,7 +711,6 @@ VG_STATIC void world_update( world_instance *world, v3f pos )
       }
    }
 
-   world_global.in_volume = in_volume;
 #endif
 
 #if 0
index 63cb1ef98f1e91c38799f1f9d2e78a7a65e81b69..fac1fe7ebb602dbffac6088bb4101d2a3474e075 100644 (file)
@@ -791,6 +791,44 @@ VG_STATIC void world_entities_init( world_instance *world )
       world->water.enabled = 1;
       water_set_surface( world, water->transform.co[1] );
    }
+   
+   /* volumes */
+   for( u32 j=0; j<mdl_arrcount(&world->ent_volume); j++ ){
+      ent_volume *volume = mdl_arritm( &world->ent_volume, j );
+      mdl_transform_m4x3( &volume->transform, volume->to_world );
+      m4x3_invert_affine( volume->to_world, volume->to_local );
+   }
+
+   /* audio packs */
+   for( u32 j=0; j<mdl_arrcount(&world->ent_audio); j++ ){
+      ent_audio *audio = mdl_arritm( &world->ent_audio, j );
+
+      for( u32 k=0; k<audio->clip_count; k++ ){
+         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;
+
+            /* FIXME: Ditchable asset! */
+            void *data = mdl_arritm(&world->meta.pack, clip->file.pack_offset);
+
+            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;
+         }
+
+         audio_clip_load( &clip->clip, world_global.generic_heap );
+      }
+   }
 }
 
 VG_STATIC void world_load( world_instance *world, const char *path )
@@ -804,6 +842,8 @@ VG_STATIC void world_load( world_instance *world, const char *path )
    mdl_load_metadata_block( &world->meta, world_global.generic_heap );
    mdl_load_animation_block( &world->meta, world_global.generic_heap );
    mdl_load_mesh_block( &world->meta, world_global.generic_heap );
+
+   /* TODO: This should get a seperate memory area */
    mdl_load_pack_block( &world->meta, world_global.generic_heap );
 
    mdl_load_array( &world->meta, &world->ent_gate, 
@@ -823,6 +863,12 @@ VG_STATIC void world_load( world_instance *world, const char *path )
                    "ent_route", world_global.generic_heap );
    mdl_load_array( &world->meta, &world->ent_water,
                    "ent_water", world_global.generic_heap );
+   mdl_load_array( &world->meta, &world->ent_audio_clip,
+                   "ent_audio_clip", world_global.generic_heap );
+   mdl_load_array( &world->meta, &world->ent_audio,
+                   "ent_audio", world_global.generic_heap );
+   mdl_load_array( &world->meta, &world->ent_volume,
+                   "ent_volume", world_global.generic_heap );
 
    mdl_close( &world->meta );
 
@@ -838,6 +884,11 @@ VG_STATIC void world_load( world_instance *world, const char *path )
 #endif
    world_routes_ent_init( world );
    world_entities_init( world );
+   world->volume_bh = bh_create( world_global.generic_heap,
+                                 &bh_system_volumes,
+                                 world,
+                                 mdl_arrcount( &world->ent_volume ),
+                                 1 );
    
    /* main bulk */
    world_generate( world );
index f333626087586a752d4aeeeb10e3aa9f3c2ce64e..da39d265644848fd93989ae3ecbac8f9b78cfec5 100644 (file)
@@ -3,7 +3,6 @@
 
 #include "world.h"
 
-#if 0
 /*
  * BVH implementation
  * ----------------------------------------------------------------------------
@@ -13,35 +12,30 @@ VG_STATIC void volume_vg_expand_bound( void *user, boxf bound, u32 item_index )
 {
    world_instance *world = user;
 
-   ent_volume *volume_array = world_ent_array( world, k_ent_volume ),
-              *volume       = volume_array + item_index;
+   ent_volume *volume = mdl_arritm( &world->ent_volume, item_index );
 
-   m4x3_expand_aabb_point( volume->transform, bound, (v3f){ 1.0f, 1.0f, 1.0f} );
-   m4x3_expand_aabb_point( volume->transform, bound, (v3f){ 1.0f, 1.0f,-1.0f} );
-   m4x3_expand_aabb_point( volume->transform, bound, (v3f){ 1.0f,-1.0f, 1.0f} );
-   m4x3_expand_aabb_point( volume->transform, bound, (v3f){ 1.0f,-1.0f,-1.0f} );
-   m4x3_expand_aabb_point( volume->transform, bound, (v3f){-1.0f, 1.0f, 1.0f} );
-   m4x3_expand_aabb_point( volume->transform, bound, (v3f){-1.0f, 1.0f,-1.0f} );
-   m4x3_expand_aabb_point( volume->transform, bound, (v3f){-1.0f,-1.0f, 1.0f} );
-   m4x3_expand_aabb_point( volume->transform, 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} );
+   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_array = world_ent_array( world, k_ent_volume ),
-              *volume       = volume_array + item_index;
-
-   return volume->transform[3][axis];
+   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 *volume_array = world_ent_array( world, k_ent_volume ),
-              *a            = volume_array + ia,
-              *b            = volume_array + ib,
+   ent_volume *a = mdl_arritm( &world->ent_volume, ia ),
+              *b = mdl_arritm( &world->ent_volume, ib ),
               temp;
 
    temp = *a;
@@ -52,12 +46,10 @@ VG_STATIC void volume_vg_swap( void *user, u32 ia, u32 ib )
 VG_STATIC void volume_vg_debug( void *user, u32 item_index )
 {
    world_instance *world = user;
-   ent_volume *volume_array = world_ent_array( world, k_ent_volume ),
-              *volume       = volume_array + item_index;
-
-   vg_line_boxf_transformed( volume->transform, (boxf){{-1.0f,-1.0f,-1.0f},
-                                                       { 1.0f, 1.0f, 1.0f}}, 
-                                                       0xff00ff00 );
+   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 );
 }
 
 VG_STATIC bh_system bh_system_volumes = 
@@ -69,6 +61,5 @@ VG_STATIC bh_system bh_system_volumes =
    .item_debug = volume_vg_debug,
    .cast_ray = NULL
 };
-#endif
 
 #endif /* WORLD_VOLUMES_H */