large reduction, redoing things
authorhgn <hgodden00@gmail.com>
Wed, 15 Mar 2023 19:15:44 +0000 (19:15 +0000)
committerhgn <hgodden00@gmail.com>
Wed, 15 Mar 2023 19:15:44 +0000 (19:15 +0000)
14 files changed:
blender_export.py
bvh.h
common.h
maps_src/mp_home.mdl
maps_src/mp_mtzero.mdl
model.h
models_src/ch_jordan.mdl
models_src/ch_new.mdl
models_src/ch_outlaw.mdl
skaterift.c
world.h
world_gen.h
world_logic_bricks.h
world_volumes.h [new file with mode: 0644]

index d0a1c8aa50932b67a7cd4389865dedc983aed23c..091718d15d5b660c240d4b8017197832dbbfba1c 100644 (file)
@@ -171,8 +171,161 @@ class mdl_keyframe(Structure):
 #  def editor_interface( layout, obj ):
 #
 
-# Classtype 1
+# 000: Intrinsic
+# ---------------------------------------------------------------------------- #
+
+#  Purpose: intrinsic bone type, stores collision information and limits too
+#
+class classtype_bone(Structure):
+#{
+   _pack_ = 1
+   _fields_ = [("flags",c_uint32),
+               ("ik_target",c_uint32),
+               ("ik_pole",c_uint32),
+               ("hitbox",(c_float*3)*2),
+               ("conevx",c_float*3),
+               ("conevy",c_float*3),
+               ("coneva",c_float*3),
+               ("conet",c_float)]
+
+   def encode_obj(_, node,node_def):
+   #{
+      node.classtype = 1
+
+      armature_def = node_def['linked_armature']
+      obj = node_def['bone']
+      
+      _.flags = node_def['deform']
+      
+      if 'ik_target' in node_def:
+      #{
+         _.flags |= 0x2
+         _.ik_target = armature_def['bones'].index( node_def['ik_target'] )
+         _.ik_pole   = armature_def['bones'].index( node_def['ik_pole'] )
+      #}
+      
+      # For ragdolls
+      #
+      if obj.cv_data.collider != 'collider_none':
+      #{
+         if obj.cv_data.collider == 'collider_box':
+            _.flags |= 0x4
+         else:
+            _.flags |= 0x8
+
+         _.hitbox[0][0] =  obj.cv_data.v0[0]
+         _.hitbox[0][1] =  obj.cv_data.v0[2]
+         _.hitbox[0][2] = -obj.cv_data.v1[1]
+         _.hitbox[1][0] =  obj.cv_data.v1[0]
+         _.hitbox[1][1] =  obj.cv_data.v1[2]
+         _.hitbox[1][2] = -obj.cv_data.v0[1]
+      #}
+
+      if obj.cv_data.con0:
+      #{
+         _.flags |= 0x100
+         _.conevx[0] =  obj.cv_data.conevx[0]
+         _.conevx[1] =  obj.cv_data.conevx[2]
+         _.conevx[2] = -obj.cv_data.conevx[1]
+         _.conevy[0] =  obj.cv_data.conevy[0]
+         _.conevy[1] =  obj.cv_data.conevy[2]
+         _.conevy[2] = -obj.cv_data.conevy[1]
+         _.coneva[0] =  obj.cv_data.coneva[0]
+         _.coneva[1] =  obj.cv_data.coneva[2]
+         _.coneva[2] = -obj.cv_data.coneva[1]
+         _.conet = obj.cv_data.conet
+      #}
+   #}
+#}
+
+#  Purpose: defines the allocation requirements for a skeleton
+#
+class classtype_skeleton(Structure):
+#{
+   _pack_ = 1
+   _fields_ = [("channels",c_uint32),
+               ("ik_count",c_uint32),
+               ("collider_count",c_uint32),
+               ("anim_start",c_uint32),
+               ("anim_count",c_uint32)]
+
+   def encode_obj(_, node,node_def):
+   #{
+      node.classtype = 2
+      
+      _.channels        = len( node_def['bones'] )
+      _.ik_count        = node_def['ik_count']
+      _.collider_count  = node_def['collider_count']
+      _.anim_start      = node_def['anim_start']
+      _.anim_count      = node_def['anim_count']
+   #}
+#}
+
+#  Purpose: links an mesh node to a type 11
+#
+class classtype_skin(Structure):
+#{
+   _pack_ = 1
+   _fields_ = [("skeleton",c_uint32)]
+
+   def encode_obj(_, node,node_def):
+   #{
+      node.classtype = 3
+      
+      armature_def = node_def['linked_armature']
+      _.skeleton = armature_def['obj'].cv_data.uid
+   #}
+#}
+
+#  Purpose: world light
 #
+class classtype_world_light( Structure ):
+#{
+   _pack_ = 1
+   _fields_ = [("type",c_uint32),
+               ("colour",c_float*4),
+               ("angle",c_float),
+               ("range",c_float)]
+
+   def encode_obj(_, node, node_def):
+   #{
+      node.classtype = 4
+
+      obj  = node_def['obj']
+      data = obj.data
+      _.colour[0] = data.color[0]
+      _.colour[1] = data.color[1]
+      _.colour[2] = data.color[2]
+      _.colour[3] = data.energy
+      _.range = data.cutoff_distance # this has to be manually set
+                                     # TODO: At some point, automate a min
+                                     #       threshold value
+
+      if obj.data.type == 'POINT':
+      #{
+         _.type = 0
+         _.angle = 0.0
+      #}
+      elif obj.data.type == 'SPOT':
+      #{
+         _.type = 1
+         _.angle = data.spot_size*0.5
+      #}
+
+      if data.cv_data.bp0:
+         _.type += 2
+   #}
+
+   @staticmethod
+   def editor_interface( layout, obj ):
+   #{
+      pass
+   #}
+#}
+
+# 100: Gates
+# ---------------------------------------------------------------------------- #
+
 #  Purpose: A rift. must target another gate, the target gate can not have more 
 #           than one target nodes of its own.
 #
@@ -184,7 +337,7 @@ class classtype_gate(Structure):
 
    def encode_obj(_, node,node_def):
    #{
-      node.classtype = 1
+      node.classtype = 100
 
       obj = node_def['obj']
 
@@ -259,7 +412,7 @@ class classtype_nonlocal_gate(classtype_gate):
 #{
    def encode_obj(_,node,node_def):
    #{
-      node.classtype = 300
+      node.classtype = 101
 
       obj = node_def['obj']
       _.target = encoder_process_pstr( node_def['obj'].cv_data.strp )
@@ -289,8 +442,9 @@ class classtype_nonlocal_gate(classtype_gate):
    #}
 #}
 
-# Classtype 3
-#
+# 200: Spawns/Waypoints
+# ---------------------------------------------------------------------------- #
+
 #  Purpose: player can reset here, its a safe place
 #           spawns can share the same name, the closest one will be picked
 #           
@@ -303,7 +457,7 @@ class classtype_spawn(Structure):
 
    def encode_obj(_, node,node_def):
    #{
-      node.classtype = 3
+      node.classtype = 200
       _.pstr_alias = encoder_process_pstr( node_def['obj'].cv_data.strp )
    #}
 
@@ -339,8 +493,9 @@ class classtype_spawn(Structure):
    #}
 #}
 
-# Classtype 4
-#
+# 300: Water
+# ---------------------------------------------------------------------------- #
+
 #  Purpose: Tells the game to draw water HERE, at this entity. 
 #
 class classtype_water(Structure):
@@ -350,710 +505,156 @@ class classtype_water(Structure):
 
    def encode_obj(_, node,node_def):
    #{
-      node.classtype = 4
+      node.classtype = 300
       # no data, spooky
    #}
 #}
 
