mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Decoupled Chunk data loading/generation and geometry generation
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using GlitchyEngine.Math;
|
||||
using GlitchyEngine;
|
||||
using GlitchyEngine.Math;
|
||||
|
||||
namespace Sandbox.VoxelFun
|
||||
{
|
||||
class Block
|
||||
@@ -34,7 +35,7 @@ namespace Sandbox.VoxelFun
|
||||
*/
|
||||
public virtual void OnPlacing(Int32_3 blockCoordinate)
|
||||
{
|
||||
Log.ClientLogger.Info($"I broke. {{{blockCoordinate}}}");
|
||||
Log.ClientLogger.Info($"I live! {{{blockCoordinate}}}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace Sandbox.VoxelFun
|
||||
private bool _isDirty;
|
||||
private bool _isGeometryDirty;
|
||||
|
||||
/// Neighbors that will trigger a regeneration of this chunks geometry
|
||||
public BlockFace _reqiredNeighbors;
|
||||
|
||||
public bool IsDirty => _isDirty;
|
||||
|
||||
public bool IsGeometryDirty
|
||||
@@ -196,7 +199,7 @@ namespace Sandbox.VoxelFun
|
||||
SaveChunkToFile(chunk);
|
||||
}
|
||||
|
||||
GenChunkGeo(chunk);
|
||||
chunk.IsGeometryDirty = true;
|
||||
|
||||
using(chunkListLock.Enter())
|
||||
{
|
||||
@@ -212,10 +215,7 @@ namespace Sandbox.VoxelFun
|
||||
}
|
||||
|
||||
// Raise chunk loaded event (this will wake up all calls of LoadChunk waiting for our chunk)
|
||||
using(_chunkLoadedLock.Enter())
|
||||
{
|
||||
_chunkLoaded.Invoke(chunkCoordinate);
|
||||
}
|
||||
OnChunkLoaded(chunkCoordinate);
|
||||
}
|
||||
else if(!noBlocking)
|
||||
{
|
||||
@@ -256,6 +256,59 @@ namespace Sandbox.VoxelFun
|
||||
return chunk;
|
||||
}
|
||||
|
||||
void OnChunkLoaded(Int32_3 chunkCoordinate)
|
||||
{
|
||||
// Raise chunk loaded event (this will wake up all calls of LoadChunk waiting for our chunk)
|
||||
using(_chunkLoadedLock.Enter())
|
||||
{
|
||||
_chunkLoaded.Invoke(chunkCoordinate);
|
||||
}
|
||||
|
||||
// Left
|
||||
{
|
||||
var chunkCoordinate;
|
||||
|
||||
chunkCoordinate.X--;
|
||||
Chunk neighbor = GetChunk(chunkCoordinate);
|
||||
|
||||
if(neighbor != null && neighbor._reqiredNeighbors.HasFlag(.Right))
|
||||
neighbor.IsGeometryDirty = true;
|
||||
}
|
||||
|
||||
// Right
|
||||
{
|
||||
var chunkCoordinate;
|
||||
|
||||
chunkCoordinate.X++;
|
||||
Chunk neighbor = GetChunk(chunkCoordinate);
|
||||
|
||||
if(neighbor != null && neighbor._reqiredNeighbors.HasFlag(.Left))
|
||||
neighbor.IsGeometryDirty = true;
|
||||
}
|
||||
|
||||
// Back
|
||||
{
|
||||
var chunkCoordinate;
|
||||
|
||||
chunkCoordinate.Z--;
|
||||
Chunk neighbor = GetChunk(chunkCoordinate);
|
||||
|
||||
if(neighbor != null && neighbor._reqiredNeighbors.HasFlag(.Front))
|
||||
neighbor.IsGeometryDirty = true;
|
||||
}
|
||||
|
||||
// Front
|
||||
{
|
||||
var chunkCoordinate;
|
||||
|
||||
chunkCoordinate.Z++;
|
||||
Chunk neighbor = GetChunk(chunkCoordinate);
|
||||
|
||||
if(neighbor != null && neighbor._reqiredNeighbors.HasFlag(.Back))
|
||||
neighbor.IsGeometryDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetChunkPos(Int32_3 chunkPos)
|
||||
{
|
||||
chunkPosLock.Enter();
|
||||
@@ -543,7 +596,7 @@ namespace Sandbox.VoxelFun
|
||||
{
|
||||
var oldGeometry = chunk.Geometry;
|
||||
|
||||
var newGeometry = voxelGeoGen.GenerateGeometry(chunk.Data);
|
||||
var newGeometry = voxelGeoGen.GenerateGeometry(chunk);
|
||||
|
||||
Interlocked.Store(ref chunk.Geometry, newGeometry);
|
||||
chunk.IsGeometryDirty = false;
|
||||
@@ -559,11 +612,12 @@ namespace Sandbox.VoxelFun
|
||||
Chunk chunk = pair.value;
|
||||
|
||||
GeometryBinding chunkGeo = Interlocked.Load(ref chunk.Geometry);
|
||||
chunkGeo.AddRef();
|
||||
|
||||
if(chunkGeo == null)
|
||||
continue;
|
||||
|
||||
chunkGeo.AddRef();
|
||||
|
||||
Texture.Bind();
|
||||
|
||||
Renderer.Submit(chunk.Geometry, TextureEffect, chunk.Transform);
|
||||
|
||||
@@ -47,15 +47,69 @@ namespace Sandbox.VoxelFun
|
||||
public GraphicsContext Context;
|
||||
public VertexLayout Layout;
|
||||
|
||||
BlockFace GetVisibleFaces(VoxelChunk chunk, int x, int y, int z)
|
||||
BlockFace GetVisibleFaces(VoxelChunk chunk, int x, int y, int z, Chunk[3][3] chunks)
|
||||
{
|
||||
BlockFace visibleFaces = .None;
|
||||
|
||||
if(z == 0 || chunk.Data[x][y][z - 1].VisibleNeighbors.HasFlag(.Front))
|
||||
// Back
|
||||
int idx = z;
|
||||
Chunk readChunk = chunks[1][1];
|
||||
|
||||
if(idx == 0)
|
||||
{
|
||||
readChunk = chunks[1][0];
|
||||
idx = VoxelChunk.Size.Z;
|
||||
}
|
||||
|
||||
if(readChunk == null || readChunk.Data.Data[x][y][idx - 1].VisibleNeighbors.HasFlag(.Front))
|
||||
visibleFaces |= .Back;
|
||||
if(z == VoxelChunk.SizeZ - 1 || chunk.Data[x][y][z + 1].VisibleNeighbors.HasFlag(.Back))
|
||||
|
||||
// Front
|
||||
idx = z + 1;
|
||||
readChunk = chunks[1][1];
|
||||
|
||||
if(idx == VoxelChunk.Size.Z)
|
||||
{
|
||||
readChunk = chunks[1][2];
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
if(readChunk == null || readChunk.Data.Data[x][y][idx].VisibleNeighbors.HasFlag(.Back))
|
||||
visibleFaces |= .Front;
|
||||
|
||||
// Left
|
||||
idx = x;
|
||||
readChunk = chunks[1][1];
|
||||
|
||||
if(idx == 0)
|
||||
{
|
||||
readChunk = chunks[0][1];
|
||||
idx = VoxelChunk.Size.X;
|
||||
}
|
||||
|
||||
if(readChunk == null || readChunk.Data.Data[idx - 1][y][z].VisibleNeighbors.HasFlag(.Right))
|
||||
visibleFaces |= .Left;
|
||||
|
||||
// Right
|
||||
idx = x + 1;
|
||||
readChunk = chunks[1][1];
|
||||
|
||||
if(idx == VoxelChunk.Size.X)
|
||||
{
|
||||
readChunk = chunks[2][1];
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
if(readChunk == null || readChunk.Data.Data[idx][y][z].VisibleNeighbors.HasFlag(.Left))
|
||||
visibleFaces |= .Right;
|
||||
|
||||
// TODO: implement for top and bottom as we have 3D chunks
|
||||
if(y == 0 || chunk.Data[x][y - 1][z].VisibleNeighbors.HasFlag(.Top))
|
||||
visibleFaces |= .Bottom;
|
||||
if(y == VoxelChunk.SizeY - 1 || chunk.Data[x][y + 1][z].VisibleNeighbors.HasFlag(.Bottom))
|
||||
visibleFaces |= .Top;
|
||||
|
||||
/*
|
||||
if(x == 0 || chunk.Data[x - 1][y][z].VisibleNeighbors.HasFlag(.Right))
|
||||
visibleFaces |= .Left;
|
||||
if(x == VoxelChunk.SizeX - 1 || chunk.Data[x + 1][y][z].VisibleNeighbors.HasFlag(.Left))
|
||||
@@ -65,11 +119,11 @@ namespace Sandbox.VoxelFun
|
||||
visibleFaces |= .Bottom;
|
||||
if(y == VoxelChunk.SizeY - 1 || chunk.Data[x][y + 1][z].VisibleNeighbors.HasFlag(.Bottom))
|
||||
visibleFaces |= .Top;
|
||||
|
||||
*/
|
||||
return visibleFaces;
|
||||
}
|
||||
|
||||
public GeometryBinding GenerateGeometry(VoxelChunk chunk)
|
||||
public GeometryBinding GenerateGeometry(Chunk chunk)
|
||||
{
|
||||
List<VertexColorTexture> vertices = scope List<VertexColorTexture>();
|
||||
List<uint32> indices = scope List<uint32>();
|
||||
@@ -77,17 +131,64 @@ namespace Sandbox.VoxelFun
|
||||
|
||||
Stopwatch sw = .StartNew();
|
||||
|
||||
var chunkData = chunk.Data.Data;
|
||||
|
||||
Chunk[3][3] chunks;
|
||||
|
||||
var coord = chunk.Coordinate;
|
||||
|
||||
// left
|
||||
coord.X -= 1;
|
||||
chunks[0][1] = chunk.ChunkManager.GetChunk(coord);
|
||||
if(chunks[0][1] == null)
|
||||
{
|
||||
// TODO: register reload when neighbor generated
|
||||
chunk._reqiredNeighbors |= .Left;
|
||||
}
|
||||
|
||||
// back
|
||||
coord.X += 1;
|
||||
coord.Z -= 1;
|
||||
chunks[1][0] = chunk.ChunkManager.GetChunk(coord);
|
||||
if(chunks[1][0] == null)
|
||||
{
|
||||
// TODO: register reload when neighbor generated
|
||||
chunk._reqiredNeighbors |= .Back;
|
||||
}
|
||||
|
||||
// center
|
||||
chunks[1][1] = chunk;
|
||||
|
||||
// front
|
||||
coord.Z += 2;
|
||||
chunks[1][2] = chunk.ChunkManager.GetChunk(coord);
|
||||
if(chunks[1][2] == null)
|
||||
{
|
||||
// TODO: register reload when neighbor generated
|
||||
chunk._reqiredNeighbors |= .Front;
|
||||
}
|
||||
|
||||
// right
|
||||
coord.X += 1;
|
||||
coord.Z -= 1;
|
||||
chunks[2][1] = chunk.ChunkManager.GetChunk(coord);
|
||||
if(chunks[2][1] == null)
|
||||
{
|
||||
// TODO: register reload when neighbor generated
|
||||
chunk._reqiredNeighbors |= .Right;
|
||||
}
|
||||
|
||||
for(int x < VoxelChunk.SizeX)
|
||||
for(int y < VoxelChunk.SizeY)
|
||||
for(int z < VoxelChunk.SizeZ)
|
||||
{
|
||||
Block block = chunk.Data[x][y][z];
|
||||
Block block = chunkData[x][y][z];
|
||||
|
||||
Vector3 blockPos = .(x, y, z);
|
||||
|
||||
if(block != Blocks.Air)
|
||||
{
|
||||
BlockFace visibleFaces = GetVisibleFaces(chunk, x, y, z);
|
||||
BlockFace visibleFaces = GetVisibleFaces(chunk.Data, x, y, z, chunks);
|
||||
|
||||
if(visibleFaces != .None)
|
||||
block.Model.GenerateGeometry(block, blockPos, visibleFaces, vertices, indices, ref lastIndex);
|
||||
|
||||
@@ -408,6 +408,9 @@ namespace Sandbox.VoxelFun
|
||||
|
||||
if(intersectInfo.Face != .None)
|
||||
{
|
||||
if(rightHandBlock == null)
|
||||
rightHandBlock = Blocks.Stone;
|
||||
|
||||
if(Input.IsMouseButtonPressing(.LeftButton))
|
||||
{
|
||||
_world.BreakBlock(intersectInfo.Coordinate);
|
||||
@@ -427,7 +430,7 @@ namespace Sandbox.VoxelFun
|
||||
Renderer.EndScene();
|
||||
}
|
||||
|
||||
Block rightHandBlock = Blocks.Stone;
|
||||
Block rightHandBlock;
|
||||
|
||||
struct IntersectionInfo
|
||||
{
|
||||
|
||||
@@ -317,6 +317,8 @@ namespace Sandbox.VoxelFun
|
||||
block.OnBreaking(blockCoordinate);
|
||||
|
||||
chunk.SetBlock(coordInChunk, Blocks.Air);
|
||||
|
||||
MarkNeighborGeometryDirty(chunkCoordinate, coordInChunk);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -336,6 +338,8 @@ namespace Sandbox.VoxelFun
|
||||
block.OnPlacing(blockCoordinate);
|
||||
|
||||
chunk.SetBlock(coordInChunk, block);
|
||||
|
||||
MarkNeighborGeometryDirty(chunkCoordinate, coordInChunk);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -379,6 +383,43 @@ namespace Sandbox.VoxelFun
|
||||
Int32_3 coordInChunk = BlockCoordInChunk(blockCoordinate);
|
||||
|
||||
chunk.SetBlock(coordInChunk, block);
|
||||
|
||||
MarkNeighborGeometryDirty(chunkCoordinate, coordInChunk);
|
||||
}
|
||||
|
||||
void MarkNeighborGeometryDirty(Int32_3 chunkCoordinate, Int32_3 coordInChunk)
|
||||
{
|
||||
var chunkCoordinate;
|
||||
|
||||
Chunk chunk;
|
||||
|
||||
// if we are on a chunk border mark the neighbor as dirty
|
||||
|
||||
if(coordInChunk.X == 0)
|
||||
{
|
||||
chunkCoordinate.X--;
|
||||
chunk = _chunkManager.GetChunk(chunkCoordinate);
|
||||
chunk?.IsGeometryDirty = true;
|
||||
}
|
||||
else if(coordInChunk.X == VoxelChunk.Size.X - 1)
|
||||
{
|
||||
chunkCoordinate.X++;
|
||||
chunk = _chunkManager.GetChunk(chunkCoordinate);
|
||||
chunk?.IsGeometryDirty = true;
|
||||
}
|
||||
// TODO: implement Y
|
||||
else if(coordInChunk.Z == 0)
|
||||
{
|
||||
chunkCoordinate.Z--;
|
||||
chunk = _chunkManager.GetChunk(chunkCoordinate);
|
||||
chunk?.IsGeometryDirty = true;
|
||||
}
|
||||
else if(coordInChunk.Z == VoxelChunk.Size.Z - 1)
|
||||
{
|
||||
chunkCoordinate.Z++;
|
||||
chunk = _chunkManager.GetChunk(chunkCoordinate);
|
||||
chunk?.IsGeometryDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user