2024-01-04 22:47:50 +01:00
|
|
|
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
2021-06-03 20:08:57 +02:00
|
|
|
|
2024-01-04 22:47:50 +01:00
|
|
|
local EvolutionModel = dofile(modpath .. '/terrainlib_lua/erosion.lua')
|
|
|
|
local twist = dofile(modpath .. '/terrainlib_lua/twist.lua')
|
2021-06-03 20:08:57 +02:00
|
|
|
|
2024-01-04 22:47:50 +01:00
|
|
|
local blocksize = tonumber(mapgen_rivers.settings:get("blocksize"))
|
|
|
|
local tectonic_speed = tonumber(mapgen_rivers.settings:get("tectonic_speed"))
|
2021-06-03 20:08:57 +02:00
|
|
|
|
2024-01-04 22:47:50 +01:00
|
|
|
local np_base = mapgen_rivers.settings:get_np_group("np_base")
|
|
|
|
np_base.spread.x = np_base.spread.x / blocksize
|
|
|
|
np_base.spread.y = np_base.spread.y / blocksize
|
|
|
|
np_base.spread.z = np_base.spread.z / blocksize
|
2021-06-06 13:25:43 +02:00
|
|
|
|
2024-01-04 22:47:50 +01:00
|
|
|
local evol_params = {
|
|
|
|
K = tonumber(mapgen_rivers.settings:get("river_erosion_coef")),
|
|
|
|
m = tonumber(mapgen_rivers.settings:get("river_erosion_power")),
|
|
|
|
d = tonumber(mapgen_rivers.settings:get("difusive_erosion")),
|
|
|
|
}
|
|
|
|
|
|
|
|
local time = tonumber(mapgen_rivers.settings:get("evol_time"))
|
|
|
|
local time_step = tonumber(mapgen_rivers.settings:get("evol_time_step"))
|
2021-06-03 20:08:57 +02:00
|
|
|
local niter = math.ceil(time/time_step)
|
|
|
|
time_step = time / niter
|
|
|
|
|
2023-12-28 15:27:36 +01:00
|
|
|
-- Setup the model
|
2024-01-04 23:28:33 +01:00
|
|
|
local size = {
|
|
|
|
x = tonumber(mapgen_rivers.settings:get("grid_x_size")),
|
|
|
|
y = tonumber(mapgen_rivers.settings:get("grid_z_size")),
|
|
|
|
}
|
2021-06-05 11:24:28 +02:00
|
|
|
|
2023-12-28 15:27:36 +01:00
|
|
|
local seed = tonumber(minetest.get_mapgen_setting("seed"))
|
|
|
|
np_base.seed = (np_base.seed or 0) + seed
|
2021-06-03 20:08:57 +02:00
|
|
|
|
2023-12-28 15:27:36 +01:00
|
|
|
local nobj_base = PerlinNoiseMap(np_base, {x=size.x, y=1, z=size.y})
|
2021-06-03 23:30:04 +02:00
|
|
|
|
2023-12-28 15:27:36 +01:00
|
|
|
local dem = nobj_base:get_3d_map_flat({x=0, y=0, z=0})
|
|
|
|
dem.X = size.x
|
|
|
|
dem.Y = size.y
|
2021-06-03 20:08:57 +02:00
|
|
|
|
2023-12-28 15:27:36 +01:00
|
|
|
local model = EvolutionModel(evol_params)
|
|
|
|
model.dem = dem
|
|
|
|
local ref_dem = model:define_isostasy(dem)
|
2021-06-03 20:08:57 +02:00
|
|
|
|
2023-12-28 15:27:36 +01:00
|
|
|
local tectonic_step = tectonic_speed * time_step
|
|
|
|
collectgarbage()
|
2021-07-26 22:28:45 +02:00
|
|
|
|
2023-12-28 15:27:36 +01:00
|
|
|
-- Run the model
|
|
|
|
for i=1, niter do
|
|
|
|
minetest.log("info", "[mapgen_rivers] Iteration " .. i .. " of " .. niter)
|
|
|
|
|
|
|
|
model:diffuse(time_step)
|
2021-06-03 20:08:57 +02:00
|
|
|
model:flow()
|
2023-12-28 15:27:36 +01:00
|
|
|
model:erode(time_step)
|
|
|
|
if i < niter then
|
|
|
|
if tectonic_step ~= 0 then
|
|
|
|
nobj_base:get_3d_map_flat({x=0, y=tectonic_step*i, z=0}, ref_dem)
|
|
|
|
end
|
|
|
|
model:isostasy()
|
|
|
|
end
|
2021-06-03 20:08:57 +02:00
|
|
|
|
2023-12-28 15:27:36 +01:00
|
|
|
collectgarbage()
|
|
|
|
end
|
|
|
|
model:flow()
|
|
|
|
|
|
|
|
local mfloor = math.floor
|
|
|
|
local mmin, mmax = math.min, math.max
|
|
|
|
local offset_x, offset_y = twist(model.dirs, model.rivers, 5)
|
|
|
|
for i=1, size.x*size.y do
|
|
|
|
offset_x[i] = mmin(mmax(offset_x[i]*256, -128), 127)
|
|
|
|
offset_y[i] = mmin(mmax(offset_y[i]*256, -128), 127)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Write the results in the world directory
|
2024-01-04 23:28:33 +01:00
|
|
|
local datapath = minetest.get_worldpath() .. "/river_data/"
|
2024-01-04 22:47:50 +01:00
|
|
|
minetest.mkdir(datapath)
|
2023-12-28 15:27:36 +01:00
|
|
|
|
|
|
|
local function write_map(filename, data, bytes)
|
|
|
|
local size = #data
|
2024-01-04 22:47:50 +01:00
|
|
|
local file = io.open(datapath .. filename, 'wb')
|
2023-12-28 15:27:36 +01:00
|
|
|
|
|
|
|
local bytelist = {}
|
|
|
|
for j=1, bytes do
|
|
|
|
bytelist[j] = 0
|
2021-06-03 20:08:57 +02:00
|
|
|
end
|
|
|
|
|
2023-12-28 15:27:36 +01:00
|
|
|
local unpk = unpack
|
|
|
|
local schar = string.char
|
|
|
|
local floor = math.floor
|
|
|
|
for i=1, size do
|
|
|
|
local n = floor(data[i])
|
|
|
|
data[i] = n
|
|
|
|
for j=bytes, 2, -1 do
|
|
|
|
bytelist[j] = n % 256
|
|
|
|
n = floor(n / 256)
|
|
|
|
end
|
|
|
|
bytelist[1] = n % 256
|
|
|
|
|
|
|
|
file:write(schar(unpk(bytelist)))
|
2021-06-26 13:13:41 +02:00
|
|
|
end
|
2023-12-28 15:27:36 +01:00
|
|
|
|
|
|
|
file:close()
|
2021-06-03 20:08:57 +02:00
|
|
|
end
|
|
|
|
|
2023-12-28 15:27:36 +01:00
|
|
|
write_map('dem', model.dem, 2)
|
|
|
|
write_map('lakes', model.lakes, 2)
|
|
|
|
write_map('dirs', model.dirs, 1)
|
|
|
|
write_map('rivers', model.rivers, 4)
|
|
|
|
write_map('offset_x', offset_x, 1)
|
|
|
|
write_map('offset_y', offset_y, 1)
|
2024-01-04 22:47:50 +01:00
|
|
|
local sfile = io.open(datapath .. 'size', "w")
|
2023-12-28 15:27:36 +01:00
|
|
|
sfile:write(size.x..'\n'..size.y)
|
|
|
|
sfile:close()
|
|
|
|
|
2024-01-04 22:47:50 +01:00
|
|
|
local use_interactive_loader
|
|
|
|
if minetest.settings:has("mapgen_rivers_use_interactive_loader") then
|
|
|
|
use_interactive_loader = minetest.settings:get_bool("mapgen_rivers_use_interactive_loader")
|
|
|
|
else
|
|
|
|
use_interactive_loader = not minetest.settings:get_bool("mapgen_rivers_load_all")
|
|
|
|
end
|
|
|
|
|
|
|
|
if not use_interactive_loader then
|
2023-12-28 15:27:36 +01:00
|
|
|
mapgen_rivers.grid = {
|
2024-01-04 23:28:33 +01:00
|
|
|
size = size,
|
2023-12-28 15:27:36 +01:00
|
|
|
dem = model.dem,
|
|
|
|
lakes = model.lakes,
|
|
|
|
dirs = model.dirs,
|
|
|
|
rivers = model.rivers,
|
|
|
|
offset_x = offset_x,
|
|
|
|
offset_y = offset_y,
|
|
|
|
}
|
|
|
|
end
|