mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Added chunk editing
This commit is contained in:
@@ -15,10 +15,48 @@ namespace Sandbox.VoxelFun
|
|||||||
{
|
{
|
||||||
public class Chunk
|
public class Chunk
|
||||||
{
|
{
|
||||||
|
public ChunkManager ChunkManager;
|
||||||
public GeometryBinding Geometry ~ _?.ReleaseRef();
|
public GeometryBinding Geometry ~ _?.ReleaseRef();
|
||||||
|
|
||||||
public VoxelChunk Data;
|
public VoxelChunk Data;
|
||||||
public Matrix Transform;
|
public Matrix Transform;
|
||||||
public Int32_3 Position;
|
public Int32_3 Position;
|
||||||
|
public Int32_3 Coordinate;
|
||||||
|
|
||||||
|
private bool _isDirty;
|
||||||
|
private bool _isGeometryDirty;
|
||||||
|
|
||||||
|
public bool IsDirty => _isDirty;
|
||||||
|
|
||||||
|
public bool IsGeometryDirty
|
||||||
|
{
|
||||||
|
get => _isGeometryDirty;
|
||||||
|
set => _isGeometryDirty = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBlock(Int32_3 coordinate, uint8 blockId)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.AssertDebug(coordinate.X >= 0 && coordinate.Y >= 0 && coordinate.Z >= 0 && coordinate.X < VoxelChunk.Size.X && coordinate.Y < VoxelChunk.Size.Y && coordinate.Z < VoxelChunk.Size.Z, "Specified coordinate is out of range.");
|
||||||
|
|
||||||
|
Data.Data[coordinate.X][coordinate.Y][coordinate.Z] = blockId;
|
||||||
|
|
||||||
|
_isDirty = true;
|
||||||
|
_isGeometryDirty = true;
|
||||||
|
ChunkManager.[Friend]chunkPosLock.Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint8 GetBlock(Int32_3 coordinate)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.AssertDebug(coordinate.X >= 0 && coordinate.Y >= 0 && coordinate.Z >= 0 && coordinate.X < VoxelChunk.Size.X && coordinate.Y < VoxelChunk.Size.Y && coordinate.Z < VoxelChunk.Size.Z, "Specified coordinate is out of range.");
|
||||||
|
|
||||||
|
return Data.Data[coordinate.X][coordinate.Y][coordinate.Z];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Serialize(Stream stream)
|
||||||
|
{
|
||||||
|
stream.Write(Data);
|
||||||
|
_isDirty = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ChunkManager
|
public class ChunkManager
|
||||||
@@ -30,7 +68,7 @@ namespace Sandbox.VoxelFun
|
|||||||
|
|
||||||
private String _chunkBasePath ~ delete _;
|
private String _chunkBasePath ~ delete _;
|
||||||
|
|
||||||
Dictionary<Int32_3, Chunk> _chunks = new .() ~ DeleteDictionaryAndValues!(_);
|
Dictionary<Int32_3, Chunk> _chunks = new .() ~ delete _;
|
||||||
|
|
||||||
private HashSet<Int32_3> _generatingChunks = new .() ~ delete _;
|
private HashSet<Int32_3> _generatingChunks = new .() ~ delete _;
|
||||||
private Monitor _generatingChunksLock = new .() ~ delete _;
|
private Monitor _generatingChunksLock = new .() ~ delete _;
|
||||||
@@ -83,6 +121,12 @@ namespace Sandbox.VoxelFun
|
|||||||
stopChunkLoader = true;
|
stopChunkLoader = true;
|
||||||
|
|
||||||
chunkLoader.Join();
|
chunkLoader.Join();
|
||||||
|
|
||||||
|
// Unload (and save) all chunks
|
||||||
|
for(var pair in _chunks)
|
||||||
|
{
|
||||||
|
UnloadChunk(pair.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,13 +177,15 @@ namespace Sandbox.VoxelFun
|
|||||||
if(!alreadyInList)
|
if(!alreadyInList)
|
||||||
{
|
{
|
||||||
chunk = new Chunk();
|
chunk = new Chunk();
|
||||||
|
chunk.ChunkManager = this;
|
||||||
|
chunk.Coordinate = chunkCoordinate;
|
||||||
chunk.Position = chunkCoordinate * .(VoxelChunk.SizeX, VoxelChunk.SizeY, VoxelChunk.SizeZ);
|
chunk.Position = chunkCoordinate * .(VoxelChunk.SizeX, VoxelChunk.SizeY, VoxelChunk.SizeZ);
|
||||||
chunk.Transform = .Translation(chunk.Position.X, chunk.Position.Y, chunk.Position.Z);
|
chunk.Transform = .Translation(chunk.Position.X, chunk.Position.Y, chunk.Position.Z);
|
||||||
|
|
||||||
if(LoadChunkFromFile(chunkCoordinate, chunk) case .Err)
|
if(LoadChunkFromFile(chunkCoordinate, chunk) case .Err)
|
||||||
{
|
{
|
||||||
GenTestChunk(chunk);
|
GenTestChunk(chunk);
|
||||||
SaveChunkToFile(chunkCoordinate, chunk);
|
SaveChunkToFile(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
GenChunkGeo(chunk);
|
GenChunkGeo(chunk);
|
||||||
@@ -243,8 +289,8 @@ namespace Sandbox.VoxelFun
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Position didn't change -> skip
|
// Position didn't change -> skip
|
||||||
if(curChunkPosition == oldChunkPosition)
|
//if(curChunkPosition == oldChunkPosition)
|
||||||
continue;
|
// continue;
|
||||||
|
|
||||||
ChunkLoaderThread_GenerateChunks(curChunkPosition);
|
ChunkLoaderThread_GenerateChunks(curChunkPosition);
|
||||||
|
|
||||||
@@ -252,6 +298,20 @@ namespace Sandbox.VoxelFun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UnloadChunk(Chunk chunk)
|
||||||
|
{
|
||||||
|
if(chunk.IsDirty)
|
||||||
|
{
|
||||||
|
SaveChunkToFile(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
using(chunkListLock.Enter())
|
||||||
|
{
|
||||||
|
_chunks.Remove(chunk.Coordinate);
|
||||||
|
delete chunk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void ChunkLoaderThread_GenerateChunks(Int32_3 chunkPos)
|
public void ChunkLoaderThread_GenerateChunks(Int32_3 chunkPos)
|
||||||
{
|
{
|
||||||
for(var chunk in _chunks)
|
for(var chunk in _chunks)
|
||||||
@@ -260,11 +320,11 @@ namespace Sandbox.VoxelFun
|
|||||||
|
|
||||||
if(dist.X > _viewDistance || dist.Z > _viewDistance)
|
if(dist.X > _viewDistance || dist.Z > _viewDistance)
|
||||||
{
|
{
|
||||||
using(chunkListLock.Enter())
|
UnloadChunk(chunk.value);
|
||||||
{
|
}
|
||||||
delete chunk.value;
|
else if(chunk.value.IsGeometryDirty)
|
||||||
_chunks.Remove(chunk.key);
|
{
|
||||||
}
|
GenChunkGeo(chunk.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,16 +373,16 @@ namespace Sandbox.VoxelFun
|
|||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> SaveChunkToFile(Int32_3 chunkCoordinate, Chunk outChunk)
|
Result<void> SaveChunkToFile(Chunk chunk)
|
||||||
{
|
{
|
||||||
String chunkFileName = scope String(_chunkBasePath);
|
String chunkFileName = scope String(_chunkBasePath);
|
||||||
chunkFileName.AppendF($"{chunkCoordinate.X}_{chunkCoordinate.Y}_{chunkCoordinate.Z}.cdata");
|
chunkFileName.AppendF($"{chunk.Coordinate.X}_{chunk.Coordinate.Y}_{chunk.Coordinate.Z}.cdata");
|
||||||
|
|
||||||
FileStream fs = scope FileStream();
|
FileStream fs = scope FileStream();
|
||||||
|
|
||||||
fs.Open(chunkFileName, FileMode.Create, .Write);
|
fs.Open(chunkFileName, FileMode.Create, .Write);
|
||||||
|
|
||||||
fs.Write(outChunk.Data);
|
chunk.Serialize(fs);
|
||||||
|
|
||||||
fs.Close();
|
fs.Close();
|
||||||
|
|
||||||
@@ -463,8 +523,14 @@ namespace Sandbox.VoxelFun
|
|||||||
|
|
||||||
void GenChunkGeo(Chunk chunk)
|
void GenChunkGeo(Chunk chunk)
|
||||||
{
|
{
|
||||||
chunk.Geometry?.ReleaseRef();
|
var oldGeometry = chunk.Geometry;
|
||||||
chunk.Geometry = voxelGeoGen.GenerateGeometry(chunk.Data);
|
|
||||||
|
var newGeometry = voxelGeoGen.GenerateGeometry(chunk.Data);
|
||||||
|
|
||||||
|
Interlocked.Store(ref chunk.Geometry, newGeometry);
|
||||||
|
chunk.IsGeometryDirty = false;
|
||||||
|
|
||||||
|
oldGeometry?.ReleaseRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw()
|
public void Draw()
|
||||||
@@ -474,12 +540,16 @@ namespace Sandbox.VoxelFun
|
|||||||
{
|
{
|
||||||
Chunk chunk = pair.value;
|
Chunk chunk = pair.value;
|
||||||
|
|
||||||
if(chunk?.Geometry == null)
|
GeometryBinding chunkGeo = Interlocked.Load(ref chunk.Geometry);
|
||||||
|
chunkGeo.AddRef();
|
||||||
|
|
||||||
|
if(chunkGeo == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Texture.Bind();
|
Texture.Bind();
|
||||||
|
|
||||||
Renderer.Submit(chunk.Geometry, TextureEffect, chunk.Transform);
|
Renderer.Submit(chunk.Geometry, TextureEffect, chunk.Transform);
|
||||||
|
chunkGeo.ReleaseRef();
|
||||||
}
|
}
|
||||||
chunkListLock.Exit();
|
chunkListLock.Exit();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -398,6 +398,38 @@ namespace Sandbox.VoxelFun
|
|||||||
|
|
||||||
Renderer.Submit(_cubeGeo, _textureEffect, .Translation(intersectInfo.Location) * .Scaling(0.1f) * .Translation(-0.5f.XXX));
|
Renderer.Submit(_cubeGeo, _textureEffect, .Translation(intersectInfo.Location) * .Scaling(0.1f) * .Translation(-0.5f.XXX));
|
||||||
|
|
||||||
|
if(intersectInfo.Face != .None)
|
||||||
|
{
|
||||||
|
if(Input.IsMouseButtonPressing(.LeftButton))
|
||||||
|
{
|
||||||
|
_world.SetBlock(intersectInfo.Coordinate, 0);
|
||||||
|
}
|
||||||
|
else if(Input.IsMouseButtonPressing(.RightButton))
|
||||||
|
{
|
||||||
|
var newBlockCoord = intersectInfo.Coordinate;
|
||||||
|
|
||||||
|
switch(intersectInfo.Face)
|
||||||
|
{
|
||||||
|
case .Front:
|
||||||
|
newBlockCoord.Z--;
|
||||||
|
case .Back:
|
||||||
|
newBlockCoord.Z++;
|
||||||
|
case .Left:
|
||||||
|
newBlockCoord.X--;
|
||||||
|
case .Right:
|
||||||
|
newBlockCoord.X++;
|
||||||
|
case .Bottom:
|
||||||
|
newBlockCoord.Y--;
|
||||||
|
case .Top:
|
||||||
|
newBlockCoord.Y++;
|
||||||
|
default:
|
||||||
|
Log.ClientLogger.Error("Unknown block face.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_world.SetBlock(newBlockCoord, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_world.ChunkManager.Draw();
|
_world.ChunkManager.Draw();
|
||||||
|
|
||||||
Renderer.EndScene();
|
Renderer.EndScene();
|
||||||
|
|||||||
@@ -280,13 +280,7 @@ namespace Sandbox.VoxelFun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Int32_3 chunkCoordinate = ChunkCoordFromBlockCoord(walker);
|
uint8 blockData = [Inline]GetBlock(walker);
|
||||||
|
|
||||||
Chunk chunk = _chunkManager.LoadChunk(chunkCoordinate);
|
|
||||||
|
|
||||||
Int32_3 coordInChunk = BlockCoordInChunk(walker);
|
|
||||||
|
|
||||||
uint8 blockData = chunk.Data.Data[coordInChunk.X][coordInChunk.Y][coordInChunk.Z];
|
|
||||||
|
|
||||||
if(blockData != 0)
|
if(blockData != 0)
|
||||||
{
|
{
|
||||||
@@ -294,12 +288,41 @@ namespace Sandbox.VoxelFun
|
|||||||
|
|
||||||
return walker;
|
return walker;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
intersectionFace = .None;
|
intersectionFace = .None;
|
||||||
intersectionPosition = .(float.NaN);
|
intersectionPosition = .(float.NaN);
|
||||||
return .(int32.MaxValue, int32.MaxValue, int32.MaxValue);
|
return .(int32.MaxValue, int32.MaxValue, int32.MaxValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the block at the specified coordinate.
|
||||||
|
* @remarks If the blocks chunk is not loaded it will be loaded from the disk.
|
||||||
|
*/
|
||||||
|
public void SetBlock(Int32_3 blockCoordinate, uint8 blockId)
|
||||||
|
{
|
||||||
|
Int32_3 chunkCoordinate = ChunkCoordFromBlockCoord(blockCoordinate);
|
||||||
|
|
||||||
|
Chunk chunk = _chunkManager.LoadChunk(chunkCoordinate);
|
||||||
|
|
||||||
|
Int32_3 coordInChunk = BlockCoordInChunk(blockCoordinate);
|
||||||
|
|
||||||
|
chunk.SetBlock(coordInChunk, blockId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the block at the specified coordinate.
|
||||||
|
* @remarks If the blocks chunk is not loaded it will be loaded from the disk.
|
||||||
|
*/
|
||||||
|
public uint8 GetBlock(Int32_3 blockCoordinate)
|
||||||
|
{
|
||||||
|
Int32_3 chunkCoordinate = ChunkCoordFromBlockCoord(blockCoordinate);
|
||||||
|
|
||||||
|
Chunk chunk = _chunkManager.LoadChunk(chunkCoordinate);
|
||||||
|
|
||||||
|
Int32_3 coordInChunk = BlockCoordInChunk(blockCoordinate);
|
||||||
|
|
||||||
|
return chunk.GetBlock(coordInChunk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user