-# Classtype 8
-#
-#  Purpose: Defines a route node and links to up to two more nodes
-#
-class classtype_route_node(Structure):
-#{
-   _pack_ = 1
-   _fields_ = [("target",c_uint32),
-               ("target1",c_uint32)]
-
-   def encode_obj(_, node,node_def):
-   #{
-      node.classtype = 8
-      obj = node_def['obj']
-
-      if obj.cv_data.target != None:
-         _.target = obj.cv_data.target.cv_data.uid
-      if obj.cv_data.target1 != None: 
-         _.target1 = obj.cv_data.target1.cv_data.uid
-   #}
-
-   @staticmethod
-   def draw_scene_helpers( obj ):
-   #{
-      global cv_view_verts, cv_view_colours
-
-      sw = Vector((0.4,0.4,0.4,0.2))
-      sw2 = Vector((1.5,0.2,0.2,0.0))
-      if obj.cv_data.target != None:
-         cv_draw_bpath( obj, obj.cv_data.target, sw, sw )
-      if obj.cv_data.target1 != None:
-         cv_draw_bpath( obj, obj.cv_data.target1, sw, sw )
-
-      cv_draw_bhandle( obj,  1.0, (0.8,0.8,0.8,1.0) )
-      cv_draw_bhandle( obj, -1.0, (0.4,0.4,0.4,1.0) )
-
-      p1 = obj.location+ \
-            obj.matrix_world.to_quaternion() @ Vector((0,0,-6+1.5))
-      cv_draw_arrow( obj.location, p1, sw )
-   #}
-
-   @staticmethod
-   def editor_interface( layout, obj ):
-   #{
-      layout.prop( obj.cv_data, "target", text="Left" )
-      layout.prop( obj.cv_data, "target1", text="Right" )
-   #}
-#}
-
-# Classtype 9
-#
-#  Purpose: Defines a route, its 'starting' point, and the colour to use for it
-#
-class classtype_route(Structure):
-#{
-   _pack_ = 1
-   _fields_ = [("id_start",c_uint32),
-               ("pstr_name",c_uint32),
-               ("colour",c_float*3)]
-
-   def encode_obj(_, node,node_def):
-   #{
-      node.classtype = 9
-      obj = node_def['obj']
-
-      _.colour[0] = obj.cv_data.colour[0]
-      _.colour[1] = obj.cv_data.colour[1]
-      _.colour[2] = obj.cv_data.colour[2]
-      _.pstr_name = encoder_process_pstr( obj.cv_data.strp )
-
-      if obj.cv_data.target != None: 
-         _.id_start = obj.cv_data.target.cv_data.uid
-   #}
-
-   @staticmethod
-   def draw_scene_helpers( obj ):
-   #{
-      global cv_view_verts, cv_view_colours, cv_view_course_i
-
-      if obj.cv_data.target:
-         cv_draw_arrow( obj.location, obj.cv_data.target.location, [1,1,1,1] )
-      
-      # Tries to simulate how we do it in the game
-      #
-      stack = [None]*64
-      stack_i = [0]*64
-      stack[0] = obj.cv_data.target
-      si = 1
-      loop_complete = False
-
-      while si > 0:
-      #{
-         if stack_i[si-1] == 2:
-         #{
-            si -= 1
-            continue
-
-            if si == 0: # Loop failed to complete
-               break
-         #}
-
-         node = stack[si-1]
-
-         targets = [None,None]
-         targets[0] = node.cv_data.target
-
-         if node.cv_data.classtype == 'classtype_route_node':
-         #{
-            targets[1] = node.cv_data.target1
-         #}
-         
-         nextnode = targets[stack_i[si-1]]
-         stack_i[si-1] += 1
-
-         if nextnode != None: # branch
-         #{
-            if nextnode == stack[0]: # Loop completed
-            #{
-               loop_complete = True
-               break
-            #}
-
-            valid=True
-            for sj in range(si):
-            #{
-               if stack[sj] == nextnode: # invalidated path
-               #{
-                  valid=False
-                  break
-               #}
-            #}
-
-            if valid:
-            #{
-               stack_i[si] = 0
-               stack[si] = nextnode
-               si += 1
-               continue
-            #}
-         #}
-      #}
-
-      if loop_complete:
-      #{
-         cc = Vector((obj.cv_data.colour[0],\
-                      obj.cv_data.colour[1],\
-                      obj.cv_data.colour[2],\
-                      1.0))
-
-         for sj in range(si):
-         #{
-            sk = (sj+1)%si
-
-            if stack[sj].cv_data.classtype == 'classtype_gate' and \
-               stack[sk].cv_data.classtype == 'classtype_gate':
-            #{
-               dist = (stack[sj].location-stack[sk].location).magnitude
-               cv_draw_sbpath( stack[sj], stack[sk], cc*0.4, cc, dist, dist )
-            #}
-            else:
-               cv_draw_bpath( stack[sj], stack[sk], cc, cc )
-         #}
-
-         cv_view_course_i += 1
-      #}
-   #}
-
-   @staticmethod
-   def editor_interface( layout, obj ):
-   #{
-      layout.prop( obj.cv_data, "target", text="'Start' from" )
-      layout.prop( obj.cv_data, "colour" )
-      layout.prop( obj.cv_data, "strp", text="Name" )
-   #}
-#}
-
-# Classtype 12
-#
-#  Purpose: links an mesh node to a type 11
-#
-class classtype_skin(Structure):
-#{
-   _pack_ = 1
-   _fields_ = [("skeleton",c_uint32)]
-
-   def encode_obj(_, node,node_def):
-   #{
-      node.classtype = 12
-      
-      armature_def = node_def['linked_armature']
-      _.skeleton = armature_def['obj'].cv_data.uid
-   #}
-#}
-
-# Classtype 11
-#
-#  Purpose: defines the allocation requirements for a skeleton
-#
-class classtype_skeleton(Structure):
-#{
-   _pack_ = 1
-   _fields_ = [("channels",c_uint32),
-               ("ik_count",c_uint32),
-               ("collider_count",c_uint32),
-               ("anim_start",c_uint32),
-               ("anim_count",c_uint32)]
-
-   def encode_obj(_, node,node_def):
-   #{
-      node.classtype = 11
-      
-      _.channels        = len( node_def['bones'] )
-      _.ik_count        = node_def['ik_count']
-      _.collider_count  = node_def['collider_count']
-      _.anim_start      = node_def['anim_start']
-      _.anim_count      = node_def['anim_count']
-   #}
-#}
-
-
-# Classtype 10
-#
-#  Purpose: intrinsic bone type, stores collision information and limits too
-#
-class classtype_bone(Structure):
-#{
-   _pack_ = 1
-   _fields_ = [("flags",c_uint32),
-               ("ik_target",c_uint32),
-               ("ik_pole",c_uint32),
-               ("hitbox",(c_float*3)*2),
-               ("conevx",c_float*3),
-               ("conevy",c_float*3),
-               ("coneva",c_float*3),
-               ("conet",c_float)]
-
-   def encode_obj(_, node,node_def):
-   #{
-      node.classtype = 10
-
-      armature_def = node_def['linked_armature']
-      obj = node_def['bone']
-      
-      _.flags = node_def['deform']
-      
-      if 'ik_target' in node_def:
-      #{
-         _.flags |= 0x2
-         _.ik_target = armature_def['bones'].index( node_def['ik_target'] )
-         _.ik_pole   = armature_def['bones'].index( node_def['ik_pole'] )
-      #}
-      
-      # For ragdolls
-      #
-      if obj.cv_data.collider != 'collider_none':
-      #{
-         if obj.cv_data.collider == 'collider_box':
-            _.flags |= 0x4
-         else:
-            _.flags |= 0x8
-
-         _.hitbox[0][0] =  obj.cv_data.v0[0]
-         _.hitbox[0][1] =  obj.cv_data.v0[2]
-         _.hitbox[0][2] = -obj.cv_data.v1[1]
-         _.hitbox[1][0] =  obj.cv_data.v1[0]
-         _.hitbox[1][1] =  obj.cv_data.v1[2]
-         _.hitbox[1][2] = -obj.cv_data.v0[1]
-      #}
-
-      if obj.cv_data.con0:
-      #{
-         _.flags |= 0x100
-         _.conevx[0] =  obj.cv_data.conevx[0]
-         _.conevx[1] =  obj.cv_data.conevx[2]
-         _.conevx[2] = -obj.cv_data.conevx[1]
-         _.conevy[0] =  obj.cv_data.conevy[0]
-         _.conevy[1] =  obj.cv_data.conevy[2]
-         _.conevy[2] = -obj.cv_data.conevy[1]
-         _.coneva[0] =  obj.cv_data.coneva[0]
-         _.coneva[1] =  obj.cv_data.coneva[2]
-         _.coneva[2] = -obj.cv_data.coneva[1]
-         _.conet = obj.cv_data.conet
-      #}
-   #}
-#}
-
-# Classtype 100
-#
-#  Purpose: sends a signal to another entity
-#
-class classtype_trigger(Structure):
-#{
-   _pack_ = 1
-   _fields_ = [("target",c_uint32)]
-
-   def encode_obj(_, node,node_def ):
-   #{
-      node.classtype = 100
-      if node_def['obj'].cv_data.target:
-         _.target = node_def['obj'].cv_data.target.cv_data.uid
-   #}
-
-   @staticmethod
-   def draw_scene_helpers( obj ):
-   #{
-      global cv_view_verts, cv_view_colours
-      cv_draw_ucube( obj.matrix_world, [0,1,0,1] )
-
-      white = (1,1,1,1)
-
-      if obj.cv_data.target:
-         cv_draw_arrow( obj.location, obj.cv_data.target.location, white, 0.7 )
-   #}
-
-   @staticmethod
-   def editor_interface( layout, obj ):
-   #{
-      layout.prop( obj.cv_data, "target", text="Triggers" )
-   #}
-#}
-
-# Classtype 101
-# 
-#  Purpose: Gives the player an achievement.
-#           No cheating! You shouldn't use this entity anyway, since only ME can
-#           add achievements to the steam ;)
-#
-class classtype_logic_achievement(Structure):
-#{
-   _pack_ = 1
-   _fields_ = [("pstr_name",c_uint32)]
-
-   def encode_obj(_, node,node_def ):
-   #{
-      node.classtype = 101
-      _.pstr_name = encoder_process_pstr( node_def['obj'].cv_data.strp )
-   #}
-
-   @staticmethod
-   def editor_interface( layout, obj ):
-   #{
-      layout.prop( obj.cv_data, "strp", text="Achievement ID" )
-   #}
-#}
-
-class union_128bit_data(Union):
-#{
-   _pack_ = 1
-   _fields_ = [("f32",c_float),
-               ("u32",c_uint32),
-               ("i32",c_int32),
-               ("v4f",c_float*4)]
-#}
-
-# Class type 105
-#
-#  Purpose:
-#
-class classtype_logic_wire(Structure):
-#{
-   _pack_ = 1
-   _fields_ = [("next",c_uint32),
-               ("function",c_uint32),
-               ("data",union_128bit_data),
-               ("data_type",c_uint32),
-               ("enabled",c_uint32)]
-
-   function_enum = [('0',"pass along",""),
-                    ('1',"enable",""),
-                    ('2',"disable",""),
-                    ('3',"","")]
-
-   def encode_obj(_,node,node_def):
-   #{
-      node.classtype = 105
-
-      obj = node_def['obj']
-
-      if obj.cv_data.target:  _.next = obj.cv_data.target.cv_data.uid
-
-      _.data_type = obj.cv_data.intp1
-      _.function = int(obj.cv_data.function)
-      _.enabled = obj.cv_data.bp0
-
-      if _.data_type == 1:                  # an integer
-         _.data.i32 = obj.cv_data.intp
-      elif _.data_type == 2:                # a number
-         _.data.f32 = obj.cv_data.fltp
-      elif _.data_type == 3:                # a target
-         if obj.cv_data.target2:
-            _.data.u32 = obj.cv_data.target2.cv_data.uid
-      elif _.data_type == 4:                # a string
-         _.data.u32 = encoder_process_pstr( obj.cv_data.strp )
-   #}
-
-   @staticmethod
-   def editor_interface( layout, obj ):
-   #{
-      layout.prop( obj.cv_data, "bp0", text="Start disabled" )
-      box = layout.box()
-      box.label( text="Target" )
-      box.prop( obj.cv_data, "target", text="connection" )
-
-      row = box.row()
-      if not obj.cv_data.target:
-         row.enabled=False
-      row.prop( obj.cv_data, "function", text="function" )
-
-      box = layout.box()
-      box.label( text="Data packet" )
-      box.prop( obj.cv_data, "intp1", text="type" )
-
-      if obj.cv_data.intp1 == 1:
-         box.prop( obj.cv_data, "intp", text="Signed Integer" )
-      elif obj.cv_data.intp1 == 2:
-         box.prop( obj.cv_data, "fltp", text="Float" )
-      elif obj.cv_data.intp1 == 3:
-         box.prop( obj.cv_data, "target2", text="Object reference" )
-      elif obj.cv_data.intp1 == 4:
-         box.prop( obj.cv_data, "strp", text="String" )
-      else:
-      #{
-         row = box.row()
-         row.enabled=False
-         row.label( text="this wire will not impart any data" )
-      #}
-   #}
-
-   @staticmethod
-   def draw_scene_helpers( obj ):
-   #{
-      global cv_view_verts, cv_view_colours
-
-      white = (1,1,1,1)
-      purple = (0.5,0.2,1,1)
-
-      if obj.cv_data.target:
-         cv_draw_arrow( obj.location, obj.cv_data.target.location, white, 0.7 )
-      if (obj.cv_data.target2) and (obj.cv_data.intp1 == 3):
-         cv_draw_arrow( obj.cv_data.target2.location, obj.location,purple, 0.7 )
-   #}
-
-   @staticmethod
-   def get_targeted_methods( scene, context ):
-   #{
-      obj = context.object
-      invalid = [('0',"",""),
-                 ('1',"",""),
-                 ('2',"",""),
-                 ('3',"","")]
-
-      if obj.cv_data.target:
-      #{
-         classtype = obj.cv_data.target.cv_data.classtype
-         if classtype == 'classtype_none' or classtype not in globals():
-         #{
-            return invalid
-         #}
-         else:
-         #{
-            cl = globals()[ classtype ]
-            if getattr( cl, "function_enum", None ):
-            #{
-               return cl.function_enum
-            #}
-            else:
-            #{
-               return invalid
-            #}
-         #}
-      #}
-      else:
-      #{
-         return invalid
-      #}
-   #}
-#}
-
-# Class type 108
-#
-#  Purpose:
-#
-class classtype_particle_box(Structure):
-#{
-   _pack_ = 1
-   _fields_ = [("target",c_uint32),
-               ("rate",c_float)]
-
-   function_enum = [('0',"set rate",""),
-                    ('1',"",""),
-                    ('2',"",""),
-                    ('3',"","")]
-
-   def encode_obj(_, node,node_def ):
-   #{
-      node.classtype = 108
-
-      obj = node_def['obj']
-
-      _.rate = obj.cv_data.fltp
-      if obj.cv_data.target:
-         _.target = obj.cv_data.target.cv_data.uid
-   #}
-
-   @staticmethod
-   def draw_scene_helpers( obj ):
-   #{
-      global cv_view_verts, cv_view_colours
-      cv_draw_ucube( obj.matrix_world, [1,0.8,0,1] )
-
-      white = (1,1,1,1)
-      if obj.cv_data.target:
-         cv_draw_arrow( obj.location, obj.cv_data.target.location, white, 0.7 )
-   #}
-
-   @staticmethod
-   def editor_interface( layout, obj ):
-   #{
-      layout.prop( obj.cv_data, "target", text="Triggers" )
-      layout.prop( obj.cv_data, "fltp", text="count per second" )
-   #}
-#}
-
-# Class type 109
-#
-#  Purpose:
-#
-class classtype_signal_splitter(Structure):
-#{
-   _pack_ = 1
-   _fields_ = [("next",c_uint32*4)]
-
-   function_enum = [('0',"pass along",""),
-                    ('1',"",""),
-                    ('2',"",""),
-                    ('3',"","")]
-
-   def encode_obj(_,node,node_def):
-   #{
-      node.classtype = 109
-
-      obj = node_def['obj']
-
-      if obj.cv_data.target:   _.next[0] = obj.cv_data.target.cv_data.uid
-      if obj.cv_data.target1:  _.next[1] = obj.cv_data.target1.cv_data.uid
-      if obj.cv_data.target2:  _.next[2] = obj.cv_data.target2.cv_data.uid
-      if obj.cv_data.target3:  _.next[3] = obj.cv_data.target3.cv_data.uid
-   #}
-
-   @staticmethod
-   def editor_interface( layout, obj ):
-   #{
-      layout.label( text="The split signals will run in order" )
-      layout.prop( obj.cv_data, "target", text="#0" )
-      layout.prop( obj.cv_data, "target1", text="#1" )
-      layout.prop( obj.cv_data, "target2", text="#2" )
-      layout.prop( obj.cv_data, "target3", text="#3" )
-   #}
-
-   @staticmethod
-   def draw_scene_helpers( obj ):
-   #{
-      global cv_view_verts, cv_view_colours
-
-      c0 = (1,0.5,0.2,1)
-      c1 = (0.8,1,0.1,1)
-      c2 = (0.3,0.9,0.4,1)
-      c3 = (0.1,0.4,1.0,1)
-
-      if obj.cv_data.target:
-         cv_draw_arrow( obj.location, obj.cv_data.target.location, c0, 0.7 )
-      if obj.cv_data.target1:
-         cv_draw_arrow( obj.location, obj.cv_data.target1.location, c1, 0.7 )
-      if obj.cv_data.target2:
-         cv_draw_arrow( obj.location, obj.cv_data.target2.location, c2, 0.7 )
-      if obj.cv_data.target3:
-         cv_draw_arrow( obj.location, obj.cv_data.target3.location, c3, 0.7 )
-   #}
-#}
+# 400: Routes
+# ---------------------------------------------------------------------------- #
 
