[Mod] Map generator with Rivers [mapgen_rivers]

User avatar
Gael de Sailly
Member
Posts: 845
Joined: Sun Jan 26, 2014 17:01
GitHub: gaelysam
IRC: Gael-de-Sailly
In-game: Gael-de-Sailly gaelysam
Location: Voiron, France

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by Gael de Sailly » Post

Hi ShadMOrdre,

Thank you very much for your tests!
This looks absolutely beautiful with the shadows and the mods you added. Definitely I would be interested to see how you accommodated the mods, as I would like to improve the compatibility of mapgen_rivers with other mods.

If you use "biomegen": I'll push some fixes soon.
ShadMOrdre wrote:
Sun Jun 27, 2021 01:02
Would like to know if terrain can be customized? When you run the pregen at world start, is there a "simple" insertion point for adding a custom terrain heightmap for the flow and erosion calculations.
For now I have not thought about this, but that's a good idea to implement a clean way to do this.
If you wanna hack a bit, you can replace variable dem at pregenerate.lua line 27, and set tectonic_speed to zero.
(dem means Digital Elevation Model (=heightmap). Maybe I should rename some variables to be more explcit / less technical)
ShadMOrdre wrote:
Sun Jun 27, 2021 01:02
Thanks for this. It's definately the best mapgen out there!! I got around 0.09 ms average generation time with default settings, and 0.2ms once I added the ecosystems, villages, and geomorea.
Glad to see that you like it :)

Image
Just realize how bored we would be if the world was perfect.

ShadMOrdre
Member
Posts: 1118
Joined: Mon Dec 29, 2014 08:07
Location: USA

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by ShadMOrdre » Post

Gael,

The dem variable is a flat 3d noise. I'm confused as to how to use a 2d heightmap replacement.

Also, changing the block size from 12 to 60 does not seem to allow a full sized map.

The two seem related.

My voronoi mapgen does it's calculations during the ongen call. I measure against 3 layers of recursive voronoi cells defined only as 2d pos values, (x and z). Each "point" also has an index and an associated tier, (1-3). The tier defines the layer within the voronoi diagram. During each ongen, I calculate the closest cell at each tier. The sum of the distances is subtracted from a predefined maximum terrain height. The results of this provide a base 2d "noise", but because this is calculated during the ongen call, there isn't a single "noise" that I can point to, but instead a function that returns a value for a given coordinate.

I can calculate the voronoi data for chunk center, vastly reducing processing and runtime, but then the map is blocky. If I calculated each map block only during pregen, I might still be able to provide a scaled heightmap to the pregen code, but unsure how the flat 3d map is handled.

Sorry for the long explanation, just wanted to provide some more detailed info about what I'm trying to accomplish, how I do it, and how I can integrate the two projects to provide a more manageable way to control noise based terrain.

If you are interested, I can post my "hacked" version of init.lua here as a spoiler. None of my recent updates are posted to github yet.

Shad

Image

Image

Image
Attachments
screenshot_20210630_002830.jpg
screenshot_20210630_002830.jpg (376.59 KiB) Viewed 4877 times
screenshot_20210629_235104.jpg
screenshot_20210629_235104.jpg (255.64 KiB) Viewed 4877 times
screenshot_20210629_234842.jpg
screenshot_20210629_234842.jpg (309.35 KiB) Viewed 4877 times

User avatar
Gael de Sailly
Member
Posts: 845
Joined: Sun Jan 26, 2014 17:01
GitHub: gaelysam
IRC: Gael-de-Sailly
In-game: Gael-de-Sailly gaelysam
Location: Voiron, France

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by Gael de Sailly » Post

Hi,
Sorry for the late answer.
ShadMOrdre wrote:
Thu Jul 01, 2021 04:58
The dem variable is a flat 3d noise. I'm confused as to how to use a 2d heightmap replacement.
It is a 2D slice of a 3D noise, so it has the same structure than a 2D noise (the Y axis is 1)
This weird thing is there because I am using successive slices of a 3D noise at pre-generation, to generate 2D noises that have similarities but with temporal variations (this simulates a landscape that evolves over time due to tectonics).

So you can replace it with a regular 2D-noise-like array. If you put a constant array (that does not vary over iterations), your final landscape may be a bit less varied, but you can have good results anyway.
This seems doable with your workflow, if it can produce this kind of 2D map.
ShadMOrdre wrote:
Thu Jul 01, 2021 04:58
Also, changing the block size from 12 to 60 does not seem to allow a full sized map.

The two seem related.
Here I don't really see what you mean.
For now the size of the grid is hardcoded to 1000x1000 (but I will make it a setting shortly), so if you set blocksize to 60, I expect you will have a 60kx60k map (but I've not tested such large values yet). Did you get something else?
ShadMOrdre wrote:
Thu Jul 01, 2021 04:58
If you are interested, I can post my "hacked" version of init.lua here as a spoiler. None of my recent updates are posted to github yet.
Yes I can be interested ;)
Just realize how bored we would be if the world was perfect.

ShadMOrdre
Member
Posts: 1118
Joined: Mon Dec 29, 2014 08:07
Location: USA

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by ShadMOrdre » Post

Gael,

The block size variable affects how much of the world map will be used, so with the default setting of 12, the world map had abrupt edges at 6000m from origin, meaning the world will generate within (-6000, -6000) to (6000, 6000). Outside of those areas, is nothing but flat ocean, and any terrain get a nicely shaped cliff.

I assumed that I could set the value higher, so tried 60, so that the entire worldmap can emerge. This simply led to out of memory.

Changing the grid size from the default of 1000x1000 to 5000x5000, (multiple of 12 * 5), but again, out of memory.

All this was simply to have the entire worldmap playable. As of now, only the 36sqkm surrounding origin are generated.



