2020-04-14 21:11:54 +02:00
mapgen_rivers = { }
2020-04-09 21:13:38 +02:00
2020-04-14 21:11:54 +02:00
local modpath = minetest.get_modpath ( minetest.get_current_modname ( ) ) .. ' / '
2020-04-09 21:13:38 +02:00
2020-04-14 21:11:54 +02:00
dofile ( modpath .. ' settings.lua ' )
2020-04-09 21:13:38 +02:00
2020-04-14 21:11:54 +02:00
local blocksize = mapgen_rivers.blocksize
local sea_level = mapgen_rivers.sea_level
local riverbed_slope = mapgen_rivers.riverbed_slope
2020-04-12 09:40:10 +02:00
2020-04-14 21:11:54 +02:00
local make_polygons = dofile ( modpath .. ' polygons.lua ' )
2020-04-12 09:40:10 +02:00
2020-04-14 21:11:54 +02:00
local transform_quadri = dofile ( modpath .. ' geometry.lua ' )
2020-04-09 21:13:38 +02:00
2020-05-23 15:52:16 +02:00
local heightmaps = dofile ( modpath .. ' heightmap.lua ' )
2020-04-26 17:13:38 +02:00
-- Linear interpolation
2020-04-13 10:31:38 +02:00
local function interp ( v00 , v01 , v11 , v10 , xf , zf )
2020-04-12 09:40:10 +02:00
local v0 = v01 * xf + v00 * ( 1 - xf )
local v1 = v11 * xf + v10 * ( 1 - xf )
2020-04-09 21:13:38 +02:00
return v1 * zf + v0 * ( 1 - zf )
end
local data = { }
2020-05-23 15:52:16 +02:00
local noise_x_params = {
offset = 0 ,
scale = 1 ,
seed = - 4574 ,
spread = { x = 64 , y = 32 , z = 64 } ,
octaves = 3 ,
persistence = 0.75 ,
lacunarity = 2 ,
}
local noise_z_params = {
offset = 0 ,
scale = 1 ,
seed = - 7940 ,
spread = { x = 64 , y = 32 , z = 64 } ,
octaves = 3 ,
persistence = 0.75 ,
lacunarity = 2 ,
}
local noise_distort_params = {
offset = 0 ,
scale = 10 ,
seed = 676 ,
spread = { x = 1024 , y = 1024 , z = 1024 } ,
octaves = 5 ,
persistence = 0.5 ,
lacunarity = 2 ,
flags = " absvalue " ,
}
local noise_x_obj , noise_z_obj , noise_distort_obj
local noise_x_map = { }
local noise_z_map = { }
local noise_distort_map = { }
local mapsize
local init = false
2020-04-09 21:13:38 +02:00
local function generate ( minp , maxp , seed )
2020-05-23 15:52:16 +02:00
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 ,
}
noise_x_obj = minetest.get_perlin_map ( noise_x_params , mapsize )
noise_z_obj = minetest.get_perlin_map ( noise_z_params , mapsize )
noise_distort_obj = minetest.get_perlin_map ( noise_distort_params , chulens )
init = true
end
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 ( minp , noise_distort_map )
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 [ i ] * distort + x
if xv < xmin then xmin = xv end
if xv > xmax then xmax = xv end
noise_x_map [ i ] = xv
local zv = noise_z_map [ i ] * distort + z
if zv < zmin then zmin = zv end
if zv > zmax then zmax = zv end
noise_z_map [ i ] = 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 }
local incr = pmaxp.z - pminp.z + 1
local i_origin = 1 - pminp.x * incr - pminp.z
local terrain_map , lake_map = heightmaps ( pminp , pmaxp )
2020-04-09 21:13:38 +02:00
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_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 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.
2020-04-13 15:01:54 +02:00
2020-05-23 15:52:16 +02:00
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
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
for y = maxp.y + 1 , minp.y , - 1 do
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 + x0 * incr + z0
local i1 = i0 + incr
local i2 = i1 + 1
local i3 = i0 + 1
local terrain = interp ( terrain_map [ i0 ] , terrain_map [ i1 ] , terrain_map [ i2 ] , terrain_map [ i3 ] , xn - x0 , zn - z0 )
if y <= maxp.y then
local lake = math.min ( lake_map [ i0 ] , lake_map [ i1 ] , lake_map [ i2 ] , lake_map [ i3 ] )
local is_lake = lake > terrain
local ivm = a : index ( x , y , z )
if y <= terrain then
if y <= terrain - 1 or ground_above then
2020-04-09 21:13:38 +02:00
data [ ivm ] = c_stone
2020-05-23 15:52:16 +02:00
elseif is_lake then
data [ ivm ] = c_sand
else
data [ ivm ] = c_lawn
2020-04-09 21:13:38 +02:00
end
2020-05-23 15:52:16 +02:00
elseif y <= lake and lake > sea_level then
data [ ivm ] = c_rwater
elseif y <= sea_level then
2020-04-09 21:13:38 +02:00
data [ ivm ] = c_water
end
end
2020-05-23 15:52:16 +02:00
ground_above = y <= terrain
ivm = ivm + ystride
nid = nid + incrY
2020-04-09 21:13:38 +02:00
end
2020-05-23 15:52:16 +02:00
nid = nid + incrX
2020-04-09 21:13:38 +02:00
end
2020-05-23 15:52:16 +02:00
nid = nid + incrZ
2020-04-09 21:13:38 +02:00
end
vm : set_data ( data )
minetest.generate_ores ( vm , minp , maxp )
vm : set_lighting ( { day = 0 , night = 0 } )
vm : calc_lighting ( )
vm : update_liquids ( )
vm : write_to_map ( )
end
minetest.register_on_generated ( generate )