-# Class type 106
-#
-#  Purpose:
+#  Purpose: Defines a route, its 'starting' point, and the colour to use for it
 #
-class classtype_soundscape(Structure):
+class classtype_route(Structure):
 #{
    _pack_ = 1
-   _fields_ = [("max_instances",c_uint32),
-               ("allow_transitions",c_uint32),
-               ("transition_duration",c_float),
-               ("label",c_uint32)]
-
-   function_enum = [('0',"play",""),
-                    ('1',"set position",""),
-                    ('2',"",""),
-                    ('3',"","")]
+   _fields_ = [("id_start",c_uint32),
+               ("pstr_name",c_uint32),
+               ("colour",c_float*3)]
 
-   def encode_obj(_,node,node_def):
+   def encode_obj(_, node,node_def):
    #{
-      node.classtype = 106
-
+      node.classtype = 400
       obj = node_def['obj']
 
-      _.max_instances = obj.cv_data.intp
-      _.allow_transitions = obj.cv_data.bp0
-      _.transition_duration = obj.cv_data.fltp
-      _.label = encoder_process_pstr( obj.cv_data.strp )
+      _.colour[0] = obj.cv_data.colour[0]
+      _.colour[1] = obj.cv_data.colour[1]
+      _.colour[2] = obj.cv_data.colour[2]
+      _.pstr_name = encoder_process_pstr( obj.cv_data.strp )
+
+      if obj.cv_data.target != None: 
+         _.id_start = obj.cv_data.target.cv_data.uid
    #}
 
    @staticmethod