Regarding the dem variable, a flat_3d_map, I haven't yet tried to generate one from a 2D noise. The functions I use to generate terrain are not noise based, and so trying to provide a flat map of 1000x1000 also leads to memory issues.

My voronoi mapgen finds the nearest point, and uses the distance from that point to the current position. In the now 2 layer recursive voronoi, I end up with a distance to a cell's defined point, and the distance to the subcell's defined point. The sum of the two distances is subtracted from a maximum terrain height. As each of these calculations occurs during the on_gen call, utilizing the existing z,y,x, for loops, I can only provide the heightmap of the chunk/block that is generated.

As promised, here is my "hacked" init.lua for mapgen_rivers. References to my GAL project are numerous. If you'd like to see any relevant functions, such as my biome selection functions, just ask. Most of my hack is to enable the biomes, but you'll see some experiements with 2D noises, which aren't as successful as I'd like.

Spoiler

if gal.mapgen.name ~= "mg_mapgenrivers" then
return
end

mapgen_rivers = {}

local modpath = minetest.get_modpath(minetest.get_current_modname()) .. '/'
mapgen_rivers.modpath = modpath
mapgen_rivers.world_data_path = minetest.get_worldpath() .. '/river_data/'

dofile(modpath .. 'settings.lua')

-- mapgen_rivers.heightmap = {}
-- mapgen_rivers.biomemap = {}
-- mapgen_rivers.biome_info = {}


local sea_level = mapgen_rivers.settings.sea_level
local elevation_chill = mapgen_rivers.settings.elevation_chill
local use_distort = mapgen_rivers.settings.distort
local use_biomes = mapgen_rivers.settings.biomes
local use_biomegen_mod = use_biomes and minetest.global_exists('biomegen')
use_biomes = use_biomes and not use_biomegen_mod

if use_biomegen_mod then
biomegen.set_elevation_chill(elevation_chill)
end
dofile(modpath .. 'noises.lua')

--
gal.mapgen.biome_vertical_range = 50
--gal.mapgen.biome_vertical_range = mapgen_rivers.noise_params.base.scale / 10
gal.mapgen.biome_vertical_blend = (gal.mapgen.biome_vertical_range / 5) * gal.mapgen.mg_world_scale
gal.mapgen.mg_biome_mode = "full"
gal.mapgen.use_heat_scalar = true
gal.mapgen.use_humid_scalar = true

gal.mapgen.ocean_depth = -2000 * gal.mapgen.mg_world_scale
gal.mapgen.beach_depth = -4 * gal.mapgen.mg_world_scale
gal.mapgen.sea_level = gal.mapgen.water_level
gal.mapgen.maxheight_beach = 4 * gal.mapgen.mg_world_scale
gal.mapgen.maxheight_coastal = gal.mapgen.sea_level + gal.mapgen.biome_vertical_range
gal.mapgen.maxheight_lowland = gal.mapgen.maxheight_coastal + gal.mapgen.biome_vertical_range
gal.mapgen.maxheight_shelf = gal.mapgen.maxheight_lowland + gal.mapgen.biome_vertical_range
gal.mapgen.maxheight_highland = gal.mapgen.maxheight_shelf + gal.mapgen.biome_vertical_range
gal.mapgen.maxheight_mountain = gal.mapgen.maxheight_highland + gal.mapgen.biome_vertical_range
--gal.mapgen.minheight_snow = gal.mapgen.maxheight_mountain + gal.mapgen.biome_vertical_range
gal.mapgen.minheight_snow = gal.mapgen.maxheight_mountain + (gal.mapgen.biome_vertical_range * 2)
gal.mapgen.maxheight_snow = gal.mapgen.minheight_snow + (gal.mapgen.biome_vertical_range * 2)
gal.mapgen.maxheight_strato = gal.mapgen.maxheight_snow + (gal.mapgen.biome_vertical_range * (gal.mapgen.biome_vertical_blend / 2))


local nobj_terrain = nil
local nbuf_terrain = {}

local nobj_cliffs = nil
local nbuf_cliffs = {}

local np_v7_alt = {
offset = -4,
scale = 100,
seed = 5934,
spread = {x = 1200, y = 1200, z = 1200},
octaves = 7,
persist = 0.4,
lacunarity = 2.15,
--flags = "defaults"
--flags = "eased",
}
local np_v7_base = {
offset = -4,
scale = 240,
seed = 5934,
spread = {x = 1200, y = 1200, z = 1200},
octaves = 7,
persist = 0.4,
lacunarity = 2.15,
flags = "defaults"
}
local np_v7_height = {
offset = 0.5,
scale = 1,
spread = {x = 1000, y = 1000, z = 1000},
seed = 4213,
octaves = 7,
persist = 0.4,
lacunarity = 2.15,
flags = "defaults",
}
local np_v7_persist = {
offset = 0.6,
scale = 0.1,
spread = {x = 2000, y = 2000, z = 2000},
seed = 539,
octaves = 3,
persist = 0.6,
lacunarity = 2.15,
flags = "defaults",
}
local np_v7_cliffs = {
offset = 0,
scale = 0.72,
spread = {x = 180, y = 180, z = 180},
seed = 78901,
octaves = 5,
persist = 0.5,
lacunarity = 2.19,
}

local abs = math.abs
local max = math.max
local min = math.min
local floor = math.floor
local cliffs_thresh = floor((np_v7_alt.scale) * 0.5)

mapgen_rivers.rangelim = function(v, min, max)
if v < min then return min end
if v > max then return max end
return v
end

mapgen_rivers.get_terrain_height_cliffs = function(theight,cheight)
-- cliffs
local t_cliff = 0
if theight > 1 and theight < cliffs_thresh then
local clifh = max(min(cheight,1),0)
if clifh > 0 then
clifh = -1 * (clifh - 1) * (clifh - 1) + 1
t_cliff = clifh
theight = theight + (cliffs_thresh - theight) * clifh * ((theight < 2) and theight - 1 or 1)
end
end
return theight, t_cliff
end

