ChunkMesher class

Face-culling, greedy mesher with baked ambient occlusion, sky + block light, liquids (lowered surface, own transparent surface), cross plants, torches, and the sub-block solids (slab, fence, stairs) built from axis-aligned boxes lit like cube faces. Works on a volume padded on every horizontal side, filled from the eight neighbour chunks, so a border face and its AO corners never guess.

The light is not baked into the vertex colour: the colour carries block tint × face tint × AO, and MeshSurface.light carries (sky / 15, block / 15). The two light volumes (chunk-sized) ride the result.

Cube and liquid faces are merged: coplanar neighbours of the same block, light, lowered top and AO corners become one quad, across a direction only where the AO does not change along it, so the interpolated colour is the one the unit faces had. What made every face different, the per-voxel colour variation, is not in the colour: a renderer computes it from the cell with voxelTint (voxel_scene's terrain shader does). Only the ChunkMeshResult.glow surface, meant for an unlit material, keeps it baked and its faces unmerged.

The padding is the whole 3×3 ring (48×48×128 cells), so the light flood sees every emitter within reach of this chunk and a torch beside a border lights both sides alike.

Its work buffers are static, so one set exists per isolate: build on one isolate at a time from one mesher, as a worker isolate does.

Constructors

ChunkMesher({required Float32List palette, required Uint8List shape, required Uint8List opaque, required Uint8List emission, bool lighting = true})
A mesher over one block table's arrays, indexed by block id: palette holds four linear floats (rgba) per id, shape a BlockShape index, opaque 1 where the id occludes faces and light, emission 0..15. VoxelBlockTable.mesher builds one from a table.

Properties

emission → Uint8List
The emitted light of every block id, 0..15.
final
hashCode → int
The hash code for this object.
no setterinherited
lighting → bool
False skips the light flood: skylight 15 everywhere, no block light. For measuring what the light costs.
final
palette → Float32List
Four floats per block id (rgba, linear).
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
shape → Uint8List
The BlockShape index of every block id.
final

Methods

build(int chunkX, int chunkZ, List<Uint8List?> ring) → ChunkMeshResult
Meshes chunk (chunkX, chunkZ). ring is the chunk volume and its eight neighbours in ChunkStreamer.ring order (c, nx, px, nz, pz, nxnz, pxnz, nxpz, pxpz); a missing neighbour is null and reads as air.
buildWith<T>(int chunkX, int chunkZ, List<Uint8List?> ring, T use(ChunkMeshResult result)) → T
Meshes chunk (chunkX, chunkZ) as build does and hands the result to use, whose value it returns. That result's arrays are the mesher's own, valid only inside use: read or copy them there. A worker that sends the mesh away copies it anyway, and so allocates no copy of its own.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toString() → String
A string representation of this object.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited

Static Properties

fullSkySeed ↔ bool
Tests only: seed the sky flood from every lit cell instead of only the cells with a darker side neighbour. Both give the same light; this is the slow reference the fast seeding is checked against.
getter/setter pair

Static Methods

voxelTint(int x, int y, int z) → double
The colour variation of the block at world cell (x, y, z), a factor in 0.93..1.07: a hash of the cell in 32-bit unsigned arithmetic, so a shader reproduces it exactly (voxel_scene's terrain.frag ports it). The mesher bakes it into ChunkMeshResult.glow only.

Constants

glowThreshold → const int
A cube whose emission is at or above this goes on ChunkMeshResult.glow.
noNeighbours → const List<Uint8List?>
The eight neighbours of a chunk meshed alone: [chunk, ...noNeighbours]. Every cell past its border reads as air.
shapeIndices → const List<int>
The shape ints above in BlockShape order. They stay const ints, not BlockShape.index reads, because they sit in the hottest loop; a test pins this list to the enum.