-   def editor_interface( layout, obj ):
+   def draw_scene_helpers( obj ):
    #{
-      layout.prop( obj.cv_data, "intp", text="max instances" )
-      layout.prop( obj.cv_data, "strp", text="label" )
+      global cv_view_verts, cv_view_colours, cv_view_course_i
 
-      box = layout.box()
-      box.label( text="If its a 3d sound, where can it spawn?" )
-      box.prop( obj.cv_data, "bp1", text="Only in water" )
-      box.prop( obj.cv_data, "bp2", text="Only on grass" )
-      box.prop( obj.cv_data, "bp3", text="Only on wood" )
+      if obj.cv_data.target:
+         cv_draw_arrow( obj.location, obj.cv_data.target.location, [1,1,1,1] )
+      
+      # Tries to simulate how we do it in the game
+      #
+      stack = [None]*64
+      stack_i = [0]*64
+      stack[0] = obj.cv_data.target
+      si = 1
+      loop_complete = False
 
-      box = layout.box()
-      box.prop( obj.cv_data, "bp0", text="allow transitions" )
+      while si > 0:
+      #{
+         if stack_i[si-1] == 2:
+         #{
+            si -= 1
+            continue
 
-      row = box.row()
-      if not obj.cv_data.bp0:
-         row.enabled=False
-      row.prop( obj.cv_data, "fltp", text="transition duration" )
-   #}
-#}
+            if si == 0: # Loop failed to complete
+               break
+         #}
 
-class classtype_logic_chances(Structure):
-#{
-   _pack_ = 1
-   _fields_ = [("targets",c_uint32*2),
-               ("p",c_float)]
+         node = stack[si-1]
 
-   function_enum = [('0',"pass along",""),
-                    ('1',"set ratio",""),
-                    ('2',"",""),
-                    ('3',"","")]
+         targets = [None,None]
+         targets[0] = node.cv_data.target
 
-   def encode_obj(_,node,node_def):
-   #{
-      node.classtype = 107
+         if node.cv_data.classtype == 'classtype_route_node':
+         #{
+            targets[1] = node.cv_data.target1
+         #}
+         
+         nextnode = targets[stack_i[si-1]]
+         stack_i[si-1] += 1
 
-      obj = node_def['obj']
+         if nextnode != None: # branch
+         #{
+            if nextnode == stack[0]: # Loop completed
+            #{
+               loop_complete = True
+               break
+            #}
 
-      if obj.cv_data.target:  _.targets[0] = obj.cv_data.target.cv_data.uid
-      if obj.cv_data.target1: _.targets[1] = obj.cv_data.target1.cv_data.uid
-      
-      _.p = obj.cv_data.fltp
-   #}
+            valid=True
+            for sj in range(si):
+            #{
+               if stack[sj] == nextnode: # invalidated path
+               #{
+                  valid=False
+                  break
+               #}
+            #}
 
-   @staticmethod
-   def editor_interface( layout, obj ):
-   #{
-      box = layout.box()
-      box.prop( obj.cv_data, "target", text="red" )
-      box.prop( obj.cv_data, "target1", text="black" )
-      box.prop( obj.cv_data, "fltp", text="p(red)" )
+            if valid:
+            #{
+               stack_i[si] = 0
+               stack[si] = nextnode
+               si += 1
+               continue
+            #}
+         #}
+      #}
+
+      if loop_complete:
+      #{
+         cc = Vector((obj.cv_data.colour[0],\
+                      obj.cv_data.colour[1],\
+                      obj.cv_data.colour[2],\
+                      1.0))
+
+         for sj in range(si):
+         #{
+            sk = (sj+1)%si
+
+            if stack[sj].cv_data.classtype == 'classtype_gate' and \
+               stack[sk].cv_data.classtype == 'classtype_gate':
+            #{
+               dist = (stack[sj].location-stack[sk].location).magnitude
+               cv_draw_sbpath( stack[sj], stack[sk], cc*0.4, cc, dist, dist )
+            #}
+            else:
+               cv_draw_bpath( stack[sj], stack[sk], cc, cc )
+         #}
+
+         cv_view_course_i += 1
+      #}
    #}
 
    @staticmethod
-   def draw_scene_helpers( obj ):
+   def editor_interface( layout, obj ):
    #{
-      global cv_view_verts, cv_view_colours
-
-      red = (1,0,0,1)
-      black = (0,0,0,1)
-
-      if obj.cv_data.target:
-         cv_draw_arrow( obj.location, obj.cv_data.target.location, red, 0.7 )
-      if obj.cv_data.target1:
-         cv_draw_arrow( obj.location, obj.cv_data.target1.location, black, 0.7 )
+      layout.prop( obj.cv_data, "target", text="'Start' from" )
+      layout.prop( obj.cv_data, "colour" )
+      layout.prop( obj.cv_data, "strp", text="Name" )
    #}
 #}
 
-# Classtype 102 [ DEPRECATED ]
-#
-#  Purpose: sends a signal to another entity
+#  Purpose: Defines a route node and links to up to two more nodes
 #
-class classtype_logic_relay(Structure):
+class classtype_route_node(Structure):
 #{
    _pack_ = 1
-   _fields_ = [("targets",c_uint32*4)]
+   _fields_ = [("target",c_uint32),
+               ("target1",c_uint32)]
 
-   def encode_obj(_, node,node_def ):
+   def encode_obj(_, node,node_def):
    #{
-      node.classtype = 102
+      node.classtype = 401
       obj = node_def['obj']
-      if obj.cv_data.target:
-         _.targets[0] = obj.cv_data.target.cv_data.uid
-      if obj.cv_data.target1:
-         _.targets[1] = obj.cv_data.target1.cv_data.uid
-      if obj.cv_data.target2:
-         _.targets[2] = obj.cv_data.target2.cv_data.uid
-      if obj.cv_data.target3:
-         _.targets[3] = obj.cv_data.target3.cv_data.uid
+
+      if obj.cv_data.target != None:
+         _.target = obj.cv_data.target.cv_data.uid
+      if obj.cv_data.target1 != None: 
+         _.target1 = obj.cv_data.target1.cv_data.uid
    #}
 
    @staticmethod
@@ -1061,40 +662,45 @@ class classtype_logic_relay(Structure):
    #{
       global cv_view_verts, cv_view_colours
 
-      if obj.cv_data.target:
-         cv_draw_arrow( obj.location, obj.cv_data.target.location, [1,1,1,1] )
-      if obj.cv_data.target1:
-         cv_draw_arrow( obj.location, obj.cv_data.target1.location, [1,1,1,1] )
-      if obj.cv_data.target2:
-         cv_draw_arrow( obj.location, obj.cv_data.target2.location, [1,1,1,1] )
-      if obj.cv_data.target3:
-         cv_draw_arrow( obj.location, obj.cv_data.target3.location, [1,1,1,1] )
+      sw = Vector((0.4,0.4,0.4,0.2))
+      sw2 = Vector((1.5,0.2,0.2,0.0))
+      if obj.cv_data.target != None:
+         cv_draw_bpath( obj, obj.cv_data.target, sw, sw )
+      if obj.cv_data.target1 != None:
+         cv_draw_bpath( obj, obj.cv_data.target1, sw, sw )
+
+      cv_draw_bhandle( obj,  1.0, (0.8,0.8,0.8,1.0) )
+      cv_draw_bhandle( obj, -1.0, (0.4,0.4,0.4,1.0) )
+
+      p1 = obj.location+ \
+            obj.matrix_world.to_quaternion() @ Vector((0,0,-6+1.5))
+      cv_draw_arrow( obj.location, p1, sw )
    #}
 
    @staticmethod
    def editor_interface( layout, obj ):
    #{
-      layout.prop( obj.cv_data, "target", text="Triggers" )
-      layout.prop( obj.cv_data, "target1", text="Triggers" )
-      layout.prop( obj.cv_data, "target2", text="Triggers" )
-      layout.prop( obj.cv_data, "target3", text="Triggers" )
+      layout.prop( obj.cv_data, "target", text="Left" )
+      layout.prop( obj.cv_data, "target1", text="Right" )
    #}
 #}
 
-# Classtype 14
-#
-#  Purpose: Plays some audio (44100hz .ogg vorbis only)
-#           NOTE: There is a 32mb limit on the audio buffer, world audio is
-#                 decompressed and stored in signed 16 bit integers (2 bytes)
-#                 per sample.
-#
-#   volume: not used if has 3D flag
+
+# 500: Audio
+# ---------------------------------------------------------------------------- #
+
+AUDIO_SPRITE_CATEGORIES_ENUM = [
+      ('0', "Bird", ""),
+      ('1', "Nocturnal Bird", ""),
+      ('2', "Grass", ""),
+      ('3', "Wave",""),
+      ('4', "Wind",""),
+      ('5', "Wood Creaks", ""),
+   ]
+
 #    flags: 
 #           AUDIO_FLAG_LOOP        0x1
 #           AUDIO_FLAG_SPACIAL_3D  0x4  (Probably what you want)
-#           AUDIO_FLAG_AUTO_START  0x8  (Play when the world starts)
-#           ......
-#           the rest are just internal flags, only use the above 3.
 #
 class classtype_audio(Structure):
 #{