mapgen_rivers.get_v7_height = function(z,x)

local aterrain = 0

local hselect = minetest.get_perlin(np_v7_height):get_2d({x=x,y=z})
local hselect = mapgen_rivers.rangelim(hselect, 0, 1)

local persist = minetest.get_perlin(np_v7_persist):get_2d({x=x,y=z})

np_v7_base.persistence = persist;
local height_base = minetest.get_perlin(np_v7_base):get_2d({x=x,y=z})

np_v7_alt.persistence = persist;
local height_alt = minetest.get_perlin(np_v7_alt):get_2d({x=x,y=z})

if (height_alt > height_base) then
aterrain = floor(height_alt)
else
aterrain = floor((height_base * hselect) + (height_alt * (1 - hselect)))
end

return aterrain
end




local heightmaps = dofile(modpath .. 'heightmap.lua')

-- Linear interpolation
local function interp(v00, v01, v11, v10, xf, zf)
local v0 = v01*xf + v00*(1-xf)
local v1 = v11*xf + v10*(1-xf)
return v1*zf + v0*(1-zf)
end

local data = {}

local noise_x_obj, noise_z_obj, noise_distort_obj, noise_heat_obj, noise_heat_blend_obj, noise_humid_obj, noise_humid_blend_obj
local noise_x_map = {}
local noise_z_map = {}
local noise_distort_map = {}
local noise_heat_map = {}
local noise_heat_blend_map = {}
local noise_humid_map = {}
local noise_humid_blend_map = {}
local mapsize
local init = false

local sumtime = 0
local sumtime2 = 0
local ngen = 0

local mapgen_times = {
noisemaps = {},
preparation = {},
loop2d = {},
loop3d = {},
biomes = {},
mainloop = {},
setdata = {},
liquid_lighting = {},
writing = {},
make_chunk = {},
}

local function generate(minp, maxp, seed)
print(("[mapgen_rivers] Generating from %s to %s"):format(minetest.pos_to_string(minp), minetest.pos_to_string(maxp)))

local chulens = {
x = maxp.x-minp.x+1,
y = maxp.y-minp.y+1,
z = maxp.z-minp.z+1,
}

if not init then
mapsize = {
x = chulens.x,
y = chulens.y+1,
z = chulens.z,
}
if use_distort then
noise_x_obj = minetest.get_perlin_map(mapgen_rivers.noise_params.distort_x, mapsize)
noise_z_obj = minetest.get_perlin_map(mapgen_rivers.noise_params.distort_z, mapsize)
noise_distort_obj = minetest.get_perlin_map(mapgen_rivers.noise_params.distort_amplitude, chulens)
end
if use_biomes then
noise_heat_obj = minetest.get_perlin_map(mapgen_rivers.noise_params.heat, chulens)
noise_heat_blend_obj = minetest.get_perlin_map(mapgen_rivers.noise_params.heat_blend, chulens)
noise_humid_obj = minetest.get_perlin_map(mapgen_rivers.noise_params.humid, chulens)
noise_humid_blend_obj = minetest.get_perlin_map(mapgen_rivers.noise_params.humid_blend, chulens)
end
init = true
end

local sidelen = maxp.x - minp.x + 1
local permapdims2d = {x = sidelen, y = sidelen, z = 0}
local minpos2d = {x = minp.x, y = minp.z}

--nobj_terrain = nobj_terrain or minetest.get_perlin_map(np_terrain, permapdims2d)
--nbuf_terrain = nobj_terrain:get_2d_map(minpos2d)
nobj_cliffs = nobj_cliffs or minetest.get_perlin_map(np_v7_cliffs, permapdims2d)
nbuf_cliffs = nobj_cliffs:get_2d_map(minpos2d)

local t0 = os.clock()
local minp2d = {x=minp.x, y=minp.z}
if use_distort then
noise_x_obj:get_3d_map_flat(minp, noise_x_map)
noise_z_obj:get_3d_map_flat(minp, noise_z_map)
noise_distort_obj:get_2d_map_flat(minp2d, noise_distort_map)
end
if use_biomes then
noise_heat_obj:get_2d_map_flat(minp2d, noise_heat_map)
noise_heat_blend_obj:get_2d_map_flat(minp2d, noise_heat_blend_map)
noise_humid_obj:get_2d_map_flat(minp2d, noise_humid_map)
noise_humid_blend_obj:get_2d_map_flat(minp2d, noise_humid_blend_map)
end

local terrain_map, lake_map, incr, i_origin

if use_distort then
local xmin, xmax, zmin, zmax = minp.x, maxp.x, minp.z, maxp.z
local i = 0
local i2d = 0
for z=minp.z, maxp.z do
for y=minp.y, maxp.y+1 do
for x=minp.x, maxp.x do
i = i+1
i2d = i2d+1
local distort = noise_distort_map[i2d]
local xv = noise_x_map*distort + x
if xv < xmin then xmin = xv end
if xv > xmax then xmax = xv end
noise_x_map = xv
local zv = noise_z_map*distort + z
if zv < zmin then zmin = zv end
if zv > zmax then zmax = zv end
noise_z_map = zv
end
i2d = i2d-chulens.x
end
end

local pminp = {x=math.floor(xmin), z=math.floor(zmin)}
local pmaxp = {x=math.floor(xmax)+1, z=math.floor(zmax)+1}
incr = pmaxp.x-pminp.x+1
i_origin = 1 - pminp.z*incr - pminp.x
terrain_map, lake_map = heightmaps(pminp, pmaxp)
else
terrain_map, lake_map = heightmaps(minp, maxp)
end

