Files
VoxelEngine/World/Streaming/NeighborSnapshots.cs

53 lines
2.3 KiB
C#

using VoxelEngine.World.Chunk;
namespace VoxelEngine.World.Streaming;
// Snapshots of the six cardinal neighbor chunks' block arrays, taken on the
// main thread at job-dispatch time. Each slot is null if that neighbor is not
// currently loaded. The ChunkMesher reads only these arrays from a worker
// thread — never the live World.
public sealed class NeighborSnapshots
{
public ushort[]? NegX { get; }
public ushort[]? PosX { get; }
public ushort[]? NegY { get; }
public ushort[]? PosY { get; }
public ushort[]? NegZ { get; }
public ushort[]? PosZ { get; }
// Snapshots take ownership of the arrays passed in. Callers must hand
// in fresh copies (not live references into a chunk's _ids buffer) —
// the snapshot does NOT copy defensively. This is enforced at the
// single call-site in ChunkStreamer.SnapshotNeighbors which allocates
// fresh arrays. The arrays must not be mutated after construction.
public NeighborSnapshots(
ushort[]? negX, ushort[]? posX,
ushort[]? negY, ushort[]? posY,
ushort[]? negZ, ushort[]? posZ)
{
this.NegX = negX; this.PosX = posX;
this.NegY = negY; this.PosY = posY;
this.NegZ = negZ; this.PosZ = posZ;
}
// Returns true if the out-of-chunk position (nx, ny, nz) — exactly one of
// which is out of [0, Chunk.Chunk.Size) — is occupied by an opaque block
// in the snapshot. Returns false if the relevant neighbor is null.
public bool IsOpaqueOutside(int nx, int ny, int nz, Func<ushort, bool> isOpaque)
{
ushort[]? n;
int lx = nx, ly = ny, lz = nz;
if (nx < 0) { n = this.NegX; lx = Chunk.Chunk.Size - 1; }
else if (nx >= Chunk.Chunk.Size) { n = this.PosX; lx = 0; }
else if (ny < 0) { n = this.NegY; ly = Chunk.Chunk.Size - 1; }
else if (ny >= Chunk.Chunk.Size) { n = this.PosY; ly = 0; }
else if (nz < 0) { n = this.NegZ; lz = Chunk.Chunk.Size - 1; }
else if (nz >= Chunk.Chunk.Size) { n = this.PosZ; lz = 0; }
else return false; // not actually outside — shouldn't happen, mesher guards
if (n == null) return false;
int index = (lx * Chunk.Chunk.Size + ly) * Chunk.Chunk.Size + lz;
return isOpaque(n[index]);
}
}