2022-09-19 01:18:03 +02:00
local wea_c = worldeditadditions_core
local Vector3 = wea_c.Vector3
2024-01-02 17:59:51 +01:00
---
-- @module worldeditadditions
2020-09-20 19:03:29 +02:00
-- ███████ ██ ██ ██ ██████ ███████ ███████
-- ██ ██ ██ ██ ██ ██ ██ ██
-- █████ ██ ██ ██ ██████ ███████ █████
-- ██ ██ ██ ██ ██ ██ ██
-- ███████ ███████ ███████ ██ ██ ███████ ███████
2018-06-09 14:05:09 +02:00
2021-10-13 23:50:37 +02:00
--- Fills an ellipsoidal area around the given position with the target node.
-- The resulting ellipsoid may optionally be hollow (in which case
-- nodes inside the ellipsoid are left untouched).
-- @param position Vector3 The centre position of the ellipsoid.
-- @param radius Vector3 The radius of the ellipsoid in all 3 dimensions.
-- @param target_node string The name of the node to use to fill the ellipsoid.
-- @param hollow bool Whether the ellipsoid should be hollow or not.
-- @returns number The number of nodes filled to create the (optionally hollow) ellipsoid. This number will be lower with hollow ellipsoids, since the internals of an ellipsoid aren't altered.
2020-05-11 00:29:49 +02:00
function worldeditadditions . ellipsoid ( position , radius , target_node , hollow )
2022-09-19 01:18:03 +02:00
radius = Vector3.clone ( radius )
2018-06-09 14:05:09 +02:00
-- position = { x, y, z }
2022-09-19 01:18:03 +02:00
local hollow_inner_radius = radius - 1
2018-06-09 14:05:09 +02:00
-- Fetch the nodes in the specified area
-- OPTIMIZE: We should be able to calculate a more efficient box-area here
2018-06-09 14:10:42 +02:00
local manip , area = worldedit.manip_helpers . init_radius ( position , math.max ( radius.x , radius.y , radius.z ) )
2018-06-09 14:05:09 +02:00
local data = manip : get_data ( )
local node_id = minetest.get_content_id ( target_node )
local stride_z , stride_y = area.zstride , area.ystride
2018-06-09 14:10:42 +02:00
local count = 0 -- The number of nodes replaced
2018-06-09 20:38:23 +02:00
local idx_z_base = area : index ( position.x - radius.x , position.y - radius.y , position.z - radius.z ) -- initial z offset
2018-06-09 14:05:09 +02:00
for z = - radius.z , radius.z do
local idx_y_base = idx_z_base
2018-06-09 14:36:25 +02:00
for y = - radius.y , radius.y do
2018-06-09 14:05:09 +02:00
local i = idx_y_base
2018-06-09 14:36:25 +02:00
for x = - radius.x , radius.x do
2022-09-19 01:18:03 +02:00
local here = Vector3.new ( x , y , z )
2018-06-09 14:05:09 +02:00
-- If we're inside the ellipse, then fill it in
2022-09-19 01:18:03 +02:00
local comp = here / radius
local ellipsoid_dist = Vector3.dot ( comp , comp )
2018-06-09 21:02:30 +02:00
if ellipsoid_dist <= 1 then
local place_ok = not hollow ;
2018-06-09 20:35:32 +02:00
2018-06-09 21:02:30 +02:00
if not place_ok then
-- It must be hollow! Do some additional calculations.
2022-09-19 01:18:03 +02:00
local h_comp = here / hollow_inner_radius
2018-06-09 21:02:30 +02:00
-- It's only ok to place it if it's outside our inner ellipse
2022-09-19 01:18:03 +02:00
place_ok = Vector3.dot ( h_comp , h_comp ) >= 1
2018-06-09 21:02:30 +02:00
end
2018-06-09 20:35:32 +02:00
2018-06-09 21:02:30 +02:00
if place_ok then
data [ i ] = node_id
count = count + 1
end
2018-06-09 14:05:09 +02:00
end
i = i + 1
end
2018-06-09 14:36:25 +02:00
idx_y_base = idx_y_base + stride_y
2018-06-09 14:05:09 +02:00
end
2018-06-09 14:36:25 +02:00
idx_z_base = idx_z_base + stride_z
2018-06-09 14:05:09 +02:00
end
-- Save the modified nodes back to disk & return
worldedit.manip_helpers . finish ( manip , data )
2018-06-09 14:10:42 +02:00
return count
2018-06-09 14:05:09 +02:00
end