--local c_stone = minetest.get_content_id("default:stone")
--local c_dirt = minetest.get_content_id("default:dirt")
--local c_lawn = minetest.get_content_id("default:dirt_with_grass")
--local c_dirtsnow = minetest.get_content_id("default:dirt_with_snow")
--local c_snow = minetest.get_content_id("default:snowblock")
--local c_sand = minetest.get_content_id("default:sand")
--local c_water = minetest.get_content_id("default:water_source")
--local c_rwater = minetest.get_content_id("default:river_water_source")
--local c_ice = minetest.get_content_id("default:ice")
local c_stone = minetest.get_content_id("gal:stone")
local c_dirt = minetest.get_content_id("gal:dirt")
local c_lawn = minetest.get_content_id("gal:dirt_with_grass")
local c_dirtsnow = minetest.get_content_id("gal:dirt_with_snow")
local c_snow = minetest.get_content_id("gal:snow_block")
local c_sand = minetest.get_content_id("gal:sand")
local c_water = minetest.get_content_id("gal:liquid_water_source")
local c_rwater = minetest.get_content_id("gal:liquid_water_river_source")
local c_ice = minetest.get_content_id("gal:ice")

local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
vm:get_data(data)

local a = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local ystride = a.ystride -- Tip : the ystride of a VoxelArea is the number to add to the array index to get the index of the position above. It's faster because it avoids to completely recalculate the index.

local t1 = os.clock()

local nid = mapsize.x*(mapsize.y-1) + 1
local incrY = -mapsize.x
local incrX = 1 - mapsize.y*incrY
local incrZ = mapsize.x*mapsize.y - mapsize.x*incrX - mapsize.x*mapsize.y*incrY

local i2d = 1

local t2 = os.clock()

local t3 = os.clock()

for z = minp.z, maxp.z do
for x = minp.x, maxp.x do
local ivm = a:index(x, minp.y, z)
local ground_above = false
local temperature
if use_biomes then
--temperature = gal.mapgen.get_heat_scalar(z) + noise_heat_map[i2d]+noise_heat_blend_map[i2d]
temperature = noise_heat_map[i2d]+noise_heat_blend_map[i2d]
--humidity = gal.mapgen.get_humid_scalar(z) + noise_humid_map[i2d]+noise_humid_blend_map[i2d]
humidity = noise_humid_map[i2d]+noise_humid_blend_map[i2d]
end
local terrain, lake
if not use_distort then
terrain = terrain_map[i2d]
lake = lake_map[i2d]
end

--local nterrain = minetest.get_perlin(np_v7_alt):get_2d({x=x,y=z})
--local nterrain = nbuf_terrain[z-minp.z+1][x-minp.x+1]
--local aterrain = minetest.get_perlin(np_v7_alt):get_2d({x=x,y=z})
--local bterrain = minetest.get_perlin(np_v7_base):get_2d({x=x,y=z})
local ncliff = nbuf_cliffs[z-minp.z+1][x-minp.x+1]

local vterrain = mapgen_rivers.get_v7_height(z,x)
local t_y, t_c = mapgen_rivers.get_terrain_height_cliffs(vterrain,ncliff)
local theight = t_y
local t_cliff = t_c or 0


for y = maxp.y+1, minp.y, -1 do
if use_distort then
local xn = noise_x_map[nid]
local zn = noise_z_map[nid]
local x0 = math.floor(xn)
local z0 = math.floor(zn)

local i0 = i_origin + z0*incr + x0
local i1 = i0+1
local i2 = i1+incr
local i3 = i2-1

--terrain = interp(terrain_map[i0], terrain_map[i1], terrain_map[i2], terrain_map[i3], xn-x0, zn-z0)
terrain = interp(terrain_map[i0] + t_y, terrain_map[i1] + t_y, terrain_map[i2] + t_y, terrain_map[i3] + t_y, xn-x0, zn-z0)
--terrain = interp(aterrain, bterrain, vterrain, t_y, xn-x0, zn-z0)
lake = math.min(lake_map[i0] + t_y, lake_map[i1] + t_y, lake_map[i2] + t_y, lake_map[i3] + t_y)
end

theight = terrain

local t_biome_name = gal.mapgen.get_biome_name(temperature,humidity,theight)

gal.mapgen.heightmap[i2d] = theight
--gal.mapgen.heightmap[i2d] = terrain - 1
gal.mapgen.biomemap[i2d] = t_biome_name

local fill_depth = 4
local top_depth = 1
local riverbed_depth = 6
--local river_size_factor = (riverbed_depth - (terrain / 40)) / 100
local river_size_factor = riverbed_depth - (theight / 40)

local t_air = gal.mapgen.c_air
local t_ignore = gal.mapgen.c_ignore

local t_top = gal.mapgen.c_top
local t_top_depth = top_depth
local t_filler = gal.mapgen.c_filler
local t_filldepth = fill_depth
local t_stone = gal.mapgen.c_stone
local t_water = gal.mapgen.c_water
local t_river = gal.mapgen.c_river
local t_riverbed = gal.mapgen.c_gravel
local t_riverbed_depth = riverbed_depth
local t_ice = gal.mapgen.c_ice
local t_mud = gal.mapgen.c_mud
--local t_sand = gal.mapgen.c_sand

t_top = gal.mapgen.biome_info[t_biome_name].b_top
t_top_depth = gal.mapgen.biome_info[t_biome_name].b_top_depth
t_filler = gal.mapgen.biome_info[t_biome_name].b_filler
t_filldepth = gal.mapgen.biome_info[t_biome_name].b_filler_depth
t_stone = gal.mapgen.biome_info[t_biome_name].b_stone
t_water = gal.mapgen.biome_info[t_biome_name].b_water
t_river = gal.mapgen.biome_info[t_biome_name].b_river
t_riverbed = gal.mapgen.biome_info[t_biome_name].b_riverbed
t_riverbed_depth = gal.mapgen.biome_info[t_biome_name].b_riverbed_depth

