Add cave shape optimizations

pull/1/head
Bram van den Heuvel 2024-04-23 11:06:59 +02:00
parent 67f780b2b3
commit 7319d58525
1 changed files with 72 additions and 47 deletions

View File

@ -37,6 +37,19 @@ local default_biome =
, maxp = { x = 1e5, y = 1e5, z = 1e5 }
}
local cave_shape_chunk_size = 8
local cluster_shape_chunks_x = 4
local cluster_shape_chunks_y = 6
local cluster_shape_chunks_z = 4
local function reduced_pos(pos)
return
{ x = math.floor(pos.x / (cave_shape_chunk_size * cluster_shape_chunks_x))
, y = math.floor(pos.y / (cave_shape_chunk_size * cluster_shape_chunks_y))
, z = math.floor(pos.z / (cave_shape_chunk_size * cluster_shape_chunks_z))
}
end
-- Convert 3d relative coordinates to an index on a flat array
local function from_3d_to_flat(dx, dy, dz, nx, ny)
return (nx * ny * dz) + (nx * dy) + dx + 1
@ -252,7 +265,13 @@ local function get_connectivity_noise_params(shape_size)
return {
offset = 50,
scale = 50,
spread = { x = factor * 250, y = factor * 100, z = factor * 250 },
spread =
reduced_pos(
{ x = factor * 250
, y = factor * 100
, z = factor * 250
}
),
seed = 297948,
octaves = 2,
persistence = 0.2,
@ -269,7 +288,13 @@ local function get_verticality_noise_params(shape_size)
return {
offset = 50,
scale = 50,
spread = { x = factor * 100, y = factor * 250, z = factor * 100 },
spread =
reduced_pos(
{ x = factor * 100
, y = factor * 250
, z = factor * 100
}
),
seed = 35644,
octaves = 2,
persistence = 0.2,
@ -278,26 +303,30 @@ local function get_verticality_noise_params(shape_size)
}
end
-- Get the distance of each cave shape to calculate their weight.
local function shape_distance_weight(shape_size, dx, dy)
-- Get whether a cave shape is within distance.
local function shape_within_distance(shape_size, dx, dy)
local factor = math.max(math.abs(shape_size) ^ 0.5, 1)
local max_distance = 100 / factor
local max_distance = 30 / factor
if dx^2 + dy^2 > max_distance^2 then
return 0
else
return 1 / (dx^5 + dy^5)
return dx^2 + dy^2 <= max_distance^2
end
local function shape_def_distance(def, x, y)
local dx = math.abs(x - def.connectivity_point)
local dy = math.abs(y - def.verticality_point)
return dx^2 + dy^2
end
-- Get a flat map containing all flat threshold values
local function get_threshold_flat(minp, maxp)
local connectivity = get_flat_from_noise_params(
minp, maxp,
reduced_pos(minp), reduced_pos(maxp),
get_connectivity_noise_params(#noordstar_caves.registered_shapes)
)
local verticality = get_flat_from_noise_params(
minp, maxp,
reduced_pos(minp), reduced_pos(maxp),
get_verticality_noise_params(#noordstar_caves.registered_shapes)
)
@ -305,41 +334,37 @@ local function get_threshold_flat(minp, maxp)
-- Get noise for all cave shapes
for key, def in pairs(noordstar_caves.registered_shapes) do
noise[key] = {
key = key,
noise = get_flat_from_shape_def(def, minp, maxp),
def = def
}
noise[key] = get_flat_from_shape_def(def, reduced_pos(minp), reduced_pos(maxp))
end
-- Create the flat array
return Flat3dArray:from_func(minp, maxp, function(i, pos)
local total = 0
local count = 0
-- Create a (reduced) flat array
local reduced = Flat3dArray:from_func(
reduced_pos(minp), reduced_pos(maxp),
function(i, pos)
local x = connectivity:get_pos(pos)
local y = verticality:get_pos(pos)
for _, n in pairs(noise) do
local v = n.noise:get_pos(pos)
local value = 0
local dx = math.abs(x - n.def.connectivity_point)
local dy = math.abs(y - n.def.verticality_point)
for key, def in pairs(noordstar_caves.registered_shapes) do
local dx = math.abs(x - def.connectivity_point)
local dy = math.abs(y - def.verticality_point)
local w = math.abs(shape_distance_weight(
#noordstar_caves.registered_shapes, dx, dy
))
total = total + v * w
count = count + w
if shape_within_distance(#noordstar_caves.registered_shapes, dx, dy) then
value = math.max(value, noise[key]:get_pos(pos))
end
end
if count <= 0 then
return -1000
else
return total / count
return value
end
)
-- Create the flat array
local x = Flat3dArray:from_func(minp, maxp, function(i, pos)
return reduced:get_pos(reduced_pos(pos))
end)
return x
end
@ -470,13 +495,13 @@ local function biome_def_to_content_id(def, nt, original_block)
local node_air = get_node(def.node_air, minetest.get_content_id("air"))
local node_floor = get_node(def.node_floor, original_block)
local node_stone = original_block
local node_stone = get_node(nil, original_block)
local node_roof = get_node(def.node_roof, original_block)
local node_unknown = original_block
local node_unknown = get_node(nil, original_block)
local node_wall = get_node(def.node_wall, original_block)
if nt == node_type.unknown then
return node_unknown
return node_unknown()
elseif nt == node_type.floor then
return node_floor()
elseif nt == node_type.wall then
@ -486,7 +511,7 @@ local function biome_def_to_content_id(def, nt, original_block)
elseif nt == node_type.content then
return node_air()
elseif nt == node_type.stone then
return node_stone
return node_stone()
else
return original_block
end