wowwww
authorhgn <hgodden00@gmail.com>
Wed, 5 Apr 2023 01:29:59 +0000 (02:29 +0100)
committerhgn <hgodden00@gmail.com>
Wed, 5 Apr 2023 01:29:59 +0000 (02:29 +0100)
20 files changed:
blender_export.py
build.c
conf.h
entity.h
maps_src/mp_mtzero.mdl
menu.h
models_src/ch_jordan.mdl
models_src/ch_outlaw.mdl
models_src/rs_menu.mdl [new file with mode: 0644]
player.c
player.h
player_common.c
player_skate.c
player_walk.c
scene.h
skaterift.c
textures_src/menu.qoi
world.h
world_gen.h
world_routes.h

index dcab66f51953ffbf08fa2b2d080b4e34328995ab..cbd2a1989087302c7844d535e44cd73b5aaf1a3a 100644 (file)
@@ -23,7 +23,8 @@ sr_entity_alias = {
    'ent_route': 4,
    'ent_water': 5,
    'ent_volume': 6,
-   'ent_audio': 7
+   'ent_audio': 7,
+   'ent_marker': 8
 }
 
 class mdl_vert(Structure):              # 48 bytes. Quite large. Could compress
@@ -282,6 +283,12 @@ class ent_audio(Structure):
                ("max_channels",c_uint32)]
 #}
 
+class ent_marker(Structure):
+#{
+   _fields_ = [("transform",mdl_transform),
+               ("name",c_uint32)]
+#}
+
 def obj_ent_type( obj ):
 #{
    if obj.type == 'ARMATURE': return 'mdl_armature'
@@ -1097,8 +1104,6 @@ def sr_compile( collection ):
       #}
    #}
 
-   checkpoint_count = 0
-   pathindice_count = 0
    audio_clip_count = 0
 
    for ent_type, arr in sr_compile.entities.items():#{
@@ -1167,76 +1172,9 @@ def sr_compile( collection ):
             spawn = ent_spawn()
             compile_obj_transform( obj, spawn.transform )
             obj_data = obj.SR_data.ent_spawn[0]
-            spawn.pstr_name = sr_compile_string( obj_data.name )
+            spawn.pstr_name = sr_compile_string( obj_data.alias )
             sr_ent_push( spawn )
          #}
-         elif ent_type == 'ent_route': #{
-            obj_data = obj.SR_data.ent_route[0]
-            route = ent_route()
-            route.pstr_name = sr_compile_string( obj_data.alias )
-            route.checkpoints_start = checkpoint_count
-            route.checkpoints_count = 0
-
-            for ci in range(3):
-               route.colour[ci] = obj_data.colour[ci]
-            route.colour[3] = 1.0
-
-            compile_obj_transform( obj, route.transform )
-
-            checkpoints = obj_data.gates
-            route_nodes = []
-
-            for uc in obj.users_collection[0].objects:#{
-               uc_type = obj_ent_type( uc )
-               if uc_type == 'ent_gate' or uc_type == 'ent_route_node':
-                  route_nodes += [uc]
-            #}
-            graph = node_graph( route_nodes )
-
-            for i in range(len(checkpoints)):#{
-               gi = checkpoints[i].target
-               gj = checkpoints[(i+1)%len(checkpoints)].target
-               gate = gi
-
-               if gi:#{
-                  dest = gi.SR_data.ent_gate[0].target
-                  gi = dest
-               #}
-
-               if gi==gj: continue # error?
-               if not gi or not gj: continue
-
-               checkpoint = ent_checkpoint()
-               checkpoint.gate_index = sr_compile.entity_ids[gate.name]
-               checkpoint.path_start = pathindice_count
-               checkpoint.path_count = 0
-               
-               path = dijkstra( graph, gj.name, gi.name )
-               if path:#{
-                  for pi in range(1,len(path)-1):#{
-                     pathindice = ent_path_index()
-                     pathindice.index = sr_compile.entity_ids[path[pi]]
-                     sr_ent_push( pathindice )
-
-                     checkpoint.path_count += 1
-                     pathindice_count += 1
-                  #}
-               #}
-               
-               sr_ent_push( checkpoint )
-               route.checkpoints_count += 1
-               checkpoint_count += 1
-            #}
-
-            sr_ent_push( route )
-         #}
-         elif ent_type == 'ent_route_node':#{
-            rn = ent_route_node()
-            rn.co[0] =  obj.location[0]
-            rn.co[1] =  obj.location[2]
-            rn.co[2] = -obj.location[1]
-            sr_ent_push( rn )
-         #}
          elif ent_type == 'ent_water':#{
             water = ent_water()
             compile_obj_transform( obj, water.transform )
@@ -1305,9 +1243,116 @@ def sr_compile( collection ):
 
             sr_ent_push(volume)
          #}
+         elif ent_type == 'ent_marker':#{
+            marker = ent_marker()
+            marker.name = sr_compile_string( obj.SR_data.ent_marker[0].alias )
+            compile_obj_transform( obj, marker.transform )
+            sr_ent_push(marker)
+         #}
       #}
    #}
-   
+
+   def _children( col ):#{
+      yield col
+      for c in col.children:#{
+         yield from _children(c)
+      #}
+   #}
+
+   checkpoint_count = 0
+   pathindice_count = 0
+   routenode_count = 0
+
+   for col in _children(collection):#{
+      print( F"Adding routes for subcollection: {col.name}" )
+      route_gates = []
+      route_curves = []
+      routes = []
+
+      for obj in col.objects:#{
+         if obj.type == 'ARMATURE': pass
+         else:#{
+            ent_type = obj_ent_type( obj )
+
+            if ent_type == 'ent_gate':
+               route_gates += [obj]
+            elif ent_type == 'ent_route_node':#{
+               if obj.type == 'CURVE':#{
+                  route_curves += [obj]
+               #}
+            #}
+            elif ent_type == 'ent_route':
+               routes += [obj]
+         #}
+      #}
+
+      dij = create_node_graph( route_curves, route_gates )
+      
+      for obj in routes:#{
+         obj_data = obj.SR_data.ent_route[0]
+         route = ent_route()
+         route.pstr_name = sr_compile_string( obj_data.alias )
+         route.checkpoints_start = checkpoint_count
+         route.checkpoints_count = 0
+
+         for ci in range(3):
+            route.colour[ci] = obj_data.colour[ci]
+         route.colour[3] = 1.0
+
+         compile_obj_transform( obj, route.transform )
+         checkpoints = obj_data.gates
+
+         for i in range(len(checkpoints)):#{
+            gi = checkpoints[i].target
+            gj = checkpoints[(i+1)%len(checkpoints)].target
+            gate = gi
+
+            if gi:#{
+               dest = gi.SR_data.ent_gate[0].target
+               gi = dest
+            #}
+
+            if gi==gj: continue # error?
+            if not gi or not gj: continue
+
+            checkpoint = ent_checkpoint()
+            checkpoint.gate_index = sr_compile.entity_ids[gate.name]
+            checkpoint.path_start = pathindice_count
+            checkpoint.path_count = 0
+            
+            path = solve_graph( dij, gi.name, gj.name )
+
+            if path:#{
+               for pi in range(len(path)):#{
+                  pathindice = ent_path_index()
+                  pathindice.index = routenode_count + path[pi]
+                  sr_ent_push( pathindice )
+
+                  checkpoint.path_count += 1
+                  pathindice_count += 1
+               #}
+            #}
+            
+            sr_ent_push( checkpoint )
+            route.checkpoints_count += 1
+            checkpoint_count += 1
+         #}
+
+         sr_ent_push( route )
+      #}
+
+      for point in dij.points:#{
+         rn = ent_route_node()
+         rn.co[0] =  point[0]
+         rn.co[1] =  point[2]
+         rn.co[2] = -point[1]
+         sr_ent_push( rn )
+      #}
+
+      routenode_count += len(dij.points)
+   #}
+
+
    print( F"[SR] Writing file" )
 
    file_array_instructions = {}
@@ -1609,7 +1654,7 @@ class SR_INTERFACE(bpy.types.Panel):
          elif active_object.type == 'LIGHT': #{
             _draw_prop_collection( [active_object.data.SR_data] )
          #}
-         elif active_object.type == 'EMPTY' or active_object.type == 'MESH': #{
+         elif active_object.type in ['EMPTY','CURVE','MESH']:#{
             box.prop( active_object.SR_data, "ent_type" )
             ent_type = active_object.SR_data.ent_type
             
@@ -1970,6 +2015,11 @@ class SR_OBJECT_ENT_AUDIO(bpy.types.PropertyGroup):
    #}
 #}
 
+class SR_OBJECT_ENT_MARKER(bpy.types.PropertyGroup):
+#{
+   alias: bpy.props.StringProperty()
+#}
+
 class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup):
 #{
    ent_gate: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_GATE)
@@ -1977,6 +2027,7 @@ class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup):
    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_marker: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_MARKER)
 
    ent_type: bpy.props.EnumProperty(
       name="Type",
@@ -1987,7 +2038,8 @@ class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup):
              ('ent_route', 'Route', '', 4),
              ('ent_water', 'Water Surface', '', 5),
              ('ent_volume', 'Volume', '', 6 ),
-             ('ent_audio', 'Audio Files', '', 7)],
+             ('ent_audio', 'Audio Files', '', 7),
+             ('ent_marker', 'Marker', '', 8)],
       update=sr_on_type_change
    )
 #}
@@ -2143,8 +2195,7 @@ def cv_draw_sphere( pos, radius, colour ):
    
    pi = 3.14159265358979323846264
 
-   for i in range(16):
-   #{
+   for i in range(16):#{
       t = ((i+1.0) * 1.0/16.0) * pi * 2.0
       s = math.sin(t)
       c = math.cos(t)
@@ -2178,8 +2229,7 @@ def cv_draw_halfsphere( pos, tx, ty, tz, radius, colour ):
    
    pi = 3.14159265358979323846264
 
-   for i in range(16):
-   #{
+   for i in range(16):#{
       t = ((i+1.0) * 1.0/16.0) * pi
       s = math.sin(t)
       c = math.cos(t)
@@ -2226,8 +2276,7 @@ def cv_draw_ucube( transform, colour, s=Vector((1,1,1)), o=Vector((0,0,0)) ):
    indices = [(0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),\
               (0,4),(1,5),(2,6),(3,7)]
 
-   for l in indices:
-   #{
+   for l in indices:#{
       v0 = vs[l[0]]
       v1 = vs[l[1]]
       cv_view_verts += [(v0[0],v0[1],v0[2])]
@@ -2263,14 +2312,12 @@ def cv_draw_line2( p0, p1, c0, c1 ):
 #
 def cv_tangent_basis( n, tx, ty ):
 #{
-   if abs( n[0] ) >= 0.57735027:
-   #{
+   if abs( n[0] ) >= 0.57735027:#{
       tx[0] =  n[1]
       tx[1] = -n[0]
       tx[2] =  0.0
    #}
-   else:
-   #{
+   else:#{
       tx[0] =  0.0
       tx[1] =  n[2]
       tx[2] = -n[1]