@@ -1103,9 +709,16 @@ class classtype_audio(Structure):
                ("flags",c_uint32),
                ("volume",c_float)]
 
+   dynamic_enum = [
+      ('0', "mono", ""),
+      ('1', "stereo", ""),
+      ('2', "remain compressed", ""),
+      ('3', "synthetic bird",""),
+   ]
+
    def encode_obj(_, node,node_def ):
    #{
-      node.classtype = 14
+      node.classtype = 500
 
       obj = node_def['obj']
 
@@ -1116,12 +729,9 @@ class classtype_audio(Structure):
       if obj.cv_data.bp1: flags |= 0x4
       if obj.cv_data.bp2: flags |= 0x8
 
-      if obj.cv_data.audio_format == 'stereo':
-         flags |= 0x200
-      if obj.cv_data.audio_format == 'remain compressed':
-         flags |= 0x400
-      if obj.cv_data.audio_format == 'synthetic bird':
-         flags |= 0x1000
+      if obj.cv_data.dynamic_enum == '1': flags |= 0x200
+      if obj.cv_data.dynamic_enum == '2': flags |= 0x400
+      if obj.cv_data.dynamic_enum == '3': flags |= 0x1000
 
       _.flags = flags
       _.volume = obj.cv_data.fltp
@@ -1130,12 +740,12 @@ class classtype_audio(Structure):
    @staticmethod
    def editor_interface( layout, obj ):
    #{
-      layout.prop( obj.cv_data, "strp", text = "File (.ogg)" )
+      layout.prop( obj.cv_data, "strp", text = "File (.ogg/DATA)" )
 
       layout.prop( obj.cv_data, "bp0", text = "Looping" )
       layout.prop( obj.cv_data, "bp1", text = "3D Audio" )
-      layout.prop( obj.cv_data, "bp2", text = "Auto Start" )
-      layout.prop( obj.cv_data, "audio_format" )
+      layout.prop( obj.cv_data, "bp2", text = "Play here" )
+      layout.prop( obj.cv_data, "dynamic_enum" )
 
       layout.prop( obj.cv_data, "fltp", text = "Volume (0-1)" )
    #}
@@ -1145,127 +755,101 @@ class classtype_audio(Structure):
    #{
       global cv_view_verts, cv_view_colours
 
-      cv_draw_sphere( obj.location, obj.scale[0], [1,1,0,1] )
+      if bpy.context.active_object == obj:
+         cv_draw_sphere( obj.location, obj.scale[0], [1,1,0,1] )
    #}
 #}
 
-
-# Classtype 200
-# 
-#  Purpose: world light
-#
-class classtype_world_light( Structure ):
+class classtype_audio_sprite(Structure):
 #{
    _pack_ = 1
-   _fields_ = [("type",c_uint32),
-               ("colour",c_float*4),
-               ("angle",c_float),
-               ("range",c_float)]
+   _fields_ = [("audio",c_uint32),
+               ("category",c_uint32),
+               ("probability",c_float)]
 
-   def encode_obj(_, node, node_def):
-   #{
-      node.classtype = 200
+   dynamic_enum = AUDIO_SPRITE_CATEGORIES_ENUM
 
-      obj  = node_def['obj']
-      data = obj.data
-      _.colour[0] = data.color[0]
-      _.colour[1] = data.color[1]
-      _.colour[2] = data.color[2]
-      _.colour[3] = data.energy
-      _.range = data.cutoff_distance # this has to be manually set
-                                     # TODO: At some point, automate a min
-                                     #       threshold value
+   def encode_obj(_, node,node_def ):
+   #{
+      node.classtype = 501
+      obj = node_def['obj']
 
-      if obj.data.type == 'POINT':
-      #{
-         _.type = 0
-         _.angle = 0.0
-      #}
-      elif obj.data.type == 'SPOT':
-      #{
-         _.type = 1
-         _.angle = data.spot_size*0.5
-      #}
+      _.category = int( obj.cv_data.dynamic_enum )
+      _.probability = obj.cv_data.fltp
 
-      if data.cv_data.bp0:
-         _.type += 2
+      if obj.cv_data.target:
+         _.audio = obj.cv_data.target.cv_data.uid
    #}
 
    @staticmethod
    def editor_interface( layout, obj ):
    #{
-      pass
+      layout.prop( obj.cv_data, "dynamic_enum", text="Category" )
+      layout.prop( obj.cv_data, "target", text="Sound" )
+      layout.prop( obj.cv_data, "fltp", text="Probability" )
+   #}
+
+   @staticmethod
+   def draw_scene_helpers( obj ):
+   #{
+      global cv_view_verts, cv_view_colours
+
+      purple = (0.5,0.2,1,1)
+      if obj.cv_data.target:
+         cv_draw_arrow( obj.location, obj.cv_data.target.location, purple, 0.1 )
    #}
 #}
 
-# Classtype 201
-# 
-#  Purpose: lighting settings for world
-#
-class classtype_lighting_info(Structure):
+
+# 600: Volumes
+# ---------------------------------------------------------------------------- #
+
+class classtype_volume_audio(Structure):
 #{
    _pack_ = 1
-   _fields_ = [("colours",(c_float*3)*3),
-               ("directions",(c_float*2)*3),
-               ("states",c_uint32*3),
-               ("shadow_spread",c_float),
-               ("shadow_length",c_float),
-               ("ambient",c_float*3)]
+   _fields_ = [("category",c_uint32)]
 
-   def encode_obj(_, node, node_def):
+   dynamic_enum = AUDIO_SPRITE_CATEGORIES_ENUM
+
+   def encode_obj(_, node,node_def ):
    #{
-      node.classtype = 201
+      node.classtype = 600
+
+      obj = node_def['obj']
+      _.category = int(obj.cv_data.dynamic_enum)
+   #}
 
-      # TODO
+   @staticmethod
+   def draw_scene_helpers( obj ):
+   #{
+      global cv_view_verts, cv_view_colours
+      cv_draw_ucube( obj.matrix_world, [1,0.8,0,1] )
    #}
 
    @staticmethod
    def editor_interface( layout, obj ):
    #{
-      pass
+      layout.prop( obj.cv_data, "dynamic_enum", text="Category" )
    #}
 #}
 
-class classtype_spawn_link(Structure):
+class classtype_volume_event(Structure):
 #{
    _pack_ = 1
-   _fields_ = [("connections",c_uint32*4)]
+   _fields_ = [("event",c_uint32)]
 
    def encode_obj(_, node,node_def ):
    #{
-      node.classtype = 0
-   #}
-
-   @staticmethod
-   def editor_interface( layout, obj ):
-   #{
-      pass
+      node.classtype = 601
+      obj = node_def['obj']
+      _.event = encoder_process_pstr( obj.cv_data.strp )
    #}
 
    @staticmethod
    def draw_scene_helpers( obj ):
    #{
       global cv_view_verts, cv_view_colours
-
-      count = 0
-
-      for obj1 in bpy.context.collection.objects:
-      #{
-         if (obj1.cv_data.classtype != 'classtype_spawn_link') and \
-            (obj1.cv_data.classtype != 'classtype_spawn') :
-            continue
-
-         if (obj1.location - obj.location).length < 40.0:
-         #{
-            cv_draw_line( obj.location, obj1.location, [1,1,1,1] )
-            count +=1
-         #}
-
-         if count == 4:
-            break
-      #}
-      
-      cv_draw_sphere( obj.location, 20.0, [0.5,0,0.2,0.4] )
+      cv_draw_ucube( obj.matrix_world, [0.0,1.0,0,1] )
    #}
 #}
 
@@ -3020,6 +2604,33 @@ class CV_LIGHT_PANEL(bpy.types.Panel):
    #}
 #}
 
+def cv_variable_enum( scene, context ):
+#{
+   obj = context.object
+   invalid = [('0',"",""),
+              ('1',"",""),
+              ('2',"",""),
+              ('3',"",""),
+              ('4',"",""),
+              ('5',"",""),
+              ('6',"",""),
+              ('7',"",""),
+              ('8',"",""),
+              ('9',"","")]
+
+   classtype = obj.cv_data.classtype
+
+   if classtype in globals():
+   #{
+      cl = globals()[ classtype ]
+      if getattr( cl, "dynamic_enum", None ):
+         if len(cl.dynamic_enum)>0:
+            return cl.dynamic_enum
+   #}
+
+   return invalid
+#}
+
 class CV_OBJ_SETTINGS(bpy.types.PropertyGroup):
 #{
    uid: bpy.props.IntProperty( name="" )
@@ -3045,40 +2656,28 @@ class CV_OBJ_SETTINGS(bpy.types.PropertyGroup):
    colour: bpy.props.FloatVectorProperty( name="colour",subtype='COLOR',\
                                           min=0.0,max=1.0)
 
