← Back to Documentation Index

🧱 Voxel Engine

Minecraft-style voxel world with greedy meshing, lighting, fluids, entities, ECS, schematics, and custom block shapes

📋 Overview

The Nova64 Voxel Engine provides a complete block-world system rivaling noa-engine, with 50+ API functions.

💡 Key Features
  • Chunk System — 16×128×16 chunks with configurable render distance and async loading
  • Greedy Meshing — True greedy mesher with per-vertex ambient occlusion
  • Lighting — BFS sky light + block light propagation, day/night cycle
  • 36 Block Types — Cubes, slabs, stairs, fences, cross shapes (flowers/grass)
  • Fluid Simulation — Water/lava with BFS flow and retraction
  • Entity System — Spawn, damage, heal entities with AI callbacks and spatial hashing
  • ECS Components — Attach/query arbitrary components, archetypes, A* pathfinding
  • Schematics — Export/import regions and worlds (RLE compressed)
  • Custom Block Shapes — Slabs, stairs, fences, cross shapes with shape-aware collision
  • LOD System — Automatic level-of-detail for distant chunks
  • Texture Atlas — 27 procedural pixel-art tiles, custom atlas support
  • World Persistence — Save/load worlds via IndexedDB
  • DDA Raycasting — Pixel-perfect block targeting
  • Swept AABB Physics — Per-axis collision, auto-step, swimming

📦 Block Types

Standard Cube Blocks (0–25)

ConstantIDDescription
BLOCK_TYPES.AIR0Empty space
BLOCK_TYPES.GRASS1Grass block
BLOCK_TYPES.DIRT2Dirt
BLOCK_TYPES.STONE3Stone
BLOCK_TYPES.SAND4Sand
BLOCK_TYPES.WATER5Water (transparent, fluid)
BLOCK_TYPES.WOOD6Wood log
BLOCK_TYPES.LEAVES7Leaves (transparent)
BLOCK_TYPES.COBBLESTONE8Cobblestone
BLOCK_TYPES.PLANKS9Wooden planks
BLOCK_TYPES.GLASS10Glass (transparent)
BLOCK_TYPES.BRICK11Brick
BLOCK_TYPES.SNOW12Snow
BLOCK_TYPES.ICE13Ice (transparent)
BLOCK_TYPES.BEDROCK14Bedrock (indestructible)
BLOCK_TYPES.COAL_ORE15Coal ore
BLOCK_TYPES.IRON_ORE16Iron ore
BLOCK_TYPES.GOLD_ORE17Gold ore
BLOCK_TYPES.DIAMOND_ORE18Diamond ore
BLOCK_TYPES.GRAVEL19Gravel
BLOCK_TYPES.CLAY20Clay
BLOCK_TYPES.TORCH21Torch (light emitter, non-solid)
BLOCK_TYPES.GLOWSTONE22Glowstone (max light)
BLOCK_TYPES.LAVA23Lava (fluid, light emitter)
BLOCK_TYPES.OBSIDIAN24Obsidian
BLOCK_TYPES.MOSSY_COBBLESTONE25Mossy cobblestone

Shape Blocks (26–35)

ConstantIDShapeDescription
BLOCK_TYPES.STONE_SLAB26slab_bottomHalf-height stone slab
BLOCK_TYPES.STONE_SLAB_TOP27slab_topUpper half stone slab
BLOCK_TYPES.PLANK_SLAB28slab_bottomHalf-height plank slab
BLOCK_TYPES.STONE_STAIR29stairStone staircase
BLOCK_TYPES.PLANK_STAIR30stairPlank staircase
BLOCK_TYPES.FENCE31fenceThin fence post
BLOCK_TYPES.FLOWER32crossFlower (non-solid)
BLOCK_TYPES.TALL_GRASS33crossTall grass (non-solid)
BLOCK_TYPES.BRICK_SLAB34slab_bottomHalf-height brick slab
BLOCK_TYPES.BRICK_STAIR35stairBrick staircase

🌍 World Management

configureVoxelWorld(options)

Configure world generation parameters. Call before generating chunks.

options.seed number — World seed for deterministic generation
options.chunkHeight number — Vertical chunk size (default: 128)
options.renderDistance number — Chunks in each direction (default: 4)
options.seaLevel number — Water level (default: 62)
options.generateTerrain function — Custom terrain generator callback
options.lodLevels array — LOD distance thresholds [lod0Max, lod1Max]
Example:
configureVoxelWorld({
  seed: 42,
  renderDistance: 6,
  seaLevel: 62,
  lodLevels: [4, 8],
  generateTerrain: (chunk, ctx) => {
    // Custom flat world
    for (let x = 0; x < ctx.CHUNK_SIZE; x++)
      for (let z = 0; z < ctx.CHUNK_SIZE; z++)
        for (let y = 0; y < 60; y++)
          chunk.setBlock(x, y, z, ctx.BLOCK_TYPES.STONE);
  },
});
updateVoxelWorld(playerX, playerZ)

