mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-12-13 09:23:22 +01:00
60 lines
2.7 KiB
Lua
60 lines
2.7 KiB
Lua
local wea_c = worldeditadditions_core
|
|
local Vector3 = wea_c.Vector3
|
|
|
|
---
|
|
-- @module worldeditadditions.sculpt
|
|
|
|
|
|
--- Applies the given brush at the given x/z position to the given heightmap.
|
|
-- Important: Where a Vector3 is mentioned in the parameter list, it reall MUST
|
|
-- be a Vector3 instance.
|
|
-- Also important: Remember that the position there is RELATIVE TO THE HEIGHTMAP'S origin (0, 0) and is on the X and Z axes!
|
|
-- @param brush table The ZERO-indexed brush to apply. Values should be normalised to be between 0 and 1.
|
|
-- @param brush_size Vector3 The size of the brush on the x/y axes.
|
|
-- @pram height number The multiplier to apply to each brush pixel value just before applying it. Negative values are allowed - this will cause a subtraction operation instead of an addition.
|
|
-- @param position Vector3 The position RELATIVE TO THE HEIGHTMAP on the x/z coordinates to centre the brush application on.
|
|
-- @param heightmap table The heightmap to apply the brush to. See worldeditadditions.make_heightmap for how to obtain one of these.
|
|
-- @param heightmap_size Vector3 The size of the aforementioned heightmap. See worldeditadditions.make_heightmap for more information.
|
|
-- @returns true,number,number|false,string If the operation was not successful, then false followed by an error message as a string is returned. If it was successful however, 3 values are returned: true, then the number of nodes added, then the number of nodes removed.
|
|
local function apply_heightmap(brush, brush_size, height, position, heightmap, heightmap_size)
|
|
-- Convert brush_size to match the scheme used in the heightmap
|
|
brush_size = brush_size:clone()
|
|
brush_size.z = brush_size.y
|
|
brush_size.y = 0
|
|
|
|
local brush_radius = (brush_size/2):ceil() - 1
|
|
local pos_start = (position - brush_radius)
|
|
:clamp(Vector3.new(0, 0, 0), heightmap_size)
|
|
local pos_end = (pos_start + brush_size)
|
|
:clamp(Vector3.new(0, 0, 0), heightmap_size)
|
|
|
|
local added = 0
|
|
local removed = 0
|
|
-- TODO: Make the strength of the brush depend on the height of the nodes in the heightmap?
|
|
|
|
-- Iterate over the heightmap and apply the brush
|
|
-- Note that we do not iterate over the brush, because we don't know if the
|
|
-- brush actually fits inside the region.... O.o
|
|
for z = pos_end.z - 1, pos_start.z, -1 do
|
|
for x = pos_end.x - 1, pos_start.x, -1 do
|
|
local hi = z*heightmap_size.x + x
|
|
local pos_brush = Vector3.new(x, 0, z) - pos_start
|
|
local bi = pos_brush.z*brush_size.x + pos_brush.x
|
|
|
|
local adjustment = math.floor(brush[bi]*height)
|
|
if adjustment > 0 then
|
|
added = added + adjustment
|
|
elseif adjustment < 0 then
|
|
removed = removed + math.abs(adjustment)
|
|
end
|
|
|
|
heightmap[hi] = heightmap[hi] + adjustment
|
|
end
|
|
end
|
|
|
|
return true, added, removed
|
|
end
|
|
|
|
|
|
return apply_heightmap
|