-   function: bpy.props.EnumProperty(
-      name="Function",
-      items= classtype_logic_wire.get_targeted_methods
+   dynamic_enum: bpy.props.EnumProperty(
+      name="",
+      items = cv_variable_enum
    )
 
    classtype: bpy.props.EnumProperty(
-      name="Format", 
-      items = [
-      ('classtype_none', "classtype_none", "", 0),
-      ('classtype_gate', "classtype_gate", "", 1),
-      ('classtype_spawn', "classtype_spawn", "", 3),
-      ('classtype_water', "classtype_water", "", 4),
-      ('classtype_route_node', "classtype_route_node", "", 8 ),
-      ('classtype_route', "classtype_route", "", 9 ),
-      ('classtype_audio',"classtype_audio","",14),
-      ('classtype_trigger',"classtype_trigger","",100),
-      ('classtype_logic_achievement',"classtype_logic_achievement","",101),
-      ('classtype_logic_relay',"classtype_logic_relay","",102),
-      ('classtype_logic_wire',"classtype_logic_wire","",105),
-      ('classtype_soundscape',"classtype_soundscape","",106),
-      ('classtype_logic_chances',"classtype_logic_chances","",107),
-      ('classtype_particle_box',"classtype_particle_box","",108),
-      ('classtype_signal_splitter',"classtype_signal_splitter","",109),
-      ('classtype_spawn_link',"classtype_spawn_link","",150),
-      ('classtype_nonlocal_gate', "classtype_nonlocal_gate", "", 300)
-      ])
-
-   audio_format: bpy.props.EnumProperty(
-      name="Loaded format",
+      name="Class", 
       items = [
-         ('mono', "mono", "", 0),
-         ('stereo', "stereo", "", 1),
-         ('remain compressed', "remain compressed", "", 2),
-         ('synthetic bird',"synthetic bird","",3)
+      ('classtype_none',            "None",             ""), #000
+      ('classtype_gate',            "Gate",             ""), #100
+      ('classtype_nonlocal_gate',   "Gate:NonLocal",    ""), #101
+      ('classtype_spawn',           "Spawn",            ""), #200
+      ('classtype_water',           "Water Surface",    ""), #300
+      ('classtype_route',           "Route",            ""), #400
+      ('classtype_route_node',      "Route:Node",       ""), #401
+      ('classtype_audio',           "Audio:File",       ""), #500
+      ('classtype_audio_player',    "Audio:Player",     ""), #501
+      ('classtype_audio_sprite',    "Audio:Sprite",     ""), #502
+      ('classtype_volume_audio',    "Volume:Audio",     ""), #600
+      ('classtype_volume_event',    "Volume:Event",     ""), #601
+
+      ('300',                       "ERROR",            "",300)
       ])
 #}
 
diff --git a/bvh.h b/bvh.h
index 94ea69bdf91d95c8ea86b0f79a44c3a33b940848..23f8a564d54cd7ce1b7830457da97ce15ad790d7 100644 (file)
--- a/bvh.h
+++ b/bvh.h
@@ -167,7 +167,7 @@ VG_STATIC bh_tree *bh_create( void *lin_alloc, bh_system *system,
    totsize = sizeof(bh_tree) + sizeof(bh_node) * bh->node_count;
    bh = vg_linear_resize( lin_alloc, bh, totsize );
 
-   vg_success( "BVH done, size: %u/%u\n", bh->node_count, (item_count*2-1) );
+   vg_success( "BVH done, size: %u/%u\n", bh->node_count, (alloc_count*2-1) );
    return bh;
 }
 
index be210a5d49ff89046aafe263a7475857b163d9a8..19b5a6fa5d84130b030ec431864fb0a911270aaa 100644 (file)
--- a/common.h
+++ b/common.h
@@ -119,7 +119,6 @@ VG_STATIC int   k_debug_light_indices = 0,
                 k_light_preview = 0;
 
 VG_STATIC int freecam = 0;
-VG_STATIC int debug_logic_bricks = 0;
 VG_STATIC int walk_grid_iterations = 1;
 VG_STATIC float fc_speed = 10.0f;
 VG_STATIC int cl_thirdperson = 0;
@@ -151,7 +150,6 @@ VG_STATIC void common_var_temp(void)
    VG_VAR_F32( k_walk_accel );
 
    VG_VAR_I32( freecam );
-   VG_VAR_F32_PERSISTENT( debug_logic_bricks );
    VG_VAR_I32( cl_thirdperson );
    VG_VAR_F32_PERSISTENT( fc_speed );
 
index d451ace265f6c8f7bc58cf841a68640ac204e37f..b5569f6680389f02a73f70d08275cf3185f043cd 100644 (file)
Binary files a/maps_src/mp_home.mdl and b/maps_src/mp_home.mdl differ
index a6dde601850623af86d031a2a729b3770ce93f7d..c6b5f5be87042eadd6aa14c340a9546144a801d4 100644 (file)
Binary files a/maps_src/mp_mtzero.mdl and b/maps_src/mp_mtzero.mdl differ
diff --git a/model.h b/model.h
index 6134fc50dd9d9df836d09022fcfb8121d2bb63cd..6f99fb61d77044d489147a9fa9a9a32b97569a3a 100644 (file)
--- a/model.h
+++ b/model.h
@@ -29,29 +29,21 @@ typedef struct mdl_context mdl_context;
 
 enum classtype
 {
-   k_classtype_none                 = 0,
-   k_classtype_gate                 = 1,
-   k_classtype_spawn                = 3,
-   k_classtype_water                = 4,
-   k_classtype_route_node           = 8,
-   k_classtype_route                = 9,
-   k_classtype_bone                 = 10,
-   k_classtype_skeleton             = 11,
-   k_classtype_skin                 = 12,
-   k_classtype_audio                = 14,
-   k_classtype_trigger              = 100,
-   k_classtype_logic_achievement    = 101,
-   k_classtype_logic_relay          = 102,
-   k_classtype_logic_script         = 103,
-
-   k_classtype_logic_wire           = 105,
-   k_classtype_soundscape           = 106,
-   k_classtype_logic_chances        = 107,
-   k_classtype_particle_box         = 108,
-   k_classtype_signal_splitter      = 109,
-
-   k_classtype_world_light          = 200,
-   k_classtype_nonlocal_gate        = 300
+   k_classtype_none                 = 000,
+   k_classtype_bone                 = 001,
+   k_classtype_skeleton             = 002,
+   k_classtype_skin                 = 003,
+   k_classtype_world_light          = 004,
+
+   k_classtype_gate                 = 100,
+   k_classtype_nonlocal_gate        = 101,
+   k_classtype_spawn                = 200,
+   k_classtype_water                = 300,
+   k_classtype_route                = 400,
+   k_classtype_route_node           = 401,
+   k_classtype_audio                = 500,
+   k_classtype_audio_sprite         = 502,
+   k_classtype_volume_audio         = 600,
 };
 
 enum mdl_shader
@@ -203,35 +195,7 @@ struct mdl_file_header
  * Entity data structures
  */
 
-struct classtype_gate
-{
-   u32 target;
-   v3f dims;
-};
-
-struct classtype_spawn
-{
-   u32 pstr_alias;
-};
-
-struct classtype_water
-{
-   u32 temp;
-};
-
-struct classtype_route_node
-{
-   u32 target, target1;
-};
-
-struct classtype_route
-{
-   u32 id_start;
-   u32 pstr_name;
-   v3f colour;
-};
-
-struct classtype_bone
+struct classtype_bone            /* 001 */
 {
    u32 flags,
        ik_target,
@@ -243,7 +207,7 @@ struct classtype_bone
    float conet;
 };
 
-struct classtype_skeleton
+struct classtype_skeleton        /* 002 */
 {
    u32 channels,
        ik_count,
@@ -252,103 +216,80 @@ struct classtype_skeleton
        anim_count;
 };
 
-struct classtype_skin
+struct classtype_skin            /* 003 */
 {
    u32 skeleton;
 };
 
-struct classtype_trigger
+struct classtype_world_light     /* 004 */
 {
-   u32 target;
+   enum light_type 
+   {
+      k_light_type_point,
+      k_light_type_spot,
+      k_light_type_point_nighttime_only,
+      k_light_type_spot_nighttime_only
+   } 
+   type;
+
+   v4f colour; /* RGB, Energy */
+   float angle, range;
 };
 
-struct classtype_particle_box
+
+struct classtype_gate            /* 100, 101 */
 {
    u32 target;
-   float rate;
+   v3f dims;
 };
 
-struct classtype_signal_splitter
+struct classtype_spawn           /* 200 */
 {
-   u32 next[4];
+   u32 pstr_alias;
 };
 
-struct classtype_logic_relay
+struct classtype_water           /* 300 */
 {
-   u32 targets[4];
+   u32 temp;
 };
 
-struct classtype_logic_achievement
+struct classtype_route           /* 400 */
 {
+   u32 id_start;
    u32 pstr_name;
+   v3f colour;
 };
 
-struct classtype_audio
+struct classtype_route_node      /* 401 */
 {
-   u32 pstr_file,
-       flags;
-
-   float volume;
+   u32 target, target1;
 };
 
-struct classtype_world_light
+
+struct classtype_audio           /* 500 */
 {
-   enum light_type 
-   {
-      k_light_type_point,
-      k_light_type_spot,
-      k_light_type_point_nighttime_only,
-      k_light_type_spot_nighttime_only
-   } 
-   type;
+   u32 pstr_file,
+       flags;
 
-   v4f colour; /* RGB, Energy */
-   float angle, range;
+   float volume;
 };
 
-struct classtype_logic_wire
+struct classtype_audio_sprite    /* 501 */
 {
-   u32 next,
-       function;
-
-   union mdl_128bit_union
-   {
-      float _f32;
-      u32   _u32;
-      i32   _i32;
-      v4f   _v4f;
-   }
-   data;
+   u32 audio,
+       category;
 
-   enum mdl_128bit_datatype
-   {
-      k_mdl_128bit_datatype_nothing = 0u,
-      k_mdl_128bit_datatype_integer = 1u,
-      k_mdl_128bit_datatype_number  = 2u,
-      k_mdl_128bit_datatype_target  = 3u,
-      k_mdl_128bit_datatype_string  = 4u,
-      k_mdl_128bit_datatype_vec2    = 5u,
-      k_mdl_128bit_datatype_vec3    = 6u,
-      k_mdl_128bit_datatype_vec4    = 7u
-   }
-   data_type;
-
-   u32 enabled;
+   float probability;
 };
 
-struct classtype_soundscape
+struct classtype_volume_audio    /* 600 */
 {
-   u32 max_instances,
-       allow_transitions;
-
-   float transition_duration;
-   u32 label;
+   u32 category;
 };
 
-struct classtype_logic_chances
+struct classtype_volume_event    /* 601 */
 {
-   u32 targets[2];
-   float p;
+   u32 event;
 };
 
 #pragma pack(pop)
index 56c776c820b3f7c77880bbf50d85d04e912eb30b..6170a11f03d4e69fbf22e114f0d62bc9156a6eec 100644 (file)
Binary files a/models_src/ch_jordan.mdl and b/models_src/ch_jordan.mdl differ
index b50b895de16a5238fb39ac5db39351d5d50690fe..e727a00356922d019d0bac8059d180e9756d6f3f 100644 (file)
Binary files a/models_src/ch_new.mdl and b/models_src/ch_new.mdl differ
index 5a1caca7ad76be8459f0700515084008a70ad42d..13229be188e5bd1afb5177218211fe596d5f3e25 100644 (file)
Binary files a/models_src/ch_outlaw.mdl and b/models_src/ch_outlaw.mdl differ
index e5d228865fac8e154d012f3d062603aa8b2a71a7..a6abbee67913f079006d93baf1e3477ffc771685 100644 (file)
@@ -254,7 +254,6 @@ VG_STATIC void vg_load(void)
 
    vg_bake_shaders();
    vg_loader_step( audio_init, audio_free );
-   world_audio_init();
 
    /* 'systems' are completely loaded now */
 
@@ -263,10 +262,10 @@ VG_STATIC void vg_load(void)
 
 #if 0
    world_load( &world_global.worlds[1], "maps/mp_gridmap.mdl" );
-   world_load( &world_global.worlds[2], "maps/mp_mtzero.mdl" );
    world_link_nonlocal_gates( 0, 1 );
-   world_link_nonlocal_gates( 0, 2 );
 #endif
+   world_load( &world_global.worlds[2], "maps/mp_mtzero.mdl" );
+   world_link_nonlocal_gates( 0, 2 );
 
    vg_console_load_autos();
 }
