forked from mtcontrib/vector_extras
Merge branch 'master' of yunohost.local:mtcontrib/vector_extras into nalc-1.2-dev
This commit is contained in:
commit
268c6a0c36
@ -1 +1 @@
|
|||||||
WTFPL
|
CC0, except for code copied from e.g. minetest's builtin
|
||||||
|
116
adammil_flood_fill.lua
Normal file
116
adammil_flood_fill.lua
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
-- http://www.adammil.net/blog/v126_A_More_Efficient_Flood_Fill.html
|
||||||
|
|
||||||
|
local can_go
|
||||||
|
local marked_places
|
||||||
|
local function calc_2d_index(x, y)
|
||||||
|
return (y + 32768) * 65536 + x + 32768
|
||||||
|
end
|
||||||
|
local function mark(x, y)
|
||||||
|
marked_places[calc_2d_index(x, y)] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local _fill
|
||||||
|
local function fill(x, y)
|
||||||
|
if can_go(x, y) then
|
||||||
|
_fill(x, y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local corefill
|
||||||
|
function _fill(x, y)
|
||||||
|
while true do
|
||||||
|
local ox = x
|
||||||
|
local oy = y
|
||||||
|
while can_go(x, y-1) do
|
||||||
|
y = y-1
|
||||||
|
end
|
||||||
|
while can_go(x-1, y) do
|
||||||
|
x = x-1
|
||||||
|
end
|
||||||
|
if x == ox
|
||||||
|
and y == oy then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
corefill(x, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
function corefill(x, y)
|
||||||
|
local lastcnt = 0
|
||||||
|
repeat
|
||||||
|
local cnt = 0
|
||||||
|
local sx = x
|
||||||
|
if lastcnt ~= 0
|
||||||
|
and not can_go(y, x) then
|
||||||
|
-- go right to find the x start
|
||||||
|
repeat
|
||||||
|
lastcnt = lastcnt-1
|
||||||
|
if lastcnt == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
x = x+1
|
||||||
|
until can_go(x, y)
|
||||||
|
sx = x
|
||||||
|
else
|
||||||
|
-- go left if possible, and mark and _fill above
|
||||||
|
while can_go(x-1, y) do
|
||||||
|
x = x-1
|
||||||
|
mark(x, y)
|
||||||
|
if can_go(x, y-1) then
|
||||||
|
_fill(x, y-1)
|
||||||
|
end
|
||||||
|
cnt = cnt+1
|
||||||
|
lastcnt = lastcnt+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- go right if possible, and mark
|
||||||
|
while can_go(sx, y) do
|
||||||
|
mark(sx, y)
|
||||||
|
cnt = cnt+1
|
||||||
|
sx = sx+1
|
||||||
|
end
|
||||||
|
|
||||||
|
if cnt < lastcnt then
|
||||||
|
local e = x + lastcnt
|
||||||
|
sx = sx+1
|
||||||
|
while sx < e do
|
||||||
|
if can_go(sx, y) then
|
||||||
|
corefill(sx, y)
|
||||||
|
end
|
||||||
|
sx = sx+1
|
||||||
|
end
|
||||||
|
elseif cnt > lastcnt then
|
||||||
|
local ux = x + lastcnt + 1
|
||||||
|
while ux < sx do
|
||||||
|
if can_go(ux, y-1) then
|
||||||
|
_fill(ux, y-1)
|
||||||
|
end
|
||||||
|
ux = ux+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
lastcnt = cnt
|
||||||
|
y = y+1
|
||||||
|
until lastcnt == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local function apply_fill(go_test, x0, y0, allow_revisit)
|
||||||
|
if allow_revisit then
|
||||||
|
can_go = go_test
|
||||||
|
else
|
||||||
|
local visited = {}
|
||||||
|
can_go = function(x, y)
|
||||||
|
local vi = calc_2d_index(x, y)
|
||||||
|
if visited[vi] then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
visited[vi] = true
|
||||||
|
return go_test(x, y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
marked_places = {}
|
||||||
|
fill(x0, y0)
|
||||||
|
return marked_places
|
||||||
|
end
|
||||||
|
|
||||||
|
return apply_fill
|
53
fill_3d.lua
Normal file
53
fill_3d.lua
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
-- Algorithm created by sofar and changed by others:
|
||||||
|
-- https://github.com/minetest/minetest/commit/d7908ee49480caaab63d05c8a53d93103579d7a9
|
||||||
|
|
||||||
|
local function search(go, p, apply_move, moves)
|
||||||
|
local num_moves = #moves
|
||||||
|
|
||||||
|
-- We make a stack, and manually maintain size for performance.
|
||||||
|
-- Stored in the stack, we will maintain tables with pos, and
|
||||||
|
-- last neighbor visited. This way, when we get back to each
|
||||||
|
-- node, we know which directions we have already walked, and
|
||||||
|
-- which direction is the next to walk.
|
||||||
|
local s = {}
|
||||||
|
local n = 0
|
||||||
|
-- The neighbor order we will visit from our table.
|
||||||
|
local v = 1
|
||||||
|
|
||||||
|
while true do
|
||||||
|
-- Push current pos onto the stack.
|
||||||
|
n = n + 1
|
||||||
|
s[n] = {p = p, v = v}
|
||||||
|
-- Select next node from neighbor list.
|
||||||
|
p = apply_move(p, moves[v])
|
||||||
|
-- Now we check out the node. If it is in need of an update,
|
||||||
|
-- it will let us know in the return value (true = updated).
|
||||||
|
if not go(p) then
|
||||||
|
-- If we don't need to "recurse" (walk) to it then pop
|
||||||
|
-- our previous pos off the stack and continue from there,
|
||||||
|
-- with the v value we were at when we last were at that
|
||||||
|
-- node
|
||||||
|
repeat
|
||||||
|
local pop = s[n]
|
||||||
|
p = pop.p
|
||||||
|
v = pop.v
|
||||||
|
s[n] = nil
|
||||||
|
n = n - 1
|
||||||
|
-- If there's nothing left on the stack, and no
|
||||||
|
-- more sides to walk to, we're done and can exit
|
||||||
|
if n == 0 and v == num_moves then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
until v < num_moves
|
||||||
|
-- The next round walk the next neighbor in list.
|
||||||
|
v = v + 1
|
||||||
|
else
|
||||||
|
-- If we did need to walk the neighbor, then
|
||||||
|
-- start walking it from the walk order start (1),
|
||||||
|
-- and not the order we just pushed up the stack.
|
||||||
|
v = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return search
|
64
init.lua
64
init.lua
@ -1,4 +1,4 @@
|
|||||||
local load_time_start = minetest.get_us_time()
|
local path = minetest.get_modpath"vector_extras"
|
||||||
|
|
||||||
local funcs = {}
|
local funcs = {}
|
||||||
|
|
||||||
@ -399,6 +399,66 @@ function funcs.from_number(i)
|
|||||||
return {x=i, y=i, z=i}
|
return {x=i, y=i, z=i}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local adammil_fill = dofile(path .. "/adammil_flood_fill.lua")
|
||||||
|
function funcs.search_2d(go_test, x0, y0, allow_revisit, give_map)
|
||||||
|
marked_places = adammil_fill(go_test, x0, y0, allow_revisit)
|
||||||
|
if give_map then
|
||||||
|
return marked_places
|
||||||
|
end
|
||||||
|
local l = {}
|
||||||
|
for vi in pairs(marked_places) do
|
||||||
|
local x = (vi % 65536) - 32768
|
||||||
|
local y = (math.floor(x / 65536) % 65536) - 32768
|
||||||
|
l[#l+1] = {x, y}
|
||||||
|
end
|
||||||
|
return l
|
||||||
|
end
|
||||||
|
|
||||||
|
local fallings_search = dofile(path .. "/fill_3d.lua")
|
||||||
|
local moves_touch = {
|
||||||
|
{x = -1, y = 0, z = 0},
|
||||||
|
{x = 0, y = 0, z = 0},
|
||||||
|
{x = 1, y = 0, z = 0},
|
||||||
|
{x = 0, y = -1, z = 0},
|
||||||
|
{x = 0, y = 1, z = 0},
|
||||||
|
{x = 0, y = 0, z = -1},
|
||||||
|
{x = 0, y = 0, z = 1},
|
||||||
|
}
|
||||||
|
local moves_near = {}
|
||||||
|
for z = -1,1 do
|
||||||
|
for y = -1,1 do
|
||||||
|
for x = -1,1 do
|
||||||
|
moves_near[#moves_near+1] = {x = x, y = y, z = z}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function funcs.search_3d(can_go, startpos, apply_move, moves)
|
||||||
|
local visited = {}
|
||||||
|
local found = {}
|
||||||
|
local function on_visit(pos)
|
||||||
|
local vi = minetest.hash_node_position(pos)
|
||||||
|
if visited[vi] then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
visited[vi] = true
|
||||||
|
local valid_pos = can_go(pos)
|
||||||
|
if valid_pos then
|
||||||
|
found[#found+1] = pos
|
||||||
|
end
|
||||||
|
return valid_pos
|
||||||
|
end
|
||||||
|
if apply_move == "touch" then
|
||||||
|
apply_move = vector.add
|
||||||
|
moves = moves_touch
|
||||||
|
elseif apply_move == "near" then
|
||||||
|
apply_move = vector.add
|
||||||
|
moves = moves_near
|
||||||
|
end
|
||||||
|
fallings_search(on_visit, startpos, apply_move, moves)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
local explosion_tables = {}
|
local explosion_tables = {}
|
||||||
function funcs.explosion_table(r)
|
function funcs.explosion_table(r)
|
||||||
local table = explosion_tables[r]
|
local table = explosion_tables[r]
|
||||||
@ -961,7 +1021,6 @@ end
|
|||||||
|
|
||||||
vector_extras_functions = funcs
|
vector_extras_functions = funcs
|
||||||
|
|
||||||
local path = minetest.get_modpath"vector_extras"
|
|
||||||
dofile(path .. "/legacy.lua")
|
dofile(path .. "/legacy.lua")
|
||||||
--dofile(minetest.get_modpath("vector_extras").."/vector_meta.lua")
|
--dofile(minetest.get_modpath("vector_extras").."/vector_meta.lua")
|
||||||
|
|
||||||
@ -977,7 +1036,6 @@ for name,func in pairs(funcs) do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local time = (minetest.get_us_time() - load_time_start) / 1000000
|
local time = (minetest.get_us_time() - load_time_start) / 1000000
|
||||||
local msg = "[vector_extras] loaded after ca. " .. time .. " seconds."
|
local msg = "[vector_extras] loaded after ca. " .. time .. " seconds."
|
||||||
if time > 0.01 then
|
if time > 0.01 then
|
||||||
|
Loading…
Reference in New Issue
Block a user