Replace trace_node_ray algorithm

This is an algorithm that I designed myself.  It fixes an
issue with the old code where it would be more eager to
move in some directions rather than others.  This bug
resulted in, eg, a lead block on a radiation source's
+x side protecting you when you were directly overhead.
This commit is contained in:
ShadowNinja 2016-03-21 02:59:42 -04:00 committed by ShadowNinja
parent cfd4cb7871
commit e501c4622b

View File

@ -63,64 +63,50 @@ technic.tube_inject_item = pipeworks.tube_inject_item or function(pos, start_pos
end end
-- Based on code by Uberi: https://gist.github.com/Uberi/3125280 --- Iterates over the node positions along the specified ray.
-- The returned positions will not include the starting position.
function technic.trace_node_ray(pos, dir, range) function technic.trace_node_ray(pos, dir, range)
local p = vector.round(pos) local x_step = dir.x > 0 and 1 or -1
local x_step, y_step, z_step = 0, 0, 0 local y_step = dir.y > 0 and 1 or -1
local x_component, y_component, z_component = 0, 0, 0 local z_step = dir.z > 0 and 1 or -1
local x_intersect, y_intersect, z_intersect = 0, 0, 0
if dir.x == 0 then local i = 1
x_intersect = math.huge return function(p)
elseif dir.x > 0 then -- Approximation of where we should be if we weren't rounding
x_step = 1 -- to nodes. This moves forward a bit faster then we do.
x_component = 1 / dir.x -- A correction is done below.
x_intersect = x_component local real_x = pos.x + (dir.x * i)
else local real_y = pos.y + (dir.y * i)
x_step = -1 local real_z = pos.z + (dir.z * i)
x_component = 1 / -dir.x
end -- How far off we've gotten from where we should be.
if dir.y == 0 then local dx = math.abs(real_x - p.x)
y_intersect = math.huge local dy = math.abs(real_y - p.y)
elseif dir.y > 0 then local dz = math.abs(real_z - p.z)
y_step = 1
y_component = 1 / dir.y -- If the real position moves ahead too fast, stop it so we
y_intersect = y_component -- can catch up. If it gets too far ahead it will smooth
else -- out our movement too much and we won't turn fast enough.
y_step = -1 if dx + dy + dz < 2 then
y_component = 1 / -dir.y i = i + 1
end
if dir.z == 0 then
z_intersect = math.huge
elseif dir.z > 0 then
z_step = 1
z_component = 1 / dir.z
z_intersect = z_component
else
z_step = -1
z_component = 1 / -dir.z
end end
return function() -- Step in whichever direction we're most off course in.
if x_intersect < y_intersect then if dx > dy then
if x_intersect < z_intersect then if dx > dz then
p.x = p.x + x_step p.x = p.x + x_step
x_intersect = x_intersect + x_component
else else
p.z = p.z + z_step p.z = p.z + z_step
z_intersect = z_intersect + z_component
end end
elseif y_intersect < z_intersect then elseif dy > dz then
p.y = p.y + y_step p.y = p.y + y_step
y_intersect = y_intersect + y_component
else else
p.z = p.z + z_step p.z = p.z + z_step
z_intersect = z_intersect + z_component
end end
if vector.distance(pos, p) > range then if vector.distance(pos, p) > range then
return nil return nil
end end
return p return p
end end, vector.round(pos)
end end