diff --git a/worldeditadditions/lib/convolution/convolution.lua b/worldeditadditions/lib/convolution/convolution.lua index 75fa928..9e21276 100644 --- a/worldeditadditions/lib/convolution/convolution.lua +++ b/worldeditadditions/lib/convolution/convolution.lua @@ -12,7 +12,7 @@ dofile(worldeditadditions.modpath.."/lib/conv/convolve.lua") -- @param width number The width of the kernel to create (must be an odd integer). -- @param height number The height of the kernel to create (must be an odd integer). -- @param arg number The argument to pass when creating the kernel. Currently only used by gaussian kernel as the sigma value. -function worldeditadditions.get_kernel(name, width, height, arg) +function worldeditadditions.get_conv_kernel(name, width, height, arg) if width % 2 ~= 1 then return false, "Error: The width must be an odd integer."; end @@ -33,6 +33,8 @@ function worldeditadditions.get_kernel(name, width, height, arg) local success, result = worldeditadditions.conv.kernel_gaussian(width, arg) return success, result end + + return false, "Error: Unknown kernel. Valid values: box, pascal, gaussian" end diff --git a/worldeditadditions_commands/commands/convolve.lua b/worldeditadditions_commands/commands/convolve.lua new file mode 100644 index 0000000..7966143 --- /dev/null +++ b/worldeditadditions_commands/commands/convolve.lua @@ -0,0 +1,74 @@ +-- ██████ ██████ ███ ██ ██ ██ ██████ ██ ██ ██ ███████ +-- ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ █████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ██████ ██████ ██ ████ ████ ██████ ███████ ████ ███████ +worldedit.register_command("convolve", { + params = " [[,]] []", + description = "Advanced version of //smooth from we_env. Convolves over the defined region with the given kernel. Possible kernels: box, pascal, gaussian. The width & height (if specified) must be odd integers. If the height is not specified, it defaults to the width. gaussian should give the smoothest result, but the width & height must be identical. The sigma value is only applicable to gaussian kernels.", + privs = { worldedit = true }, + require_pos = 2, + parse = function(params_text) + if not params_text or params_text == "" then + return false, "Error: No arguments specified" + end + + local parts = worldeditadditions.split(params_text, "%s+", false) + + local kernel_name = "gaussian" + local width = 5 + local height = 5 + local sigma = nil + + if #parts >= 1 then + kernel_name = parts[1] + end + if #parts >= 2 then + local parts_dimension = worldeditadditions.split(parts[2], ",%s*", false) + width = tonumber(parts[1]) + if not width then + return false, "Error: Invalid width (it must be a positive odd integer)." + end + if #parts_dimension >= 2 then + height = tonumber(parts[2]) + if not height then + return false, "Error: Invalid height (it must be a positive odd integer)." + end + else + height = width + end + end + if #parts >= 3 then + sigma = tonumber(parts[3]) + if not sigma then + return false, "Error: Invalid sigma value (it must be a valid number - floating point numbers are allowed)" + end + end + + return true, kernel_name, math.floor(width), math.floor(height), sigma + end, + nodes_needed = function(name) + return worldedit.volume(worldedit.pos1[name], worldedit.pos2[name]) + end, + func = function(kernel_name, kernel_width, kernel_height, sigma) + local start_time = os.clock() + + local success, kernel = worldeditadditions.get_conv_kernel(kernel_name, kernel_width, kernel_height, sigma) + if not success then return success, kernel end + + local kernel_size = {} + kernel_size[0] = kernel_height + kernel_size[1] = kernel_width + + local success, stats = worldeditadditions.convolve( + worldedit.pos1[name], worldedit.pos2[name], + kernel, kernel_size + ) + + local time_taken = os.clock() - start_time + + + minetest.log("action", name.." used //convolve at "..worldeditadditions.vector.tostring(worldedit.pos1[name]).." - "..worldeditadditions.vector.tostring(worldedit.pos2[name])..", adding "..stats.added.." nodes and removing "..stats.removed.." nodes in "..time_taken.."s") + return true, "Added "..stats.added.." and removed "..stats.removed.." nodes" + end +}) diff --git a/worldeditadditions_commands/init.lua b/worldeditadditions_commands/init.lua index b052f08..3104fa3 100644 --- a/worldeditadditions_commands/init.lua +++ b/worldeditadditions_commands/init.lua @@ -24,6 +24,7 @@ dofile(we_c.modpath.."/commands/torus.lua") dofile(we_c.modpath.."/commands/walls.lua") dofile(we_c.modpath.."/commands/maze.lua") dofile(we_c.modpath.."/commands/replacemix.lua") +dofile(we_c.modpath.."/commands/convolve.lua") dofile(we_c.modpath.."/commands/count.lua") @@ -31,5 +32,5 @@ dofile(we_c.modpath.."/commands/count.lua") if minetest.get_modpath("bonemeal") then dofile(we_c.modpath.."/commands/bonemeal.lua") else - minetest.log("action", "[WorldEditAdditions] bonemeal mod not detected: //bonemeal command not registered") + minetest.log("action", "[WorldEditAdditions] bonemeal mod not detected: //bonemeal command not registered (if you see this message and you're using an alternative mod that provides bonemeal, please get in touch by opening an issue)") end