Optimize mapgen.

master
Duane Robertson 2016-09-27 16:43:57 -05:00
parent 0e5fd71e59
commit 60d4f91e57
1 changed files with 94 additions and 81 deletions

View File

@ -12,6 +12,9 @@ local node = setmetatable({}, {
loud_walking.node = node
local math_abs = math.abs
local math_floor = math.floor
local cloud_i = 0.5
local glass = {"loud_walking:sky_scrith", "loud_walking:cloud_scrith", "loud_walking:transparent_scrith"}
@ -98,9 +101,9 @@ mushroom_stones[node["loud_walking:stone_with_algae"]] = true
mushroom_stones[node["loud_walking:stone_with_lichen"]] = true
local function connection(x, y, z)
local min_x = math.floor((x + 32) / csize.x)
local min_y = math.floor((y + 32) / csize.y)
local min_z = math.floor((z + 32) / csize.z)
local min_x = math_floor((x + 32) / csize.x)
local min_y = math_floor((y + 32) / csize.y)
local min_z = math_floor((z + 32) / csize.z)
--local seed_noise = minetest.get_perlin({offset = 0, scale = 32768,
--seed = 5202, spread = {x = 80, y = 80, z = 80}, octaves = 2,
@ -137,12 +140,12 @@ end
local pod_size = {x=300, y=100, z=200}
local half_pod = {x=math.floor(pod_size.x / 2), y=math.floor(pod_size.y / 2), z=math.floor(pod_size.z / 2)}
local half_pod = {x=math_floor(pod_size.x / 2), y=math_floor(pod_size.y / 2), z=math_floor(pod_size.z / 2)}
local bridge_size = 50
local fcsize = {x=pod_size.x + bridge_size, y=pod_size.y + bridge_size, z=pod_size.z + bridge_size}
local bevel = half_pod.y
local room_size = 20
local control_off = math.floor(room_size / 4)
local control_off = math_floor(room_size / 4)
local biome_look = {}
local cave_look = {}
@ -157,8 +160,8 @@ local function place_schematic(pos, schem, center)
end
if center then
pos.x = pos.x - math.floor(schem.size.x / 2)
pos.z = pos.z - math.floor(schem.size.z / 2)
pos.x = pos.x - math_floor(schem.size.x / 2)
pos.z = pos.z - math_floor(schem.size.z / 2)
end
for z1 = 0, schem.size.z - 1 do
@ -201,9 +204,9 @@ end
local function get_biome(x, y, z)
local px = math.floor(x / fcsize.x)
local py = math.floor(y / fcsize.y)
local pz = math.floor(z / fcsize.z)
local px = math_floor(x / fcsize.x)
local py = math_floor(y / fcsize.y)
local pz = math_floor(z / fcsize.z)
if px % 10 == 6 and pz % 10 == 6 then
return "control"
@ -233,62 +236,32 @@ local function get_biome(x, y, z)
end
local function get_height_old(dx, dz, terrain_scale, ocean, index)
local terr
local half = {x=math.floor(csize.x / 2 + 0.5), y=math.floor(csize.y / 2 + 0.5), z=math.floor(csize.z / 2 + 0.5)}
terrain_scale = terrain_scale or 1
--if index == true then
-- terr = minetest.get_perlin(terrain_noise):get2d({x=dx, y=dz})
-- -- Still need csize here...
-- dx = (dx + 32) % 80
-- dz = (dz + 32) % 80
if not index then
index = dz * csize.x + dx + 1
terr = terrain[index]
else
terr = terrain[index]
end
terr = math.floor(terr * terrain_scale + 0.5)
local d = half.y - 2 - math.abs(math.abs(dx - (half.x - 0.5)) - math.abs(dz - (half.z - 0.5)))
if math.abs(terr) > d then
if terr > 0 then
terr = math.floor(d + 0.5)
elseif not ocean then
terr = math.floor(0.5 - d)
end
end
return terr
end
local function get_height(fdx, fdz, y, index, heights, terrain_scale, ocean)
local py = math.floor(y / fcsize.y)
local py = math_floor(y / fcsize.y)
if not terrain_scale then
return
end
if not heights[py] then
print('new height')
heights[py] = minetest.get_perlin_map(terrain_noise, csize):get2dMap_flat({x=minp.x, y=minp.z})
end
local terr = math.floor(heights[py][index] * terrain_scale + 0.5)
local terr = math_floor(heights[py][index] * terrain_scale + 0.5)
local d = - math.abs(math.abs(fdx - (half_pod.x - 0.5)) - math.abs(fdz - (half_pod.z - 0.5)))
if math.abs(fdx - half_pod.x) > math.abs(fdz - half_pod.z) then
local d = - math_abs(math_abs(fdx - (half_pod.x - 0.5)) - math_abs(fdz - (half_pod.z - 0.5)))
if math_abs(fdx - half_pod.x) > math_abs(fdz - half_pod.z) then
d = d + half_pod.x - 2
else
d = d + half_pod.z - 2
end
if math.abs(terr) > d then
if math_abs(terr) > d then
if terr > 0 then
terr = math.floor(d + 0.5)
terr = math_floor(d + 0.5)
elseif not ocean then
terr = math.floor(0.5 - d)
terr = math_floor(0.5 - d)
end
end
@ -297,6 +270,8 @@ end
local function generate(p_minp, p_maxp, seed)
--local ta0, ta1, ta2 = 0, 0, 0
local t0 = os.clock()
minp, maxp = p_minp, p_maxp
vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
vm:get_data(data)
@ -312,43 +287,58 @@ local function generate(p_minp, p_maxp, seed)
cloud = minetest.get_perlin_map(cloud_noise, csize):get2dMap_flat(minp)
cave = minetest.get_perlin_map(cave_noise, csize):get3dMap_flat(minp)
local t1 = os.clock()
local index = 0
local index3d = 0
local last_biome, last_px, last_py, last_pz, node_top, node_filler, node_water_top, node_water, depth_top, depth_water_top, depth_filler, node_stone, ocean, swamp, beach, dunes, height
local biome, cave_lining
for z = minp.z, maxp.z do
local dz = z - minp.z
local fdz = z % fcsize.z
local pz = math_floor(z / fcsize.z)
for x = minp.x, maxp.x do
index = index + 1
local dx = x - minp.x
local fdx = x % fcsize.x
local px = math_floor(x / fcsize.x)
local in_cave = false
index3d = dz * csize.y * csize.x + dx + 1
local ivm = a:index(x, minp.y, z)
local cave_height = 0
last_py = nil
for y = minp.y, maxp.y do
local dy = y - minp.y
local fdy = y % fcsize.y
local biome, cave_lining = get_biome(x, y, z)
local node_top = biomes[biome].node_top or "default:dirt_with_grass"
local node_filler = biomes[biome].node_filler or "default:dirt"
local node_water_top = biomes[biome].node_water_top or "default:water_source"
local node_water = biomes[biome].node_water or "default:water_source"
local depth_top = biomes[biome].depth_top or 1
local depth_water_top = biomes[biome].node_water_top or 1
local depth_filler = biomes[biome].depth_filler or 1
local node_stone = biomes[biome].node_stone or "default:stone"
local ocean = string.find(biome, "ocean") and true or false
local swamp = string.find(biome, "swamp") and true or false
local beach = string.find(biome, "beach") and true or false
local dunes = string.find(biome, "dunes") and true or false
local height = half_pod.y - 5
if not (biome == "underground" or biome == 'control') then
height = get_height(fdx, fdz, y, index, heights, biomes[biome].terrain_scale, ocean)
local py = math_floor(y / fcsize.y)
if py ~= last_py or px ~= last_px or pz ~= last_pz then
biome, cave_lining = get_biome(x, y, z)
end
if biome ~= last_biome then
node_top = biomes[biome].node_top or "default:dirt_with_grass"
node_filler = biomes[biome].node_filler or "default:dirt"
node_water_top = biomes[biome].node_water_top or "default:water_source"
node_water = biomes[biome].node_water or "default:water_source"
depth_top = biomes[biome].depth_top or 1
depth_water_top = biomes[biome].node_water_top or 1
depth_filler = biomes[biome].depth_filler or 1
node_stone = biomes[biome].node_stone or "default:stone"
ocean = string.find(biome, "ocean") and true or false
swamp = string.find(biome, "swamp") and true or false
beach = string.find(biome, "beach") and true or false
dunes = string.find(biome, "dunes") and true or false
end
if py ~= last_py then
height = half_pod.y - 5
if not (biome == "underground" or biome == 'control') then
height = get_height(fdx, fdz, y, index, heights, biomes[biome].terrain_scale, ocean)
end
end
if not (data[ivm] == node['air'] or data[ivm] == node['ignore']) then
-- nop
elseif biome == "control" and math.abs(fdx - half_pod.x) < 3 and math.abs(fdz - half_pod.z) < 3 then
elseif biome == "control" and math_abs(fdx - half_pod.x) < 3 and math_abs(fdz - half_pod.z) < 3 then
data[ivm] = node["loud_walking:air_ladder"]
elseif fdz >= pod_size.z or fdx >= pod_size.x or fdy >= pod_size.y then
if (fdy == half_pod.y and fdx == half_pod.x) or (fdy == half_pod.y and fdz == half_pod.z) then
@ -361,7 +351,7 @@ local function generate(p_minp, p_maxp, seed)
lightmap[ivm] = 0
in_cave = false
elseif (fdx == 0 or fdx == pod_size.x - 1) or (fdz == 0 or fdz == pod_size.z - 1) or (fdy == 0 or fdy == pod_size.y - 1) or math.min(fdx, pod_size.x - fdx) + math.min(fdy, pod_size.y - fdy) + math.min(fdz, pod_size.z - fdz) < bevel + 1 then
if math.abs(fdy - half_pod.y - 2) < 2 and (fdz == half_pod.z or fdx == half_pod.x) then
if math_abs(fdy - half_pod.y - 2) < 2 and (fdz == half_pod.z or fdx == half_pod.x) then
data[ivm] = node["air"]
else
if biome == "control" then
@ -382,9 +372,9 @@ local function generate(p_minp, p_maxp, seed)
data[ivm] = node['loud_walking:scrith']
elseif biome == "control" and fdy % 5 == 0 then
data[ivm] = node["loud_walking:control_floor"]
elseif biome == "control" and (math.abs(fdx - half_pod.x) < 3 or math.abs(fdz - half_pod.z) < 3) then
elseif biome == "control" and (math_abs(fdx - half_pod.x) < 3 or math_abs(fdz - half_pod.z) < 3) then
data[ivm] = node["air"]
elseif biome == "control" and ((math.abs(fdx - half_pod.x) % room_size == 3 and (math.abs(fdz - half_pod.z) - 12) % room_size > 3) or (math.abs(fdz - half_pod.z) % room_size == 3 and (math.abs(fdx - half_pod.x) - 12) % room_size > 3)) then
elseif biome == "control" and ((math_abs(fdx - half_pod.x) % room_size == 3 and (math_abs(fdz - half_pod.z) - 12) % room_size > 3) or (math_abs(fdz - half_pod.z) % room_size == 3 and (math_abs(fdx - half_pod.x) - 12) % room_size > 3)) then
data[ivm] = node["loud_walking:control_wall"]
elseif biome == "control" then
--
@ -474,26 +464,41 @@ local function generate(p_minp, p_maxp, seed)
cave_height = 0
end
last_biome = biome
last_py = py
ivm = ivm + a.ystride
index3d = index3d + csize.x
end
last_px = px
end
last_pz = pz
end
local t2 = os.clock()
local index = 0
for z = minp.z, maxp.z do
local fdz = z % fcsize.z
local pz = math_floor(z / fcsize.z)
for x = minp.x, maxp.x do
local fdx = x % fcsize.x
local px = math_floor(x / fcsize.x)
index = index + 1
last_py = nil
for y = minp.y, maxp.y do
local fdy = y % fcsize.y
local py = math_floor(y / fcsize.y)
if fdz % 5 == 0 and fdx % 5 == 0 then
local fdy = y % fcsize.y
local pod = fdz < pod_size.z and fdx < pod_size.x and fdy < pod_size.y
local biome, cave_lining = get_biome(x, y, z)
if py ~= last_py or px ~= last_px or pz ~= last_pz then
biome, cave_lining = get_biome(x, y, z)
end
local ocean = string.find(biome, "ocean") and true or false
local height = get_height(fdx, fdz, y, index, heights, biomes[biome].terrain_scale, ocean)
if py ~= last_py then
height = get_height(fdx, fdz, y, index, heights, biomes[biome].terrain_scale, ocean)
end
if biome ~= 'control' and pod and fdy == height + ground and biomes[biome].special_tree_prob and math.random(biomes[biome].special_tree_prob) == 1 then
local rx = x + math.random(5) - 1
@ -521,6 +526,8 @@ local function generate(p_minp, p_maxp, seed)
end
end
local t3 = os.clock()
if false and pod and biome == "control" then
for dy = 0, 15 do
for dz = 0, 1 do
@ -561,7 +568,7 @@ local function generate(p_minp, p_maxp, seed)
end
end
elseif sr == 4 then
if dy < 15 and (x > 0 and x < 20 and z > 0 and z < 20) and (((x == 1 or x == 19) and math.abs(z - 10) > 3) or ((z == 1 or z == 19) and math.abs(x - 10) > 3)) then
if dy < 15 and (x > 0 and x < 20 and z > 0 and z < 20) and (((x == 1 or x == 19) and math_abs(z - 10) > 3) or ((z == 1 or z == 19) and math_abs(x - 10) > 3)) then
data[ivm + 3 * a.ystride] = node["loud_walking:controls"]
end
end
@ -574,6 +581,8 @@ local function generate(p_minp, p_maxp, seed)
end
end
local t4 = os.clock()
vm:set_data(data)
minetest.generate_ores(vm, minp, maxp)
--vm:set_param2_data(p2data)
@ -581,6 +590,10 @@ local function generate(p_minp, p_maxp, seed)
vm:update_liquids()
vm:calc_lighting(minp, maxp, false)
vm:write_to_map()
local t5 = os.clock()
print(' times: '..(t1 - t0)..', '..(t2 - t1)..', '..(t3 - t2)..', '..(t5 - t4)..' = '..(t5 - t0))
--print(' also: '..ta1..', '..ta2)
end
@ -593,7 +606,7 @@ local function generate_old(p_minp, p_maxp, seed)
csize = vector.add(vector.subtract(maxp, minp), 1)
-- Deal with memory issues. This, of course, is supposed to be automatic.
local mem = math.floor(collectgarbage("count")/1024)
local mem = math_floor(collectgarbage("count")/1024)
if mem > 300 then
print("Loud Walking: Manually collecting garbage...")
collectgarbage("collect")
@ -606,8 +619,8 @@ local function generate_old(p_minp, p_maxp, seed)
math.randomseed(seed_noise:get2d({x=minp.x, y=minp.z}))
-- Keep this first after seeding!
local px = math.floor((minp.x + 32) / csize.x)
local pz = math.floor((minp.z + 32) / csize.z)
local px = math_floor((minp.x + 32) / csize.x)
local pz = math_floor((minp.z + 32) / csize.z)
local biome = get_biome(px, pz)
local cave_lining = cave_stones[math.random(#cave_stones)]
if math.random(3) == 1 then
@ -629,7 +642,7 @@ local function generate_old(p_minp, p_maxp, seed)
local swamp = string.find(biome, "swamp") and true or false
local beach = string.find(biome, "beach") and true or false
local dunes = string.find(biome, "dunes") and true or false
local half = {x=math.floor(csize.x / 2 + 0.5), y=math.floor(csize.y / 2 + 0.5), z=math.floor(csize.z / 2 + 0.5)}
local half = {x=math_floor(csize.x / 2 + 0.5), y=math_floor(csize.y / 2 + 0.5), z=math_floor(csize.z / 2 + 0.5)}
local ground = half.y
beach = beach or dunes
@ -666,14 +679,14 @@ local function generate_old(p_minp, p_maxp, seed)
for y = minp.y, maxp.y do
local dy = y - minp.y
if pod then
if biome == "control" and math.abs(dx - half.x) < 3 and math.abs(dz - half.z) < 3 then
if biome == "control" and math_abs(dx - half.x) < 3 and math_abs(dz - half.z) < 3 then
data[ivm] = node["loud_walking:air_ladder"]
elseif math.min(dx, csize.x - dx) + math.min(dy, csize.y - dy) + math.min(dz, csize.z - dz) < bevel then
data[ivm] = node["air"]
lightmap[ivm] = 0
in_cave = false
elseif (dx == 0 or dx == csize.x - 1) or (dz == 0 or dz == csize.z - 1) or (dy == 0 or dy == csize.y - 1) or math.min(dx, csize.x - dx) + math.min(dy, csize.y - dy) + math.min(dz, csize.z - dz) < bevel + 1 then
if math.abs(dy - half.y - 2) < 2 and (dz == half.z or dx == half.x) then
if math_abs(dy - half.y - 2) < 2 and (dz == half.z or dx == half.x) then
data[ivm] = node["air"]
else
if biome == "control" then
@ -693,9 +706,9 @@ local function generate_old(p_minp, p_maxp, seed)
in_cave = false
elseif biome == "control" and dy % 5 == 0 then
data[ivm] = node["loud_walking:control_floor"]
elseif biome == "control" and (math.abs(dx - half.x) < 3 or math.abs(dz - half.z) < 3) then
elseif biome == "control" and (math_abs(dx - half.x) < 3 or math_abs(dz - half.z) < 3) then
data[ivm] = node["air"]
elseif biome == "control" and ((math.abs(dx - half.x) % 20 == 3 and (math.abs(dz - half.z) - 12) % 20 > 3) or (math.abs(dz - half.z) % 20 == 3 and (math.abs(dx - half.x) - 12) % 20 > 3)) then
elseif biome == "control" and ((math_abs(dx - half.x) % 20 == 3 and (math_abs(dz - half.z) - 12) % 20 > 3) or (math_abs(dz - half.z) % 20 == 3 and (math_abs(dx - half.x) - 12) % 20 > 3)) then
data[ivm] = node["loud_walking:control_wall"]
elseif biome == "control" then
--
@ -780,7 +793,7 @@ local function generate_old(p_minp, p_maxp, seed)
lightmap[ivm] = 0
in_cave = false
end
elseif biome == "control" and math.abs(dx - half.x) < 3 and math.abs(dz - half.z) < 3 then
elseif biome == "control" and math_abs(dx - half.x) < 3 and math_abs(dz - half.z) < 3 then
data[ivm] = node["loud_walking:air_ladder"]
elseif connection and dy == half.y and ((dx == half.x and connection % 4 == 0) or (dz == half.z and connection % 2 == 1)) then
data[ivm] = node["loud_walking:scrith"]
@ -863,7 +876,7 @@ local function generate_old(p_minp, p_maxp, seed)
end
end
elseif sr == 4 then
if dy < 15 and (x > 0 and x < 20 and z > 0 and z < 20) and (((x == 1 or x == 19) and math.abs(z - 10) > 3) or ((z == 1 or z == 19) and math.abs(x - 10) > 3)) then
if dy < 15 and (x > 0 and x < 20 and z > 0 and z < 20) and (((x == 1 or x == 19) and math_abs(z - 10) > 3) or ((z == 1 or z == 19) and math_abs(x - 10) > 3)) then
data[ivm + 3 * a.ystride] = node["loud_walking:controls"]
end
end