if y <= maxp.y then

local is_lake = lake > theight
local ivm = a:index(x, y, z)
local t_node = t_ignore

-- if y <= terrain then
-- if not use_biomes or y <= terrain-1 or ground_above then
-- t_node = t_stone
-- elseif is_lake or y < sea_level then
-- t_node = c_sand
-- else
-- local temperature_y = temperature - y*elevation_chill
-- if temperature_y >= 15 then
-- t_node = t_top
-- elseif temperature_y >= 0 then
-- t_node = c_dirtsnow
-- else
-- t_node = c_snow
-- end
-- end
-- elseif y <= lake and lake > sea_level then
-- if not use_biomes or temperature - y*elevation_chill >= 0 then
-- t_node = t_river
-- else
-- t_node = t_ice
-- end
-- elseif y <= sea_level then
-- t_node = t_water
-- end

if t_cliff > 0 then
t_filler = t_stone
end

if is_lake and y <= (lake - 1) and lake > gal.mapgen.water_level then
t_node = t_river
t_filldepth = river_size_factor
end

if y < (theight - (t_filldepth + top_depth)) then
t_node = t_stone
elseif y >= (theight - (t_filldepth + top_depth)) and y < (theight - top_depth) then
if is_lake then
if y <= lake and y > gal.mapgen.water_level then
t_filler = t_river
if y >= (theight - (t_filldepth + top_depth)) and y < (theight - ((t_filldepth * 0.25) + top_depth)) then
t_filler = t_riverbed
end
end
end
t_node = t_filler
elseif y >= (theight - top_depth) and y <= theight then
if is_lake then
if y <= lake and lake > gal.mapgen.water_level then
t_top = t_river
end
end
t_node = t_top
elseif y > theight and y <= gal.mapgen.water_level then
--Water Level (Sea Level)
t_node = t_water
end

data[ivm] = t_node
end

ground_above = y <= theight

ivm = ivm + ystride
if use_distort then
nid = nid + incrY
end
end

if use_distort then
nid = nid + incrX
end
i2d = i2d + 1
end

if use_distort then
nid = nid + incrZ
end
end



local t4 = os.clock()

local t5

if use_biomegen_mod then
biomegen.generate_all(data, a, vm, minp, maxp, seed)
t5 = os.clock()
else
vm:set_data(data)
t5 = os.clock()
minetest.generate_ores(vm, minp, maxp)
minetest.generate_decorations(vm,minp,maxp)
end

vm:set_lighting({day = 0, night = 0})
vm:calc_lighting()
vm:update_liquids()

local t6 = os.clock()

vm:write_to_map()

local t7 = os.clock()

--local t1 = os.clock()

--local t = t1-t0
--ngen = ngen + 1
--sumtime = sumtime + t
--sumtime2 = sumtime2 + t*t
--print(("[mapgen_rivers] Done in %5.3f s"):format(t))

-- Print generation time of this mapchunk.
local chugent = math.ceil((os.clock() - t0) * 1000)
print ("[mg_v7] Mapchunk generation time " .. chugent .. " ms")

table.insert(mapgen_times.noisemaps, 0)
table.insert(mapgen_times.preparation, t1 - t0)
table.insert(mapgen_times.loop2d, t2 - t1)
table.insert(mapgen_times.loop3d, t3 - t2)
table.insert(mapgen_times.mainloop, t4 - t3)
table.insert(mapgen_times.setdata, t5 - t4)
table.insert(mapgen_times.liquid_lighting, t6 - t5)
table.insert(mapgen_times.writing, t7 - t6)
table.insert(mapgen_times.make_chunk, t7 - t0)

-- Deal with memory issues. This, of course, is supposed to be automatic.
local mem = math.floor(collectgarbage("count")/1024)
if mem > 1000 then
print("mg_v7 is manually collecting garbage as memory use has exceeded 500K.")
collectgarbage("collect")
end
end

minetest.register_on_generated(generate)

local function mean( t )
local sum = 0
local count= 0

for k,v in pairs(t) do
if type(v) == 'number' then
sum = sum + v
count = count + 1
end
end

return (sum / count)
end

minetest.register_on_shutdown(function()
local avg = sumtime / ngen
local std = math.sqrt(sumtime2/ngen - avg*avg)
--print(("[mapgen_rivers] Mapgen statistics:\n- Mapgen calls: %4d\n- Mean time: %5.3f s\n- Standard deviation: %5.3f s"):format(avg, std))

if #mapgen_times.make_chunk == 0 then
return
end

local average, standard_dev
minetest.log("mg_v7 lua Mapgen Times:")

average = mean(mapgen_times.noisemaps)
minetest.log(" noisemaps: - - - - - - - - - - - - - - - "..average)

average = mean(mapgen_times.preparation)
minetest.log(" preparation: - - - - - - - - - - - - - - "..average)

average = mean(mapgen_times.loop2d)
minetest.log(" 2D Noise loops: - - - - - - - - - - - - - - - - - "..average)

average = mean(mapgen_times.loop3d)
minetest.log(" 3D Noise loops: - - - - - - - - - - - - - - - - - "..average)

average = mean(mapgen_times.mainloop)
minetest.log(" Main Render loops: - - - - - - - - - - - - - - - - - "..average)

average = mean(mapgen_times.setdata)
minetest.log(" writing: - - - - - - - - - - - - - - - - "..average)

average = mean(mapgen_times.liquid_lighting)
minetest.log(" liquid_lighting: - - - - - - - - - - - - "..average)

average = mean(mapgen_times.writing)
minetest.log(" writing: - - - - - - - - - - - - - - - - "..average)

average = mean(mapgen_times.make_chunk)
minetest.log(" makeChunk: - - - - - - - - - - - - - - - "..average)

end)



