Compare commits
5 Commits
9ffa150263
...
c175f2bbf7
Author | SHA1 | Date |
---|---|---|
Gael-de-Sailly | c175f2bbf7 | |
Gael-de-Sailly | ca68738ba7 | |
Gael-de-Sailly | 85e545d5ac | |
Gael-de-Sailly | e0aecdc3f3 | |
Gael-de-Sailly | 83728cc932 |
|
@ -55,6 +55,14 @@ Generic usage:
|
|||
- `conf_file`: Path to configuration file from which parameters should be read. If omitted, attempts to read in `terrain.conf`.
|
||||
- `output_dir`: Directory in which to save the grid data, defaults to `river_data/`. If it does not exist, it is created. If it already contains previous grid data, they are overwritten.
|
||||
|
||||
#### Config files
|
||||
The mod currently includes 3 config files, providing different terrain styles:
|
||||
- `terrain_default.conf` generates the standard terrain, with highest elevations around 250 with sharp peaks, and otherwise hilly terrain.
|
||||
- `terrain_higher.conf` generates higher mountains (up to 400 nodes), and wider valleys.
|
||||
- `terrain_original.conf` provides a terrain similar to what was generated with the first release of `mapgen_rivers`.
|
||||
|
||||
More work is needed to find better and more varied terrain styles.
|
||||
|
||||
### Complete list of parameters
|
||||
Other parameters can be specified by `--parameter value`. Syntax `--parameter=value` is also supported.
|
||||
|
||||
|
@ -78,6 +86,7 @@ Other parameters can be specified by `--parameter value`. Syntax `--parameter=va
|
|||
| `niter` | Number of iterations. Each iteration represents a time `time/niter`. | `--niter 10` |
|
||||
| `sea_level_variations` | Amplitude of sea level variations throughout the simulation (if any). | `--sea_level_variations 10` |
|
||||
| `sea_level_variations_time` | Characteristic time of variation for sea level, in the same units than `time`. Increasing it will result in slower variations between iterations. | `--sea_level_variations_time 1` |
|
||||
| `flow_method` | Algorithm used for local flow calculation. Possible values are `steepest` (every node flows toward the steepest neighbour when possible), and `semirandom` (default, flow direction is determined randomly between lower neighbours, with lowest ones having greater probability). | `--flow_method semirandom` |
|
||||
| | **Alternatives** |
|
||||
| `config` | Another way to specify configuration file | `--config terrain_higher.conf` |
|
||||
| `output` | Another way to specify output dir | `--output ~/.minetest/worlds/my_world/river_data` |
|
||||
|
|
21
generate.py
21
generate.py
|
@ -29,7 +29,7 @@ def noisemap(X, Y, scale=0.01, vscale=1.0, offset=0.0, log=False, **params):
|
|||
### PARSE COMMAND-LINE ARGUMENTS
|
||||
argc = len(sys.argv)
|
||||
|
||||
config_file = 'terrain.conf'
|
||||
config_file = 'terrain_default.conf'
|
||||
output_dir = 'river_data'
|
||||
params_from_args = {}
|
||||
i = 1 # Index of arguments
|
||||
|
@ -80,13 +80,14 @@ offset = float(get_setting('offset', 0.0))
|
|||
persistence = float(get_setting('persistence', 0.6))
|
||||
lacunarity = float(get_setting('lacunarity', 2.0))
|
||||
|
||||
K = float(get_setting('K', 1.0))
|
||||
m = float(get_setting('m', 0.35))
|
||||
d = float(get_setting('d', 0.2))
|
||||
K = float(get_setting('K', 0.5))
|
||||
m = float(get_setting('m', 0.5))
|
||||
d = float(get_setting('d', 0.5))
|
||||
sea_level = float(get_setting('sea_level', 0.0))
|
||||
sea_level_variations = float(get_setting('sea_level_variations', 0.0))
|
||||
sea_level_variations_time = float(get_setting('sea_level_variations_time', 1.0))
|
||||
flex_radius = float(get_setting('flex_radius', 20.0))
|
||||
flow_method = get_setting('flow_method', 'semirandom')
|
||||
|
||||
time = float(get_setting('time', 10.0))
|
||||
niter = int(get_setting('niter', 10))
|
||||
|
@ -94,11 +95,6 @@ niter = int(get_setting('niter', 10))
|
|||
### MAKE INITIAL TOPOGRAPHY
|
||||
n = np.zeros((mapsize+1, mapsize+1))
|
||||
|
||||
if sea_level_variations != 0.0:
|
||||
sea_ybase = np.random.randint(8192)-4096
|
||||
sea_level_ref = snoise2(time * (1-1/niter) / sea_level_variations, sea_ybase, **params_sealevel) * sea_level_variations
|
||||
offset -= (sea_level_ref + sea_level)
|
||||
|
||||
# Set noise parameters
|
||||
params = {
|
||||
"offset" : offset,
|
||||
|
@ -115,12 +111,17 @@ params_sealevel = {
|
|||
"lacunarity" : 2,
|
||||
}
|
||||
|
||||
if sea_level_variations != 0.0:
|
||||
sea_ybase = np.random.randint(8192)-4096
|
||||
sea_level_ref = snoise2(time * (1-1/niter) / sea_level_variations, sea_ybase, **params_sealevel) * sea_level_variations
|
||||
params['offset'] -= (sea_level_ref + sea_level)
|
||||
|
||||
n = noisemap(mapsize+1, mapsize+1, **params)
|
||||
|
||||
### COMPUTE LANDSCAPE EVOLUTION
|
||||
# Initialize landscape evolution model
|
||||
print('Initializing model')
|
||||
model = terrainlib.EvolutionModel(n, K=K, m=m, d=d, sea_level=sea_level, flex_radius=flex_radius)
|
||||
model = terrainlib.EvolutionModel(n, K=K, m=m, d=d, sea_level=sea_level, flex_radius=flex_radius, flow_method=flow_method)
|
||||
terrainlib.update(model.dem, model.lakes, t=5, sea_level=model.sea_level, title='Initializing...')
|
||||
|
||||
dt = time/niter
|
||||
|
|
|
@ -99,7 +99,25 @@ local function heightmaps(minp, maxp)
|
|||
xf, zf
|
||||
))
|
||||
|
||||
local lake_height = math.max(math.floor(poly.lake), terrain_height)
|
||||
-- Spatial gradient of the interpolation
|
||||
local slope_x = zf*(vdem[3]-vdem[4]) + (1-zf)*(vdem[2]-vdem[1]) < 0
|
||||
local slope_z = xf*(vdem[3]-vdem[2]) + (1-xf)*(vdem[4]-vdem[1]) < 0
|
||||
local lake_id = 0
|
||||
if slope_x then
|
||||
if slope_z then
|
||||
lake_id = 3
|
||||
else
|
||||
lake_id = 2
|
||||
end
|
||||
else
|
||||
if slope_z then
|
||||
lake_id = 4
|
||||
else
|
||||
lake_id = 1
|
||||
end
|
||||
end
|
||||
local lake_height = math.max(math.floor(poly.lake[lake_id]), terrain_height)
|
||||
|
||||
if imax > 0 and depth_factor_max > 0 then
|
||||
terrain_height = math.min(math.max(lake_height, sea_level) - math.floor(1+depth_factor_max*riverbed_slope), terrain_height)
|
||||
end
|
||||
|
|
|
@ -185,7 +185,7 @@ local function make_polygons(minp, maxp)
|
|||
|
||||
local poly_dem = {dem[iA], dem[iB], dem[iC], dem[iD]}
|
||||
polygon.dem = poly_dem
|
||||
polygon.lake = math.min(lakes[iA], lakes[iB], lakes[iC], lakes[iD])
|
||||
polygon.lake = {lakes[iA], lakes[iB], lakes[iC], lakes[iD]}
|
||||
|
||||
-- Now, rivers.
|
||||
-- Load river flux values for the 4 corners
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
mapsize = 1000
|
||||
scale = 400
|
||||
vscale = 300
|
||||
offset = 0
|
||||
persistence = 0.6
|
||||
lacunarity = 2.0
|
||||
|
||||
K = 0.5
|
||||
m = 0.5
|
||||
d = 0.5
|
||||
sea_level = 0
|
||||
sea_level_variations = 8
|
||||
sea_level_variations_time = 2
|
||||
flex_radius = 20
|
||||
|
||||
time = 10
|
||||
niter = 10
|
|
@ -6,9 +6,11 @@ persistence = 0.65
|
|||
lacunarity = 2.0
|
||||
|
||||
K = 0.5
|
||||
m = 0.55
|
||||
d = 0.45
|
||||
m = 0.45
|
||||
d = 0.55
|
||||
sea_level = 0
|
||||
sea_level_variations = 12
|
||||
sea_level_variations_time = 2
|
||||
flex_radius = 50
|
||||
|
||||
time = 10
|
||||
|
|
|
@ -4,10 +4,11 @@ vscale = 300
|
|||
offset = 0
|
||||
persistence = 0.6
|
||||
lacunarity = 2.0
|
||||
flow_method = steepest
|
||||
|
||||
K = 0.5
|
||||
m = 0.5
|
||||
d = 0.5
|
||||
K = 1
|
||||
m = 0.35
|
||||
d = 0
|
||||
sea_level = 0
|
||||
flex_radius = 20
|
||||
|
|
@ -54,7 +54,7 @@ def diffusion(dem, time, d=1):
|
|||
return im.gaussian_filter(dem, radius, mode='reflect') # Diffusive erosion is a simple Gaussian blur
|
||||
|
||||
class EvolutionModel:
|
||||
def __init__(self, dem, K=1, m=0.5, d=1, sea_level=0, flow=False, flex_radius=100):
|
||||
def __init__(self, dem, K=1, m=0.5, d=1, sea_level=0, flow=False, flex_radius=100, flow_method='semirandom'):
|
||||
self.dem = dem
|
||||
#self.bedrock = dem
|
||||
self.K = K
|
||||
|
@ -63,6 +63,8 @@ class EvolutionModel:
|
|||
self.sea_level = sea_level
|
||||
self.flex_radius = flex_radius
|
||||
self.define_isostasy()
|
||||
self.flow_method = flow_method
|
||||
#set_flow_method(flow_method)
|
||||
if flow:
|
||||
self.calculate_flow()
|
||||
else:
|
||||
|
@ -72,7 +74,7 @@ class EvolutionModel:
|
|||
self.flow_uptodate = False
|
||||
|
||||
def calculate_flow(self):
|
||||
self.dirs, self.lakes, self.rivers = flow(self.dem)
|
||||
self.dirs, self.lakes, self.rivers = flow(self.dem, method=self.flow_method)
|
||||
self.flow_uptodate = True
|
||||
|
||||
def advection(self, time):
|
||||
|
|
|
@ -12,7 +12,19 @@ from collections import defaultdict
|
|||
# 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.
|
||||
|
||||
def flow_local(plist):
|
||||
# Define two different method for local flow routing
|
||||
def flow_local_steepest(plist):
|
||||
vmax = 0.0
|
||||
imax = 0.0
|
||||
for i, p in enumerate(plist):
|
||||
if p > vmax:
|
||||
vmax = p
|
||||
imax = i
|
||||
if vmax > 0.0:
|
||||
return imax+1
|
||||
return 0
|
||||
|
||||
def flow_local_semirandom(plist):
|
||||
"""
|
||||
Determines a flow direction based on denivellation for every neighbouring node.
|
||||
Denivellation must be positive for downward and zero for flat or upward:
|
||||
|
@ -27,7 +39,16 @@ def flow_local(plist):
|
|||
return i+1
|
||||
r -= p
|
||||
|
||||
def flow(dem):
|
||||
flow_local_methods = {
|
||||
'steepest' : flow_local_steepest,
|
||||
'semirandom' : flow_local_semirandom,
|
||||
}
|
||||
|
||||
def flow(dem, method='semirandom'):
|
||||
if method in flow_local_methods:
|
||||
flow_local = flow_local_methods[method]
|
||||
else:
|
||||
raise KeyError('Flow method \'{}\' does not exist'.format(method))
|
||||
|
||||
# Flow locally
|
||||
dirs1 = np.zeros(dem.shape, dtype=int)
|
||||
|
|
Loading…
Reference in New Issue