diff --git a/world.h b/world.h
index b1fc80d9b3a1db4bc5ba46fd358c7c1146c7a041..acfd462d4d2cb1e8746ee081d8ae1bec64fedf81 100644 (file)
--- a/world.h
+++ b/world.h
@@ -172,36 +172,11 @@ struct world_instance
       v3f pos;
       float volume, range;
       u32 flags;
-
-#if 0
-      audio_player player;
-#endif
-
       audio_clip temp_embedded_clip;
    }
    * audio_things;
    u32 audio_things_count;
 
-#if 0
-   /*
-    * Relays  [ DEPRECATED ]
-    */
-   struct logic_relay
-   {
-      v3f pos;
-
-      struct relay_target
-      {
-         u32 sub_id;
-         enum classtype classtype;
-      }
-      targets[4];
-      u32 target_count;
-   }
-   * logic_relays;
-   u32 relay_count;
-#endif
-
    struct soundscape
    {
       /* locking */
@@ -219,40 +194,16 @@ struct world_instance
    * soundscapes;
    u32 soundscape_count;
 
-   struct logic_brick_ref
-   {
-      mdl_node *node;
-      float usage;
-      u32 internal_id;  /* used for things like soundscapes where another
-                           allocation is made on top */
-   }
-   * logic_bricks;
-   u32 logic_brick_count;
-
    /*
-    * Box trigger entities
+    * Box volume entities
     */
-   struct trigger_zone
+   struct world_volume
    {
       m4x3f transform, inv_transform;
-      
-      u32 target_logic_brick;
-      enum classtype classtype;
-   }
-   * 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
@@ -356,7 +307,7 @@ struct world_instance
 
    /* spacial mappings */
    bh_tree *audio_bh,
-           *trigger_bh,
+           *volume_bh,
            *geo_bh;
 
    /* graphics */
@@ -431,7 +382,7 @@ VG_STATIC struct world_global
 
    v3f render_gate_pos;
    int active_route_board;
-   int in_trigger;
+   int in_volume;
 
    int switching_to_new_world;
 
@@ -470,7 +421,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_logic_bricks.h"
+#include "world_volumes.h"
 #include "world_gen.h"
 #include "world_gate.h"
 
@@ -483,76 +434,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
-    */
-#if 0
-   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();
-#endif
-
-   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;
 
@@ -595,92 +481,6 @@ VG_STATIC void world_init(void)
                                                            VG_MEMORY_SYSTEM );
 }
 
-VG_STATIC void world_audio_init(void)
-{
-#if 0
-   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 );
-#endif
-}
-
-#if 0
-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;
-}
-#endif
-
-#if 0
-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] );
-   }
-}
-#endif
-
-#if 0
-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();
-}
-#endif
-
-#if 0
-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 },
-      { k_classtype_logic_wire, logic_bricks_trigger_brick }
-   };
-
-   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 );
-}
-#endif
-
 VG_STATIC void world_update( world_instance *world, v3f pos )
 {
    /* TEMP!!!!!! */
@@ -715,35 +515,6 @@ 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, 
@@ -807,25 +578,26 @@ VG_STATIC void world_update( world_instance *world, v3f pos )
    }
 
    float radius = 25.0f;
-   boxf trigger_proximity;
-   v3_add( pos, (v3f){ radius, radius, radius }, trigger_proximity[1] );
-   v3_sub( pos, (v3f){ radius, radius, radius }, trigger_proximity[0] );
+   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_trigger = 0;
+   int in_volume = 0;
 
-   while( bh_next( world->trigger_bh, &it, trigger_proximity, &idx ) )
+   while( bh_next( world->volume_bh, &it, volume_proximity, &idx ) )
    {
-      struct trigger_zone *zone = &world->triggers[idx];
+      struct world_volume *zone = &world->volumes[idx];
 
-      if( zone->classtype == k_classtype_particle_box )
+      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;
@@ -840,6 +612,7 @@ VG_STATIC void world_update( world_instance *world, v3f pos )
 
             logic_bricks_send_packet( world, &packet );
          }
+#endif
          continue;
       }
 
@@ -850,10 +623,11 @@ 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 )
          {
+#if 0
             logic_packet packet;
             packet.location = zone->target_logic_brick;
             packet.function = 0;
@@ -862,6 +636,7 @@ VG_STATIC void world_update( world_instance *world, v3f pos )
             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},
@@ -896,12 +671,9 @@ VG_STATIC void world_update( world_instance *world, v3f pos )
       }
    }
 
-   world_global.in_trigger = in_trigger;
+   world_global.in_volume = in_volume;
    sfd_update();
 
-   if( debug_logic_bricks )
-      logic_bricks_debug( world, pos );
-
    /* process soundscape transactions */
    audio_lock();
    for( int i=0; i<world->soundscape_count; i++ )
index a8f148c74f293e0a8b33c4eb878ed1320cfde4ad..fdbe9e58ee54aa6ddda195cb26a2aed06028de42 100644 (file)
@@ -170,27 +170,6 @@ VG_STATIC void world_ents_allocate( world_instance *world )
          (void*)&world->audio_things, 
          sizeof(struct world_audio_thing) 
       },
-      {
-         k_classtype_trigger,
-         k_classtype_particle_box,
-         (void*)&world->triggers,
-         sizeof(struct trigger_zone)
-      },
-
-#if 0
-      {
-         k_classtype_logic_relay,
-         (void*)&world->logic_relays,
-         sizeof(struct logic_relay)
-      },
-#endif
-
-      {
-         k_classtype_logic_achievement,
-         k_classtype_none,
-         (void*)&world->logic_achievements,
-         sizeof(struct logic_achievement)
-      },
       {
          k_classtype_world_light,
          k_classtype_none,
@@ -203,12 +182,6 @@ VG_STATIC void world_ents_allocate( world_instance *world )
          (void*)&world->nonlocal_gates,
          sizeof(struct nonlocal_gate)
       },
-      {
-         k_classtype_soundscape,
-         k_classtype_none,
-         (void*)&world->soundscapes,
-         sizeof(struct soundscape)
-      }
    };
 
    for( int i=0; i<vg_list_size(entity_counts); i++ )