Sorry for the lack of comments.

Shad

DOOM_possum
Member
Posts: 172
Joined: Sat Mar 27, 2021 22:06
In-game: DOOM_possum

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by DOOM_possum » Post

shad, what MODS, are You using, with the hand print, and Shape Deformation?? is It unique or part of the Data Base ??

ShadMOrdre
Member
Posts: 1118
Joined: Mon Dec 29, 2014 08:07
Location: USA

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by ShadMOrdre » Post

Doom_possum,

The hand is part of a customized texture pack that I use, which also enables me to change the default sun and moon textures, without the overhead of a full texturepack.. The actual texture for the hand came from Farlands game, IIRK.

By shape deformation, I assume you mean the slopes along the edges of the terrain. This is provided by the naturalslopes_lib mod, by kartmic.

I hope I answered your questions.

Shad

DOOM_possum
Member
Posts: 172
Joined: Sat Mar 27, 2021 22:06
In-game: DOOM_possum

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by DOOM_possum » Post

customized texture pack (??), what program are You using for sky modification? is It in Farlands Game, as well?

ShadMOrdre
Member
Posts: 1118
Joined: Mon Dec 29, 2014 08:07
Location: USA

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by ShadMOrdre » Post

Doom_possum,

Read up on texture packs. They allow you to change default graphics. In my case, the hand, sun, and moon. Everything else is either engine or game provided. They are loaded from the main menu. You can make your own, which is what I did, or you can use one of the available ones.

I use a custom game, my GAL project. The texture pack I use is a simple one I made and is not part of the GAL project, and isn't on github either. All other graphics in my screenshots are in the GAL project.

Also, let's not highjack this thread.

Shad

User avatar
Gael de Sailly
Member
Posts: 845
Joined: Sun Jan 26, 2014 17:01
GitHub: gaelysam
IRC: Gael-de-Sailly
In-game: Gael-de-Sailly gaelysam
Location: Voiron, France

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by Gael de Sailly » Post

ShadMOrdre wrote:
Fri Jul 23, 2021 17:21
I assumed that I could set the value higher, so tried 60, so that the entire worldmap can emerge. This simply led to out of memory.
I'm a bit surprised by this. At which time do you get OOM? During pre-generation or mapgen? I tried blocksize=60 with all other settings on default and did not get any issue.
Block size should not affect the amount of data produced on pre-generation, it only acts on the scale at which it will be rendered on the map. I'd even expect a large blocksize to be less intensive during mapgen, as a smaller quantity of data has to be loaded from the grid.
ShadMOrdre wrote:
Fri Jul 23, 2021 17:21
Changing the grid size from the default of 1000x1000 to 5000x5000, (multiple of 12 * 5), but again, out of memory.
This is less surprising, as the pre-generation needs to keep the full grid in memory, and 5000x5000 is huge.
From my tests, it appears that in most cases, grids over 2000x2000 result in OOM.
Just realize how bored we would be if the world was perfect.

User avatar
Gael de Sailly
Member
Posts: 845
Joined: Sun Jan 26, 2014 17:01
GitHub: gaelysam
IRC: Gael-de-Sailly
In-game: Gael-de-Sailly gaelysam
Location: Voiron, France

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by Gael de Sailly » Post

Releasing Mapgen Rivers v1.0

No more Python code to run, just download and use the mod. Pre-generation is done automatically in Lua and has been drastically optimized since the first (Python) versions.

Now available on Content DB
Download

Image
Image

Compatible with Ethereal (actually not a recent feature but a discovery, Ethereal uses only the biome system so it was already compatible with biomegen)
Last edited by Gael de Sailly on Sun Aug 01, 2021 17:47, edited 2 times in total.
Just realize how bored we would be if the world was perfect.

wsor4035
Member
Posts: 182
Joined: Sun Aug 11, 2019 21:23
GitHub: wsor4035
IRC: wsor
In-game: wsor

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by wsor4035 » Post

Gael de Sailly wrote:
Sun Aug 01, 2021 17:31

Coming soon on Content DB (it is being reviewed).
Done
j5uBLfc6NxgersvVj5D5dIsiKDkoQb0o

SciFurz
Member
Posts: 31
Joined: Tue Jun 01, 2021 22:51
Contact:

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by SciFurz » Post

I was looking into using the valleys mapgen instead of v7 for new worlds, but I'm favouring this one from trying out generating some worlds with different settings. It's really good.

Is it possible to add in an adjustable marging to the generation of the edges, so that they're less of a straight line? Something like 0-1000 nodes, or maybe more to create a smaller base map with lots of big peninsulas and/or fjords.

Also, could it be not all biomes are implemented? I used findbiome but it never found taiga or tundra, for instance.

c56
Member
Posts: 307
Joined: Wed Apr 21, 2021 03:05
GitHub: tigercoding56
In-game: bm5 or bemo5 also sell_her_on55

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by c56 » Post

this mod should be addet to default as v8 mapgen because it looks so good
this is a signature not a place to post messages also if i could change my username i would change it to sell_her_on55

User avatar
Gael de Sailly
Member
Posts: 845
Joined: Sun Jan 26, 2014 17:01
GitHub: gaelysam
IRC: Gael-de-Sailly
In-game: Gael-de-Sailly gaelysam
Location: Voiron, France

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by Gael de Sailly » Post

