mirror of
https://gitlab.com/gaelysam/mapgen_rivers.git
synced 2025-07-04 01:10:39 +02:00
Compare commits
4 Commits
terrainlib
...
distinguis
Author | SHA1 | Date | |
---|---|---|---|
b246cb775b | |||
27670addb3 | |||
54b94e6485 | |||
09de0fd298 |
@ -5,10 +5,16 @@ Semi-procedural map generator for Minetest 5.x. It aims to create realistic and
|
|||||||
|
|
||||||
Its main particularity compared to conventional Minetest mapgens is that rivers that flow strictly downhill, and combine together to form wider rivers, until they reach the sea. Another notable feature is the possibility of large lakes above sea level.
|
Its main particularity compared to conventional Minetest mapgens is that rivers that flow strictly downhill, and combine together to form wider rivers, until they reach the sea. Another notable feature is the possibility of large lakes above sea level.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
It used to be composed of a Python script doing pre-generation, and a Lua mod reading the pre-generation output and generating the map. The code has been rewritten in full Lua for version 1.0 (July 2021), and is now usable out-of-the-box as any other Minetest mod.
|
It used to be composed of a Python script doing pre-generation, and a Lua mod reading the pre-generation output and generating the map. The code has been rewritten in full Lua for version 1.0 (July 2021), and is now usable out-of-the-box as any other Minetest mod.
|
||||||
|
|
||||||
|
# Author and license
|
||||||
|
License: GNU LGPLv3.0
|
||||||
|
|
||||||
|
Code: Gaël de Sailly
|
||||||
|
Flow routing algorithm concept (in `terrainlib/rivermapper.lua`): Cordonnier, G., Bovy, B., & Braun, J. (2019). A versatile, linear complexity algorithm for flow routing in topographies with depressions. Earth Surface Dynamics, 7(2), 549-562.
|
||||||
|
|
||||||
# Requirements
|
# Requirements
|
||||||
Mod dependencies: `default` required, and [`biomegen`](https://github.com/Gael-de-Sailly/biomegen) optional (provides biome system).
|
Mod dependencies: `default` required, and [`biomegen`](https://github.com/Gael-de-Sailly/biomegen) optional (provides biome system).
|
||||||
|
|
||||||
|
5
init.lua
5
init.lua
@ -4,6 +4,11 @@ local modpath = minetest.get_modpath(minetest.get_current_modname()) .. '/'
|
|||||||
mapgen_rivers.modpath = modpath
|
mapgen_rivers.modpath = modpath
|
||||||
mapgen_rivers.world_data_path = minetest.get_worldpath() .. '/river_data/'
|
mapgen_rivers.world_data_path = minetest.get_worldpath() .. '/river_data/'
|
||||||
|
|
||||||
|
if minetest.get_mapgen_setting("mg_name") ~= "singlenode" then
|
||||||
|
minetest.set_mapgen_setting("mg_name", "singlenode", true)
|
||||||
|
print("[mapgen_rivers] Mapgen set to singlenode")
|
||||||
|
end
|
||||||
|
|
||||||
dofile(modpath .. 'settings.lua')
|
dofile(modpath .. 'settings.lua')
|
||||||
|
|
||||||
local sea_level = mapgen_rivers.settings.sea_level
|
local sea_level = mapgen_rivers.settings.sea_level
|
||||||
|
@ -1,5 +1,17 @@
|
|||||||
-- rivermapper.lua
|
-- rivermapper.lua
|
||||||
|
|
||||||
|
-- This file provide functions to construct the river tree from an elevation model.
|
||||||
|
-- Based on a research paper:
|
||||||
|
--
|
||||||
|
-- Cordonnier, G., Bovy, B., and Braun, J.:
|
||||||
|
-- A versatile, linear complexity algorithm for flow routing in topographies with depressions,
|
||||||
|
-- Earth Surf. Dynam., 7, 549–562, https://doi.org/10.5194/esurf-7-549-2019, 2019.
|
||||||
|
--
|
||||||
|
-- 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 Boruvka algorithm.
|
||||||
|
-- Only flow_local and accumulate_flow are custom algorithms.
|
||||||
|
|
||||||
local function flow_local_semirandom(plist)
|
local function flow_local_semirandom(plist)
|
||||||
local sum = 0
|
local sum = 0
|
||||||
for i=1, #plist do
|
for i=1, #plist do
|
||||||
|
29
view.py
29
view.py
@ -11,10 +11,12 @@ try:
|
|||||||
import colorcet as cc
|
import colorcet as cc
|
||||||
cmap1 = cc.cm.CET_L11
|
cmap1 = cc.cm.CET_L11
|
||||||
cmap2 = cc.cm.CET_L12
|
cmap2 = cc.cm.CET_L12
|
||||||
|
cmap3 = cc.cm.CET_L6.reversed()
|
||||||
except ImportError: # No module colorcet
|
except ImportError: # No module colorcet
|
||||||
import matplotlib.cm as cm
|
import matplotlib.cm as cm
|
||||||
cmap1 = cm.summer
|
cmap1 = cm.summer
|
||||||
cmap2 = cm.Blues
|
cmap2 = cm.ocean.reversed()
|
||||||
|
cmap3 = cm.Blues
|
||||||
except ImportError: # No module matplotlib
|
except ImportError: # No module matplotlib
|
||||||
has_matplotlib = False
|
has_matplotlib = False
|
||||||
|
|
||||||
@ -24,10 +26,12 @@ if has_matplotlib:
|
|||||||
water = np.maximum(lakes_sea - dem, 0)
|
water = np.maximum(lakes_sea - dem, 0)
|
||||||
max_elev = dem.max()
|
max_elev = dem.max()
|
||||||
max_depth = water.max()
|
max_depth = water.max()
|
||||||
|
max_lake_depth = lakes.max()
|
||||||
|
|
||||||
ls = mcl.LightSource(azdeg=315, altdeg=45)
|
ls = mcl.LightSource(azdeg=315, altdeg=45)
|
||||||
norm_ground = plt.Normalize(vmin=sea_level, vmax=max_elev)
|
norm_ground = plt.Normalize(vmin=sea_level, vmax=max_elev)
|
||||||
norm_sea = plt.Normalize(vmin=0, vmax=max_depth)
|
norm_sea = plt.Normalize(vmin=0, vmax=max_depth)
|
||||||
|
norm_lake = plt.Normalize(vmin=0, vmax=max_lake_depth)
|
||||||
rgb = ls.shade(dem, cmap=cmap1, vert_exag=1/scale, blend_mode='soft', norm=norm_ground)
|
rgb = ls.shade(dem, cmap=cmap1, vert_exag=1/scale, blend_mode='soft', norm=norm_ground)
|
||||||
|
|
||||||
(X, Y) = dem.shape
|
(X, Y) = dem.shape
|
||||||
@ -37,13 +41,23 @@ if has_matplotlib:
|
|||||||
extent = (-0.5*scale, (Y-0.5)*scale, -0.5*scale, (X-0.5)*scale)
|
extent = (-0.5*scale, (Y-0.5)*scale, -0.5*scale, (X-0.5)*scale)
|
||||||
plt.imshow(np.flipud(rgb), extent=extent, interpolation='antialiased')
|
plt.imshow(np.flipud(rgb), extent=extent, interpolation='antialiased')
|
||||||
alpha = (water > 0).astype('u1')
|
alpha = (water > 0).astype('u1')
|
||||||
plt.imshow(np.flipud(water), alpha=np.flipud(alpha), cmap=cmap2, extent=extent, vmin=0, vmax=max_depth, interpolation='antialiased')
|
lakes_alpha = ((lakes_sea - np.maximum(dem,sea_level)) > 0).astype('u1')
|
||||||
|
# plt.imshow(np.flipud(water), alpha=np.flipud(alpha), cmap=cmap2, extent=extent, vmin=0, vmax=max_depth, interpolation='antialiased')
|
||||||
|
plt.imshow(np.flipud(water), alpha=np.flipud(alpha), cmap=cmap3, extent=extent, vmin=0, vmax=max_depth, interpolation='antialiased')
|
||||||
|
plt.imshow(np.flipud(water), alpha=np.flipud(lakes_alpha), cmap=cmap2, extent=extent, vmin=0, vmax=max_depth, interpolation='antialiased')
|
||||||
|
|
||||||
sm1 = plt.cm.ScalarMappable(cmap=cmap1, norm=norm_ground)
|
sm1 = plt.cm.ScalarMappable(cmap=cmap1, norm=norm_ground)
|
||||||
plt.colorbar(sm1).set_label('Elevation')
|
plt.colorbar(sm1).set_label('Elevation')
|
||||||
|
|
||||||
sm2 = plt.cm.ScalarMappable(cmap=cmap2, norm=norm_sea)
|
sm2 = plt.cm.ScalarMappable(cmap=cmap2, norm=norm_lake)
|
||||||
plt.colorbar(sm2).set_label('Water depth')
|
cb2 = plt.colorbar(sm2)
|
||||||
|
cb2.ax.invert_yaxis()
|
||||||
|
cb2.set_label('Lake Depth')
|
||||||
|
|
||||||
|
sm3 = plt.cm.ScalarMappable(cmap=cmap3, norm=norm_sea)
|
||||||
|
cb3 = plt.colorbar(sm3)
|
||||||
|
cb3.ax.invert_yaxis()
|
||||||
|
cb3.set_label('Ocean Depth')
|
||||||
|
|
||||||
plt.xlabel('X')
|
plt.xlabel('X')
|
||||||
plt.ylabel('Z')
|
plt.ylabel('Z')
|
||||||
@ -84,9 +98,10 @@ def stats(dem, lakes, scale=1):
|
|||||||
lake_surface = lake.sum()
|
lake_surface = lake.sum()
|
||||||
|
|
||||||
print('--- General ---')
|
print('--- General ---')
|
||||||
print('Grid size: {:5d}x{:5d}'.format(dem.shape[0], dem.shape[1]))
|
print('Grid size (dem): {:5d}x{:5d}'.format(dem.shape[0], dem.shape[1]))
|
||||||
|
print('Grid size (lakes): {:5d}x{:5d}'.format(lakes.shape[0], lakes.shape[1]))
|
||||||
if scale > 1:
|
if scale > 1:
|
||||||
print('Map size: {:5d}x{:5d}'.format(int(dem.shape[0]*scale), int(dem.shape[1]*scale)))
|
print('Map size: {:5d}x{:5d}'.format(int(dem.shape[0]*scale), int(dem.shape[1]*scale)))
|
||||||
print()
|
print()
|
||||||
print('--- Surfaces ---')
|
print('--- Surfaces ---')
|
||||||
print('Continents: {:6.2%}'.format(continent_surface/surface))
|
print('Continents: {:6.2%}'.format(continent_surface/surface))
|
||||||
@ -100,3 +115,5 @@ def stats(dem, lakes, scale=1):
|
|||||||
print('Mean continent elev: {:4.0f}'.format((dem*continent).sum()/continent_surface))
|
print('Mean continent elev: {:4.0f}'.format((dem*continent).sum()/continent_surface))
|
||||||
print('Lowest elevation: {:4.0f}'.format(dem.min()))
|
print('Lowest elevation: {:4.0f}'.format(dem.min()))
|
||||||
print('Highest elevation: {:4.0f}'.format(dem.max()))
|
print('Highest elevation: {:4.0f}'.format(dem.max()))
|
||||||
|
print()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user