Load/unload chunks around the player. Call periodically in update().

Example:
if (frameCount % 10 === 0) updateVoxelWorld(player.x, player.z);
forceLoadVoxelChunks(playerX, playerZ)

Synchronously load all chunks in render distance. Useful for initial world setup in init().

resetVoxelWorld()

Clear all chunks, entities, and meshes. Resets world to empty state.

getVoxelConfig()

Returns the current world configuration object.

🧱 Block Operations

getVoxelBlock(x, y, z)

Get the block type at world coordinates.

Returns: number — Block type ID (0 = AIR)
setVoxelBlock(x, y, z, blockType)

Place or remove a block. Automatically updates chunk meshes and propagates lighting.

Example:
setVoxelBlock(10, 65, 10, BLOCK_TYPES.STONE);    // Place stone
setVoxelBlock(10, 65, 10, BLOCK_TYPES.AIR);      // Remove block
setVoxelBlock(5, 60, 5, BLOCK_TYPES.STONE_SLAB); // Place slab
getVoxelHighestBlock(x, z)

Returns the Y of the highest non-air, non-water block at (x, z). Useful for spawning.

getVoxelBiome(x, z)

Returns the biome name at world position. One of: "Frozen Tundra", "Taiga", "Desert", "Jungle", "Savanna", "Forest", "Snowy Hills", "Plains".

registerVoxelBlock(id, options)

Register a custom block type for your cart.

id number — Block ID (use 100+ for custom)
options.name string — Block name
options.color number — Hex color
options.solid boolean — Is solid for collision (default: true)
options.transparent boolean — Render in transparent pass
options.fluid boolean — Is fluid (water/lava behavior)
options.lightEmit number — Light emission 0–15
options.lightBlock number — Light blocking 0–15
options.shape string — Shape type (default: 'cube')
options.boundingBox array — [minX, minY, minZ, maxX, maxY, maxZ] (0–1)
Example:
registerVoxelBlock(100, {
  name: 'crystal',
  color: 0xff00ff,
  solid: true,
  transparent: true,
  lightEmit: 10,
  shape: 'slab_bottom',
});

🔷 Custom Block Shapes

Blocks can have non-cube shapes. Non-cube shapes skip greedy mesh merging and emit custom geometry. They do not occlude neighboring cube faces. Collision uses shape-specific bounding boxes.

ShapeGeometryBounding Box
cubeFull block (default)[0,0,0, 1,1,1]
slab_bottomHalf-height box, bottom[0,0,0, 1,0.5,1]
slab_topHalf-height box, top[0,0.5,0, 1,1,1]
stairBottom slab + back upper half[0,0,0, 1,1,1]
fenceThin centered post[0.375,0,0.375, 0.625,1,0.625]
crossTwo diagonal X-quads[0.15,0,0.15, 0.85,1,0.85]
getVoxelBlockShape(blockId)

Returns the shape string for a block type.

Returns: string — 'cube', 'slab_bottom', 'slab_top', 'stair', 'cross', or 'fence'
getVoxelBlockBoundingBox(blockId)

Returns the collision bounding box [minX, minY, minZ, maxX, maxY, maxZ] relative to block origin (0–1 range).

isVoxelBlockFullCube(blockId)

Returns true if the block shape is 'cube'. Non-cube blocks don't occlude neighbor faces.

🎯 Raycasting & Collision

raycastVoxelBlock(origin, direction, maxDistance)

DDA voxel traversal — pixel-perfect block targeting. Returns hit info with block position, face normal, and adjacent block for placing.

Returns: object — { hit, position, normal, adjacent, blockType, distance }
Example:
const result = raycastVoxelBlock([px, py+1.6, pz], lookDir, 10);
if (result.hit) {
  // Break block
  setVoxelBlock(...result.position, BLOCK_TYPES.AIR);
  // Place block on adjacent face
  setVoxelBlock(...result.adjacent, BLOCK_TYPES.STONE);
}
checkVoxelCollision(position, size)

AABB collision check against solid blocks (excluding fluids). Uses shape-aware bounding boxes for non-cube blocks.