SciFurz wrote:
Mon Aug 02, 2021 00:20
Is it possible to add in an adjustable marging to the generation of the edges, so that they're less of a straight line? Something like 0-1000 nodes, or maybe more to create a smaller base map with lots of big peninsulas and/or fjords.
That's a good idea and I think it is possible, the base noise array could be tweaked to be progressively lowered near borders, and the flow/erosion calculations on this map would likely produce the nice coast shapes you expect :)
Not the priority right now, but I will write it in my ToDo list.
SciFurz wrote:
Mon Aug 02, 2021 00:20
Also, could it be not all biomes are implemented? I used findbiome but it never found taiga or tundra, for instance.
Are you using biomegen? mapgen_rivers generates only grass and snow if used standalone.
With biomegen I usually find taiga and tundra, but sometimes biomes are large and you have to fly a lot.
Also I don't think findbiomes is working with my mapgen (core biome function are not working in singlenode). I can try to fix it by overriding biome functions in biomegen.
Just realize how bored we would be if the world was perfect.

ShadMOrdre
Member
Posts: 1118
Joined: Mon Dec 29, 2014 08:07
Location: USA

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by ShadMOrdre » Post

Gael,

Setting block size to 60 works. I was incorrectly also adjusting the grid size to 5000. Leaving it at 1000, worked just fine. I notice, however, that the noise is stretched dramatically. Noise setting adjustments can make this work, but I may have encountered a bug, where the corresponding water level, the point at which oceans are defined, also rises. This makes the oceans generate using the biome river water, instead of water. Maybe I'm missing something??

Still, this is a very nice mapgen! The speed of this Lua mapgen is one of the best.

On another note, I wanted to share with you why I'm tinkering with your code so much.

I have a lua mapgen that creates terrain based on distance values in a 2 layer recursive voronoi diagram. My code determines the nearest cell from each layer. Layer 1 cells are large, and only 31 exist. Layer 2 cells are smaller, and I have around 350. At each run though the 2d heightmap For loop in the on_gen call, I determine the nearest cell from each layer, for each node, and calculate distance, determine the neighbors for both the parent and child voronoi cells, and use the edges of the child cells to create the following basic terrain.

Image

On a very primitive level, I can see basins and rivers flow down hill. I use the midpoint between neighboring cells as a rudimentary marker for a continental divide, thus defining watersheds.

Image

Actually finding the vertices in the voronoi diagram in code seems to be simple enough. Vertices are where either rivers converge, or are the depths of a basin.

Image

All this can easily be provided from the 3d loop in the on_gen call, as a flat_3d_map, but only at the chunk level, for memory sake. I would think that safe inferences can be made from this basic terrain generation, for erosion and flow calculations.

Thoughts?

Shad
Attachments
screenshot_20210802_135638.jpg
screenshot_20210802_135638.jpg (263.6 KiB) Viewed 4877 times
screenshot_20210802_132208.jpg
screenshot_20210802_132208.jpg (355.57 KiB) Viewed 4877 times
screenshot_20210802_132158.jpg
screenshot_20210802_132158.jpg (274.87 KiB) Viewed 4877 times

SciFurz
Member
Posts: 31
Joined: Tue Jun 01, 2021 22:51
Contact:

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by SciFurz » Post

Gael de Sailly wrote:
Mon Aug 02, 2021 17:13
SciFurz wrote:
Mon Aug 02, 2021 00:20
Is it possible to add in an adjustable marging to the generation of the edges, so that they're less of a straight line? Something like 0-1000 nodes, or maybe more to create a smaller base map with lots of big peninsulas and/or fjords.
That's a good idea and I think it is possible, the base noise array could be tweaked to be progressively lowered near borders, and the flow/erosion calculations on this map would likely produce the nice coast shapes you expect :)
Not the priority right now, but I will write it in my ToDo list.
SciFurz wrote:
Mon Aug 02, 2021 00:20
Also, could it be not all biomes are implemented? I used findbiome but it never found taiga or tundra, for instance.
Are you using biomegen? mapgen_rivers generates only grass and snow if used standalone.
With biomegen I usually find taiga and tundra, but sometimes biomes are large and you have to fly a lot.
Also I don't think findbiomes is working with my mapgen (core biome function are not working in singlenode). I can try to fix it by overriding biome functions in biomegen.
Thanks! I look forward to all improvements you'll make.

I flew around a lot in the meantime, simply enjoying the landscape, and I found the various biomes, so it looks like you're correct about findbiomes not working.
It's not a real issue to me if that mod doesn't work, as long as I know they're there. I like to see the different animals appear there from the couple of big animal mods. ;-)

I suspect I'll just spend all the time in minetest traveling and exploring every part of the map instead of actually mining and building things. *sniggers*

User avatar
Gael de Sailly
Member
Posts: 845
Joined: Sun Jan 26, 2014 17:01
GitHub: gaelysam
IRC: Gael-de-Sailly
In-game: Gael-de-Sailly gaelysam
Location: Voiron, France

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by Gael de Sailly » Post

SciFurz wrote:
Tue Aug 03, 2021 08:12
I suspect I'll just spend all the time in minetest traveling and exploring every part of the map instead of actually mining and building things. *sniggers*
Haha same for me... :)
I rarely use the map for something else than just flying around, even if I intended to. The only thing I've done is building a train network with advtrains, but I took ages to choose the area on which to settle down!
Just realize how bored we would be if the world was perfect.

twoelk
Member
Posts: 1482
Joined: Fri Apr 19, 2013 16:19
GitHub: twoelk
IRC: twoelk
In-game: twoelk
Location: northern Germany

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by twoelk » Post

lol, same here.
Mauvebic once got quite annoyed when I explored extensively his waterworld server looking for just the right island to build upon and thus enlarging his world file far more than he had planned for.
and then ...
on a tiny island
I built just a little hut.
a nice one though

SciFurz
Member
Posts: 31
Joined: Tue Jun 01, 2021 22:51
Contact:

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by SciFurz » Post

twoelk wrote:
Tue Aug 03, 2021 15:58
lol, same here.
Mauvebic once got quite annoyed when I explored extensively his waterworld server looking for just the right island to build upon and thus enlarging his world file far more than he had planned for.
and then ...
on a tiny island
I built just a little hut.
a nice one though
*lmao*