@@ -2300,7 +2347,7 @@ def cv_draw_arrow( p0, p1, c0, size=0.15 ):
    
    cv_view_verts += [p0,p1, midpt+(tx-n)*size,midpt, midpt+(-tx-n)*size,midpt ]
    cv_view_colours += [c0,c0,c0,c0,c0,c0]
-   cv_draw_lines()
+   #cv_draw_lines()
 #}
 
 def cv_draw_line_dotted( p0, p1, c0, dots=10 ):
@@ -2317,7 +2364,7 @@ def cv_draw_line_dotted( p0, p1, c0, dots=10 ):
       cv_view_verts += [p2,p3]
       cv_view_colours += [c0,c0]
    #}
-   cv_draw_lines()
+   #cv_draw_lines()
 #}
 
 # Drawhandles of a bezier control point
@@ -2342,8 +2389,7 @@ def cv_draw_bezier( p0,h0,p1,h1,c0,c1 ):
    global cv_view_verts, cv_view_colours
 
    last = p0
-   for i in range(10):
-   #{
+   for i in range(10):#{
       t = (i+1)/10
       a0 = 1-t
 
@@ -2454,7 +2500,7 @@ def draw_cone_twist( center, vx, vy, va ):
    size = 0.12
 
    cv_view_verts += [center, center+va*size]
-   cv_view_colours += [ (1,1,1,1), (1,1,1,1) ]
+   cv_view_colours += [ (1,1,1), (1,1,1) ]
 
    for x in range(32):#{
       t0 = (x/32) * math.tau
@@ -2472,7 +2518,7 @@ def draw_cone_twist( center, vx, vy, va ):
       col1 = ( abs(c1), abs(s1), 0.0, 1.0 )
 
       cv_view_verts += [center, p0, p0, p1]
-      cv_view_colours += [ (0,0,0,0), col0, col0, col1 ]
+      cv_view_colours += [ (0,0,0), col0, col0, col1 ]
    #}
 
    cv_draw_lines()
@@ -2517,7 +2563,7 @@ def draw_skeleton_helpers( obj ):
 
             cv_view_verts += [(v0[0],v0[1],v0[2])]
             cv_view_verts += [(v1[0],v1[1],v1[2])]
-            cv_view_colours += [(0.5,0.5,0.5,0.5),(0.5,0.5,0.5,0.5)]
+            cv_view_colours += [(0.5,0.5,0.5),(0.5,0.5,0.5)]
          #}
       #}
       elif bone.SR_data.collider == '2':#{
@@ -2545,7 +2591,7 @@ def draw_skeleton_helpers( obj ):
          p0 = obj.matrix_world@Vector( c + (a+b)*0.5 + v1*l*-0.5 )
          p1 = obj.matrix_world@Vector( c + (a+b)*0.5 + v1*l* 0.5 )
 
-         colour = [0.2,0.2,0.2,1.0]
+         colour = [0.2,0.2,0.2]
          colour[major_axis] = 0.5
 
          cv_draw_halfsphere( p0, -v1, ty, tx, r, colour )
@@ -2594,15 +2640,24 @@ def cv_ent_gate( obj ):
 
    indices = [(0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(7,8)]
 
+   r3d = bpy.context.area.spaces.active.region_3d
+
+   p0 = r3d.view_matrix.inverted().translation
+   v0 = (obj.matrix_world@Vector((0,0,0))) - p0
+   v1 = obj.matrix_world.to_3x3() @ Vector((0,1,0))
+
+   if v0.dot(v1) > 0.0: cc = (0,1,0)
+   else: cc = (1,0,0)
+
    for l in indices:#{
       v0 = vs[l[0]]
       v1 = vs[l[1]]
       cv_view_verts += [(v0[0],v0[1],v0[2])]
       cv_view_verts += [(v1[0],v1[1],v1[2])]
-      cv_view_colours += [(1,1,0,1),(1,1,0,1)]
+      cv_view_colours += [cc,cc]
    #}
 
-   sw = (0.4,0.4,0.4,0.2)
+   sw = (0.4,0.4,0.4)
    if data.target != None:
       cv_draw_arrow( obj.location, data.target.location, sw )
 #}
@@ -2674,53 +2729,148 @@ def dijkstra( graph, start_node, target_node ):
    return path
 #}
 
-def node_graph( route_nodes ):
+class dij_graph():
+#{
+   def __init__(_,points,graph,subsections):#{
+      _.points = points
+      _.graph = graph
+      _.subsections = subsections
+   #}
+#}
+
+def create_node_graph( curves, gates ):
 #{
+   # add endpoints of curves
    graph = {}
-   for n in route_nodes:
-      graph[n.name] = {}
+   route_points = []
+   subsections = []
+   point_count = 0
+   spline_count = 0
 
-   for i in range(len(route_nodes)-1):#{
-      for j in range(i+1, len(route_nodes)):#{
-         ni = route_nodes[i]
-         nj = route_nodes[j]
+   for c in range(len(curves)):#{
+      for s in range(len(curves[c].data.splines)):#{
+         spline = curves[c].data.splines[s]
+         l = len(spline.points)
+         if l < 2: continue
 
-         v0 = ni.location - nj.location
+         dist = round(spline.calc_length(),2)
 
-         gate = None
+         ia = point_count
+         ib = point_count+l-1
 
-         if ni.SR_data.ent_type == 'ent_gate':
-            gate = ni
+         graph[ia] = { ib: dist }
+         graph[ib] = { ia: dist }
+         
+         for i in range(len(spline.points)):#{
+            wco = curves[c].matrix_world @ spline.points[i].co
+            route_points.append(Vector((wco[0],wco[1],wco[2]+0.5)))
+
+            previous = ia+i-1
+            proxima = ia+i+1
 
-         if nj.SR_data.ent_type == 'ent_gate':#{
-            if gate: continue
-            gate = nj
+            if i == 0: previous = -1
+            if i == len(spline.points)-1: proxima = -1
+
+            subsections.append((spline_count,previous,proxima))
+            point_count += 1
          #}
 
-         if gate:#{
-            v1 = gate.matrix_world.to_3x3() @ Vector((0,-1,0))
-            if gate.SR_data.ent_gate[0].target:
-               if v1.dot(v0) > 0.0: continue
-            else:
-               if v1.dot(v0) < 0.0: continue
+         spline_count += 1
+      #}
+   #}
+
+   # link endpoints
+   graph_keys = list(graph)
+   for i in range(len(graph_keys)-1):#{
+      for j in range(i+1, len(graph_keys)):#{
+         if i%2==0 and i+1==j: continue
+
+         ni = graph_keys[i]
+         nj = graph_keys[j]
+         pi = route_points[ni]
+         pj = route_points[nj]
+
+         dist = round((pj-pi).magnitude,2)
+
+         if dist < 10.0:#{
+            graph[ni][nj] = dist
+            graph[nj][ni] = dist
          #}
+      #}
+   #}
+
+   # add and link gates( by name )
+   for gate in gates:#{
+      v1 = gate.matrix_world.to_3x3() @ Vector((0,1,0))
+      if gate.SR_data.ent_gate[0].target:
+         v1 = v1 * -1.0
+
+      graph[ gate.name ] = {}
+
+      for i in range(len(graph_keys)):#{
+         ni = graph_keys[i]
+         pi = route_points[ni]
 
-         dist = v0.magnitude
+         v0 = pi-gate.location
+         if v0.dot(v1) < 0.0: continue
 
-         if dist > 25.0: continue
-         graph[route_nodes[i].name][route_nodes[j].name] = dist
-         graph[route_nodes[j].name][route_nodes[i].name] = dist
+         dist = round(v0.magnitude,2)
+
+         if dist < 10.0:#{
+            graph[ gate.name ][ ni ] = dist
+            graph[ ni ][ gate.name ] = dist
+         #}
       #}
    #}
 
-   return graph
+   return dij_graph(route_points,graph,subsections)
 #}
 
-def cv_draw_route( route, route_nodes ):
+def solve_graph( dij, start, end ):
+#{
+   path = dijkstra( dij.graph, end, start )
+   full = []
+
+   if path:#{
+      for sj in range(1,len(path)-2):#{
+         i0 = path[sj]
+         i1 = path[sj+1]
+         map0 = dij.subsections[i0]
+         map1 = dij.subsections[i1]
+
+         if map0[0] == map1[0]:#{
+            if map0[1] == -1: direction = 2
+            else: direction = 1
+            sent = 0
+
+            while True:#{
+               map0 = dij.subsections[i0]
+               i1 = map0[direction]
+               if i1 == -1: break
+               
+               full.append( i0 )
+               sent += 1
+               i0 = i1
+               if sent > 50: break
+            #}
+         #}
+         else:#{
+            full.append( i0 )
+         #}
+      #}
+
+      full.append( path[-2] )
+   #}
+   return full
+#}
+
+def cv_draw_route( route, dij ):
 #{
    pole = Vector((0.2,0.2,10))
    hat = Vector((1,8,0.2))
-   cc = route.SR_data.ent_route[0].colour
+   cc = (route.SR_data.ent_route[0].colour[0],
+         route.SR_data.ent_route[0].colour[1],
+         route.SR_data.ent_route[0].colour[2])
 
    cv_draw_ucube(route.matrix_world,cc,Vector((0.5,-7.5,6)),\
                                        Vector((0,-6.5,5.5)))
@@ -2730,7 +2880,6 @@ def cv_draw_route( route, route_nodes ):
    cv_draw_ucube(route.matrix_world,cc,hat, Vector((-0.5,-6.5,-1)) )
 
    checkpoints = route.SR_data.ent_route[0].gates
-   graph = node_graph( route_nodes )
 
    for i in range(len(checkpoints)):#{
       gi = checkpoints[i].target
@@ -2746,13 +2895,17 @@ def cv_draw_route( route, route_nodes ):
       if gi==gj: continue # error?
       if not gi or not gj: continue
 
-      path = dijkstra( graph, gj.name, gi.name )
+      path = solve_graph( dij, gi.name, gj.name )
 
       if path:#{
-         for sj in range(len(path)-1):#{
-            o0 = bpy.data.objects[ path[sj] ]
-            o1 = bpy.data.objects[ path[sj+1] ]
-            cv_draw_arrow(o0.location,o1.location,cc,1.5)
+         cv_draw_arrow(gi.location,dij.points[path[0]],cc,1.5)
+         cv_draw_arrow(dij.points[path[len(path)-1]],gj.location,cc,1.5)
+         for j in range(len(path)-1):#{
+            i0 = path[j]
+            i1 = path[j+1]
+            o0 = dij.points[ i0 ]
+            o1 = dij.points[ i1 ]
+            cv_draw_arrow(o0,o1,cc,1.5)
          #}
       #}
       else:#{
@@ -2779,7 +2932,8 @@ def cv_draw():
    gpu.state.depth_test_set('LESS')
    gpu.state.blend_set('NONE')
 
-   route_nodes = []
+   route_gates = []
+   route_curves = []
    routes = []
 
    for obj in bpy.context.collection.objects:#{
@@ -2792,10 +2946,13 @@ def cv_draw():
 
          if ent_type == 'ent_gate':#{
             cv_ent_gate( obj )
-            route_nodes += [obj]
+            route_gates += [obj]
+         #}
+         elif ent_type == 'ent_route_node':#{
+            if obj.type == 'CURVE':#{
+               route_curves += [obj]
+            #}
          #}
-         elif ent_type == 'ent_route_node':
-            route_nodes += [obj]
          elif ent_type == 'ent_route':
             routes += [obj]
          elif ent_type == 'ent_volume':#{
@@ -2807,10 +2964,12 @@ def cv_draw():
          #}
       #}
    #}
+
+   dij = create_node_graph( route_curves, route_gates )
    
    #cv_draw_route_map( route_nodes )
    for route in routes:#{
-      cv_draw_route( route, route_nodes )
+      cv_draw_route( route, dij )
    #}
 
    cv_draw_lines()
@@ -2828,7 +2987,7 @@ classes = [ SR_INTERFACE, SR_MATERIAL_PANEL,\
             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_ENT_AUDIO,SR_OBJECT_ENT_MARKER,\
             \
             SR_OBJECT_PROPERTIES, SR_LIGHT_PROPERTIES, SR_BONE_PROPERTIES, 
             SR_MESH_PROPERTIES, SR_MATERIAL_PROPERTIES \
diff --git a/build.c b/build.c
index 1201177d9ea357b5d1349250a3c0df00861f302f..f791927809d36e7a26e2fae30e79686f3739db20 100644 (file)
--- a/build.c
+++ b/build.c
@@ -139,9 +139,4 @@ void build_shaders(void)
    _S( "blitblur",  "blit.vs",      "blitblur.fs" );
    _S( "blitcolour","blit.vs",      "colour.fs" );
    _S( "routeui",   "routeui.vs",   "routeui.fs" );
-   
-#if 0
-   // 3D Standard
-   _S( "scoretext", "shaders/scoretext.vs", "shaders/vblend.fs" );
-#endif
 }
diff --git a/conf.h b/conf.h
index ade9247a18eda299e67f2e9b9a348a7149e5fa6e..33cc44e5690c1465c0c8d65ce487a74e1f4e9bae 100644 (file)
--- a/conf.h
+++ b/conf.h
@@ -7,7 +7,8 @@
 VG_STATIC float cl_fov              = 0.86f,
                 cl_blur_strength    = 0.3f;
 VG_STATIC int   cl_blur             = 1,
-                cl_playermdl_id     = 0;
+                cl_playermdl_id     = 0,
+                cl_invert_y         = 0;
 
 VG_STATIC void g_conf_init(void)
 {
@@ -19,6 +20,14 @@ VG_STATIC void g_conf_init(void)
       .persistent = 1
    });
 