@@ -240,12 +213,10 @@ VG_STATIC void world_ents_allocate( world_instance *world )
       memset( *counter->to_allocate, 0, bufsize );
    }
 
-   logic_bricks_world_gen_allocate( world );
-
-   world->trigger_bh = bh_create( world_global.generic_heap,
-                                  &bh_system_triggers,
+   world->volume_bh = bh_create( world_global.generic_heap,
+                                  &bh_system_volumes,
                                   world,
-                                  world->trigger_count,
+                                  world->volume_count,
                                   1 );
 }
 
@@ -294,46 +265,6 @@ VG_STATIC void world_pct_audio( world_instance *world, mdl_node *pnode )
    world->audio_things_count ++;
 }
 
-#if 0
-VG_STATIC void world_pct_relay( world_instance *world, mdl_node *pnode )
-{
-   struct logic_relay *relay = &world->logic_relays[ world->relay_count ];
-   struct classtype_logic_relay *inf = mdl_get_entdata( world->meta, pnode );
-
-   relay->target_count = 0;
-
-   for( int i=0; i<vg_list_size(relay->targets); i++ )
-   {
-      if( inf->targets[i] )
-      {
-         struct relay_target *target = &relay->targets[relay->target_count ++];
-         mdl_node *other = mdl_node_from_id( world->meta, inf->targets[i] );
-         
-         target->classtype = other->classtype;
-         target->sub_id = other->sub_uid;
-      }
-   }
-
-   v3_copy( pnode->co, relay->pos );
-   world->relay_count ++;
-}
-#endif
-
-
-VG_STATIC void world_pct_achievement( world_instance *world, mdl_node *pnode )
-{
-   struct logic_achievement *ach = 
-      &world->logic_achievements[ world->achievement_count ];
-   struct classtype_logic_achievement *inf = 
-      mdl_get_entdata( world->meta, pnode );
-
-   v3_copy( pnode->co, ach->pos );
-   ach->achievement_id = mdl_pstr( world->meta, inf->pstr_name );
-   ach->achieved = 0;
-
-   world->achievement_count ++;
-}
-
 VG_STATIC void world_pct_world_light( world_instance *world, mdl_node *pnode )
 {
    struct world_light *light = &world->lights[ world->light_count ++ ];
@@ -372,10 +303,6 @@ VG_STATIC void world_entities_process( world_instance *world )
       { k_classtype_spawn,    world_pct_spawn },
       { k_classtype_water,    world_pct_water },
       { k_classtype_audio,    world_pct_audio },
-#if 0
-      { k_classtype_logic_relay, world_pct_relay },
-#endif
-      { k_classtype_logic_achievement, world_pct_achievement },
       { k_classtype_world_light, world_pct_world_light },
       { k_classtype_nonlocal_gate, world_pct_nonlocal_gate }
    };
@@ -396,7 +323,6 @@ VG_STATIC void world_entities_process( world_instance *world )
       }
    }
 }
-
 VG_STATIC void world_link_nonlocal_gates( int index_a, int index_b )
 {
    vg_info( "Linking non-local gates\n" );
@@ -1035,7 +961,7 @@ VG_STATIC void world_clean( world_instance *world )
    world->scene_lines = NULL;
 
    world->geo_bh = NULL;
-   world->trigger_bh = NULL;
+   world->volume_bh = NULL;
    world->audio_bh = NULL;
 
    world->spawns = NULL;
@@ -1044,20 +970,12 @@ VG_STATIC void world_clean( world_instance *world )
    world->audio_things = NULL;
    world->audio_things_count = 0;
 
-   world->triggers = NULL;
-   world->trigger_count = 0;
+   world->volumes = NULL;
+   world->volume_count = 0;
 
    world->lights = NULL;
    world->light_count = 0;
 
-#if 0
-   world->logic_relays = NULL;
-   world->relay_count = 0;
-#endif
-
-   world->logic_achievements = NULL;
-   world->achievement_count = 0;
-
    world->nodes = NULL;
    world->node_count = 0;
 
@@ -1073,9 +991,6 @@ VG_STATIC void world_clean( world_instance *world )
    world->soundscapes = NULL;
    world->soundscape_count = 0;
 
-   world->logic_bricks = NULL;
-   world->logic_brick_count = 0;
-
    world->nonlocal_gates = NULL;
    world->nonlocalgate_count = 0;
 
index 6d1ea26cb4121707f9cfd0e30b0e204bfb91daef..d6e9d11557fa08cf2a40ad50de2b05c4a32bfde1 100644 (file)
@@ -5,6 +5,8 @@
 
 #include "world.h"
 
+#if 0
+
 typedef struct logic_packet logic_packet;
 struct logic_packet
 {
@@ -497,68 +499,10 @@ VG_STATIC void logic_bricks_world_gen_allocate( world_instance *world )
    }
 }
 
+#endif
 
 
 
 
-/*
- * BVH implementation
- * ----------------------------------------------------------------------------
- */
-
-VG_STATIC void trigger_bh_expand_bound( void *user, boxf bound, u32 item_index )
-{
-   world_instance *world = user;
-   struct trigger_zone *trigger = &world->triggers[ item_index ];
-
-   m4x3_expand_aabb_point( trigger->transform, bound, (v3f){ 1.0f, 1.0f, 1.0f} );
-   m4x3_expand_aabb_point( trigger->transform, bound, (v3f){ 1.0f, 1.0f,-1.0f} );
-   m4x3_expand_aabb_point( trigger->transform, bound, (v3f){ 1.0f,-1.0f, 1.0f} );
-   m4x3_expand_aabb_point( trigger->transform, bound, (v3f){ 1.0f,-1.0f,-1.0f} );
-   m4x3_expand_aabb_point( trigger->transform, bound, (v3f){-1.0f, 1.0f, 1.0f} );
-   m4x3_expand_aabb_point( trigger->transform, bound, (v3f){-1.0f, 1.0f,-1.0f} );
-   m4x3_expand_aabb_point( trigger->transform, bound, (v3f){-1.0f,-1.0f, 1.0f} );
-   m4x3_expand_aabb_point( trigger->transform, bound, (v3f){-1.0f,-1.0f,-1.0f} );
-}
-
-VG_STATIC float trigger_bh_centroid( void *user, u32 item_index, int axis )
-{
-   world_instance *world = user;
-   struct trigger_zone *trigger = &world->triggers[ item_index ];
-
-   return trigger->transform[3][axis];
-}
-
-VG_STATIC void trigger_bh_swap( void *user, u32 ia, u32 ib )
-{
-   world_instance *world = user;
-   struct trigger_zone *a = &world->triggers[ ia ],
-                       *b = &world->triggers[ ib ],
-                       temp;
-
-   temp = *a;
-   *a = *b;
-   *b = temp;
-}
-
-VG_STATIC void trigger_bh_debug( void *user, u32 item_index )
-{
-   world_instance *world = user;
-   struct trigger_zone *zone = &world->triggers[ item_index ];
-
-   vg_line_boxf_transformed( zone->transform, (boxf){{-1.0f,-1.0f,-1.0f},
-                                                     { 1.0f, 1.0f, 1.0f}}, 
-                                                     0xff00ff00 );
-}
-
-VG_STATIC bh_system bh_system_triggers = 
-{
-   .expand_bound = trigger_bh_expand_bound,
-   .item_centroid = trigger_bh_centroid,
-   .item_closest = NULL,
-   .item_swap = trigger_bh_swap,
-   .item_debug = trigger_bh_debug,
-   .cast_ray = NULL
-};
 
 #endif /* WORLD_LOGIC_BRICKS_H */
diff --git a/world_volumes.h b/world_volumes.h
new file mode 100644 (file)
index 0000000..450c8c2
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef WORLD_VOLUMES_H
+#define WORLD_VOLUMES_H
+
+#include "world.h"
+
+/*
+ * BVH implementation
+ * ----------------------------------------------------------------------------
+ */
+
+VG_STATIC void volume_vg_expand_bound( void *user, boxf bound, u32 item_index )
+{
+   world_instance *world = user;
+   struct world_volume *volume = &world->volumes[ 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} );
+}
+
+VG_STATIC float volume_vg_centroid( void *user, u32 item_index, int axis )
+{
+   world_instance *world = user;
+   struct world_volume *volume = &world->volumes[ item_index ];
+
+   return volume->transform[3][axis];
+}
+
+VG_STATIC void volume_vg_swap( void *user, u32 ia, u32 ib )
+{
+   world_instance *world = user;
+   struct world_volume *a = &world->volumes[ ia ],
+                       *b = &world->volumes[ ib ],
+                       temp;
+
+   temp = *a;
+   *a = *b;
+   *b = temp;
+}
+
+VG_STATIC void volume_vg_debug( void *user, u32 item_index )
+{
+   world_instance *world = user;
+   struct world_volume *zone = &world->volumes[ item_index ];
+
+   vg_line_boxf_transformed( zone->transform, (boxf){{-1.0f,-1.0f,-1.0f},
+                                                     { 1.0f, 1.0f, 1.0f}}, 
+                                                     0xff00ff00 );
+}
+
+VG_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 */