VoxelArea

The VoxelArea metatable provides an OOP-like utility for dealing with LuaVoxelManip (specifically, for doing the index math).

VoxelArea.new(self, o)

Sets self.__index to self and self as the metatable of o, which can have the following fields:

  • MinEdge: Minimum position of the area, inclusive. Defaults to vector.new(1, 1, 1) if nil.
  • MaxEdge: Maximum position of the area, inclusive. Defaults to vector.new(0, 0, 0) if nil.

Both positions should be vectors of integer numbers; each component of MinEdge should be smaller than the respective component of MaxEdge if the VoxelArea is to be non-empty. You can use minp, maxp = vector.sort(minp, maxp) to achieve this.

Calculates ystride and zstride and stores both in o.

Common usage:

local voxelmanip = minetest.get_voxel_manip(pos_min, pos_max)
local emin, emax = voxelmanip:read_from_map(pos_min, pos_max)
local voxelarea = VoxelArea:new{ MinEdge = emin, MaxEdge = emax }

WARNING: Always pass the actual emerged min & max positions. Do not pass the desired min & max positions.

WARNING: Never pass fractional values as min- or max edge.

TIP: You can use vector.floor, vector.round or vector.apply(vec, math.ceil) to guarantee integer values.

The following methods can both be called in an imperative manner (VoxelArea.<method>(self, ...)) or an OOP manner (recommended): self:<method>(...). The below examples are documented using the latter style, where area is a valid table with VoxelArea as the metatable.

area:getExtent()

Returns the dimensions of area as integer vector.

area:getVolume()

Returns the volume of area as integer.

area:index(x, y, z)

x, y, z are absolute coordinates of a node within the area. Returns an integer index to be used for data tables returned by VoxelManip objects.

WARNING: This will silently floor the returned index instead of throwing an error. Make sure that the coordinates you pass are (1) not fractional and (2) within the area.

area:indexp(p)

Shorthand for area:index(p.x, p.y, p.z).

area:position(index)

Inverse to area:indexp. Returns the absolute node position corresponding to the index as a table with x, y and z fields.

TIP: The returned table is missing the vector metatable. If it is not performance-critical, use p = vector.new(area:position(index)) to create a copied vector with metatable.

area:contains(x, y, z)

Returns true if all x, y, z coordinates are between the respective MinEdge and MaxEdge coordinates, both inclusive.

area:containsp(p)

Shorthand for area:contains(p.x, p.y, p.z)

area:containsi(i)

Returns true if i is between 1 and the area volume, both inclusive.

WARNING: area:containsi(area:indexp(p)) is not equivalent to area:containsp(p), as area:indexp will happily produce valid indices for some out-of-area positions.

area:iter(minx, miny, minz, maxx, maxy, maxz)

Returns an iterator (a function that returns the index of the current position and advances to the next one) that iterates in XYZ order (first incrementing X until the line has been finished, then Y until the plane has been finished, then Z until the cuboid has been finished).

area:iterp(minp, maxp)

Shorthand for area:iter(minp.x, minp.y, minp.z, maxp.x, maxp.y, maxp.z).

Example:

for index in area:iterp(pos_min, pos_max) do
    content_id_data[index] = ...
end

which is equivalent to (but shorter & faster than):

for z = pos_min.z, pos_max.z do
    for y = pos_min.y, pos_max.y do
        for x = pos_min.x, pos_max.x do
            local index = area:index(x, y, z)
            content_id_data[index] = ...
        end
    end
end

This article is originally based on an article from the minetest_docs project: VoxelArea.adoc by Lars Müller, licensed under CC-BY 4.0