Returns: boolean — true if colliding
checkVoxelFluid(position, size)

Check if position is inside a fluid block (water/lava).

Returns: boolean — true if in fluid
moveVoxelEntity(position, velocity, size, dt)

Swept AABB physics with per-axis resolution, auto-step (0.6 blocks), water drag, and ground detection.

Returns: object — { position, velocity, grounded, hitCeiling, onIce, jumped }
Example:
const result = moveVoxelEntity(
  player.pos,
  player.vel,
  [0.6, 1.8, 0.6],  // width, height, depth
  dt
);
player.pos = result.position;
player.vel = result.velocity;
player.grounded = result.grounded;

💡 Lighting

BFS flood-fill light propagation with sky light (downward) and block light (torches, glowstone, lava). Smooth per-vertex interpolation combined with ambient occlusion.

getVoxelLightLevel(x, y, z)

Returns the light level (0–15) at a position. Max of sky light and block light.

setVoxelDayTime(t)

Set time of day (0.0–1.0). Sky light brightness scales with time for day/night cycle.

Example:
let time = 0;
export function update(dt) {
  time = (time + dt * 0.01) % 1;
  setVoxelDayTime(time); // Smooth day/night
}

🌊 Fluid Simulation

Water spreads 7 blocks horizontally with BFS flow. Lava spreads 3 blocks. Fluids retract when source is removed.

setVoxelFluidSource(x, y, z, blockType)

Place a fluid source block. Flow propagation begins automatically.

Example:
setVoxelFluidSource(10, 70, 10, BLOCK_TYPES.WATER); // Water source
setVoxelFluidSource(20, 70, 20, BLOCK_TYPES.LAVA);  // Lava source
removeVoxelFluidSource(x, y, z)

Remove a fluid source. Flowing blocks retract via BFS.

getVoxelFluidLevel(x, y, z)

Returns the fluid level at a position (0 = full, 7 = thinnest, -1 = no fluid).

👾 Entity System

Spawn entities with physics, AI, health, and spatial hashing for efficient radius queries.

spawnVoxelEntity(type, position, options?)

Spawn a new entity in the voxel world.

type string — Entity type name
position array — [x, y, z] world position
options.health number — Max health (default: 10)
options.mesh object — Three.js mesh to attach
options.size array — Collision box [w, h, d]
options.onUpdate function — AI callback (entity, dt)
Returns: object — Entity object with id, position, velocity, health
removeVoxelEntity(id)

Remove entity and its mesh from the world.

getVoxelEntity(id)

Retrieve an entity by ID.

damageVoxelEntity(id, amount) / healVoxelEntity(id, amount)

Modify entity health. Entity removed when health reaches 0.

updateVoxelEntities(dt)

Tick all entity AI callbacks and physics. Call in update().

getVoxelEntitiesInRadius(position, radius)

Find all entities within radius using spatial hash (O(1) bucket lookup).

getVoxelEntitiesByType(type) / getVoxelEntityCount()

Query entities by type or get total count.

🧩 ECS Components & Archetypes

Attach arbitrary components to entities for flexible game logic. Query by component sets. Spawn from predefined archetypes.

setVoxelEntityComponent(entityId, componentName, data)

Attach or update a component on an entity.

Example:
setVoxelEntityComponent(id, 'inventory', { slots: 10, items: [] });
setVoxelEntityComponent(id, 'hostile', { aggroRange: 16 });
getVoxelEntityComponent(entityId, componentName)

Get component data. Returns undefined if not present.

hasVoxelEntityComponent(entityId, componentName)

Check if entity has a specific component.

removeVoxelEntityComponent(entityId, componentName)

Remove a component from an entity.

queryVoxelEntities(requiredComponents, filterFn?)

Find all entities that have all required components, with optional filter function.

Example:
// All entities with 'hostile' and 'ai' components
const enemies = queryVoxelEntities(['hostile', 'ai']);

// With filter
const nearbyEnemies = queryVoxelEntities(['hostile'], e =>
  dist(e.position, player.pos) < 32
);
createVoxelEntityArchetype(name, components)

Define a reusable entity template with default components.

spawnVoxelEntityFromArchetype(archetypeName, position, overrides?)

Spawn an entity from a registered archetype. Built-in archetypes: mob, item, projectile, npc, vehicle.

Example:
const zombie = spawnVoxelEntityFromArchetype('mob', [10, 65, 10], {
  health: 20,
});
setVoxelEntityComponent(zombie.id, 'hostile', { damage: 3 });
findVoxelPath(start, end, options?)

