Add all code for generating a grid on world creation.

Not tested ; will likely need much testing and bugfix.
This commit is contained in:
Gaël C 2021-06-03 20:08:57 +02:00
parent 19efeaaff6
commit cb297af047
4 changed files with 105 additions and 29 deletions

63
generate.lua Normal file
View File

@ -0,0 +1,63 @@
local EvolutionModel = dofile(mapgen_rivers.modpath .. '/erosion.lua')
local twist = dofile(mapgen_rivers.modpath .. '/twist.lua')
local size = {x=1000, y=1000}
local blocksize = 12
local np_base = {
offset = 0,
scale = 200,
seed = 2469,
octaves = 8,
spread = {x=4000/blocksize, y=4000/blocksize, z=5},
persist = 0.6,
lacunarity = 2,
}
local time = 10
local time_step = 1
local niter = math.ceil(time/time_step)
time_step = time / niter
local function generate()
local nobj_base = minetest.get_perlin_map(np_base, size)
nobj_base:calc_3d_map({x=0, y=0, z=0})
local dem = nobj_base:get_map_slice({z=1}, {z=1})
dem.X = size.x
dem.Y = size.y
local model = EvolutionModel()
model.dem = dem
local ref_dem = model:define_isostasy(dem)
for i=1, niter do
nobj_base:get_map_slice({z=i+1}, {z=1}, ref_dem)
model:diffuse(time_step)
model:flow()
model:erode(time_step)
model:isostasy()
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, 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
mapgen_rivers.write_map('dem', model.dem, 2)
mapgen_rivers.write_map('lakes', model.lakes, 2)
mapgen_rivers.write_map('dirs', model.dirs, 1)
mapgen_rivers.write_map('rivers', model.rivers, 4)
mapgen_rivers.write_map('offset_x', offset_x, 1)
mapgen_rivers.write_map('offset_y', offset_y, 1)
local sfile = io.open(mapgen_rivers.world_data_path .. 'size', "w")
sfile:write(X..'\n'..Y)
sfile:close()
end
return generate

View File

@ -1,6 +1,6 @@
local worldpath = minetest.world_data_path
local function load_map(filename, bytes, signed, size)
function mapgen_rivers.load_map(filename, bytes, signed, size)
local file = io.open(worldpath .. filename, 'rb')
local data = file:read('*all')
if #data < bytes*size then
@ -28,4 +28,28 @@ local function load_map(filename, bytes, signed, size)
return map
end
return load_map
function mapgen_rivers.write_map(filename, data, bytes)
local size = #data
local file = io.open(worldpath .. filename, 'wb')
local mfloor = math.floor
local schar = string.char
local upack = unpack
local bytelist = {}
for j=1, bytes do
bytelist[j] = 0
end
for i=1, size do
local n = mfloor(data[i])
for j=bytes, 2, -1 do
bytelist[j] = n % 256
n = mfloor(n / 256)
end
bytelist[1] = n % 256
file:write(schar(upack(bytelist)))
end
file:close()
end

View File

@ -7,51 +7,39 @@ end
local world_data_path = minetest.world_data_path
minetest.mkdir(world_data_path)
local load_map = dofile(modpath .. 'load.lua')
dofile(modpath .. 'load.lua')
local function copy_if_needed(filename)
local wfilename = world_data_path..filename
local wfile = io.open(wfilename, 'rb')
if wfile then
wfile:close()
return
end
local mfilename = mod_data_path..filename
local mfile = io.open(mfilename, 'rb')
local wfile = io.open(wfilename, 'wb')
wfile:write(mfile:read("*all"))
mfile:close()
wfile:close()
-- Try to read file 'size'
local sfile = io.open(world_data_path..'size', 'r')
if not sfile then
-- Generate a map!!
local generate = dofile(mapgen_rivers.modpath .. '/generate.lua')
generate()
sfile = io.open(world_data_path..'size', 'r')
end
copy_if_needed('size')
local sfile = io.open(world_data_path..'size', 'r')
-- Read the map
-- TODO: if data has just been generated, transfer it without reloading everything
local X = tonumber(sfile:read('*l'))
local Z = tonumber(sfile:read('*l'))
sfile:close()
copy_if_needed('dem')
local dem = load_map('dem', 2, true, X*Z)
copy_if_needed('lakes')
local lakes = load_map('lakes', 2, true, X*Z)
copy_if_needed('dirs')
local dirs = load_map('dirs', 1, false, X*Z)
copy_if_needed('rivers')
local rivers = load_map('rivers', 4, false, X*Z)
local dem = mapgen_rivers.load_map('dem', 2, true, X*Z)
local lakes = mapgen_rivers.load_map('lakes', 2, true, X*Z)
local dirs = mapen_rivers.load_map('dirs', 1, false, X*Z)
local rivers = mapgen_rivers.load_map('rivers', 4, false, X*Z)
copy_if_needed('offset_x')
local offset_x = load_map('offset_x', 1, true, X*Z)
for k, v in ipairs(offset_x) do
offset_x[k] = (v+0.5)/256
end
copy_if_needed('offset_y')
local offset_z = load_map('offset_y', 1, true, X*Z)
for k, v in ipairs(offset_z) do
offset_z[k] = (v+0.5)/256
end
-- Should have finished loading
-- To index a flat array representing a 2D map
local function index(x, z)
return z*X+x+1
end

View File

@ -27,6 +27,7 @@ local function get_bounds(dirs, rivers)
end
local function twist(dirs, rivers, n)
n = n or 5
local X, Y = dirs.X, dirs.Y
local bounds_x, bounds_y = get_bounds(dirs, rivers)
local dn = 0.5 / n