diff --git a/worldeditadditions/lib/conv/convolution.lua b/worldeditadditions/lib/conv/convolution.lua index a31065a..eff91ab 100644 --- a/worldeditadditions/lib/conv/convolution.lua +++ b/worldeditadditions/lib/conv/convolution.lua @@ -41,6 +41,15 @@ end function worldeditadditions.convolve(pos1, pos2, kernel, kernel_size) pos1, pos2 = worldedit.sort_pos(pos1, pos2) + local border_size = {} + border_size[0] = (kernel_size[0]-1) / 2 -- height + border_size[1] = (kernel_size[1]-1) / 2 -- width + + pos1.z = pos1.z - border_size[0] + pos2.z = pos2.z + border_size[0] + pos1.x = pos1.x - border_size[1] + pos2.x = pos2.x + border_size[1] + local manip, area = worldedit.manip_helpers.init(pos1, pos2) local data = manip:get_data() @@ -52,8 +61,8 @@ function worldeditadditions.convolve(pos1, pos2, kernel, kernel_size) local heightmap_conv = worldeditadditions.shallowcopy(heightmap) local heightmap_size = {} - heightmap_size[0] = pos2.z - pos1.z - heightmap_size[1] = pos2.x - pos1.x + heightmap_size[0] = (pos2.z - pos1.z) + 1 + heightmap_size[1] = (pos2.x - pos1.x) + 1 worldeditadditions.conv.convolve( heightmap_conv, @@ -61,25 +70,46 @@ function worldeditadditions.convolve(pos1, pos2, kernel, kernel_size) kernel, kernel_size ) + + -- print("original") + -- worldeditadditions.print_2d(heightmap, (pos2.z - pos1.z) + 1) + -- print("transformed") + -- worldeditadditions.print_2d(heightmap_conv, (pos2.z - pos1.z) + 1) + -- It seems to be convolving as intended, but something's probably getting lost in translation below + for z = heightmap_size[0], 0, -1 do for x = heightmap_size[1], 0, -1 do local hi = z*heightmap_size[1] + x - local diff = heightmap_conv[hi] - heightmap[hi] + + + local height_old = heightmap[hi] + local height_new = heightmap_conv[hi] + -- print("[conv/save] hi", hi, "height_old", heightmap[hi], "height_new", heightmap_conv[hi], "z", z, "x", x, "pos1.y", pos1.y) -- Lua doesn't have a continue statement :-/ - if diff ~= 0 then + if height_old == height_new then + -- noop + elseif height_new < height_old then + stats.removed = stats.removed + (height_old - height_new) + local y = height_new + while y < height_old do + local ci = area:index(pos1.x + x, pos1.y + y, pos1.z + z) + -- print("[conv/save] remove at y", y, "→", pos1.y + y, "current:", minetest.get_name_from_content_id(data[ci])) + data[ci] = node_id_air + y = y + 1 + end + else -- height_new > height_old -- We subtract one because the heightmap starts at 1 (i.e. 1 = 1 node in the column), but the selected region is inclusive - local node_id = data[area:index(pos1.x + x, pos1.y + (heightmap[hi] - 1), pos1.z + z)] - if diff > 0 then - stats.added = stats.added + diff - for y = pos1.y + heightmap[hi], pos1.y + heightmap_conv[hi], 1 do - data[area:index(pos1.x + x, y, pos1.z + z)] = node_id - end - else - stats.removed = stats.removed + math.abs(diff) - for y = pos1.y + heightmap_conv[hi], pos1.y + heightmap[hi], 1 do - data[area:index(pos1.x + x, y, pos1.z + z)] = node_id_air - end + local node_id = data[area:index(pos1.x + x, pos1.y + (height_old - 1), pos1.z + z)] + -- print("[conv/save] filling with ", node_id, "→", minetest.get_name_from_content_id(node_id)) + + stats.added = stats.added + (height_new - height_old) + local y = height_old + while y < height_new do + local ci = area:index(pos1.x + x, pos1.y + y, pos1.z + z) + -- print("[conv/save] add at y", y, "→", pos1.y + y, "current:", minetest.get_name_from_content_id(data[ci])) + data[ci] = node_id + y = y + 1 end end end diff --git a/worldeditadditions/lib/conv/convolve.lua b/worldeditadditions/lib/conv/convolve.lua index 3e6243c..3b1bb70 100644 --- a/worldeditadditions/lib/conv/convolve.lua +++ b/worldeditadditions/lib/conv/convolve.lua @@ -18,31 +18,40 @@ function worldeditadditions.conv.convolve(heightmap, heightmap_size, matrix, mat border_size[1] = (matrix_size[1]-1) / 2 -- width print("[convolve] matrix_size", matrix_size[0], matrix_size[1]) print("[convolve] border_size", border_size[0], border_size[1]) + print("[convolve] heightmap_size: ", heightmap_size[0], heightmap_size[1]) + + print("[convolve] z: from", (heightmap_size[0]-border_size[0]) - 1, "to", border_size[0], "step", -1) + print("[convolve] x: from", (heightmap_size[1]-border_size[1]) - 1, "to", border_size[1], "step", -1) -- Convolve over only the bit that allows us to use the full convolution matrix - for y = (heightmap_size[0]-border_size[0]) - 1, border_size[0], -1 do + for z = (heightmap_size[0]-border_size[0]) - 1, border_size[0], -1 do for x = (heightmap_size[1]-border_size[1]) - 1, border_size[1], -1 do local total = 0 - for my = matrix_size[0]-1, 0, -1 do - for mx = matrix_size[1]-1, 0, -1 do - local mi = (my * matrix_size[1]) + mx - local cy = y + (my - border_size[0]) - local cx = x + (mx - border_size[1]) - - local i = (cy * heightmap_size[1]) + cx - - -- print("[convolve] i", i, "mi", mi, "matrix[mi]", matrix[mi], "heightmap[i]", heightmap[i]) - -- A value of -1 = nothing in this column (so we should ignore it) - if heightmap[i] ~= -1 then - total = total + (matrix[mi] * heightmap[i]) + local hi = (z * heightmap_size[1]) + x + -- print("[convolve/internal] z", z, "x", x, "hi", hi) + + -- No continue statement in Lua :-/ + if heightmap[hi] ~= -1 then + for mz = matrix_size[0]-1, 0, -1 do + for mx = matrix_size[1]-1, 0, -1 do + local mi = (mz * matrix_size[1]) + mx + local cz = z + (mz - border_size[0]) + local cx = x + (mx - border_size[1]) + + local i = (cz * heightmap_size[1]) + cx + + -- A value of -1 = nothing in this column (so we should ignore it) + if heightmap[i] ~= -1 then + total = total + (matrix[mi] * heightmap[i]) + end end end + -- Rounding hack - ref https://stackoverflow.com/a/18313481/1460422 + -- heightmap[hi] = math.floor(total + 0.5) + heightmap[hi] = math.ceil(total) end - - -- Rounding hack - ref https://stackoverflow.com/a/18313481/1460422 - heightmap[(y * heightmap_size[1]) + x] = math.floor(total + 0.5) end end diff --git a/worldeditadditions/utils/strings.lua b/worldeditadditions/utils/strings.lua index 13bfce8..94fda4b 100644 --- a/worldeditadditions/utils/strings.lua +++ b/worldeditadditions/utils/strings.lua @@ -95,7 +95,7 @@ function worldeditadditions.print_2d(tbl, width) for i=0, #tbl do table.insert(next, worldeditadditions.str_padstart(tostring(tbl[i]), display_width)) if #next == width then - print(table.concat(next, "\t")) + print(table.concat(next, "")) next = {} end end