first pass of bubble caves

This commit is contained in:
FaceDeer 2022-09-12 17:06:18 -06:00
parent dd0468b376
commit 476f8a7b89
2 changed files with 148 additions and 0 deletions

144
bubble_caves/init.lua Normal file
View File

@ -0,0 +1,144 @@
local modpath = minetest.get_modpath(minetest.get_current_modname())
local mapgen_test_path = minetest.get_modpath("mapgen_test")
--local S = minetest.get_translator(minetest.get_current_modname())
local c_air = minetest.get_content_id("air")
local c_glow
if minetest.get_modpath("df_underworld_items") then
c_glow = minetest.get_content_id("df_underworld_items:glowstone")
end
local perlin_params = {
offset = 0,
scale = 1,
spread = {x=1000, y=500, z=1000},
seed = 501221,
octaves = 3,
persist = 0.67
}
local data = {}
local light_data = {}
local light = 15 + (15 * 16)
local max_depth = -5000
local min_depth = -6000
local noise_obj
local block_size = 80
local cube_inside = 1/math.sqrt(3) -- https://www.quora.com/What-is-the-largest-volume-of-a-cube-that-can-be-enclosed-in-a-sphere-of-diameter-2
local get_bubbles = function(pos)
noise_obj = noise_obj or minetest.get_perlin(perlin_params)
local bubbles = {}
local next_seed = math.random(1000000)
for block_x = -1, 1 do
for block_y = -1, 1 do
for block_z = -1, 1 do
local this_pos = vector.add(pos, {x=block_x*block_size, y=block_y*block_size, z=block_z*block_size})
math.randomseed(this_pos.x + this_pos.y*8 + this_pos.z*16)
this_pos.x = this_pos.x + math.floor(math.random()*block_size - block_size/2)
this_pos.y = this_pos.y + math.floor(math.random()*block_size - block_size/2)
this_pos.z = this_pos.z + math.floor(math.random()*block_size - block_size/2)
local noise_val = math.min(noise_obj:get_3d(this_pos), 1.0)
if noise_val > 0 then
local radius = noise_val*block_size*math.random()+5
local y = this_pos.y
if y + radius < max_depth and y - radius > min_depth then -- make sure bubbles remain within the layer
if mapgen_test_path then
if noise_val < 0.1 then
mapgen_test.record_first_location("bubble cave sparse", this_pos, "a bubble cave in a sparsely populated region")
elseif noise_val < 0.55 and noise_val > 0.45 then
mapgen_test.record_first_location("bubble cave middle", this_pos, "a bubble cave in a middlingly populated region")
elseif noise_val > 0.9 then
mapgen_test.record_first_location("bubble cave dense", this_pos, "a bubble cave in a densely populated region")
end
end
table.insert(bubbles, {loc=this_pos, radius=radius})
end
end
end
end
end
math.randomseed(next_seed)
return bubbles
end
if mapgen_test_path then
mapgen_test.log_time_settings("bubble_caves")
end
minetest.register_on_generated(function(minp, maxp, seed)
if minp.y > max_depth or maxp.y < min_depth then
return
end
local nearby_bubbles = get_bubbles({x=minp.x+block_size/2, y=minp.y+block_size/2, z=minp.z+block_size/2})
if not next(nearby_bubbles) then
return
end
if mapgen_test_path then
mapgen_test.log_time_start("bubble_caves")
end
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
vm:get_data(data)
vm:set_lighting({day = 0, night = 0})
vm:get_light_data(light_data)
for vi, x, y, z in area:iterp_xyz(emin, emax) do
for _, bubble in pairs(nearby_bubbles) do
if data[vi] ~= c_air then
local loc = bubble.loc
local loc_x = loc.x
local loc_y = loc.y
local loc_z = loc.z
local radius = bubble.radius
-- check outer bounding box first, faster than true distance
if x <= loc_x + radius and x >= loc_x - radius and y <= loc_y + radius and y >= loc_y - radius and z <= loc_z + radius and z >= loc_z - radius then
local inner_box = radius * cube_inside
if (x <= loc_x + inner_box and x >= loc_x - inner_box and y <= loc_y + inner_box and y >= loc_y - inner_box and z <= loc_z + inner_box and z >= loc_z - inner_box)
or vector.distance({x=x, y=y, z=z}, loc) < radius+math.random()/2 then
data[vi] = c_air
light_data[vi] = light
end
end
end
end
end
if c_glow then
for _, bubble in pairs(nearby_bubbles) do
local loc = bubble.loc
if area:containsp(loc) then
local vol = math.floor(bubble.radius / 20)
if vol > 0 then
for vi in area:iter(loc.x-vol, loc.y-vol, loc.z-vol, loc.x+vol, loc.y+vol, loc.z+vol) do
if area:containsi(vi) then
data[vi] = c_glow
end
end
else
data[area:indexp(loc)] = c_glow
end
end
end
end
--send data back to voxelmanip
vm:set_data(data)
--calc lighting
vm:set_light_data(light_data)
vm:calc_lighting()
vm:update_liquids()
--write it to world
vm:write_to_map()
if mapgen_test_path then
mapgen_test.log_time_stop("bubble_caves")
end
end)

4
bubble_caves/mod.conf Normal file
View File

@ -0,0 +1,4 @@
name = bubble_caves
description = Inserts foamy spherical bubble caves in a layer underground
depends = mapgen_helper
optional_depends = mapgen_test, df_underworld_items