2022-01-26 11:25:17 +01:00
-- Generate the grid using terrainlib_lua
-- Only called on first mapgen, if there is no grid yet
2024-02-01 19:30:07 +01:00
-- Constants
2021-06-03 23:30:04 +02:00
local EvolutionModel = dofile ( mapgen_rivers.modpath .. ' /terrainlib_lua/erosion.lua ' )
local twist = dofile ( mapgen_rivers.modpath .. ' /terrainlib_lua/twist.lua ' )
2021-06-03 20:08:57 +02:00
2021-06-06 13:25:43 +02:00
local blocksize = mapgen_rivers.settings . blocksize
local tectonic_speed = mapgen_rivers.settings . tectonic_speed
2021-06-03 20:08:57 +02:00
2021-06-06 13:25:43 +02:00
local np_base = table.copy ( mapgen_rivers.noise_params . base )
2022-01-18 14:25:37 +01:00
np_base.spread = vector.divide ( np_base.spread , blocksize )
2021-06-03 20:08:57 +02:00
2021-06-06 13:25:43 +02:00
local evol_params = mapgen_rivers.settings . evol_params
local time = mapgen_rivers.settings . evol_time
local time_step = mapgen_rivers.settings . evol_time_step
2021-06-03 20:08:57 +02:00
local niter = math.ceil ( time / time_step )
time_step = time / niter
2022-01-03 15:45:27 +01:00
local use_margin = mapgen_rivers.settings . margin
local margin_width = mapgen_rivers.settings . margin_width / blocksize
local margin_elev = mapgen_rivers.settings . margin_elev
2022-01-02 15:13:12 +01:00
2024-01-31 11:32:24 +01:00
local X = math.floor ( mapgen_rivers.settings . map_x_size / blocksize )
local Y = math.floor ( mapgen_rivers.settings . map_z_size / blocksize )
2022-01-02 15:13:12 +01:00
local function margin ( dem , width , elev )
local X , Y = dem.X , dem.Y
for i = 1 , width do
local c1 = ( ( i - 1 ) / width ) ^ 0.5
local c2 = ( 1 - c1 ) * elev
local index = ( i - 1 ) * X + 1
for x = 1 , X do
dem [ index ] = dem [ index ] * c1 + c2
index = index + 1
end
index = i
for y = 1 , Y do
dem [ index ] = dem [ index ] * c1 + c2
index = index + X
end
index = X * ( Y - i ) + 1
for x = 1 , X do
dem [ index ] = dem [ index ] * c1 + c2
index = index + 1
end
index = X - i + 1
for y = 1 , Y do
dem [ index ] = dem [ index ] * c1 + c2
index = index + X
end
end
end
2024-02-01 19:30:07 +01:00
-- Generate grid
2021-06-05 11:24:28 +02:00
2024-01-31 11:32:24 +01:00
minetest.log ( " action " , ' [mapgen_rivers] Generating grid, this may take a while... ' )
2022-01-18 17:58:51 +01:00
2024-01-31 11:32:24 +01:00
if X * Y > 4e6 then
minetest.log ( " warning " , " [mapgen_rivers] You are going to generate a very large grid (>4M nodes). If you experience problems, you should increase blocksize or reduce map size. " )
end
2021-06-03 23:30:04 +02:00
2024-01-31 11:32:24 +01:00
local seed = tonumber ( minetest.get_mapgen_setting ( " seed " ) : sub ( - 10 ) )
np_base.seed = ( np_base.seed or 0 ) + seed
2021-06-03 20:08:57 +02:00
2024-01-31 11:32:24 +01:00
local nobj_base = PerlinNoiseMap ( np_base , { x = X , y = 1 , z = Y } )
2022-01-02 15:13:12 +01:00
2024-01-31 11:32:24 +01:00
local dem = nobj_base : get_3d_map_flat ( { x = 0 , y = 0 , z = 0 } )
dem.X = X
dem.Y = Y
2021-06-03 20:08:57 +02:00
2024-01-31 11:32:24 +01:00
if use_margin then
margin ( dem , margin_width , margin_elev )
end
2021-07-26 22:28:45 +02:00
2024-01-31 11:32:24 +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
2024-01-31 11:32:24 +01:00
local tectonic_step = tectonic_speed * time_step
collectgarbage ( )
for i = 1 , niter do
minetest.log ( " info " , " [mapgen_rivers] Iteration " .. i .. " of " .. niter )
2021-06-03 20:08:57 +02:00
2024-01-31 11:32:24 +01:00
model : diffuse ( time_step )
model : flow ( )
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 )
if use_margin then
margin ( ref_dem , margin_width , margin_elev )
end
end
model : isostasy ( )
end
2022-01-25 19:09:24 +01:00
2021-07-26 22:28:45 +02:00
collectgarbage ( )
2021-06-03 20:08:57 +02:00
end
2024-01-31 11:32:24 +01:00
model : flow ( )
local mfloor = math.floor
local mmin , mmax = math.min , math.max
2024-02-01 19:30:07 +01:00
local unpk , schar = unpack , string.char
2024-01-31 11:32:24 +01:00
local offset_x , offset_y = twist ( model.dirs , model.rivers , 5 )
for i = 1 , X * 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
2024-02-01 19:30:07 +01:00
-- Write data
2024-01-31 11:32:24 +01:00
2024-02-01 19:30:07 +01:00
local datapath = mapgen_rivers.world_data_path
minetest.mkdir ( datapath )
local sfile = io.open ( datapath .. ' size ' , " w " )
sfile : write ( X .. ' \n ' .. Y )
sfile : close ( )
local function write_file ( filename , data , bytes )
local file = io.open ( datapath .. filename , ' wb ' )
local bytelist = { }
for j = 1 , bytes do
bytelist [ j ] = 0
end
for i = 1 , # data do
local n = mfloor ( data [ i ] )
data [ i ] = n
for j = bytes , 2 , - 1 do
bytelist [ j ] = n % 256
n = mfloor ( n / 256 )
end
bytelist [ 1 ] = n % 256
file : write ( schar ( unpk ( bytelist ) ) )
end
file : close ( )
end
2024-01-31 11:32:24 +01:00
2024-02-01 19:30:07 +01:00
write_file ( ' dem ' , model.dem , 2 )
write_file ( ' lakes ' , model.lakes , 2 )
write_file ( ' dirs ' , model.dirs , 1 )
write_file ( ' rivers ' , model.rivers , 4 )
write_file ( ' offset_x ' , offset_x , 1 )
write_file ( ' offset_y ' , offset_y , 1 )