aboutsummaryrefslogtreecommitdiff
path: root/advtrains/path.lua
diff options
context:
space:
mode:
Diffstat (limited to 'advtrains/path.lua')
-rw-r--r--advtrains/path.lua164
1 files changed, 153 insertions, 11 deletions
diff --git a/advtrains/path.lua b/advtrains/path.lua
index 506f27f..07b60b2 100644
--- a/advtrains/path.lua
+++ b/advtrains/path.lua
@@ -24,17 +24,7 @@ function advtrains.conway(midreal, prev, drives_on)--in order prev,mid,return
return vector.add(advtrains.round_vector_floor_y(next), {x=0, y=nextrailheight, z=0}), midconns[nconnid].c
end
---about regular: Used by 1. to ensure path gets generated far enough, since end index is not known at this time.
-function advtrains.pathpredict(id, train, regular)
- --TODO duplicate code under 5b.
- local path_pregen=10
-
- local gen_front= path_pregen
- local gen_back= - train.trainlen - path_pregen
- if regular then
- gen_front=math.max(train.index, train.detector_old_index) + path_pregen
- gen_back=math.min(train.end_index, train.detector_old_end_index) - path_pregen
- end
+function advtrains.pathpredict(id, train, gen_front, gen_back)
local maxn=train.path_extent_max or 0
while maxn < gen_front do--pregenerate
@@ -80,3 +70,155 @@ function advtrains.pathpredict(id, train, regular)
if not train.min_index_on_track then train.min_index_on_track=-1 end
if not train.max_index_on_track then train.max_index_on_track=0 end
end
+
+-- Naming conventions:
+-- 'index' - An index of the train.path table.
+-- 'offset' - A value in meters that determines how far on the path to walk relative to a certain index
+-- 'n' - Referring or pointing towards the 'next' path item, the one with index+1
+-- 'p' - Referring or pointing towards the 'prev' path item, the one with index-1
+-- 'f' - Referring to the positive end of the path (the end with the higher index)
+-- 'b' - Referring to the negative end of the path (the end with the lower index)
+
+-- New path structure of trains:
+--Tables:
+-- path - path positions. 'indices' are relative to this. At the moment, at.round_vector_floor_y(path[i])
+-- is the node this item corresponds to, however, this will change in the future.
+-- path_node - (reserved)
+-- path_cn - Connid of the current node that points towards path[i+1]
+-- path_cp - Connid of the current node that points towards path[i-1]
+-- When the day comes on that path!=node, these will only be set if this index represents a transition between rail nodes
+-- path_dist - The distance (in meters) between this (path[i]) and the next (path[i+1]) item of the path
+-- path_dir - The direction of this path item's transition to the next path item, which is the angle of conns[path_cn[i]].c
+--Variables:
+-- path_ext_f/b - how far path[i] is set
+-- path_trk_f/b - how far the path extends along a track. beyond those values, paths are generated in a straight line.
+-- path_req_f/b - how far path items were requested in the last step
+
+-- creates the path data structure, reconstructing the train from a position and a connid
+-- Important! train.drives_on must exist while calling this method
+-- returns: true - successful
+-- nil - node not yet available/unloaded, please wait
+-- false - node definitely gone, remove train
+function advtrains.path_create(train, pos, connid, rel_index)
+ local posr = advtrains.round_vector_floor_y(pos)
+ local node_ok, conns, rhe = advtrains.get_rail_info_at(pos, train.drives_on)
+ if not node_ok then
+ return node_ok
+ end
+ local mconnid = advtrains.get_matching_conn(connid, #conns)
+ train.index = rel_index
+ train.path = { [0] = { x=posr.x, y=posr.y+rhe, z=posr.z } }
+ train.path_cn = { [0] = connid }
+ train.path_cp = { [0] = mconnid }
+ train.path_dist = {}
+
+ train.path_dir = {
+ [ 0] = conns[connid],
+ [-1] = conns[mconnid]
+ }
+
+ train.path_ext_f=0
+ train.path_ext_b=0
+ train.path_trk_f=0
+ train.path_trk_b=0
+ train.path_req_f=0
+ train.path_req_b=0
+
+end
+
+-- Function to get path entry at a position. This function will automatically calculate more of the path when required.
+-- returns: pos, on_track
+function advtrains.path_get(train, index)
+ if index ~= atfloor(index) then
+ error("For train "..train.id..": Called path_get() but index="..index.." is not a round number")
+ end
+ while index > train.path_ext_f do
+ local pos = train.path[train.path_ext_f]
+ local connid = train.path_cn[train.path_ext_f]
+ local node_ok, this_conns, adj_pos, adj_connid, conn_idx, nextrail_y
+ if train.path_ext_f == train.path_trk_f then
+ node_ok, this_conns = advtrains.get_rail_info_at(this_pos)
+ if not node_ok then error("For train "..train.id..": Path item "..train.path_ext_f.." on-track but not a valid node!") end
+ adj_pos, adj_connid, conn_idx, nextrail_y = advtrains.get_adjacent_rail(pos, this_conns, connid, train.drives_on)
+ end
+ train.path_ext_f = train.path_ext_f + 1
+ if adj_pos then
+ adj_pos.y = adj_pos.y + nextrail_y
+ train.path_cp[train.path_ext_f] = adj_connid
+ local mconnid = advtrains.get_matching_conn(adj_connid)
+ train.path_cn[train.path_ext_f] = mconnid
+ train.path_dir[train.path_ext_f] = this_conns[mconnid]
+ train.path_trk_f = train.path_ext_f
+ else
+ -- off-track fallback behavior
+ adj_pos = advtrains.pos_add_dir(pos, train.path_dir[train.path_ext_f-1])
+ train.path_dir[train.path_ext_f] = train.path_dir[train.path_ext_f-1]
+ end
+ train.path[train.path_ext_f] = adj_pos
+ train.path_dist[train.path_ext_f - 1] = vector.distance(pos, adj_pos)
+ end
+ while index < train.path_ext_b do
+ local pos = train.path[train.path_ext_b]
+ local connid = train.path_cp[train.path_ext_b]
+ local node_ok, this_conns, adj_pos, adj_connid, conn_idx, nextrail_y
+ if train.path_ext_b == train.path_trk_b then
+ node_ok, this_conns = advtrains.get_rail_info_at(this_pos)
+ if not node_ok then error("For train "..train.id..": Path item "..train.path_ext_f.." on-track but not a valid node!") end
+ adj_pos, adj_connid, conn_idx, nextrail_y = advtrains.get_adjacent_rail(pos, this_conns, connid, train.drives_on)
+ end
+ train.path_ext_b = train.path_ext_b - 1
+ if adj_pos then
+ adj_pos.y = adj_pos.y + nextrail_y
+ train.path_cp[train.path_ext_b] = adj_connid
+ local mconnid = advtrains.get_matching_conn(adj_connid)
+ train.path_cn[train.path_ext_b] = mconnid
+ train.path_dir[train.path_ext_b] = advtrains.oppd(this_conns[mconnid]) --we need to rotate this here so that it points in positive path direction
+ train.path_trk_b = train.path_ext_b
+ else
+ -- off-track fallback behavior
+ adj_pos = advtrains.pos_add_dir(pos, train.path_dir[train.path_ext_b-1])
+ train.path_dir[train.path_ext_b] = train.path_dir[train.path_ext_b-1]
+ end
+ train.path[train.path_ext_b] = adj_pos
+ train.path_dist[train.path_ext_b] = vector.distance(pos, adj_pos)
+ end
+
+ return train.path[index], (index<=train.path_trk_f and index>=train.path_trk_b)
+
+end
+
+-- interpolated position to fractional index given, and angle based on path_dir
+-- returns: pos, angle(yaw)
+function advtrains.path_get_interpolated(train, index)
+ local i_floor = atfloor(index)
+ local i_ceil = i_floor + 1
+ local frac = index - i_floor
+ local p_floor, = advtrains.path_get(train, i_floor)
+ local p_ceil = advtrains.path_get(train, i_ceil)
+
+ local d_floor = train.path_dir[i_floor]
+ local d_ceil = train.path_dir[i_ceil]
+ local a_floor = advtrains.dir_to_angle(d_floor)
+ local a_ceil = advtrains.dir_to_angle(d_ceil)
+
+ local ang = advtrains.minAngleDiffRad(a_floor, a_ceil)
+
+ return vector.add(p_floor, vector.multiply(vector.subtract(p_ceil, p_floor), frac), (a_floor + frac * ang)%(2*math.pi) -- TODO does this behave correctly?
+end
+
+function advtrains.path_get_by_offset(train, index, offset)
+ local pos_in_train_left=pit
+ local index=train.index
+ if pos_in_train_left>(index-math.floor(index))*(train.path_dist[math.floor(index)] or 1) then
+ pos_in_train_left=pos_in_train_left - (index-math.floor(index))*(train.path_dist[math.floor(index)] or 1)
+ index=math.floor(index)
+ while pos_in_train_left>(train.path_dist[index-1] or 1) do
+ pos_in_train_left=pos_in_train_left - (train.path_dist[index-1] or 1)
+ index=index-1
+ end
+ index=index-(pos_in_train_left/(train.path_dist[index-1] or 1))
+ else
+ index=index-(pos_in_train_left/(train.path_dist[math.floor(index-1)] or 1))
+ end
+ return index
+end