+   vg_var_push( (struct vg_var){
+      .name = "cl_invert_y",
+      .data = &cl_invert_y,
+      .data_type = k_var_dtype_i32,
+      .opt_i32 = { .min=0, .max=1, .clamp=1 },
+      .persistent = 1
+   });
+
    vg_var_push( (struct vg_var){
       .name = "cl_blur_strength",
       .data = &cl_blur_strength,
index 5b0d4a73bb82842d63959434e4e86eb882b8cf55..e437d3d77810f059bfc8dd22f5a488ed464df4a9 100644 (file)
--- a/entity.h
+++ b/entity.h
@@ -17,6 +17,7 @@ typedef struct volume_trigger volume_trigger;
 typedef struct ent_volume ent_volume;
 typedef struct ent_audio ent_audio;
 typedef struct ent_index ent_index;
+typedef struct ent_marker ent_marker;
 
 enum entity_alias{
    k_ent_gate = 1,
@@ -25,7 +26,8 @@ enum entity_alias{
    k_ent_route = 4,
    k_ent_water = 5,
    k_ent_volume = 6,
-   k_ent_audio = 7
+   k_ent_audio = 7,
+   k_ent_marker = 8
 };
 
 struct ent_index{
@@ -182,6 +184,11 @@ struct ent_audio{
        max_channels;
 };
 
+struct ent_marker{
+   mdl_transform transform;
+   u32 pstr_alias;
+};
+
 enum channel_behaviour{
    k_channel_behaviour_unlimited = 0,
    k_channel_behaviour_discard_if_full = 1,
@@ -194,4 +201,18 @@ enum probability_curve{
    k_probability_curve_wildlife_night = 2
 };
 
+VG_STATIC ent_marker *ent_find_marker( mdl_context *mdl,
+                                       mdl_array_ptr *arr, const char *alias )
+{
+   for( u32 i=0; i<mdl_arrcount(arr); i++ ){
+      ent_marker *marker = mdl_arritm( arr, i );
+
+      if( !strcmp( mdl_pstr( mdl, marker->pstr_alias ), alias ) ){
+         return marker;
+      }
+   }
+
+   return NULL;
+}
+
 #endif /* ENTITY_H */
index e6919785d5e0fb98d1f47a07765264cf79aca937..1b58c565fc093de3d7a2f98b439b9f39910f0f54 100644 (file)
Binary files a/maps_src/mp_mtzero.mdl and b/maps_src/mp_mtzero.mdl differ
diff --git a/menu.h b/menu.h
index 4f6564407990d6346ac91320bd051036dd836309..bcd614198626e540ab06c4e792960c7b0758161e 100644 (file)
--- a/menu.h
+++ b/menu.h
@@ -5,18 +5,23 @@
 #include "model.h"
 #include "world_render.h"
 #include "player.h"
+#include "conf.h"
 
-#include "shaders/menu.h"
+#include "shaders/model_menu.h"
 #include "vg_steam_friends.h"
 #include "submodules/tinydir/tinydir.h"
 
 VG_STATIC mdl_context menu_model;
+VG_STATIC mdl_array_ptr   menu_markers;
 VG_STATIC glmesh      menu_glmesh;
 VG_STATIC m4x3f       menu_mdl_mtx;
 VG_STATIC float       menu_opacity = 0.0f;
 VG_STATIC float       menu_input_cooldown = 0.0f;
-VG_STATIC float       menu_fov_target = 97.0f;
+VG_STATIC float       menu_fov_target = 97.0f,
+                      menu_smooth_fov = 97.0f;
 VG_STATIC v2f         menu_extra_angles;
+VG_STATIC v3f         menu_camera_pos;
+VG_STATIC v2f         menu_camera_angles;
 
 VG_STATIC int         cl_menu         = 0,
                       cl_menu_go_away = 0;
@@ -41,23 +46,24 @@ VG_STATIC void menu_btn_fuckoff( int event );
 VG_STATIC void menu_btn_reset( int event );
 VG_STATIC void menu_btn_map( int event );
 VG_STATIC void menu_btn_settings( int event );
+VG_STATIC void menu_btn_invert_y( int event );
 
-VG_STATIC mdl_node *menu_pnode_fov_slider,
-                   *menu_pnode_fov_min,
-                   *menu_pnode_fov_max,
-                   *menu_pnode_vol_slider,
-                   *menu_pnode_vol_min,
-                   *menu_pnode_vol_max;
+VG_STATIC mdl_mesh *menu_mesh_fov_slider,
+                   *menu_mesh_vol_slider;
 
-struct
-{
+VG_STATIC ent_marker
+                   *menu_mark_fov_min,
+                   *menu_mark_fov_max,
+                   *menu_mark_vol_min,
+                   *menu_mark_vol_max;
+
+struct{
    /* state */
    int loc;
    u32 page;
 
    /* map browser */
-   struct menu_map_file
-   {
+   struct menu_map_file{
       char name[ 64 ];
    }
    maps_list[ 16 ];
@@ -67,8 +73,7 @@ struct
 }
 VG_STATIC game_menu;
 
-enum menu_page
-{
+enum menu_page{
    k_menu_page_main     = 0x1,
    k_menu_page_skater   = 0x2,
    k_menu_page_quit     = 0x4,
@@ -76,16 +81,14 @@ enum menu_page
    k_menu_page_map      = 0x10
 };
 
-struct menu_btn_userdata
-{
+struct menu_btn_userdata{
    int   i;
    void *ptr_generic;
 };
 
 VG_STATIC int menu_settings_if( struct menu_btn_userdata ud )
 {
-   if( game_menu.page & k_menu_page_settings )
-   {
+   if( game_menu.page & k_menu_page_settings ){
       int *ptr = ud.ptr_generic;
       return *ptr;
    }
@@ -131,7 +134,7 @@ struct menu_button
               *lr,
               *ld;
 
-   mdl_node *pnode;
+   mdl_mesh *mesh;
    float falpha, fsize;
 }
 VG_STATIC menu_buttons[] = 
@@ -139,7 +142,7 @@ VG_STATIC menu_buttons[] =
    { 
       "text_quit", menu_vis, {.i=k_menu_page_main|k_menu_page_quit},   
       .fn_press = menu_btn_quit,
-         .ld="text_reset", .lr="text_settings", .ll="text_map"
+         .ld="text_reset", .lr="text_settings", /*.ll="text_map"*/
    },
    {
       "text_quitty", menu_vis, {.i=k_menu_page_quit}
@@ -151,18 +154,20 @@ VG_STATIC menu_buttons[] =
 {
    "text_reset", menu_vis, {.i=k_menu_page_main},
    .fn_press = menu_btn_reset,
-      .lu="text_quit", .ld="text_skater", .ll="text_map", .lr="text_settings"
+      .lu="text_quit", .ld="text_skater", /*.ll="text_map",*/ .lr="text_settings"
 },
 {  
    "text_skater", menu_vis, {.i=k_menu_page_main|k_menu_page_skater}, 
    .fn_press = menu_btn_skater,
-      .lu="text_reset", .ll="text_map", .lr="text_settings"
+      .lu="text_reset", /*.ll="text_map",*/ .lr="text_settings"
 },
+/*
 {
    "text_map", menu_vis, {.i=k_menu_page_main},
    .fn_press = menu_btn_map,
       .lr="text_reset"
 },
+*/
 {
    "text_settings", menu_vis, {.i=k_menu_page_main|k_menu_page_settings},
    .fn_press = menu_btn_settings,
@@ -177,7 +182,7 @@ VG_STATIC menu_buttons[] =
 
 { 
    "fov_slider",     menu_vis, {k_menu_page_settings},
-   .ld="text_blur
+   .ld="text_invert_y
 },
 { "fov_info",        menu_vis, {k_menu_page_settings} },
 
@@ -187,10 +192,18 @@ VG_STATIC menu_buttons[] =
 },
 { "vol_info",        menu_vis, {k_menu_page_settings} },
 
+{
+   "text_invert_y",  menu_vis, {k_menu_page_settings},
+   .fn_press = menu_btn_invert_y,
+   .lu = "fov_slider", .ld="text_blur"
+},
+{
+   "text_invert_y_check", menu_settings_if, {.ptr_generic=&cl_invert_y}
+},
 { 
    "text_blur",      menu_vis, {k_menu_page_settings},
    .fn_press = menu_btn_blur, 
-   .lu="fov_slider", .ld="vol_slider"
+   .lu="text_invert_y", .ld="vol_slider"
 },
 {
    "text_blur_check", menu_settings_if, {.ptr_generic=&cl_blur} 
@@ -221,11 +234,10 @@ VG_STATIC int menu_get_loc( const char *loc )
    return 0;
 }
 
+VG_STATIC int __respawn( int argc, const char *argv[] );
 VG_STATIC void menu_btn_reset( int event )
 {
-   reset_player(0,NULL);
-   world_routes_clear();
-
+   __respawn(0,NULL);
    cl_menu_go_away = 1;
    game_menu.page = 0;
 }
@@ -257,6 +269,11 @@ VG_STATIC void menu_btn_blur( int event )
    cl_blur ^= 0x1;
 }
 
+VG_STATIC void menu_btn_invert_y( int event )
+{
+   cl_invert_y ^= 0x1;
+}
+
 VG_STATIC void menu_btn_map( int event )
 {
    game_menu.page = k_menu_page_map;
@@ -266,13 +283,11 @@ VG_STATIC void menu_btn_map( int event )
    tinydir_dir dir;
    tinydir_open( &dir, "maps" );
 
-   while( dir.has_next )
-   {
+   while( dir.has_next ){
       tinydir_file file;
       tinydir_readfile( &dir, &file );
       
-      if( file.is_reg )
-      {
+      if( file.is_reg ){
          struct menu_map_file *mf = &game_menu.maps_list[ game_menu.map_count ];
          
          vg_strncpy( file.name, mf->name, 
@@ -291,8 +306,7 @@ VG_STATIC void menu_btn_map( int event )
 
 VG_STATIC void menu_crap_ui(void)
 {
-   if( cl_menu && (game_menu.page == k_menu_page_map) )
-   {
+   if( cl_menu && (game_menu.page == k_menu_page_map) ){
       ui_rect box;
       box[0] = vg.window_x/2 - 150;
       box[1] = vg.window_y/2 - 300;
@@ -301,18 +315,15 @@ VG_STATIC void menu_crap_ui(void)
 
       ui_fill_rect( box, 0xa0000000 );
 
-      if( game_menu.map_count == 0 )
-      {
+      if( game_menu.map_count == 0 ){
          ui_text( (ui_rect){ vg.window_x/2, box[1]+8, 0,0 }, "No maps found", 1,
                   k_text_align_center );
       }
-      else
-      {
+      else{
          ui_rect_pad( box, 4 );
          box[3] = 16;
 
-         for( int i=0; i<game_menu.map_count; i++ )
-         {
+         for( int i=0; i<game_menu.map_count; i++ ){
             struct menu_map_file *mf = &game_menu.maps_list[ i ];
 
             ui_fill_rect( box, game_menu.selected_map == i? 0xa0ffffff:
@@ -330,8 +341,7 @@ VG_STATIC void steam_on_game_overlay( CallbackMsg_t *msg )
    GameOverlayActivated_t *inf = (GameOverlayActivated_t *)msg->m_pubParam;
    vg_info( "Steam game overlay activated; pausing\n" );
 
-   if( inf->m_bActive )
-   {
+   if( inf->m_bActive ){
       cl_menu = 1;
       game_menu.page = k_menu_page_main;
       game_menu.loc = menu_get_loc( "text_skater" );
@@ -362,10 +372,11 @@ VG_STATIC void menu_init(void)
 
    vg_linear_clear( vg_mem.scratch );
 
-   mdl_open( &menu_model, "models/rs_menu.mdl" );
-   mdl_load_metadata( &menu_model, vg_mem.rtmemory );
-   mdl_load_mesh_data( &menu_model, vg_mem.scratch );
-   mdl_invert_uv_coordinates( &menu_model );
+   mdl_open( &menu_model, "models/rs_menu.mdl", vg_mem.rtmemory );
+   mdl_load_metadata_block( &menu_model, vg_mem.rtmemory );
+   mdl_load_mesh_block( &menu_model, vg_mem.scratch );
+   mdl_load_array( &menu_model, &menu_markers, "ent_marker", vg_mem.rtmemory );
+   //mdl_invert_uv_coordinates( &menu_model );
    mdl_close( &menu_model );
 
    vg_acquire_thread_sync();
@@ -375,26 +386,29 @@ VG_STATIC void menu_init(void)
    }
    vg_release_thread_sync();
 
-   for( int i=0; i<vg_list_size(menu_buttons); i++ )
-   {
+   for( int i=0; i<vg_list_size(menu_buttons); i++ ){
       struct menu_button *btn = &menu_buttons[i];
-      btn->pnode = mdl_node_from_name( &menu_model, btn->name );
+      btn->mesh = mdl_find_mesh( &menu_model, btn->name );
 
-      if( !btn->pnode )
-      {
+      if( !btn->mesh ){
          vg_info( "info: %s\n", btn->name );
          vg_fatal_exit_loop( "Menu programming error" );
       }
    }
 
-   menu_pnode_fov_max = mdl_node_from_name( &menu_model, "fov_slider_max" );
-   menu_pnode_fov_min = mdl_node_from_name( &menu_model, "fov_slider_min" );
-   menu_pnode_fov_slider = mdl_node_from_name( &menu_model, "fov_slider" );
-   menu_pnode_vol_max = mdl_node_from_name( &menu_model, "vol_slider_max" );
-   menu_pnode_vol_min = mdl_node_from_name( &menu_model, "vol_slider_min" );
-   menu_pnode_vol_slider = mdl_node_from_name( &menu_model, "vol_slider" );
+   menu_mark_fov_max = 
+      ent_find_marker( &menu_model, &menu_markers, "fov_slider_max" );
+   menu_mark_fov_min = 
+      ent_find_marker( &menu_model, &menu_markers, "fov_slider_min" );
+   menu_mark_vol_max = 
+      ent_find_marker( &menu_model, &menu_markers, "vol_slider_max" );
+   menu_mark_vol_min = 
+      ent_find_marker( &menu_model, &menu_markers, "vol_slider_min" );
+
+   menu_mesh_fov_slider = mdl_find_mesh( &menu_model, "fov_slider" );
+   menu_mesh_vol_slider = mdl_find_mesh( &menu_model, "vol_slider" );
 
-   shader_menu_register();
+   shader_model_menu_register();
 
 #ifdef SR_NETWORKED
    steam_register_callback( k_iGameOverlayActivated, steam_on_game_overlay );
@@ -405,12 +419,10 @@ VG_STATIC void menu_run_directional(void)
 {
    struct menu_button *btn = &menu_buttons[ game_menu.loc ];
 
-   if( vg_input_button_down( &input_menu_press ) )
-   {
-      if( btn->fn_press )
-      {
+   if( vg_input_button_down( &input_menu_press ) ){
+      if( btn->fn_press ){
          audio_lock();
-         audio_play_oneshot( &audio_ui[0], 1.0f );
+         audio_oneshot( &audio_ui[0], 1.0f, 0.0f );
          audio_unlock();
 
          btn->fn_press( 1 );
@@ -418,28 +430,23 @@ VG_STATIC void menu_run_directional(void)
       }
    }
 
-   if( menu_input_cooldown <= 0.0f )
-   {
+   if( menu_input_cooldown <= 0.0f ){
       v2f dir = {  input_menu_h.axis.value,
                   -input_menu_v.axis.value };
 
-      if( v2_length2( dir ) > 0.8f*0.8f )
-      {
+      if( v2_length2( dir ) > 0.8f*0.8f ){
          const char *link = NULL;
 
-         if( fabsf(dir[0]) > fabsf(dir[1]) )
-         {
+         if( fabsf(dir[0]) > fabsf(dir[1]) ){
             if( dir[0] > 0.0f ) link = btn->lr;
             else link = btn->ll;
          }
-         else
-         {
+         else{
             if( dir[1] > 0.0f ) link = btn->ld;
             else link = btn->lu;
          }
 
-         if( link )
-         {
+         if( link ){
             game_menu.loc = menu_get_loc( link );
             menu_input_cooldown = 0.25f;
          }
@@ -473,23 +480,19 @@ VG_STATIC void menu_page_main(void)
 
 VG_STATIC void menu_page_map(void)
 {
-   if( menu_page_should_backout() )
-   {
+   if( menu_page_should_backout() ){
       game_menu.page = k_menu_page_main;
       game_menu.loc = menu_get_loc( "text_map" );
    }
 
-   if( game_menu.map_count > 0 )
-   {
+   if( game_menu.map_count > 0 ){
       float v = input_menu_v.axis.value;
-      if( (fabsf(v) > 0.7f) && (menu_input_cooldown <= 0.0f) )
-      {
+      if( (fabsf(v) > 0.7f) && (menu_input_cooldown <= 0.0f) ){
          audio_lock();
-         audio_play_oneshot( &audio_rewind[4], 1.0f );
+         audio_oneshot( &audio_rewind[4], 1.0f, 0.0f );
          audio_unlock();
 
-         if( v > 0.0f )
-         {
+         if( v > 0.0f ){
             game_menu.selected_map --;
 
             if( game_menu.selected_map < 0 )
@@ -497,8 +500,7 @@ VG_STATIC void menu_page_map(void)
 
             menu_input_cooldown = 0.25f;
          }
-         else
-         {
+         else{
             game_menu.selected_map ++;
 
             if( game_menu.selected_map >= game_menu.map_count )
@@ -508,8 +510,8 @@ VG_STATIC void menu_page_map(void)
          }
       }
 
-      if( vg_input_button_down( &input_menu_press ) )
-      {
+      if( vg_input_button_down( &input_menu_press ) ){
+#if 0
          /* load map */
          char temp[256];
          strcpy( temp, "maps/" );
@@ -517,6 +519,7 @@ VG_STATIC void menu_page_map(void)
 
          world_change_world( 1, (const char *[]){ temp } );
          menu_close();
+#endif
       }
    }
 
@@ -525,8 +528,7 @@ VG_STATIC void menu_page_map(void)
 
 VG_STATIC void menu_page_quit(void)
 {
-   if( menu_page_should_backout() )
-   {
+   if( menu_page_should_backout() ){
       game_menu.page = k_menu_page_main;
       game_menu.loc = menu_get_loc( "text_quit" );
    }
@@ -535,26 +537,26 @@ VG_STATIC void menu_page_quit(void)
    menu_run_directional();
 }
 
+void temp_update_playermodel(void);
 VG_STATIC void menu_page_skater(void)
 {
    float h = input_menu_h.axis.value;
    menu_fov_target = 97.0f;
 
-   if( menu_page_should_backout() )
-   {
+   if( menu_page_should_backout() ){
       game_menu.page = k_menu_page_main;
       game_menu.loc = menu_get_loc( "text_skater" );
       return;
    }
 
-   if( (fabsf(h) > 0.7f) && (menu_input_cooldown <= 0.0f) )
-   {
+   if( (fabsf(h) > 0.7f) && (menu_input_cooldown <= 0.0f) ){
       audio_lock();
-      audio_play_oneshot( &audio_rewind[4], 1.0f );
+      audio_oneshot( &audio_rewind[4], 1.0f, 0.0f );
       audio_unlock();
 
-      if( h < 0.0f )
-      {
+      vg_info( "%f\n", h );
+
+      if( h < 0.0f ){
          cl_playermdl_id --;
          if( cl_playermdl_id < 0 )
             cl_playermdl_id = 2;
@@ -566,34 +568,34 @@ VG_STATIC void menu_page_skater(void)
 
          menu_input_cooldown = 0.25f;
       }
-      else
-      {
+      else{
          cl_playermdl_id ++;
          if( cl_playermdl_id > 2 )
             cl_playermdl_id = 0;
          
-         int ri = menu_get_loc( "skater_left" );
+         int ri = menu_get_loc( "skater_right" );
 
          menu_buttons[ri].fsize = 0.4f;
          menu_buttons[ri].falpha = 1.0f;
 
          menu_input_cooldown = 0.25f;
       }
+
+      temp_update_playermodel();
    }
 }
 
 VG_STATIC void menu_slider( float *value, int set_value,
-                            mdl_node *slider, mdl_node *pmin, mdl_node *pmax )
+                            mdl_mesh *slider, v3f co_min, v3f co_max )
 {
-   if( set_value )
-   {
+   if( set_value ){
       float h = input_menu_h.axis.value;
       if( fabsf(h) > 0.04f )
          *value += h * vg.frame_delta;
       *value = vg_clampf( *value, 0.0f, 1.0f );
    }
 
-   v3_lerp( pmin->co, pmax->co, *value, slider->co );
+   v3_lerp( co_min, co_max, *value, slider->transform.co );
 }
 
 VG_STATIC void menu_page_settings(void)
@@ -602,25 +604,26 @@ VG_STATIC void menu_page_settings(void)
 
    int fov_select = game_menu.loc == menu_get_loc( "fov_slider" );
    menu_slider( &cl_fov, fov_select,
-                  menu_pnode_fov_slider, menu_pnode_fov_min,
-                  menu_pnode_fov_max );
+                  menu_mesh_fov_slider, menu_mark_fov_min->transform.co,
+                  menu_mark_fov_max->transform.co );
 
    if( fov_select )
       menu_fov_target = vg_lerpf( 97.0f, 135.0f, cl_fov ) * 0.8f;
 
-   menu_slider( &vg_audio.volume_console, 
+   menu_slider( &vg_audio.external_global_volume,
                   (game_menu.loc == menu_get_loc( "vol_slider" )),
-                  menu_pnode_vol_slider, menu_pnode_vol_min,
-                  menu_pnode_vol_max );
+                  menu_mesh_vol_slider, menu_mark_vol_min->transform.co,
+                  menu_mark_vol_max->transform.co );
 
-   if( menu_page_should_backout() )
-   {
+   if( menu_page_should_backout() ){
       game_menu.page = k_menu_page_main;
       game_menu.loc = menu_get_loc( "text_settings" );
       return;
    }
 }
 
+player_instance *tmp_localplayer(void);
+
 VG_STATIC void menu_update(void)
 {
    vg_input_update( 1, &input_menu_h );
@@ -634,17 +637,13 @@ VG_STATIC void menu_update(void)
        toggle_kb = vg_input_button_down( &input_menu_toggle_kbm ),
        wait_for_a_sec = 0;
 
-   if( toggle_gp || toggle_kb )
-   {
-      if( cl_menu )
-      {
-         if( toggle_gp )
-         {
+   if( toggle_gp || toggle_kb ){
+      if( cl_menu ){
+         if( toggle_gp ){
             menu_close();
          }
       }
-      else
-      {
+      else{
          if( toggle_kb )
             wait_for_a_sec = 1;
 
@@ -653,8 +652,7 @@ VG_STATIC void menu_update(void)
       }
    }
 
-   if( !wait_for_a_sec && cl_menu )
-   {
+   if( !wait_for_a_sec && cl_menu ){
       if( game_menu.page == k_menu_page_main )
          menu_page_main();
       else if( game_menu.page == k_menu_page_skater )
@@ -669,48 +667,59 @@ VG_STATIC void menu_update(void)
 
    struct menu_button *btn = &menu_buttons[ game_menu.loc ];
 
-   v3f pos;
-   v2f angles;
-
    /* Base */
    {
-      v3f lookdir;
-      v3f *mtx = player.mdl.sk.final_mtx[player.mdl.id_head];
-      m3x3_mulv( mtx, (v3f){-1.0f,0.0f,0.0f}, lookdir );
-
-      lookdir[1] = 0.0f;
-      v3_normalize( lookdir );
-
+      player_instance *player = tmp_localplayer();
+      struct player_avatar *av = player->playeravatar;
+      
       v3f center_rough;
+      if( player->subsystem == k_player_subsystem_dead ){
+         m4x3_mulv( av->sk.final_mtx[av->id_hip], (v3f){0.0f,0.9f,0.0f},
+                    center_rough );
+      }
+      else{
+         m4x3_mulv( av->sk.final_mtx[av->id_head], (v3f){0.0f,1.5f,0.0f},
+                    center_rough );
+      }
 
-      if( player.is_dead )
-      {
-         v3_copy(player.mdl.ragdoll[ player.mdl.id_hip-1 ].rb.co, center_rough);
+      v3f cam_offset;
+      float cam_rot;
+      if( player->subsystem == k_player_subsystem_walk ){
+         v3_muls( player->rb.to_world[2],  1.0f, cam_offset );
+         cam_rot = 0.0f;
       }
-      else
-      {
-         v3_add( player.camera_pos, player.visual_transform[3], center_rough );
-         v3_muls( center_rough, 0.5f, center_rough );
+      else{
+         v3_muls( player->rb.to_world[0], -1.0f, cam_offset );
+         cam_rot = -VG_PIf*0.5f;
       }
 
-      v3_muladds( center_rough, lookdir, 1.5f, pos );
-      v3_add( (v3f){ 0.0f,0.8f,0.0f}, pos, pos );
 
-      angles[1] = 0.0f;
-      angles[0] = -atan2f( lookdir[0], lookdir[2] );
+      v3f lookdir;
+      m3x3_mulv( player->invbasis, cam_offset, lookdir );
+      lookdir[1] = 0.0f;
+      v3_normalize( lookdir );
+
+      m3x3_mulv( player->basis, lookdir, cam_offset );
+      v3_muladds( center_rough, cam_offset, 2.0f, menu_camera_pos );
+
+      menu_camera_angles[1] = 0.0f;
+      menu_camera_angles[0] = -atan2f( lookdir[0], lookdir[2] );
 
       /* setup model matrix */
       v4f qmenu_mdl;
-      q_axis_angle( qmenu_mdl, (v3f){0.0f,1.0f,0.0f}, -angles[0] );
-
+      q_axis_angle( qmenu_mdl, (v3f){0.0f,1.0f,0.0f}, -menu_camera_angles[0] );
       q_m3x3( qmenu_mdl, menu_mdl_mtx );
-      v3_copy( center_rough, menu_mdl_mtx[3] );
+      v3_add( center_rough, (v3f){0.0f,-0.5f,0.0f}, menu_mdl_mtx[3] );
+      m3x3_mul( player->basis, menu_mdl_mtx, menu_mdl_mtx );
+
+      menu_smooth_fov = vg_lerpf( menu_smooth_fov, menu_fov_target, 
+                                  vg.frame_delta * 8.2f );
    }
 
    /* Extra */
    {
       v3f delta;
-      v3_sub( btn->pnode->co, (v3f){ 0.0f,1.5f,-1.5f }, delta );
+      v3_sub( btn->mesh->transform.co, (v3f){ 0.0f,1.5f,-1.5f }, delta );
       v3_normalize( delta );
 
       float y = atan2f( delta[0], delta[2] ),
@@ -720,36 +729,22 @@ VG_STATIC void menu_update(void)
       menu_extra_angles[0] = vg_lerpf( menu_extra_angles[0], y, dt );
       menu_extra_angles[1] = vg_lerpf( menu_extra_angles[1], p, dt );
 
-      v2_muladds( angles, menu_extra_angles, 0.8f, angles );
-      angles[0] = fmodf( angles[0], VG_TAUf );
-   }
-   
-   /* Update camera */
-#if 0
-   {
-      main_camera.angles[0] = 
-         vg_alerpf( main_camera.angles[0], angles[0], menu_opacity );
-      main_camera.angles[1] = 
-         vg_lerpf ( main_camera.angles[1], angles[1], menu_opacity );
-      v3_lerp( main_camera.pos, pos, menu_opacity, main_camera.pos );
-
-      camera_update_transform( &main_camera );
+      v2_muladds( menu_camera_angles, menu_extra_angles, 0.8f, 
+                  menu_camera_angles );
+      menu_camera_angles[0] = fmodf( menu_camera_angles[0], VG_TAUf );
    }
-#endif
 
    float dt = vg.frame_delta * 6.0f;
    menu_opacity = vg_lerpf( menu_opacity, cl_menu&&!cl_menu_go_away, dt );
 
-   if( menu_opacity <= 0.01f )
-   {
+   if( menu_opacity <= 0.01f ){
       cl_menu = 0;
       cl_menu_go_away = 0;
    }
 
    vg.time_rate = 1.0-(double)menu_opacity;
 
-   if( cl_menu )
-   {
+   if( cl_menu ){
       menu_input_cooldown -= vg.frame_delta;
    }
 }
@@ -761,7 +756,7 @@ float expSustainedImpulse( float x, float f, float k )
     return fminf( x*x/(f*f), 1.0f+(2.0f/f)*s*expf(-k*s));
 }
 
-VG_STATIC void menu_render( camera *cam )
+VG_STATIC void menu_render_bg(void)
 {
    glEnable(GL_BLEND);
    glDisable(GL_DEPTH_TEST);
@@ -771,23 +766,25 @@ VG_STATIC void menu_render( camera *cam )
    shader_blitcolour_use();
    shader_blitcolour_uColour( (v4f){ 0.1f, 0.1f, 0.3f, menu_opacity*0.5f } );
    render_fsquad();
+}
 
+VG_STATIC void menu_render_fg( camera *cam )
+{
    glEnable( GL_DEPTH_TEST );
    glDisable( GL_BLEND );
 
    m4x3f mtx;
    
-   shader_menu_use();
-   shader_menu_uColour( (v4f){ 1.0f,1.0f,1.0f,1.0f} );
-   shader_menu_uTexMain( 1 );
+   shader_model_menu_use();
+   shader_model_menu_uColour( (v4f){ 1.0f,1.0f,1.0f,1.0f} );
+   shader_model_menu_uTexMain( 1 );
    vg_tex2d_bind( &tex_menu, 1 );
 
-   shader_menu_uPv( cam->mtx.pv );
-   shader_menu_uPvmPrev( cam->mtx_prev.pv );
+   shader_model_menu_uPv( cam->mtx.pv );
+   shader_model_menu_uPvmPrev( cam->mtx_prev.pv );
    mesh_bind( &menu_glmesh );
 
-   for( int i=0; i<vg_list_size(menu_buttons); i++ )
-   {
+   for( int i=0; i<vg_list_size(menu_buttons); i++ ){
       struct menu_button *btn = &menu_buttons[i];
       float talpha = i==game_menu.loc? 1.0f: 0.0f,
             tsize0 = btn->fn_visibility( btn->user )? 1.0f: 0.0f,
@@ -795,7 +792,7 @@ VG_STATIC void menu_render( camera *cam )
             tsize  = tsize0+tsize1;
 
       btn->falpha = vg_lerpf( btn->falpha, talpha, vg.frame_delta * 14.0f );
-      btn->fsize  = vg_lerpf( btn->fsize,  tsize,  vg.frame_delta * 3.0f  );
+      btn->fsize  = vg_lerpf( btn->fsize,  tsize,  vg.frame_delta * 7.0f  );
 
       /* Colour */
       v4f vselected = {0.95f*1.3f,0.45f*1.3f,0.095f*1.3f, 1.0f},
@@ -803,21 +800,20 @@ VG_STATIC void menu_render( camera *cam )
           vcurrent;
 
       v4_lerp( vnormal, vselected, btn->falpha, vcurrent );
-      shader_menu_uColour( vcurrent );
+      shader_model_menu_uColour( vcurrent );
 
       /* Create matrix */
       m4x3f mtx_size;
-      mdl_node_transform( btn->pnode, mtx );
+      mdl_transform_m4x3( &btn->mesh->transform, mtx );
       m4x3_mul( menu_mdl_mtx, mtx, mtx );
       m4x3_identity( mtx_size );
       m4x3_scale( mtx_size, expSustainedImpulse( btn->fsize, 0.5f, 8.7f) );
       m4x3_mul( mtx, mtx_size, mtx );
-      shader_menu_uMdl( mtx );
+      shader_model_menu_uMdl( mtx );
 
-      for( int j=0; j<btn->pnode->submesh_count; j++ )
-      {
+      for( int j=0; j<btn->mesh->submesh_count; j++ ){
          mdl_submesh *sm = 
-            &menu_model.submesh_buffer[ btn->pnode->submesh_start+j ];
+            mdl_arritm( &menu_model.submeshs, btn->mesh->submesh_start+j );
          mdl_draw_submesh( sm );
       }
    }
index 7fe4aa18ad94781f662bd5954cff13524e80e2e2..c1ac5b3fb8aee08de8d1475ccb21583331d07f20 100644 (file)
Binary files a/models_src/ch_jordan.mdl and b/models_src/ch_jordan.mdl differ
index 70355912bafaee36784164533d887b3126a11a3d..80e52abe94c1d77cdf798b002cf0db6412d78d10 100644 (file)
Binary files a/models_src/ch_outlaw.mdl and b/models_src/ch_outlaw.mdl differ
diff --git a/models_src/rs_menu.mdl b/models_src/rs_menu.mdl
new file mode 100644 (file)
index 0000000..2bcc670
Binary files /dev/null and b/models_src/rs_menu.mdl differ
index 483df660638629a2cef7de9952095b28e9fbc91f..8d6429f097d0ff0d937dd0315ea61ab034638fbb 100644 (file)
--- a/player.c
+++ b/player.c
@@ -88,7 +88,8 @@ void player__create( player_instance *inst )
 
       "bind use gp-y",
       "bind use e",
-      "bind camera c"
+      "bind camera c",
+      "bind camera gp-rb"
    };
 
    for( int i=0; i<vg_list_size(default_cfg); i++ )
@@ -199,8 +200,7 @@ void player__pre_update( player_instance *player )
       }
       else{
          if( player->subsystem == k_player_subsystem_dead ){
-            player->subsystem = k_player_subsystem_walk;
-            //reset_player( 0, NULL );
+            __respawn( 0, NULL );
          }
          else{
             /* cant do that */
@@ -321,6 +321,8 @@ void player__pass_gate( player_instance *player, ent_gate *gate )
    if( gate->type == k_gate_type_nonlocal )
       world_global.active_world = gate->target;
 
+   world_global.in_volume = 0;
+
    audio_lock();
    audio_oneshot( &audio_gate_pass, 1.0f, 0.0f );
    audio_unlock();
@@ -375,6 +377,7 @@ VG_STATIC void player__pre_render( player_instance *player )
          player->rewind_total_length = 0.0f;
          player->rewind_accum = 0.0f;
          world_global.sky_target_rate = 1.0;
+         world_global.last_use = world_global.time;
       }
       else{
          world_global.sky_target_rate = -100.0;
@@ -526,6 +529,7 @@ PLAYER_API void player__spawn( player_instance *player,
 
    player->subsystem = k_player_subsystem_walk;
    player->viewable_world = get_active_world();
+   player->gate_waiting = NULL;
 
    if( _player_reset[ player->subsystem ] )
       _player_reset[ player->subsystem ]( player, rp );
index cd7fd57a5996b28554968ed1c2b626fa043783c1..53016cd68884f2a6c32a085d745f844c8ab4c44b 100644 (file)
--- a/player.h
+++ b/player.h
@@ -28,8 +28,8 @@ struct player_instance
 
    enum camera_mode
    {
-      k_cam_firstperson = 0,
-      k_cam_thirdperson = 1
+      k_cam_firstperson = 1,
+      k_cam_thirdperson = 0
    }
    camera_mode;
    float camera_type_blend;
index 259a7987fc6bd5adda266765ce0834fe58f8c6a0..432fbaec639b39ab6025b6523997213488def673 100644 (file)
@@ -2,6 +2,7 @@
 #define PLAYER_COMMON_C
 
 #include "player.h"
+#include "conf.h"
 
 VG_STATIC void player_vector_angles( v3f angles, v3f v, float C, float k )
 {
@@ -115,8 +116,10 @@ VG_STATIC void player__cam_iterate( player_instance *player )
          vg.frame_delta * 8.0f, player->tpv_offset_smooth );
 
    /* fov -- simple blend */
-   /* FIXME: cl_fov */
-   player->cam.fov = vg_lerpf( 97.0f, 128.0f, player->camera_type_blend );
+   float fov_skate = vg_lerpf( 97.0f, 135.0f, cl_fov ),
+         fov_walk  = vg_lerpf( 90.0f, 110.0f, cl_fov );
+
+   player->cam.fov = vg_lerpf( fov_walk, fov_skate, player->camera_type_blend );
 
    /* 
     * first person camera
@@ -226,7 +229,12 @@ VG_STATIC void player__cam_iterate( player_instance *player )
 VG_STATIC void player_look( player_instance *player, v3f angles )
 {
    angles[2] = 0.0f;
-   v2_muladds( angles, vg.mouse_delta, 0.0025f, angles );
+
+   v2f mouse_input;
+   v2_copy( vg.mouse_delta, mouse_input );
+   if( cl_invert_y )
+      mouse_input[1] *= -1.0f;
+   v2_muladds( angles, mouse_input, 0.0025f, angles );
 
    if( vg_input.controller_should_use_trackpad_look ){
       static v2f last_input;
@@ -236,6 +244,9 @@ VG_STATIC void player_look( player_instance *player, v3f angles )
       v2f input = { player->input_js2h->axis.value,
                     player->input_js2v->axis.value };
 
+      if( cl_invert_y )
+         input[1] *= -1.0f;
+
       if( (v2_length2(last_input) > 0.001f) && (v2_length2(input) > 0.001f) ){
          v2_sub( input, last_input, vel );
          v2_muls( vel, 1.0f/vg.time_delta, vel );
@@ -251,7 +262,12 @@ VG_STATIC void player_look( player_instance *player, v3f angles )
    }
    else{
       angles[0] += player->input_js2h->axis.value * vg.time_delta * 4.0f;
-      angles[1] += player->input_js2v->axis.value * vg.time_delta * 4.0f;
+
+      float input_y = player->input_js2v->axis.value * vg.time_delta * 4.0f;
+      if( cl_invert_y )
+         input_y *= -1.0f;
+
+      angles[1] += input_y;
    }
 
    angles[1] = vg_clampf( angles[1], -VG_PIf*0.5f, VG_PIf*0.5f );
index bec54539ecd625135513fd136df79ad731a8f117..bd83545df6d7f43a9ece7c7dc86f9810621a26db 100644 (file)
@@ -4,6 +4,7 @@
 #include "player.h"
 #include "audio.h"
 #include "vg/vg_perlin.h"
+#include "menu.h"
 
 VG_STATIC void player__skate_bind( player_instance *player )
 {
@@ -127,10 +128,8 @@ VG_STATIC int skate_grind_scansq( player_instance *player,
       v3f tri[3];
 
       struct world_surface *surf = world_tri_index_surface(world,ptri[0]);
-#if 0
       if( !(surf->info.flags & k_material_flag_skate_surface) )
          continue;
-#endif
 
       for( int j=0; j<3; j++ )
          v3_copy( world->scene_geo->arrvertices[ptri[j]].co, tri[j] );
@@ -579,8 +578,6 @@ void player__approximate_best_trajectory( player_instance *player )
          v3_add( launch_co, co0, co0 );
 
          /* rough scan to make sure we dont collide with anything */
-         /* NOTE this was rarely needed and ends up with false negatives. */
-#if 0
          for( int j=1; j<=16; j++ ){
             t  = (float)j*(1.0f/16.0f);
             t *= 0.9f;
@@ -595,14 +592,13 @@ void player__approximate_best_trajectory( player_instance *player )
             v3f n;
 
             int idx = spherecast_world( world, co0,co1,
-                                        k_board_radius*0.5f, &t1, n);
+                                        k_board_radius*0.1f, &t1, n);
             if( idx != -1 ){
                goto invalidated_grind;
             }
 
             v3_copy( co1, co0 );
          }
-#endif
 
          v3_copy( grind.n, jump->n );
 
@@ -614,10 +610,8 @@ void player__approximate_best_trajectory( player_instance *player )
 
          s->possible_jumps[ s->possible_jump_count ++ ] = *jump;
 
-#if 0
          continue;
 invalidated_grind:;
-#endif
       }
    }
 
@@ -1010,7 +1004,8 @@ VG_STATIC void skate_apply_pump_model( player_instance *player )
       v3_muladds( s->state.throw_v, player->rb.to_world[1], -doty, Fl);
 
       if( s->state.activity == k_skate_activity_ground ){
-         v3_muladds( player->rb.v,     Fl,  k_mmcollect_lat, player->rb.v );
+         if( v3_length2(player->rb.v)<(20.0f*20.0f) )
+            v3_muladds( player->rb.v,     Fl,  k_mmcollect_lat, player->rb.v );
          v3_muladds( s->state.throw_v, Fl, -k_mmcollect_lat, s->state.throw_v );
       }
 
@@ -1191,10 +1186,13 @@ VG_STATIC void player__skate_post_update( player_instance *player )
       slide = 0.0f;
    }
 
+   static float menu_gate = 1.0f;
+   menu_gate = vg_lerpf( menu_gate, 1-cl_menu, vg.frame_delta*4.0f );
+
    float
-         vol_main    = sqrtf( (1.0f-air)*attn*(1.0f-slide) * 0.4f ),
-         vol_air     = sqrtf(       air *attn * 0.5f ),
-         vol_slide   = sqrtf( (1.0f-air)*attn*slide * 0.25f );
+         vol_main    = sqrtf( (1.0f-air)*attn*(1.0f-slide) * 0.4f ) * menu_gate,
+         vol_air     = sqrtf(       air *attn * 0.5f )              * menu_gate,
+         vol_slide   = sqrtf( (1.0f-air)*attn*slide * 0.25f )       * menu_gate;
 
    const u32 flags = AUDIO_FLAG_SPACIAL_3D|AUDIO_FLAG_LOOP;
 
index 692a296acd525e4f32e6652dd7cc1ec9eaf9aa31..1e92bb1a26015e4118361c957284daabd16f1600 100644 (file)
@@ -587,6 +587,7 @@ VG_STATIC void player__walk_update( player_instance *player )
       w->state_gate_storage = w->state;
       player__pass_gate( player, gate );
    }
+   rb_update_transform( &player->rb );
 }
 
 VG_STATIC void player__walk_restore( player_instance *player )
diff --git a/scene.h b/scene.h
index 74c4ea61a10476c4af5de918d2a07c066621521a..aeecd4e1e3d4df1e7a179dd1701efe66a2159e38 100644 (file)
--- a/scene.h
+++ b/scene.h
@@ -115,8 +115,8 @@ VG_STATIC void scene_add_mdl_submesh( scene *pscene, mdl_context *mdl,
    v3_normalize( normal_matrix[2] );
    
    for( u32 i=0; i<sm->vertex_count; i++ ){
-      mdl_vert   *src   = &src_verts[ i ];
-      scene_vert *pvert = &dst_verts[ i ];
+      mdl_vert   *src   = &src_verts[i];
+      scene_vert *pvert = &dst_verts[i];
 
       m4x3_mulv( transform, src->co, pvert->co );
 
index 795ca58fdf38b7c0f06745606c64ecbfa6f971db..1db6db52ab3e8c4d939f4ea91d1a9cee95dd3557 100644 (file)
@@ -27,16 +27,13 @@ VG_STATIC struct player_avatar localplayer_avatar;
 VG_STATIC glmesh localplayer_meshes[3];
 vg_tex2d localplayer_texture = { .path = "textures/ch_gradient.qoi" };
 
-
-
-
-
+player_instance *tmp_localplayer(void)
+{
+   return &localplayer;
+}
 
 #include "network.h"
-
-#if 0
 #include "menu.h"
-#endif
 #include "vehicle.h"
 
 static int cl_ui      = 1,
@@ -220,10 +217,14 @@ VG_STATIC void load_playermodels(void)
    vg_release_thread_sync();
 }
 
+void temp_update_playermodel(void){
+   player__use_mesh( &localplayer, &localplayer_meshes[cl_playermdl_id] );
+}
+
 VG_STATIC void vg_load(void)
 {
    vg_loader_step( render_init, NULL );
-   //vg_loader_step( menu_init, NULL );
+   vg_loader_step( menu_init, NULL );
    vg_loader_step( world_init, NULL );
    //vg_loader_step( player_init, NULL );
    //vg_loader_step( vehicle_init, NULL );
@@ -237,7 +238,7 @@ VG_STATIC void vg_load(void)
    player__create( &localplayer );
    player_avatar_load( &localplayer_avatar, "models/ch_new.mdl" );
    player__use_avatar( &localplayer, &localplayer_avatar );
-   player__use_mesh( &localplayer, &localplayer_meshes[0] );
+   player__use_mesh( &localplayer, &localplayer_meshes[cl_playermdl_id] );
    player__use_texture( &localplayer, &localplayer_texture );
    player__bind( &localplayer );
 
@@ -249,7 +250,7 @@ VG_STATIC void vg_load(void)
    /* 'systems' are completely loaded now */
 
    /* load home world */
-   world_load( &world_global.worlds[0], "maps/mp_gridmap.mdl" );
+   world_load( &world_global.worlds[0], "maps/mp_mtzero.mdl" );
 
 #if 0
    world_load( &world_global.worlds[1], "maps/mp_gridmap.mdl" );
@@ -360,15 +361,12 @@ VG_STATIC void vg_update_post(void)
 
       float dist = 200.0f;
 
-      for( int i=0; i<10; i++ )
-      {
-         if( ray_world( get_active_world(), rc, rd, &ray ) )
-         {
+      for( int i=0; i<10; i++ ){
+         if( ray_world( get_active_world(), rc, rd, &ray ) ){
             dist = (float)i*5.0f + ray.dist;
             break;
          }
-         else
-         {
+         else{
             v3_muladds( rc, rd, ray.dist, rc );
          }
       }
@@ -376,10 +374,8 @@ VG_STATIC void vg_update_post(void)
       distances[si] = dist;
 
 
-      for( int i=0; i<14; i++ )
-      {
-         if( distances[i] != 200.0f )
-         {
+      for( int i=0; i<14; i++ ){
+         if( distances[i] != 200.0f ){
             u32 colours[] = { VG__RED, VG__BLUE, VG__GREEN,
                               VG__CYAN, VG__YELOW, VG__PINK,
                               VG__WHITE };
@@ -404,13 +400,21 @@ VG_STATIC void vg_update_post(void)
 
       v3f ears = { 1.0f,0.0f,0.0f };
       m3x3_mulv( main_camera.transform, ears, ears );
-      v3_copy( ears, vg_audio.listener_ears );
-      v3_copy( main_camera.transform[3], vg_audio.listener_pos );
-      v3_copy( localplayer.rb.v, vg_audio.listener_velocity );
+      v3_copy( ears, vg_audio.external_listener_ears );
+      v3_copy( main_camera.transform[3], vg_audio.external_listener_pos );
+
+      /* TODO: this is transformed back and fourth twice. */
+      if( localplayer.gate_waiting ){
+         m4x3_mulv( localplayer.gate_waiting->transport,
+                    vg_audio.external_listener_pos, 
+                    vg_audio.external_listener_pos );
+      }
+
+      v3_copy( localplayer.rb.v, vg_audio.external_lister_velocity );
       audio_unlock();
 
-#if 0
       menu_update();
+#if 0
       vehicle_update_post();
 #endif
    }
@@ -430,16 +434,14 @@ VG_STATIC void present_view_with_post_processing(void)
    glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
    glBlendEquation(GL_FUNC_ADD);
 
-   if( cl_blur )
-   {
+   if( cl_blur ){
       shader_blitblur_use();
       shader_blitblur_uTexMain( 0 );
       shader_blitblur_uTexMotion( 1 );
       shader_blitblur_uBlurStrength(cl_blur_strength / (vg.frame_delta*60.0f));
 
       v2f menu_blurring;
-      //v2_muls( (v2f){ 0.04f, 0.001f }, menu_opacity, menu_blurring );
-      v2_muls( (v2f){ 0.04f, 0.001f }, 0.0f, menu_blurring );
+      v2_muls( (v2f){ 0.04f, 0.001f }, menu_opacity, menu_blurring );
       shader_blitblur_uOverrideDir( menu_blurring );
 
       if( cl_view_id == 0 )
@@ -451,8 +453,7 @@ VG_STATIC void present_view_with_post_processing(void)
 
       render_fb_bind_texture( gpipeline.fb_main, 1, 1 );
    }
-   else
-   {
+   else{
       shader_blit_use();
       shader_blit_uTexMain( 0 );
       render_fb_bind_texture( gpipeline.fb_main, 0, 0 );
@@ -500,17 +501,6 @@ VG_STATIC void render_scene(void)
 
    render_world( view_world, &main_camera, 0 );
 
-   int player_transparent = 1,
-       player_draw        = 1;
-
-#if 0
-   if( (localplayer.subsystem == k_player_subsystem_dead) ||
-       (localplayer.camera_mode == k_cam_thirdperson) )
-      player_transparent = 0;
-#endif
-               
-   if( !player_transparent && player_draw )
-      player__render( &main_camera, &localplayer );
 
    render_water_texture( view_world, &main_camera, 0 );
    render_fb_bind( gpipeline.fb_main );
@@ -520,18 +510,10 @@ VG_STATIC void render_scene(void)
    if( localplayer.gate_waiting ) depth = 0;
    render_world_gates( view_world, &main_camera, depth );
 
-   if( player_transparent && player_draw )
+   if( !cl_menu )
       render_player_transparent();
 }
 
-VG_STATIC void render_menu(void)
-{
-   glClear( GL_DEPTH_BUFFER_BIT );
-#if 0
-   menu_render( &main_camera );
-#endif
-}
-
 VG_STATIC void render_main_game(void)
 {
 #if 0
@@ -549,31 +531,33 @@ VG_STATIC void render_main_game(void)
    main_camera.fov   = fov;
 #endif
 
-   /* copy camera from player.
-    * TODO: blend with camera from menu */
-
-   /* FIXME: TEMP!! */
    player__pre_render( &localplayer );
 
-   v3_copy( localplayer.cam.pos, main_camera.pos );
-   v3_copy( localplayer.cam.angles, main_camera.angles );
-   main_camera.fov = localplayer.cam.fov;
+   v3_lerp( localplayer.cam.pos, menu_camera_pos, menu_opacity, 
+            main_camera.pos );
+   main_camera.angles[0] = 
+      vg_alerpf(  localplayer.cam.angles[0], menu_camera_angles[0], 
+                  menu_opacity );
+   main_camera.angles[1] = 
+      vg_lerpf ( localplayer.cam.angles[1], menu_camera_angles[1], 
+                 menu_opacity );
+
+   main_camera.fov = vg_lerpf( localplayer.cam.fov, menu_smooth_fov,
+                               menu_opacity );
    main_camera.nearz = 0.1f;
    main_camera.farz  = 2100.0f;
 
    camera_update_transform( &main_camera );
 
-   if( localplayer.gate_waiting )
-   {
+   if( localplayer.gate_waiting ){
       m3x3_mul( localplayer.basis_gate, main_camera.transform, 
                 main_camera.transform );
    }
-   else
-   {
+   else{
       m3x3_mul( localplayer.basis, main_camera.transform, 
                 main_camera.transform );
    }
-
+   
    camera_update_view( &main_camera );
    camera_update_projection( &main_camera );
    camera_finalize( &main_camera );
@@ -581,15 +565,18 @@ VG_STATIC void render_main_game(void)
    /* ========== Begin Frame ========== */
 
    render_scene();
-   present_view_with_post_processing();
 
-#if 0
-   if( cl_menu ) 
-   {
-      render_menu();
+   if( cl_menu ) {
+      glClear( GL_DEPTH_BUFFER_BIT );
+      menu_render_bg();
+      glEnable( GL_DEPTH_TEST );
       render_player_transparent();
    }
-#endif
+
+   present_view_with_post_processing();
+
+   if( cl_menu )
+      menu_render_fg( &main_camera );
 
    /* =========== End Frame =========== */
 }
@@ -618,12 +605,11 @@ VG_STATIC void vg_render(void)
 VG_STATIC void run_light_widget( struct light_widget *lw );
 VG_STATIC void vg_ui(void)
 {
+#if 0
    player__im_gui( &localplayer );
+#endif
    world_instance *world = get_active_world();
-
-#if 0
    menu_crap_ui();
-#endif
 
 #if 0
    if( cl_light_edit )
index 26e22f05b3ac7c303044037a39c2e23f97b4a490..e626f9f88f806574c896d86862d4324a4d6df883 100644 (file)
Binary files a/textures_src/menu.qoi and b/textures_src/menu.qoi differ
diff --git a/world.h b/world.h
index e23ae219e3abca7e8d610fbf53b0db6f3deb57ef..b9814f89aff027da117e8e6503237c56f99ac86b 100644 (file)
--- a/world.h
+++ b/world.h
@@ -570,7 +570,8 @@ VG_STATIC void ent_audio_call( world_instance *world, ent_call *call )
                      return;
                   }
                  
-                  existing = audio_channel_fadeout( existing, audio->crossfade);
+                  existing->group = 0;
+                  existing = audio_channel_fadeout(existing, audio->crossfade);
                }
 
                ch = audio_get_first_idle_channel();
index 500592d27eec550986eaab15d2e39cfc11893149..64395bc513748d277613b358f7ffca9943624f6f 100644 (file)
@@ -334,16 +334,23 @@ VG_STATIC void world_compute_light_indices( world_instance *world )
       icubes_max[i] = cubes_max[i];
    }
 
+   v3f cube_size;
+
    v3i icubes_count;
    v3i_sub( icubes_max, icubes_min, icubes_count );
    
    for( int i=0; i<3; i++ ){
-      icubes_count[i] = VG_MIN( 128, icubes_count[i]+1 );
-      cubes_max[i] = icubes_min[i] + icubes_count[i];
+      int clamped_count = VG_MIN( 128, icubes_count[i]+1 );
+      float clamped_max = icubes_min[i] + clamped_count,
+                    max = icubes_min[i] + icubes_count[i]+1;
+
+      icubes_count[i] = clamped_count;
+      cube_size[i] = (max / clamped_max) * k_light_cube_size;
+      cubes_max[i] = clamped_max;
    }
 
-   v3_muls( cubes_min, k_light_cube_size, cubes_min );
-   v3_muls( cubes_max, k_light_cube_size, cubes_max );
+   v3_mul( cubes_min, cube_size, cubes_min );
+   v3_mul( cubes_max, cube_size, cubes_max );
 
    for( int i=0; i<3; i++ ){
       float range = cubes_max[i]-cubes_min[i];
@@ -361,12 +368,8 @@ VG_STATIC void world_compute_light_indices( world_instance *world )
    vg_info( "Computing light cubes (%d) [%f %f %f] -> [%f %f %f]\n", 
              total_cubes, cubes_min[0], -cubes_min[2], cubes_min[1],
                           cubes_max[0], -cubes_max[2], cubes_max[1] );
-
    v3_copy( cubes_min, world->ub_lighting.g_cube_min );
 
-   v3f cube_size;
-   v3_div( (v3f){1.0f,1.0f,1.0f}, world->ub_lighting.g_cube_inv_range, 
-            cube_size );
    float bound_radius = v3_length( cube_size );
 
    for( int iz = 0; iz<icubes_count[2]; iz ++ ){
@@ -522,10 +525,10 @@ VG_STATIC void world_post_process( world_instance *world )
 
          /* colour  + night */
          v3_muls( light->colour, light->colour[3] * 2.0f, light_dst[i*3+0] );
-         light_dst[i*3+0][3] = -1.0f;
+         light_dst[i*3+0][3] = 2.0f;
 
          if( !light->daytime ){
-            u32 hash = (i * 29986577) & 0xff;
+            u32 hash = (i * 29986577u) & 0xffu;
             float switch_on = hash;
                   switch_on *= (1.0f/255.0f);
 
index f8a566c825878b534d2cef5aceef0fde9b5c27bc..d866cb7c543d7291f190ab057bd3426f01c4c5fe 100644 (file)
@@ -35,14 +35,18 @@ void world_routes_local_set_record( world_instance *world, ent_route *route,
       temp.points   = 0;
       temp.time     = time_centiseconds;
 
+#if 0
       highscores_push_record( &temp );
+#endif
 
       struct track_info *ti = &track_infos[ route->official_track_id ];
       ti->push = 1;
       
       if( ti->achievement_id ){
+#if 0
          steam_set_achievement( ti->achievement_id );
          steam_store_achievements();
+#endif
       }
    }
    else{
@@ -128,7 +132,8 @@ VG_STATIC void world_routes_activate_entry_gate( world_instance *world,
                                                  route->checkpoints_start+k );
 
                ent_gate *gk = mdl_arritm( &world->ent_gate, cp->gate_index );
-               if( gk == rg ){
+                         gk = mdl_arritm( &world->ent_gate, gk->target );
+               if( gk == dest ){
                   route->active_checkpoint = k;
                   world_routes_time_lap( world, route );
                   break;
@@ -253,35 +258,48 @@ VG_STATIC void world_routes_place_curve( world_instance *world,
       ray_hit ha, hb;
       ha.dist = 8.0f;
       hb.dist = 8.0f;
-      if( ray_world( world, sa, down, &ha ) && 
-          ray_world( world, sb, down, &hb ))
-      {
-         scene_vert va, vb;
-         
-         v3_muladds( ha.pos, up, 0.06f, va.co );
-         v3_muladds( hb.pos, up, 0.06f, vb.co );
-
-         scene_vert_pack_norm( &va, up );
-         scene_vert_pack_norm( &vb, up );
-
-         float t1 = (travel_length / total_length) * patch_count;
-         va.uv[0] = t1;
-         va.uv[1] = 0.0f;
-         vb.uv[0] = t1;
-         vb.uv[1] = 1.0f;
-
-         scene_push_vert( world->scene_lines, &va );
-         scene_push_vert( world->scene_lines, &vb );
-
-         if( last_valid ){
-            /* Connect them with triangles */
-            scene_push_tri( world->scene_lines, (u32[3]){ 
-                  last_valid+0-2, last_valid+1-2, last_valid+2-2} );
-            scene_push_tri( world->scene_lines, (u32[3]){ 
-                  last_valid+1-2, last_valid+3-2, last_valid+2-2} );
+
+      int resa = ray_world( world, sa, down, &ha ),
+          resb = ray_world( world, sb, down, &hb );
+
+      if( resa && resb ){
+         struct world_surface *surfa = ray_hit_surface( world, &ha ),
+                              *surfb = ray_hit_surface( world, &hb );
+
+         if( (surfa->info.flags & k_material_flag_skate_surface) &&
+             (surfb->info.flags & k_material_flag_skate_surface) )
+         {
+            scene_vert va, vb;
+
+            float gap = vg_fractf(cur_x*0.5f)*0.02f;
+            
+            v3_muladds( ha.pos, up, 0.06f+gap, va.co );
+            v3_muladds( hb.pos, up, 0.06f+gap, vb.co );
+
+            scene_vert_pack_norm( &va, up );
+            scene_vert_pack_norm( &vb, up );
+
+            float t1 = (travel_length / total_length) * patch_count;
+            va.uv[0] = t1;
+            va.uv[1] = 0.0f;
+            vb.uv[0] = t1;
+            vb.uv[1] = 1.0f;
+
+            scene_push_vert( world->scene_lines, &va );
+            scene_push_vert( world->scene_lines, &vb );
+
+            if( last_valid ){
+               /* Connect them with triangles */
+               scene_push_tri( world->scene_lines, (u32[3]){ 
+                     last_valid+0-2, last_valid+1-2, last_valid+2-2} );
+               scene_push_tri( world->scene_lines, (u32[3]){ 
+                     last_valid+1-2, last_valid+3-2, last_valid+2-2} );
+            }
+            
+            last_valid = world->scene_lines->vertex_count;
          }
-         
-         last_valid = world->scene_lines->vertex_count;
+         else
+            last_valid = 0;
       }
       else
          last_valid = 0;
@@ -312,7 +330,8 @@ VG_STATIC void world_routes_create_mesh( world_instance *world, u32 route_id )
       ent_gate *start_gate = mdl_arritm( &world->ent_gate, c0->gate_index );
       start_gate = mdl_arritm( &world->ent_gate, start_gate->target );
 
-      ent_gate *end_gate = mdl_arritm( &world->ent_gate, c1->gate_index );
+      ent_gate *end_gate = mdl_arritm( &world->ent_gate, c1->gate_index ),
+               *collector = mdl_arritm( &world->ent_gate, end_gate->target );
 
       v4f p[3];
 
@@ -377,9 +396,13 @@ VG_STATIC void world_routes_create_mesh( world_instance *world, u32 route_id )
          else{
             v3_copy( end_gate->co[0], p[2] );
             v3_add( (v3f){0.0f,0.1f,0.0f}, p[2], p[2] );
-            p[2][3] = end_gate->ref_count;
-            p[2][3] -= (float)end_gate->ref_total * 0.5f;
-            end_gate->ref_count ++;
+            p[2][3] = collector->ref_count;
+
+            if( i == route->checkpoints_count-1)
+               p[2][3] -= 1.0f;
+
+            p[2][3] -= (float)collector->ref_total * 0.5f;
+            //collector->ref_count ++;
          }
 
          /* p0,p1,p2 bezier patch is complete
@@ -439,8 +462,6 @@ VG_STATIC void world_routes_generate( world_instance *world )
 
          ent_gate *start_gate = mdl_arritm( &world->ent_gate, c0->gate_index );
          start_gate = mdl_arritm( &world->ent_gate, start_gate->target );
-
-         ent_gate *end_gate = mdl_arritm( &world->ent_gate, c1->gate_index );
          start_gate->ref_total ++;
 
          if( !c0->path_count )
@@ -452,12 +473,6 @@ VG_STATIC void world_routes_generate( world_instance *world )
             ent_route_node *rn = mdl_arritm( &world->ent_route_node,
                                              index->index );
             rn->ref_total ++;
-
-            if( j+1 < c0->path_count ){
-            }
-            else{
-               end_gate->ref_total ++;
-            }
          }
       }
    }
@@ -516,6 +531,10 @@ VG_STATIC void world_routes_ent_init( world_instance *world )
             gate = mdl_arritm(&world->ent_gate, gate->target );
 
             for( u32 k=0; k<4; k++ ){
+               if( gate->routes[k] == i ){
+                  vg_error( "already assigned route to gate\n" );
+                  break;
+               }
                if( gate->routes[k] == 0xffff ){
                   gate->routes[k] = i;
                   break;
@@ -525,6 +544,15 @@ VG_STATIC void world_routes_ent_init( world_instance *world )
       }
    }
 
+   for( u32 i=0; i<mdl_arrcount(&world->ent_gate); i++ ){
+      ent_gate *gate = mdl_arritm( &world->ent_gate, i );
+
+      vg_info( "ROUTES :: %hu %hu %hu %hu\n", gate->routes[0],
+                                              gate->routes[1],
+                                              gate->routes[2],
+                                              gate->routes[3] );
+   }
+
    world_routes_clear( world );
 }