mirror of
https://gitlab.com/gaelysam/mapgen_rivers.git
synced 2024-12-29 12:20:41 +01:00
terrainlib_lua: Hardcode flow_local for performance
as it is unlikely that it will be changed one day. This results in a drastic performance improvement (x4 speed for step 1)
This commit is contained in:
parent
d00295600d
commit
0bc100030c
@ -134,7 +134,7 @@ local rivermapper = dofile(modpath .. "rivermapper.lua")
|
|||||||
local gaussian = dofile(modpath .. "gaussian.lua")
|
local gaussian = dofile(modpath .. "gaussian.lua")
|
||||||
|
|
||||||
local function flow(model)
|
local function flow(model)
|
||||||
model.dirs, model.lakes = rivermapper.flow_routing(model.dem, model.dirs, model.lakes, 'semirandom')
|
model.dirs, model.lakes = rivermapper.flow_routing(model.dem, model.dirs, model.lakes)
|
||||||
model.rivers = rivermapper.accumulate(model.dirs, model.rivers)
|
model.rivers = rivermapper.accumulate(model.dirs, model.rivers)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -10,50 +10,18 @@
|
|||||||
-- Big thanks to them for releasing this paper under a free license ! :)
|
-- Big thanks to them for releasing this paper under a free license ! :)
|
||||||
|
|
||||||
-- The algorithm here makes use of most of the paper's concepts, including the Planar Borůvka algorithm.
|
-- The algorithm here makes use of most of the paper's concepts, including the Planar Borůvka algorithm.
|
||||||
-- Only flow_local and accumulate_flow are custom algorithms.
|
|
||||||
|
|
||||||
|
|
||||||
local function flow_local_semirandom(plist)
|
|
||||||
-- Determines how water should flow at 1 node scale.
|
|
||||||
-- The straightforward approach would be "Water will flow to the lowest of the 4 neighbours", but here water flows to one of the lower neighbours, chosen randomly, but probability depends on height difference.
|
|
||||||
-- This makes rivers better follow the curvature of the topography at large scale, and be less biased by pure N/E/S/W directions.
|
|
||||||
-- 'plist': array of downward height differences (0 if upward)
|
|
||||||
local sum = 0
|
|
||||||
for i=1, #plist do
|
|
||||||
sum = sum + plist[i] -- Sum of probabilities
|
|
||||||
end
|
|
||||||
|
|
||||||
if sum == 0 then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
local r = math.random() * sum
|
|
||||||
for i=1, #plist do
|
|
||||||
local p = plist[i]
|
|
||||||
if r < p then
|
|
||||||
return i
|
|
||||||
end
|
|
||||||
r = r - p
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Maybe implement more flow methods in the future?
|
|
||||||
local flow_methods = {
|
|
||||||
semirandom = flow_local_semirandom,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Applies all steps of the flow routing, to calculate flow direction for every node, and lake surface elevation.
|
-- Applies all steps of the flow routing, to calculate flow direction for every node, and lake surface elevation.
|
||||||
-- It's quite a hard piece of code, but we will go step by step and explain what's going on, so stay with me and... let's goooooooo!
|
-- It's quite a hard piece of code, but we will go step by step and explain what's going on, so stay with me and... let's goooooooo!
|
||||||
local function flow_routing(dem, dirs, lakes, method) -- 'dirs' and 'lakes' are optional tables to reuse for memory optimization, they may contain any data.
|
local function flow_routing(dem, dirs, lakes) -- 'dirs' and 'lakes' are optional tables to reuse for memory optimization, they may contain any data.
|
||||||
method = method or 'semirandom'
|
|
||||||
local flow_local = flow_methods[method] or flow_local_semirandom
|
|
||||||
|
|
||||||
dirs = dirs or {}
|
dirs = dirs or {}
|
||||||
lakes = lakes or {}
|
lakes = lakes or {}
|
||||||
|
|
||||||
-- Localize for performance
|
-- Localize for performance
|
||||||
local tremove = table.remove
|
local tremove = table.remove
|
||||||
local mmax = math.max
|
local mmax = math.max
|
||||||
|
local mrand = math.random
|
||||||
|
|
||||||
local X, Y = dem.X, dem.Y
|
local X, Y = dem.X, dem.Y
|
||||||
dirs.X = X
|
dirs.X = X
|
||||||
@ -74,14 +42,29 @@ local function flow_routing(dem, dirs, lakes, method) -- 'dirs' and 'lakes' are
|
|||||||
for y=1, Y do
|
for y=1, Y do
|
||||||
for x=1, X do
|
for x=1, X do
|
||||||
local zi = dem[i]
|
local zi = dem[i]
|
||||||
local plist = { -- Get the height difference of the 4 neighbours (and 0 if uphill)
|
-- Determine how water should flow at 1 node scale.
|
||||||
y<Y and mmax(zi-dem[i+X], 0) or 0, -- Southward
|
-- The straightforward approach would be "Water will flow to the lowest of the 4 neighbours", but here water flows to one of the lower neighbours, chosen randomly, with probability depending on height difference.
|
||||||
x<X and mmax(zi-dem[i+1], 0) or 0, -- Eastward
|
-- This makes rivers better follow the curvature of the topography at large scale, and be less biased by pure N/E/S/W directions.
|
||||||
y>1 and mmax(zi-dem[i-X], 0) or 0, -- Northward
|
local pSouth = y<Y and mmax(zi-dem[i+X], 0) or 0
|
||||||
x>1 and mmax(zi-dem[i-1], 0) or 0, -- Westward
|
local pEast = x<X and mmax(zi-dem[i+1], 0) or 0
|
||||||
}
|
local pNorth = y>1 and mmax(zi-dem[i-X], 0) or 0
|
||||||
|
local pWest = x>1 and mmax(zi-dem[i-1], 0) or 0
|
||||||
|
|
||||||
|
local d = 0
|
||||||
|
local sum = pSouth + pEast + pNorth + pWest
|
||||||
|
local r = mrand() * sum
|
||||||
|
if sum > 0 then
|
||||||
|
if r < pSouth then
|
||||||
|
d = 1
|
||||||
|
elseif r-pSouth < pEast then
|
||||||
|
d = 2
|
||||||
|
elseif r-pSouth-pEast < pNorth then
|
||||||
|
d = 3
|
||||||
|
else
|
||||||
|
d = 4
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local d = flow_local(plist)
|
|
||||||
-- 'dirs': Direction toward which water flow
|
-- 'dirs': Direction toward which water flow
|
||||||
-- 'dirs2': Directions from which water comes
|
-- 'dirs2': Directions from which water comes
|
||||||
dirs[i] = d
|
dirs[i] = d
|
||||||
@ -438,5 +421,4 @@ end
|
|||||||
return {
|
return {
|
||||||
flow_routing = flow_routing,
|
flow_routing = flow_routing,
|
||||||
accumulate = accumulate,
|
accumulate = accumulate,
|
||||||
flow_methods = flow_methods,
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user