Add a World that stores chunks in a Dictionary keyed by chunk coordinate, with floor-division world<->chunk coordinate mapping (correct for negative coords). The mesher takes an optional neighbor sampler so faces at chunk borders are culled against adjacent chunks instead of always meshing the shell. Render one ChunkRenderer per chunk, placed via the model matrix. Reorganize the World layer into Blocks/ and Chunk/ sub-namespaces.
63 lines
1.7 KiB
C#
63 lines
1.7 KiB
C#
using System.Collections;
|
|
using OpenTK.Mathematics;
|
|
using VoxelEngine.World.Blocks;
|
|
|
|
namespace VoxelEngine.World;
|
|
|
|
public sealed class World : IWorld, IEnumerable<KeyValuePair<Vector3i, Chunk.Chunk>>
|
|
{
|
|
private readonly Dictionary<Vector3i, Chunk.Chunk> _chunks = new();
|
|
private readonly BlockRegistry _registry;
|
|
|
|
public World(BlockRegistry registry)
|
|
{
|
|
this._registry = registry;
|
|
}
|
|
|
|
public void SetChunk(Vector3i chunkPos, Chunk.Chunk chunk)
|
|
{
|
|
this._chunks[chunkPos] = chunk;
|
|
}
|
|
|
|
public Chunk.Chunk? GetChunk(Vector3i chunkPos)
|
|
{
|
|
return this._chunks.GetValueOrDefault(chunkPos);
|
|
}
|
|
|
|
public IBlock GetBlock(int worldX, int worldY, int worldZ)
|
|
{
|
|
Vector3i chunkPos = new(
|
|
World.FloorDiv(worldX, Chunk.Chunk.Size),
|
|
World.FloorDiv(worldY, Chunk.Chunk.Size),
|
|
World.FloorDiv(worldZ, Chunk.Chunk.Size)
|
|
);
|
|
|
|
Chunk.Chunk? chunk = this.GetChunk(chunkPos);
|
|
if (chunk == null)
|
|
{
|
|
return this._registry.Air;
|
|
}
|
|
|
|
int localX = worldX - chunkPos.X * Chunk.Chunk.Size;
|
|
int localY = worldY - chunkPos.Y * Chunk.Chunk.Size;
|
|
int localZ = worldZ - chunkPos.Z * Chunk.Chunk.Size;
|
|
|
|
return this._registry.Get(chunk[localX, localY, localZ]);
|
|
}
|
|
|
|
private static int FloorDiv(int value, int size)
|
|
{
|
|
int quotient = value / size;
|
|
if (value % size != 0 && value < 0)
|
|
{
|
|
quotient--;
|
|
}
|
|
return quotient;
|
|
}
|
|
|
|
public IEnumerator<KeyValuePair<Vector3i, Chunk.Chunk>> GetEnumerator()
|
|
=> this._chunks.GetEnumerator();
|
|
|
|
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
|
|
|
|
} |