An editable voxel volume returned by datumhue.voxel.new. Cells are 0-based (x, y, z) integer coordinates; each cell holds a 0-based palette index, where 0 is air (empty).
Whether the volume carries a static physics body whose collider matches its cells, following every edit; collisions and physics queries name that body as this handle. Assign a boolean to toggle.
volume:palette(1, { color = datumhue.color("#e69875") })
-- 0-based cells: x and z run 0..15 here, y 0..7.
volume:set(0, 0, 0, 1)
volume:set(15, 7, 15, 1)
Raycast through the volume with a scene-space ray (the volume's position, rotation, and cell size are accounted for). Returns the hit cell, or nil.
Example
volume:fill(0, 0, 0, 15, 0, 15, 1)
-- A scene-space ray down onto cell (0, 0, 0), whose top is at y = 1.local from = datumhue.math.vec3(-7.5, 5, -7.5)
local ray = datumhue.math.ray(from, datumhue.math.vec3(0, -1, 0))
local hit = volume:raycast(ray)
print(hit.x, hit.y, hit.z, hit.material) --> 0 0 0 1print(hit.distance, hit.normal) --> 4.0 vec3(0.0, 1.0, 0.0)
volume:palette(1, { color = datumhue.color("#a7c080") })
-- Both corners are included: a floor of 16 x 1 x 16 cells.
volume:fill(0, 0, 0, 15, 0, 15, 1)
print(volume:count(1)) --> 256
Bind a tile atlas to the volume; palette entries then pick tiles with texture / frames. The atlas image must carry readable pixel data. Binding replaces any previous atlas; a material set with set_material takes precedence over block textures.
Voxel:clear
method
Voxel:clear()
Reset every cell to air.
Voxel:count
method
Voxel:count(material?: integer) -> integer
Count cells holding material, or every non-air cell when omitted.
Example
volume:fill(0, 0, 0, 3, 0, 3, 1)
volume:set(0, 1, 0, 2)
-- Every solid cell, or the cells of one palette index.print(volume:count(), volume:count(2)) --> 17 1
Set the material for the volume's solid surfaces: a standard Material, or a Shader, whose color the surfaces show unlit. Transparent and emissive faces keep their built-in rendering.
Example
-- A Material or a Shader for every solid face.local stone = datumhue.material.standard({
color = datumhue.color("#859289"),
roughness = 0.9,
})
volume:set_material(stone)
volume:fill(0, 0, 0, 15, 1, 15, 1)
Voxel:capture
method
Voxel:capture() -> integer
Snapshot the current cells as an animation frame; returns the frame's 1-based index for play.
Play captured frames as a flip-book, swapping the volume's cells on the fps clock; the first frame applies immediately. Cell edits made while playing are overwritten at the next swap.
Example
volume:set(8, 0, 8, 1)
local lit = volume:capture()
volume:set(8, 0, 8, 0)
local dark = volume:capture()
-- Frames are the 1-based indices capture returned.
volume:play({ frames = { lit, dark }, fps = 2 })
print(lit, dark) --> 1 2
Set material wherever 3D noise meets the threshold over the region in one call, with no per-cell calls. Cells below the threshold are untouched.
Example
-- Solid wherever the noise at a cell is 0.2 or more.
volume:fill_noise({
sampler = datumhue.noise.simplex({ seed = 7, frequency = 0.15 }),
material = 1,
threshold = 0.2,
})
Fill each (x, z) column with material up to the height the source yields — terrain from noise, a grid, or a heightmap image in one call.
Example
-- Each column rises up to 6 cells where the noise reaches 1.
volume:heightmap({
source = datumhue.noise.perlin({ seed = 3, frequency = 0.1 }),
material = 1,
max_height = 6,
})