Add a hollowellipsoid command

This commit is contained in:
Starbeamrainbowlabs 2018-06-09 20:02:30 +01:00
parent 2fd63fcb25
commit 429beb2e52
Signed by: sbrl
GPG key ID: 1BE5172E637709C2
2 changed files with 57 additions and 12 deletions

View file

@ -1,9 +1,13 @@
--- Overlap command. Places a specified node on top of --- Overlap command. Places a specified node on top of
-- @module worldeditadditions.overlay -- @module worldeditadditions.overlay
function worldedit.ellipsoid(position, radius, target_node) function worldedit.ellipsoid(position, radius, target_node, hollow)
-- position = { x, y, z } -- position = { x, y, z }
local hollow_inner_radius = {
x = radius.x - 1,
y = radius.y - 1,
z = radius.z - 1
}
-- Fetch the nodes in the specified area -- Fetch the nodes in the specified area
-- OPTIMIZE: We should be able to calculate a more efficient box-area here -- OPTIMIZE: We should be able to calculate a more efficient box-area here
@ -30,11 +34,24 @@ function worldedit.ellipsoid(position, radius, target_node)
-- If we're inside the ellipse, then fill it in -- If we're inside the ellipse, then fill it in
local x_comp, y_comp, z_comp = x/radius.x, y/radius.y, z/radius.z local x_comp, y_comp, z_comp = x/radius.x, y/radius.y, z/radius.z
if x_comp*x_comp + y_comp*y_comp + z_comp*z_comp <= 1 then local ellipsoid_dist = x_comp*x_comp + y_comp*y_comp + z_comp*z_comp
if ellipsoid_dist <= 1 then
local place_ok = not hollow;
if not place_ok then
-- It must be hollow! Do some additional calculations.
local hx_comp = x/hollow_inner_radius.x
local hy_comp = y/hollow_inner_radius.y
local hz_comp = z/hollow_inner_radius.z
-- It's only ok to place it if it's outside our inner ellipse
place_ok = hx_comp*hx_comp + hy_comp*hy_comp + hz_comp*hz_comp >= 1
end
if place_ok then
data[i] = node_id data[i] = node_id
count = count + 1 count = count + 1
end
end end

View file

@ -117,13 +117,7 @@ local function parse_params_ellipsoid(params_text)
z = tonumber(radius_z) z = tonumber(radius_z)
} }
minetest.log("action", "Radius x: " .. radius_x)
minetest.log("action", "Radius y: " .. radius_y)
minetest.log("action", "Radius z: " .. radius_z)
minetest.log("action", "Raw target node: " .. replace_node)
replace_node = worldedit.normalize_nodename(replace_node) replace_node = worldedit.normalize_nodename(replace_node)
minetest.log("action", "Normalised target node: " .. replace_node)
return replace_node, radius return replace_node, radius
end end
@ -145,7 +139,7 @@ minetest.register_chatcommand("/ellipsoid", {
end end
local start_time = os.clock() local start_time = os.clock()
local replaced = worldedit.ellipsoid(worldedit.pos1[name], radius, target_node) local replaced = worldedit.ellipsoid(worldedit.pos1[name], radius, target_node, false)
local time_taken = os.clock() - start_time local time_taken = os.clock() - start_time
worldedit.player_notify(name, replaced .. " nodes replaced in " .. time_taken .. "s") worldedit.player_notify(name, replaced .. " nodes replaced in " .. time_taken .. "s")
@ -160,3 +154,37 @@ minetest.register_chatcommand("/ellipsoid", {
return math.ceil(4/3 * math.pi * radius.x * radius.y * radius.z) return math.ceil(4/3 * math.pi * radius.x * radius.y * radius.z)
end) end)
}) })
-- TODO: This duplicates a lot of code. Perhaps we can trim it down a bit?
minetest.register_chatcommand("/hollowellipsoid", {
params = "<rx> <ry> <rz> <replace_node>",
description = "Creates a 3D hollow ellipsoid with a radius of (rx, ry, rz) at pos1, filled with <replace_node>.",
privs = { worldedit = true },
func = safe_region(function(name, params_text)
local target_node, radius = parse_params_ellipsoid(params_text)
if not target_node then
worldedit.player_notify(name, "Error: Invalid node name.")
return false
end
if not radius then
worldedit.player_notify(name, "Error: Invalid radius(es).")
return false
end
local start_time = os.clock()
local replaced = worldedit.ellipsoid(worldedit.pos1[name], radius, target_node, true)
local time_taken = os.clock() - start_time
worldedit.player_notify(name, replaced .. " nodes replaced in " .. time_taken .. "s")
minetest.log("action", name .. " used //hollowellipsoid at " .. worldeditadditions.vector.tostring(worldedit.pos1[name]) .. ", replacing " .. replaced .. " nodes in " .. time_taken .. "s")
end, function(name, params_text)
local target_node, radius = parse_params_ellipsoid(params_text)
if not target_node or not radius then
worldedit.player_notify(name, "Error: Invalid input '" .. params_text .. "'. Try '/help /ellipsoid' to learn how to use this command.")
return 0
end
return math.ceil(4/3 * math.pi * radius.x * radius.y * radius.z)
end)
})