From 2a90a1d235182c7dd81e094c3f03ed983f0ce39c Mon Sep 17 00:00:00 2001 From: HybridDog Date: Wed, 12 Feb 2020 19:35:51 +0100 Subject: [PATCH] Add a hollowcuboid iteration helper --- worldedit/common.lua | 69 ++++++++++++++++++++++++++++++++++++++++ worldedit/primitives.lua | 32 ++++++++----------- 2 files changed, 82 insertions(+), 19 deletions(-) diff --git a/worldedit/common.lua b/worldedit/common.lua index 71b43eb..2617985 100644 --- a/worldedit/common.lua +++ b/worldedit/common.lua @@ -122,3 +122,72 @@ function mh.finish(manip, data) manip:update_map() end + +-- returns an iterator that returns voxelarea indices for a hollow cuboid +function mh.iter_hollowcuboid(area, minx, miny, minz, maxx, maxy, maxz) + local i = area:index(minx, miny, minz) - 1 + local xrange = maxx - minx + 1 + local nextaction = i + 1 + xrange + local do_hole = false + + local y = 0 + local ydiff = maxy - miny + local ystride = area.ystride + local ymultistride = ydiff * ystride + + local z = 0 + local zdiff = maxz - minz + local zstride = area.zstride + local zcorner = true + + return function() + -- continue i until it needs to jump ystride + i = i + 1 + if i ~= nextaction then + return i + end + + -- add the x offset if y (and z) are not 0 or maxy (or maxz) + if do_hole then + do_hole = false + i = i + xrange - 2 + nextaction = i + 1 + return i + end + + -- continue y until maxy is exceeded + y = y+1 + if y ~= ydiff + 1 then + i = i + ystride - xrange + if zcorner + or y == ydiff then + nextaction = i + xrange + else + nextaction = i + 1 + do_hole = true + end + return i + end + + -- continue z until maxz is exceeded + z = z+1 + if z == zdiff + 1 then + -- hollowcuboid finished, return nil + return + end + + -- set i to index(minx, miny, minz + z) - 1 + i = i + zstride - (ymultistride + xrange) + zcorner = z == zdiff + + -- y is 0, so traverse the xs + y = 0 + nextaction = i + xrange + return i + end +end + +function mh.iterp_hollowcuboid(area, minp, maxp) + return mh.iter_hollowcuboid(area, minp.x, minp.y, minp.z, + maxp.x, maxp.y, maxp.z) +end diff --git a/worldedit/primitives.lua b/worldedit/primitives.lua index fee1682..4c86c3f 100644 --- a/worldedit/primitives.lua +++ b/worldedit/primitives.lua @@ -14,31 +14,25 @@ local mh = worldedit.manip_helpers -- @return The number of nodes added. function worldedit.cube(pos, width, height, length, node_name, hollow) -- Set up voxel manipulator - local basepos = vector.subtract(pos, {x=math.floor(width/2), y=0, z=math.floor(length/2)}) - local manip, area = mh.init(basepos, vector.add(basepos, {x=width, y=height, z=length})) + local basepos = vector.subtract(pos, + {x = math.floor(width / 2), y = 0, z = math.floor(length / 2)}) + local endpos = vector.add(basepos, {x=width, y=height, z=length}) + local manip, area = mh.init(basepos, endpos) local data = mh.get_empty_data(area) -- Add cube local node_id = minetest.get_content_id(node_name) - local stride = vector.new(1, area.ystride, area.zstride) - local offset = vector.subtract(basepos, area.MinEdge) local count = 0 + local iterfunc + if hollow then + iterfunc = mh.iterp_hollowcuboid(area, basepos, endpos) + else + iterfunc = area:iter(basepos, endpos) + end - for z = 0, length-1 do - local index_z = (offset.z + z) * stride.z + 1 -- +1 for 1-based indexing - for y = 0, height-1 do - local index_y = index_z + (offset.y + y) * stride.y - for x = 0, width-1 do - local is_wall = z == 0 or z == length-1 - or y == 0 or y == height-1 - or x == 0 or x == width-1 - if not hollow or is_wall then - local i = index_y + (offset.x + x) - data[i] = node_id - count = count + 1 - end - end - end + for vi in iterfunc do + data[vi] = node_id + count = count+1 end mh.finish(manip, data)