twoelk
Member
Posts: 1482
Joined: Fri Apr 19, 2013 16:19
GitHub: twoelk
IRC: twoelk
In-game: twoelk
Location: northern Germany

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by twoelk » Post

nice!
Image

hmmm?
the river from the top right seems to be afraid to enter the ocean alone?
Attachments
screenshot_20210804_111251.jpg
screenshot_20210804_111251.jpg (481.62 KiB) Viewed 4877 times

User avatar
runs
Member
Posts: 3225
Joined: Sat Oct 27, 2018 08:32

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by runs » Post

I try to use this but a lot of problems (just 1 min of testing). Unusable.

1. Weird Black Shadows:
Image

No I do not use the new dynamic shadow.

2. Weird Generation of coasts:
Image
A thin layer of terrain in the top (1 block only) an a sea below.

3. Bad deco colocation:
Image

A lot of trees cut by water.

4. Flooding in some areas.

5. Mountains to high and width. They are a kind of giant hills.

6. Rivers not carved in the mountains. Simply flooding.

7. Slow generation and game loading. Maybe this is cause of LUA mapgen. Mapgens should be C++ definitively...
Attachments
4.png
4.png (694.97 KiB) Viewed 4877 times
2.png
2.png (959.37 KiB) Viewed 4877 times
1.png
1.png (369.54 KiB) Viewed 4877 times

User avatar
runs
Member
Posts: 3225
Joined: Sat Oct 27, 2018 08:32

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by runs » Post

The concept is cool:

Image

But they are not rivers, they are called torrents.
Image
It would be necessary to design a new kind of node in the engine for these torrents to become real rivers.
Attachments
2.png
2.png (535.37 KiB) Viewed 4877 times
1.png
1.png (382.8 KiB) Viewed 4877 times

User avatar
runs
Member
Posts: 3225
Joined: Sat Oct 27, 2018 08:32

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by runs » Post

Lua mapgens produce visual glitches:

Image
Attachments
1.png
1.png (391.6 KiB) Viewed 4877 times

User avatar
runs
Member
Posts: 3225
Joined: Sat Oct 27, 2018 08:32

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by runs » Post

To say the least, it produces beautiful landscapes:
Image

I don't want to be critical, because I'm really a shitty guy. I just want you to improve it and include it without bugs in the official repo. I'm sure it's going to be better than fractal, which I don't even know what it's doing there. We need more good looking mapgens or "hire" (attract) specialists in these areas, there are always talents, one or two always.
Attachments
1.png
1.png (408.17 KiB) Viewed 4877 times

Pablo.R
Member
Posts: 42
Joined: Thu Mar 24, 2016 12:02
Location: Chile

Re: [Mod] Map generator with Rivers [mapgen_rivers]

by Pablo.R » Post

The last days I was trying the new version of the mapgen (from Content DB) and I think the landscapes are beautiful and the lakes astonishing. It needs some adjusts here and there but, at least for me, it is the best terrain generator I have seen until now.

Something that don't work for me is the map viewer (it pop up a window with a white map and the log show the next exception error that repeat endlessly).

Code: Select all

$ ./view_map.py ~/snap/minetest/1744/worlds/MTG_Rivers
---   General    ---
Grid size:     1000x 1000
Map size:     15000x15000

---   Surfaces   ---
Continents:        63.39%
-> Ground:         53.30%
-> Lakes:          10.10%
Oceans:            36.61%

---  Elevations  ---
Mean elevation:        13
Mean ocean depth:     -94
Mean continent elev:   75
Lowest elevation:    -417
Highest elevation:    449
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.8/tkinter/__init__.py", line 1892, in __call__
    return self.func(*args)
  File "/usr/lib/python3.8/tkinter/__init__.py", line 814, in callit
    func(*args)
  File "/usr/lib/python3/dist-packages/matplotlib/backends/_backend_tk.py", line 338, in idle_draw
    self.draw()
  File "/usr/lib/python3/dist-packages/matplotlib/backends/backend_tkagg.py", line 9, in draw
    super(FigureCanvasTkAgg, self).draw()
  File "/usr/lib/python3/dist-packages/matplotlib/backends/backend_agg.py", line 388, in draw
    self.figure.draw(self.renderer)
  File "/usr/lib/python3/dist-packages/matplotlib/artist.py", line 38, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/matplotlib/figure.py", line 1708, in draw
    mimage._draw_list_compositing_images(
  File "/usr/lib/python3/dist-packages/matplotlib/image.py", line 135, in _draw_list_compositing_images
    a.draw(renderer)
  File "/usr/lib/python3/dist-packages/matplotlib/artist.py", line 38, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/matplotlib/axes/_base.py", line 2647, in draw
    mimage._draw_list_compositing_images(renderer, self, artists)
  File "/usr/lib/python3/dist-packages/matplotlib/image.py", line 135, in _draw_list_compositing_images
    a.draw(renderer)
  File "/usr/lib/python3/dist-packages/matplotlib/artist.py", line 38, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/matplotlib/image.py", line 618, in draw
    im, l, b, trans = self.make_image(
  File "/usr/lib/python3/dist-packages/matplotlib/image.py", line 879, in make_image
    return self._make_image(
  File "/usr/lib/python3/dist-packages/matplotlib/image.py", line 530, in _make_image
    np.asarray(alpha_channel, np.float32) * out_alpha * alpha,
ValueError: operands could not be broadcast together with shapes (318,318) (1000,1000) 
Exception in Tkinter callback
EDIT: Not worry, matplotlib was outdated. Now is working, ... is a pity that lakes have the same color than sea, but wow, having a full map of it is ... incredible! Thanks!

Post Reply

Who is online

Users browsing this forum: No registered users and 22 guests