154 lines
4.5 KiB
C#
154 lines
4.5 KiB
C#
namespace Voxel
|
|
{
|
|
public class Chunk
|
|
{
|
|
public static int Size = 16;
|
|
public static int Height = 256;
|
|
public readonly int X;
|
|
public readonly int Y;
|
|
private ChunkMesh _chunkMesh;
|
|
|
|
private Dictionary<ushort, BlockData> _blockData;
|
|
private Blocks[] _blocks;
|
|
|
|
public Chunk(int x, int y)
|
|
{
|
|
X = x;
|
|
Y = y;
|
|
|
|
_blockData = new Dictionary<ushort, BlockData>();
|
|
_blocks = new Blocks[Size * Size * Height];
|
|
_chunkMesh = new ChunkMesh(X, Y);
|
|
|
|
Initialize();
|
|
}
|
|
|
|
public void SetBlock(int x, int y, int z, Blocks block)
|
|
{
|
|
int i = GetBlockIndex(x, y, z);
|
|
if (i == -1) return;
|
|
_blocks[i] = block;
|
|
UpdateChunkMesh();
|
|
|
|
Renderer.MarkBuffersDirty();
|
|
}
|
|
|
|
public void SetBlockIndex(int i, Blocks block)
|
|
{
|
|
_blocks[i] = block;
|
|
}
|
|
|
|
public Blocks GetBlock(int x, int y, int z)
|
|
{
|
|
int i = GetBlockIndex(x, y, z);
|
|
if (i == -1) return Blocks.Air;
|
|
return _blocks[i];
|
|
}
|
|
|
|
public BlockData GetBlockData(int x, int y, int z)
|
|
{
|
|
return new BlockData();
|
|
}
|
|
|
|
private void Initialize()
|
|
{
|
|
for (int i = 0; i < Size * Size; i++)
|
|
_blocks[i] = Blocks.Bedrock;
|
|
for (int i = Size * Size * 1; i < Size * Size * 15; i++)
|
|
_blocks[i] = Blocks.Stone;
|
|
for (int i = Size * Size * 15; i < Size * Size * 16; i++)
|
|
_blocks[i] = Blocks.Grass;
|
|
UpdateChunkMesh();
|
|
}
|
|
|
|
// todo
|
|
public (int x, int y, int z) IndexToPosition(int i)
|
|
{
|
|
int x = 0;
|
|
int y = 0;
|
|
int z = 0;
|
|
|
|
return (x, y, z);
|
|
}
|
|
|
|
private int GetBlockIndex(int x, int y, int z)
|
|
{
|
|
if (x < 0 || x > 15 || y < 0 || y > 255 || z < 0 || z > 15)
|
|
return -1;
|
|
|
|
return x + z * Size + y * Size * Size;
|
|
}
|
|
|
|
private static readonly (int dx, int dy, int dz)[] Offsets = new (int, int, int)[6]
|
|
{
|
|
( 1, 0, 0), // +X
|
|
(-1, 0, 0), // -X
|
|
( 0, 1, 0), // +Y
|
|
( 0, -1, 0), // -Y
|
|
( 0, 0, 1), // +Z
|
|
( 0, 0, -1) // -Z
|
|
};
|
|
|
|
private void UpdateChunkMesh()
|
|
{
|
|
List<FaceData> faces = new List<FaceData>(Size * Size * Height / 2);
|
|
|
|
for (int x = 0; x < Size; x++)
|
|
{
|
|
for (int z = 0; z < Size; z++)
|
|
{
|
|
for (int y = 0; y < Height; y++)
|
|
{
|
|
for (byte face = 0; face < 6; face++)
|
|
{
|
|
int indexBase = y * Size * Size + z * Size + x;
|
|
Blocks block = _blocks[indexBase];
|
|
|
|
void AddFace()
|
|
{
|
|
FaceData faceData = new FaceData();
|
|
|
|
faceData.Facing = (Orientation)face;
|
|
faceData.Texture = BlockDefinitions.Blocks[block].FaceTextures[face];
|
|
|
|
faceData.X = (byte)x;
|
|
faceData.Y = (byte)y;
|
|
faceData.Z = (byte)z;
|
|
|
|
faces.Add(faceData);
|
|
}
|
|
|
|
if (block == Blocks.Air) continue; // ignore if air
|
|
|
|
int nx = x + Offsets[face].dx;
|
|
int ny = y + Offsets[face].dy;
|
|
int nz = z + Offsets[face].dz;
|
|
|
|
// check neighbor, ignore if at chunk edge
|
|
|
|
int ni = GetBlockIndex(nx, ny, nz);
|
|
if (GetBlockIndex(nx, ny, nz) == -1)
|
|
{
|
|
AddFace();
|
|
continue;
|
|
}
|
|
|
|
if (_blocks[ni] == Blocks.Air)
|
|
{
|
|
AddFace();
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_chunkMesh.SetFaces(faces);
|
|
}
|
|
|
|
public ChunkMesh GetChunkMesh()
|
|
{
|
|
return _chunkMesh;
|
|
}
|
|
}
|
|
}
|