//erode snowballs: make tweaks & add new noconv param

This commit is contained in:
Starbeamrainbowlabs 2020-08-21 22:01:24 +01:00
parent 71b7de4e10
commit b303f8758a
No known key found for this signature in database
GPG Key ID: 1BE5172E637709C2
6 changed files with 25 additions and 30 deletions

@ -290,7 +290,8 @@ velocity_hist_count | `float` | 3 | The number of previous history values to
init_velocity | `float` | 0.25 | The maximum random initial velocity of a snowball for each component of the velocity vector. init_velocity | `float` | 0.25 | The maximum random initial velocity of a snowball for each component of the velocity vector.
scale_iterations | `float` | 0.04 | How much to scale erosion by as time goes on. Higher values mean that any given snowball will erode more later on as more steps pass. scale_iterations | `float` | 0.04 | How much to scale erosion by as time goes on. Higher values mean that any given snowball will erode more later on as more steps pass.
maxdiff | `float` | 0.4 | The maximum difference in height (between 0 and 1) that is acceptable as a percentage of the defined region's height. maxdiff | `float` | 0.4 | The maximum difference in height (between 0 and 1) that is acceptable as a percentage of the defined region's height.
count | `float` | 50000 | The number of snowballs to simulate. count | `float` | 25000 | The number of snowballs to simulate.
noconv | any | n/a | When set to any value, disables to automatic 3x3 gaussian convolution.
If you find any good combinations of these parameters, please [open an issue](https://github.com/sbrl/Minetest-WorldEditAdditions/issues/new) (or a PR!) and let me know! I'll include good combinations here. If you find any good combinations of these parameters, please [open an issue](https://github.com/sbrl/Minetest-WorldEditAdditions/issues/new) (or a PR!) and let me know! I'll include good combinations here.

@ -20,23 +20,21 @@ function worldeditadditions.erode.run(pos1, pos2, algorithm, params)
-- print("[erode.run] algorithm: "..algorithm..", params:"); -- print("[erode.run] algorithm: "..algorithm..", params:");
-- print(worldeditadditions.map_stringify(params)) -- print(worldeditadditions.map_stringify(params))
worldeditadditions.print_2d(heightmap, heightmap_size[1]) -- worldeditadditions.print_2d(heightmap, heightmap_size[1])
local success, msg, stats
if algorithm == "snowballs" then if algorithm == "snowballs" then
local success, msg = worldeditadditions.erode.snowballs(heightmap, heightmap_eroded, heightmap_size, region_height, params) success, msg = worldeditadditions.erode.snowballs(heightmap, heightmap_eroded, heightmap_size, region_height, params)
if not success then return success, msg end if not success then return success, msg end
else else
return false, "Error: Unknown algorithm '"..algorithm.."'. Currently implemented algorithms: snowballs (2d; hydraulic-like). Ideas for algorithms to implement are welcome!" return false, "Error: Unknown algorithm '"..algorithm.."'. Currently implemented algorithms: snowballs (2d; hydraulic-like). Ideas for algorithms to implement are welcome!"
end end
local success, stats = worldeditadditions.apply_heightmap_changes( success, stats = worldeditadditions.apply_heightmap_changes(
pos1, pos2, area, data, pos1, pos2, area, data,
heightmap, heightmap_eroded, heightmap_size heightmap, heightmap_eroded, heightmap_size
) )
if not success then return success, stats end if not success then return success, stats end
worldedit.manip_helpers.finish(manip, data) worldedit.manip_helpers.finish(manip, data)
print("[erode] stats") return true, msg, stats
print(worldeditadditions.map_stringify(stats))
return true, stats
end end

@ -84,14 +84,13 @@ function worldeditadditions.erode.snowballs(heightmap_initial, heightmap, height
init_velocity = 0.25, init_velocity = 0.25,
scale_iterations = 0.04, scale_iterations = 0.04,
maxdiff = 0.4, maxdiff = 0.4,
count = 50000 count = 25000
} }
-- Apply the default settings -- Apply the default settings
worldeditadditions.table_apply(params_custom, params) worldeditadditions.table_apply(params_custom, params)
print("[erode/snowballs] params: ") -- print("[erode/snowballs] params: ")
print(worldeditadditions.map_stringify(params)) -- print(worldeditadditions.map_stringify(params))
local normals = worldeditadditions.calculate_normals(heightmap, heightmap_size) local normals = worldeditadditions.calculate_normals(heightmap, heightmap_size)
@ -111,7 +110,7 @@ function worldeditadditions.erode.snowballs(heightmap_initial, heightmap, height
if not success then return false, "Error: Failed at snowball "..i..":"..steps end if not success then return false, "Error: Failed at snowball "..i..":"..steps end
end end
print("[snowballs] "..#stats_steps.." snowballs simulated, max "..params.max_steps.." steps, averaged ~"..worldeditadditions.average(stats_steps).."") -- print("[snowballs] "..#stats_steps.." snowballs simulated, max "..params.max_steps.." steps, averaged ~"..worldeditadditions.average(stats_steps).."")
-- Round everything to the nearest int, since you can't really have -- Round everything to the nearest int, since you can't really have
-- something like .141592671 of a node -- something like .141592671 of a node
@ -130,14 +129,16 @@ function worldeditadditions.erode.snowballs(heightmap_initial, heightmap, height
end end
end end
local success, matrix = worldeditadditions.get_conv_kernel("gaussian", 3, 3) if not params.noconv then
if not success then return success, matrix end local success, matrix = worldeditadditions.get_conv_kernel("gaussian", 3, 3)
matrix_size = {} matrix_size[0] = 3 matrix_size[1] = 3 if not success then return success, matrix end
worldeditadditions.conv.convolve( matrix_size = {} matrix_size[0] = 3 matrix_size[1] = 3
heightmap, heightmap_size, worldeditadditions.conv.convolve(
matrix, heightmap, heightmap_size,
matrix_size matrix,
) matrix_size
)
end
return true, params.count.." snowballs simulated" return true, ""..#stats_steps.." snowballs simulated, max "..params.max_steps.." steps (average ~"..worldeditadditions.average(stats_steps)..")"
end end

@ -21,10 +21,7 @@ end
-- @param source table The source to take values from -- @param source table The source to take values from
-- @param target table The target to write values to -- @param target table The target to write values to
function worldeditadditions.table_apply(source, target) function worldeditadditions.table_apply(source, target)
print("[table_apply] start")
for key, value in pairs(source) do for key, value in pairs(source) do
print("[table_apply] Applying", key, "=", value)
target[key] = value target[key] = value
end end
print("[table_apply] end")
end end

@ -23,7 +23,6 @@ worldedit.register_command("convolve", {
end end
if #parts >= 2 then if #parts >= 2 then
local parts_dimension = worldeditadditions.split(parts[2], ",%s*", false) local parts_dimension = worldeditadditions.split(parts[2], ",%s*", false)
print("[convolve] [str]width", parts_dimension[1], "[str]height", parts_dimension[2])
width = tonumber(parts_dimension[1]) width = tonumber(parts_dimension[1])
if not width then if not width then
return false, "Error: Invalid width (it must be a positive odd integer)." return false, "Error: Invalid width (it must be a positive odd integer)."
@ -52,7 +51,6 @@ worldedit.register_command("convolve", {
func = function(name, kernel_name, kernel_width, kernel_height, sigma) func = function(name, kernel_name, kernel_width, kernel_height, sigma)
local start_time = worldeditadditions.get_ms_time() local start_time = worldeditadditions.get_ms_time()
print("[exec] kernel_width", kernel_width, "kernel_height", kernel_height)
local success, kernel = worldeditadditions.get_conv_kernel(kernel_name, kernel_width, kernel_height, sigma) local success, kernel = worldeditadditions.get_conv_kernel(kernel_name, kernel_width, kernel_height, sigma)
if not success then return success, kernel end if not success then return success, kernel end

@ -31,14 +31,14 @@ worldedit.register_command("erode", {
end, end,
func = function(name, algorithm, params) func = function(name, algorithm, params)
local start_time = worldeditadditions.get_ms_time() local start_time = worldeditadditions.get_ms_time()
local success, stats = worldeditadditions.erode.run( local success, msg, stats = worldeditadditions.erode.run(
worldedit.pos1[name], worldedit.pos2[name], worldedit.pos1[name], worldedit.pos2[name],
algorithm, params algorithm, params
) )
if not success then return success, stats end if not success then return success, msg end
local time_taken = worldeditadditions.get_ms_time() - start_time local time_taken = worldeditadditions.get_ms_time() - start_time
minetest.log("action", name .. " used //erode "..algorithm.." at " .. worldeditadditions.vector.tostring(worldedit.pos1[name]) .. ", adding " .. stats.added .. " nodes and removing " .. stats.removed .. " nodes in " .. time_taken .. "s") minetest.log("action", name .. " used //erode "..algorithm.." at " .. worldeditadditions.vector.tostring(worldedit.pos1[name]) .. ", adding " .. stats.added .. " nodes and removing " .. stats.removed .. " nodes in " .. time_taken .. "s")
return true, stats.added .. " nodes added and " .. stats.removed .. " nodes removed in " .. worldeditadditions.human_time(time_taken) return true, msg.."\n"..stats.added .. " nodes added and " .. stats.removed .. " nodes removed in " .. worldeditadditions.human_time(time_taken)
end end
}) })