A* pathfinding on the voxel grid. Returns an array of [x, y, z] positions, or null if no path found.

start array — [x, y, z] start position
end array — [x, y, z] target position
options.maxSteps number — Max search iterations (default: 1000)
options.entityHeight number — Entity height in blocks (default: 2)
Returns: array|null — Array of [x,y,z] waypoints, or null

📐 Schematics & World Import/Export

exportVoxelRegion(x1, y1, z1, x2, y2, z2)

Export a rectangular region as an RLE-compressed ArrayBuffer. Header: [version, sizeX, sizeY, sizeZ] + RLE body.

Returns: ArrayBuffer
importVoxelRegion(data, x, y, z, options?)

Import a schematic at the given position.

options.skipAir boolean — Don't overwrite existing blocks with air (default: false)
Returns: object — { sizeX, sizeY, sizeZ, placed }
exportVoxelWorldJSON()

Export the entire world (all loaded chunks) as a JSON object with seed, config, and chunk data.

Returns: object — { version, seed, chunks: [...] }
importVoxelWorldJSON(json)

Import a world from a previously exported JSON object. Replaces current world state.

Returns: object — { chunksLoaded }
Copy/Paste a Structure:
// Export a 10x10x10 building
const schematic = exportVoxelRegion(0, 60, 0, 9, 69, 9);

// Paste it somewhere else
importVoxelRegion(schematic, 100, 60, 100);

// Paste without overwriting existing blocks
importVoxelRegion(schematic, 200, 60, 200, { skipAir: true });

💾 World Persistence

saveVoxelWorld(name)

Save all modified chunks to IndexedDB under the given name.

loadVoxelWorld(name)

Load a previously saved world from IndexedDB.

listVoxelWorlds()

List all saved world names in IndexedDB.

Returns: Promise<string[]>
deleteVoxelWorld(name)

Delete a saved world from IndexedDB.

🎨 Texture Atlas

enableVoxelTextures(enabled?)

Toggle the procedural texture atlas (27 pixel-art tiles). Enabled: textured blocks. Disabled: vertex-color blocks.

loadVoxelTextureAtlas(url, mapping?)

Load a custom texture atlas image. Mapping defines which tile index goes to which block face.

🌊 Noise Functions

simplexNoise2D(x, z, octaves?, persistence?, lacunarity?, scale?)

Multi-octave 2D fractal simplex noise. Returns 0–1.

simplexNoise3D(x, y, z, octaves?, persistence?, lacunarity?, scale?)

Multi-octave 3D fractal simplex noise. Returns 0–1. Use for caves, ore veins, 3D effects.

🌳 Structures

placeVoxelTree(x, y, z)

Generate a tree (wood trunk + leaf canopy) at the specified base position. Biome-appropriate variety: oak, birch, spruce, jungle, acacia.

📊 API Summary

CategoryFunctions
WorldconfigureVoxelWorld, updateVoxelWorld, forceLoadVoxelChunks, resetVoxelWorld, getVoxelConfig
BlocksgetVoxelBlock, setVoxelBlock, getVoxelHighestBlock, getVoxelBiome, registerVoxelBlock
ShapesgetVoxelBlockShape, getVoxelBlockBoundingBox, isVoxelBlockFullCube, VOXEL_SHAPE_BBOXES
Raycast & CollisionraycastVoxelBlock, checkVoxelCollision, checkVoxelFluid, moveVoxelEntity
LightinggetVoxelLightLevel, setVoxelDayTime
FluidssetVoxelFluidSource, removeVoxelFluidSource, getVoxelFluidLevel
EntitiesspawnVoxelEntity, removeVoxelEntity, getVoxelEntity, damageVoxelEntity, healVoxelEntity, updateVoxelEntities, getVoxelEntitiesInRadius, getVoxelEntitiesByType, getVoxelEntityCount, cleanupVoxelEntities
ECSsetVoxelEntityComponent, getVoxelEntityComponent, hasVoxelEntityComponent, removeVoxelEntityComponent, queryVoxelEntities, createVoxelEntityArchetype, spawnVoxelEntityFromArchetype, findVoxelPath
SchematicsexportVoxelRegion, importVoxelRegion, exportVoxelWorldJSON, importVoxelWorldJSON
PersistencesaveVoxelWorld, loadVoxelWorld, listVoxelWorlds, deleteVoxelWorld
TexturesenableVoxelTextures, loadVoxelTextureAtlas
NoisesimplexNoise2D, simplexNoise3D
StructuresplaceVoxelTree