mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 21:01:52 +00:00
initial VoxelGame commit
This commit is contained in:
@@ -8,6 +8,8 @@ using ImGui;
|
|||||||
using GlitchyEngine.Renderer;
|
using GlitchyEngine.Renderer;
|
||||||
using GlitchyEngine.Math;
|
using GlitchyEngine.Math;
|
||||||
|
|
||||||
|
using Sandbox.VoxelFun;
|
||||||
|
|
||||||
namespace Sandbox
|
namespace Sandbox
|
||||||
{
|
{
|
||||||
class ExampleLayer : Layer
|
class ExampleLayer : Layer
|
||||||
@@ -292,7 +294,8 @@ namespace Sandbox
|
|||||||
{
|
{
|
||||||
public this()
|
public this()
|
||||||
{
|
{
|
||||||
PushLayer(new ExampleLayer());
|
PushLayer(new VoxelTestLayer());
|
||||||
|
//PushLayer(new ExampleLayer());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Export, LinkName("CreateApplication")]
|
[Export, LinkName("CreateApplication")]
|
||||||
|
|||||||
@@ -0,0 +1,367 @@
|
|||||||
|
using GlitchyEngine.Math;
|
||||||
|
using GlitchyEngine.Renderer;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Collections;
|
||||||
|
using GlitchyEngine.ImGui;
|
||||||
|
using ImGui;
|
||||||
|
|
||||||
|
namespace Sandbox.VoxelFun
|
||||||
|
{
|
||||||
|
public class Chunk
|
||||||
|
{
|
||||||
|
public GeometryBinding Geometry ~ _?.ReleaseRef();
|
||||||
|
public VoxelChunk Data;
|
||||||
|
public Matrix Transform;
|
||||||
|
public Point3 Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Point3 : IHashable
|
||||||
|
{
|
||||||
|
public int X, Y, Z;
|
||||||
|
|
||||||
|
public this(int x, int y, int z)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHashCode()
|
||||||
|
{
|
||||||
|
return (((X * 39) ^ Y) * 39) ^ Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int DistanceSq(Point3 value1, Point3 value2)
|
||||||
|
{
|
||||||
|
int dstX = value1.X - value2.X;
|
||||||
|
int dstY = value1.Y - value2.Y;
|
||||||
|
int dstZ = value1.Z - value2.Z;
|
||||||
|
|
||||||
|
return dstX * dstX + dstY * dstY + dstZ * dstZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Point3 operator +(Point3 left, Point3 right) => .(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
|
||||||
|
public static Point3 operator -(Point3 left, Point3 right) => .(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
|
||||||
|
public static Point3 operator *(Point3 left, Point3 right) => .(left.X * right.X, left.Y * right.Y, left.Z * right.Z);
|
||||||
|
|
||||||
|
public Point3 Abs()
|
||||||
|
{
|
||||||
|
return .(Math.Abs(X), Math.Abs(Y), Math.Abs(Z));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static explicit operator Vector3(Point3 point) => .(point.X, point.Y, point.Z);
|
||||||
|
|
||||||
|
public static explicit operator Point3(Vector3 point) => .((int)point.X, (int)point.Y, (int)point.Z);
|
||||||
|
|
||||||
|
public static bool operator ==(Point3 left, Point3 right) => left.X == right.X && left.Y == right.Y && left.Z == right.Z;
|
||||||
|
public static bool operator !=(Point3 left, Point3 right) => left.X != right.X || left.Y != right.Y || left.Z != right.Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ChunkManager
|
||||||
|
{
|
||||||
|
GraphicsContext _context ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
int _viewDistance = 8;
|
||||||
|
|
||||||
|
Dictionary<Point3, Chunk> chunks = new .() ~ DeleteDictionaryAndValues!(_);
|
||||||
|
|
||||||
|
public Texture2D Texture ~ _?.ReleaseRef();
|
||||||
|
public Effect TextureEffect ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
VoxelGeometryGenerator voxelGeoGen = new VoxelGeometryGenerator() ~ delete _;
|
||||||
|
|
||||||
|
Thread chunkLoader;
|
||||||
|
bool stopChunkLoader;
|
||||||
|
Monitor chunkListLock = new Monitor() ~ delete _;
|
||||||
|
|
||||||
|
Point3 chunkPosition;
|
||||||
|
Point3 oldChunkPosition = .(Int.MaxValue, Int.MaxValue, Int.MaxValue);
|
||||||
|
|
||||||
|
Monitor chunkPosLock = new Monitor() ~ delete _;
|
||||||
|
|
||||||
|
Monitor chunkPosChanged = new Monitor()..Enter() ~ delete _;
|
||||||
|
|
||||||
|
|
||||||
|
public this(GraphicsContext context, VertexLayout vertexLayout)
|
||||||
|
{
|
||||||
|
_context = context..AddRef();
|
||||||
|
|
||||||
|
voxelGeoGen.Context = _context;
|
||||||
|
voxelGeoGen.Layout = vertexLayout;
|
||||||
|
|
||||||
|
chunkLoader = new Thread(new => ChunkLoaderThread);
|
||||||
|
chunkLoader.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ~this()
|
||||||
|
{
|
||||||
|
stopChunkLoader = true;
|
||||||
|
|
||||||
|
chunkLoader.Join();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetChunkPos(Point3 chunkPos)
|
||||||
|
{
|
||||||
|
chunkPosLock.Enter();
|
||||||
|
chunkPosition = chunkPos;
|
||||||
|
|
||||||
|
if(oldChunkPosition != chunkPosition)
|
||||||
|
chunkPosChanged.Exit();
|
||||||
|
|
||||||
|
chunkPosLock.Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(Vector3 cameraPosition)
|
||||||
|
{
|
||||||
|
Vector3 chunkPosition = cameraPosition / .(VoxelChunk.SizeX, VoxelChunk.SizeY, VoxelChunk.SizeZ);
|
||||||
|
|
||||||
|
Point3 p = (Point3)chunkPosition;
|
||||||
|
p.Y = 0;
|
||||||
|
|
||||||
|
SetChunkPos(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChunkLoaderThread()
|
||||||
|
{
|
||||||
|
Point3 curChunkPosition = .(0, 0, 0);
|
||||||
|
Point3 oldChunkPosition = .(Int.MaxValue, Int.MaxValue, Int.MaxValue);
|
||||||
|
|
||||||
|
while(!stopChunkLoader)
|
||||||
|
{
|
||||||
|
// Wait for chunkPos to change
|
||||||
|
chunkPosChanged.Enter();
|
||||||
|
|
||||||
|
chunkPosLock.Enter();
|
||||||
|
curChunkPosition = chunkPosition;
|
||||||
|
chunkPosLock.Exit();
|
||||||
|
|
||||||
|
// Position didn't change -> skip
|
||||||
|
if(curChunkPosition == oldChunkPosition)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
GenerateChunks(curChunkPosition);
|
||||||
|
|
||||||
|
oldChunkPosition = curChunkPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GenerateChunks(Point3 chunkPos)
|
||||||
|
{
|
||||||
|
for(var chunk in chunks)
|
||||||
|
{
|
||||||
|
Point3 dist = (chunk.key - chunkPos).Abs();
|
||||||
|
|
||||||
|
if(dist.X > _viewDistance || dist.Z > _viewDistance)
|
||||||
|
{
|
||||||
|
chunkListLock.Enter();
|
||||||
|
delete chunk.value;
|
||||||
|
chunks.Remove(chunk.key);
|
||||||
|
chunkListLock.Exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int x = -_viewDistance; x < _viewDistance; x++)
|
||||||
|
//for(int y = -_viewDistance; y < _viewDistance; y++)
|
||||||
|
for(int z = -_viewDistance; z < _viewDistance; z++)
|
||||||
|
{
|
||||||
|
int y = 0;
|
||||||
|
Point3 chunkCoordinate = (Point3)chunkPos + .(x, y, z);
|
||||||
|
|
||||||
|
if(!chunks.ContainsKey(chunkCoordinate))
|
||||||
|
{
|
||||||
|
var chunk = new Chunk();
|
||||||
|
|
||||||
|
if(LoadChunkFromFile(chunkCoordinate, chunk) case .Err)
|
||||||
|
{
|
||||||
|
chunk.Position = chunkCoordinate * .(VoxelChunk.SizeX, VoxelChunk.SizeY, VoxelChunk.SizeZ);
|
||||||
|
chunk.Transform = .Translation(chunk.Position.X, chunk.Position.Y, chunk.Position.Z);
|
||||||
|
GenTestChunk(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
chunkListLock.Enter();
|
||||||
|
chunks.Add(chunkCoordinate, chunk);
|
||||||
|
chunkListLock.Exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> LoadChunkFromFile(Point3 chunkCoordinate, Chunk outChunk)
|
||||||
|
{
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> SaveChunkToFile(Point3 chunkCoordinate, Chunk outChunk)
|
||||||
|
{
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GeneratorSettings
|
||||||
|
{
|
||||||
|
public int32 ElevationOctaves = 5;
|
||||||
|
public float ElevationFrequency = 0.0075f;
|
||||||
|
public float ElevationLacunarity = 2f;
|
||||||
|
public float ElevationGain = 0.5f;
|
||||||
|
|
||||||
|
public Vector2 DetailAmplitude = .(32, 32);
|
||||||
|
|
||||||
|
public int32 TerrainFloorHeight = 128;
|
||||||
|
// The amplitude of the hills (eg. how high hills are and how deep valleys are)
|
||||||
|
public int32 TerrainAmplitude = 48;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenerateTerrain(Chunk chunk)
|
||||||
|
{
|
||||||
|
Stopwatch sw = .StartNew();
|
||||||
|
|
||||||
|
GeneratorSettings settings = .();
|
||||||
|
//settings.ElevationFrequency
|
||||||
|
|
||||||
|
let groundNoise = scope FastNoiseLite.FastNoiseLite();
|
||||||
|
groundNoise.SetFractalType(.FBm);
|
||||||
|
groundNoise.SetFractalOctaves(settings.ElevationOctaves);
|
||||||
|
groundNoise.SetFractalLacunarity(settings.ElevationLacunarity);
|
||||||
|
groundNoise.SetFractalGain(settings.ElevationGain);
|
||||||
|
groundNoise.SetFrequency(settings.ElevationFrequency);
|
||||||
|
|
||||||
|
for(int x < VoxelChunk.SizeX)
|
||||||
|
for(int y < VoxelChunk.SizeY)
|
||||||
|
for(int z < VoxelChunk.SizeZ)
|
||||||
|
{
|
||||||
|
float cx = x + chunk.Position.X;
|
||||||
|
float cy = y + chunk.Position.Y;
|
||||||
|
float cz = z + chunk.Position.Z;
|
||||||
|
|
||||||
|
cx += groundNoise.GetNoise(cz * 0.5f, cy) * settings.DetailAmplitude.X;
|
||||||
|
cz += groundNoise.GetNoise(cy, cx * 0.5f) * settings.DetailAmplitude.Y;
|
||||||
|
|
||||||
|
cy += groundNoise.GetNoise(cx, cz) * settings.TerrainAmplitude;
|
||||||
|
|
||||||
|
float gradientValue = cy / (float)(settings.TerrainFloorHeight * 2 - 1);
|
||||||
|
|
||||||
|
// determine whether or not gradient value is air
|
||||||
|
uint8 stepValue = gradientValue < 0.5f ? 1 : 0;
|
||||||
|
|
||||||
|
chunk.Data.Data[x][y][z] = stepValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sw.Stop();
|
||||||
|
|
||||||
|
Debug.WriteLine($"Terrain Generation: {sw.ElapsedMilliseconds}ms");
|
||||||
|
|
||||||
|
delete sw;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GroundLayer
|
||||||
|
{
|
||||||
|
public int Depth;
|
||||||
|
public uint8 BlockType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroundLayers(Chunk chunk)
|
||||||
|
{
|
||||||
|
GroundLayer[3] layers;
|
||||||
|
layers[0] = .()
|
||||||
|
{
|
||||||
|
Depth = 1,
|
||||||
|
BlockType = 3
|
||||||
|
};
|
||||||
|
layers[1] = .()
|
||||||
|
{
|
||||||
|
Depth = 4,
|
||||||
|
BlockType = 2
|
||||||
|
};
|
||||||
|
layers[2] = .()
|
||||||
|
{
|
||||||
|
Depth = 0,
|
||||||
|
BlockType = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
for(int x < VoxelChunk.SizeX)
|
||||||
|
for(int z < VoxelChunk.SizeZ)
|
||||||
|
{
|
||||||
|
int currentLayer = 0;
|
||||||
|
int currentDepth = 0;
|
||||||
|
|
||||||
|
for(int y = VoxelChunk.SizeY - 1; y > 0; y--)
|
||||||
|
{
|
||||||
|
if(chunk.Data.Data[x][y][z] == 0)
|
||||||
|
{
|
||||||
|
currentDepth--;
|
||||||
|
|
||||||
|
if(currentDepth < 0)
|
||||||
|
{
|
||||||
|
currentDepth = 0;
|
||||||
|
|
||||||
|
currentLayer--;
|
||||||
|
|
||||||
|
if(currentLayer < 0)
|
||||||
|
currentLayer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
chunk.Data.Data[x][y][z] = layers[currentLayer].BlockType;
|
||||||
|
|
||||||
|
currentDepth++;
|
||||||
|
|
||||||
|
if(currentDepth >= layers[currentLayer].Depth)
|
||||||
|
{
|
||||||
|
if(currentLayer >= layers.Count - 1)
|
||||||
|
{
|
||||||
|
currentLayer = layers.Count - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentDepth = 0;
|
||||||
|
currentLayer++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenTestChunk(Chunk chunk)
|
||||||
|
{
|
||||||
|
GenerateTerrain(chunk);
|
||||||
|
GroundLayers(chunk);
|
||||||
|
|
||||||
|
chunk.Geometry?.ReleaseRef();
|
||||||
|
chunk.Geometry = voxelGeoGen.GenerateGeometry(chunk.Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw()
|
||||||
|
{
|
||||||
|
chunkListLock.Enter();
|
||||||
|
for(let pair in chunks)
|
||||||
|
{
|
||||||
|
Chunk chunk = pair.value;
|
||||||
|
|
||||||
|
if(chunk?.Geometry == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Texture.Bind();
|
||||||
|
|
||||||
|
Renderer.Submit(chunk.Geometry, TextureEffect, chunk.Transform);
|
||||||
|
}
|
||||||
|
chunkListLock.Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnImGuiRender()
|
||||||
|
{
|
||||||
|
ImGui.Begin("Voxel Manager");
|
||||||
|
|
||||||
|
int32 oldVd = (.)_viewDistance;
|
||||||
|
|
||||||
|
ImGui.DragInt("View distance", (.)&_viewDistance, 1.0f, 1, 1000);
|
||||||
|
|
||||||
|
if(oldVd != _viewDistance)
|
||||||
|
chunkPosChanged.Exit();
|
||||||
|
|
||||||
|
ImGui.End();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Sandbox.VoxelFun
|
||||||
|
{
|
||||||
|
public struct VoxelChunk
|
||||||
|
{
|
||||||
|
public const int SizeX = 16;
|
||||||
|
public const int SizeY = 256;
|
||||||
|
public const int SizeZ = 16;
|
||||||
|
|
||||||
|
public uint8[SizeX][SizeY][SizeZ] Data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,256 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using GlitchyEngine.Renderer;
|
||||||
|
using GlitchyEngine.Math;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using static Sandbox.VoxelFun.VoxelTestLayer;
|
||||||
|
namespace Sandbox.VoxelFun
|
||||||
|
{
|
||||||
|
enum BlockFace
|
||||||
|
{
|
||||||
|
case None = 0;
|
||||||
|
case Front = 1;
|
||||||
|
case Back = 2;
|
||||||
|
case Left = 4;
|
||||||
|
case Right = 8;
|
||||||
|
case Top = 16;
|
||||||
|
case Bottom = 32;
|
||||||
|
case All = Bottom | Top | Right | Left | Back | Front;
|
||||||
|
|
||||||
|
public BlockFace Opposite
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch(this)
|
||||||
|
{
|
||||||
|
case Front:
|
||||||
|
return Back;
|
||||||
|
case Back:
|
||||||
|
return Front;
|
||||||
|
case Left:
|
||||||
|
return Right;
|
||||||
|
case Right:
|
||||||
|
return Left;
|
||||||
|
case Top:
|
||||||
|
return Bottom;
|
||||||
|
case Bottom:
|
||||||
|
return Top;
|
||||||
|
default:
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VoxelGeometryGenerator
|
||||||
|
{
|
||||||
|
public GraphicsContext Context;
|
||||||
|
public VertexLayout Layout;
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
Color HtoRGB(float h)
|
||||||
|
{
|
||||||
|
var h;
|
||||||
|
h = h % 360.0f;
|
||||||
|
|
||||||
|
float x = (1 - Math.Abs((h / 60.0f) % 2 - 1));
|
||||||
|
|
||||||
|
Vector3 cStrich;
|
||||||
|
|
||||||
|
if(h < 60)
|
||||||
|
cStrich = .(1, x, 0);
|
||||||
|
else if(h < 120)
|
||||||
|
cStrich = .(x, 1, 0);
|
||||||
|
else if(h < 180)
|
||||||
|
cStrich = .(0, 1, x);
|
||||||
|
else if(h < 240)
|
||||||
|
cStrich = .(0, x, 1);
|
||||||
|
else if(h < 300)
|
||||||
|
cStrich = .(x, 0, 1);
|
||||||
|
else
|
||||||
|
cStrich = .(1, 0, x);
|
||||||
|
|
||||||
|
cStrich *= 255.0f;
|
||||||
|
|
||||||
|
return .((uint8)cStrich.X, (uint8)cStrich.Y, (uint8)cStrich.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
//[/Inline]
|
||||||
|
BlockFace GetVisibleFaces(VoxelChunk chunk, int x, int y, int z)
|
||||||
|
{
|
||||||
|
BlockFace visibleFaces = .None;
|
||||||
|
|
||||||
|
if(z == 0 || chunk.Data[x][y][z - 1] == 0)
|
||||||
|
visibleFaces |= .Back;
|
||||||
|
if(z == VoxelChunk.SizeZ - 1 || chunk.Data[x][y][z + 1] == 0)
|
||||||
|
visibleFaces |= .Front;
|
||||||
|
|
||||||
|
if(x == 0 || chunk.Data[x - 1][y][z] == 0)
|
||||||
|
visibleFaces |= .Left;
|
||||||
|
if(x == VoxelChunk.SizeX - 1 || chunk.Data[x + 1][y][z] == 0)
|
||||||
|
visibleFaces |= .Right;
|
||||||
|
|
||||||
|
if(y == 0 || chunk.Data[x][y - 1][z] == 0)
|
||||||
|
visibleFaces |= .Bottom;
|
||||||
|
if(y == VoxelChunk.SizeY - 1 || chunk.Data[x][y + 1][z] == 0)
|
||||||
|
visibleFaces |= .Top;
|
||||||
|
|
||||||
|
return visibleFaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GeometryBinding GenerateGeometry(VoxelChunk chunk)
|
||||||
|
{
|
||||||
|
List<VertexColorTexture> vertices = scope List<VertexColorTexture>();
|
||||||
|
List<uint32> indices = scope List<uint32>();
|
||||||
|
uint32 lastIndex = 0;
|
||||||
|
|
||||||
|
Stopwatch sw = .StartNew();
|
||||||
|
|
||||||
|
for(int x < VoxelChunk.SizeX)
|
||||||
|
for(int y < VoxelChunk.SizeY)
|
||||||
|
for(int z < VoxelChunk.SizeZ)
|
||||||
|
{
|
||||||
|
uint16 blockIndex = chunk.Data[x][y][z];
|
||||||
|
|
||||||
|
Vector3 blockPos = .(x, y, z);
|
||||||
|
|
||||||
|
if(blockIndex != 0)
|
||||||
|
{
|
||||||
|
BlockFace visibleFaces = GetVisibleFaces(chunk, x, y, z);
|
||||||
|
|
||||||
|
if(visibleFaces != .None)
|
||||||
|
GenerateBlockModel(blockIndex, blockPos, visibleFaces, vertices, indices, ref lastIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GeometryBinding gb;
|
||||||
|
|
||||||
|
if(indices.Count > 0)
|
||||||
|
{
|
||||||
|
VertexBuffer vb = new VertexBuffer(Context, typeof(VertexColorTexture), (.)vertices.Count, .Default, .None);
|
||||||
|
vb.SetData<VertexColorTexture>(vertices);
|
||||||
|
|
||||||
|
IndexBuffer ib = new IndexBuffer(Context, (.)indices.Count, .Default, .None, .Index32Bit);
|
||||||
|
ib.SetData<uint32>(indices);
|
||||||
|
|
||||||
|
gb = new GeometryBinding(Context);
|
||||||
|
gb.SetVertexBufferSlot(vb, 0);
|
||||||
|
gb.SetIndexBuffer(ib);
|
||||||
|
gb.SetPrimitiveTopology(.TriangleList);
|
||||||
|
gb.SetVertexLayout(Layout);
|
||||||
|
|
||||||
|
vb.ReleaseRef();
|
||||||
|
ib.ReleaseRef();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gb = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
sw.Stop();
|
||||||
|
|
||||||
|
Debug.WriteLine($"Generation: {sw.ElapsedMilliseconds}");
|
||||||
|
|
||||||
|
delete sw;
|
||||||
|
|
||||||
|
return gb;
|
||||||
|
}
|
||||||
|
|
||||||
|
Random r = new Random(1337) ~ delete _;
|
||||||
|
float f = 0.0f;
|
||||||
|
|
||||||
|
void GenerateBlockModel(uint16 blockIndex, Vector3 blockPosition, BlockFace visibleFaces, List<VertexColorTexture> vertices, List<uint32> indices, ref uint32 lastIndex)
|
||||||
|
{
|
||||||
|
Color c = .Pink;
|
||||||
|
|
||||||
|
if(blockIndex == 1)
|
||||||
|
c = .Gray;
|
||||||
|
else if(blockIndex == 2)
|
||||||
|
c = .SaddleBrown;
|
||||||
|
else if(blockIndex == 3)
|
||||||
|
c = .Green;
|
||||||
|
|
||||||
|
//Color c = .(blockIndex, blockIndex, blockIndex);
|
||||||
|
|
||||||
|
//c = HtoRGB(f += r.Next(0, 0xBEEF));
|
||||||
|
|
||||||
|
if(blockPosition.Y == 63)
|
||||||
|
c = .Red;
|
||||||
|
|
||||||
|
if(visibleFaces.HasFlag(.Back))
|
||||||
|
{
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 0), c, .UnitY));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 0), c, .One));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 0), c, .UnitX));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 0), c, .Zero));
|
||||||
|
|
||||||
|
AddQuadIndices(ref lastIndex, indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(visibleFaces.HasFlag(.Top))
|
||||||
|
{
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 0), c, .UnitY));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 0), c, .One));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 1), c, .UnitX));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 1), c, .Zero));
|
||||||
|
|
||||||
|
AddQuadIndices(ref lastIndex, indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(visibleFaces.HasFlag(.Bottom))
|
||||||
|
{
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 1), c, .UnitY));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 1), c, .One));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 0), c, .UnitX));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 0), c, .Zero));
|
||||||
|
|
||||||
|
AddQuadIndices(ref lastIndex, indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(visibleFaces.HasFlag(.Front))
|
||||||
|
{
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 1), c, .UnitY));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 1), c, .One));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 1), c, .UnitX));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 1), c, .Zero));
|
||||||
|
|
||||||
|
AddQuadIndices(ref lastIndex, indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(visibleFaces.HasFlag(.Right))
|
||||||
|
{
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 0), c, .UnitY));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 1), c, .One));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 1), c, .UnitX));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 0), c, .Zero));
|
||||||
|
|
||||||
|
AddQuadIndices(ref lastIndex, indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(visibleFaces.HasFlag(.Left))
|
||||||
|
{
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 1), c, .UnitY));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 0), c, .One));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 0), c, .UnitX));
|
||||||
|
vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 1), c, .Zero));
|
||||||
|
|
||||||
|
AddQuadIndices(ref lastIndex, indices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddQuadIndices(ref uint32 lastIndex, List<uint32> indices)
|
||||||
|
{
|
||||||
|
uint32[6] inds;
|
||||||
|
inds[0] = lastIndex;
|
||||||
|
inds[1] = lastIndex + 1;
|
||||||
|
inds[2] = lastIndex + 2;
|
||||||
|
|
||||||
|
inds[3] = lastIndex + 2;
|
||||||
|
inds[4] = lastIndex + 3;
|
||||||
|
inds[5] = lastIndex;
|
||||||
|
|
||||||
|
indices.AddRange(inds);
|
||||||
|
lastIndex += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,605 @@
|
|||||||
|
using System;
|
||||||
|
using GlitchyEngine;
|
||||||
|
using GlitchyEngine.Math;
|
||||||
|
using GlitchyEngine.Renderer;
|
||||||
|
using ImGui;
|
||||||
|
using GlitchyEngine.ImGui;
|
||||||
|
using GlitchyEngine.Events;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Sandbox.VoxelFun
|
||||||
|
{
|
||||||
|
public class VoxelTestLayer : Layer
|
||||||
|
{
|
||||||
|
private PerspectiveCamera _camera ~ delete _;
|
||||||
|
|
||||||
|
[Ordered]
|
||||||
|
public struct VertexColorTexture : IVertexData
|
||||||
|
{
|
||||||
|
public Vector3 Position;
|
||||||
|
public Color Color;
|
||||||
|
public Vector2 TexCoord;
|
||||||
|
|
||||||
|
public this() => this = default;
|
||||||
|
|
||||||
|
public this(Vector3 pos, Color color)
|
||||||
|
{
|
||||||
|
Position = pos;
|
||||||
|
Color = color;
|
||||||
|
TexCoord = .();
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(Vector3 pos, Color color, Vector2 texCoord)
|
||||||
|
{
|
||||||
|
Position = pos;
|
||||||
|
Color = color;
|
||||||
|
TexCoord = texCoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly VertexElement[] VertexElements ~ delete _;
|
||||||
|
|
||||||
|
public static VertexElement[] IVertexData.VertexElements => VertexElements;
|
||||||
|
|
||||||
|
static this()
|
||||||
|
{
|
||||||
|
VertexElements = new VertexElement[](
|
||||||
|
VertexElement(.R32G32B32_Float, "POSITION"),
|
||||||
|
VertexElement(.R8G8B8A8_UNorm, "COLOR"),
|
||||||
|
VertexElement(.R32G32_Float, "TEXCOORD"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexLayout _vertexLayout ~ delete _;
|
||||||
|
|
||||||
|
GeometryBinding _chunkGeoBinding ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
GeometryBinding _geometryBinding ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
GeometryBinding _quadGeometryBinding ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
RasterizerState _rasterizerState ~ delete _;
|
||||||
|
|
||||||
|
Effect _effect ~ _?.ReleaseRef();
|
||||||
|
Effect _textureEffect ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
GraphicsContext _context ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
Texture2D _texture ~ _?.ReleaseRef();
|
||||||
|
Texture2D _ge_logo ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
BlendState _alphaBlendState ~ _?.ReleaseRef();
|
||||||
|
BlendState _opaqueBlendState ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
DepthStencilTarget _depthStencilTarget ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
ChunkManager _chunkManager ~ delete _;
|
||||||
|
|
||||||
|
World _world ~ delete _;
|
||||||
|
|
||||||
|
private Vector3 CircleCoord(float angle)
|
||||||
|
{
|
||||||
|
return .(Math.Cos(angle), Math.Sin(angle), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowAppend]
|
||||||
|
public this() : base("VoxelTest")
|
||||||
|
{
|
||||||
|
_context = Application.Get().Window.Context..AddRef();
|
||||||
|
|
||||||
|
_depthStencilTarget = new DepthStencilTarget(_context, _context.SwapChain.Width, _context.SwapChain.Height);
|
||||||
|
|
||||||
|
_effect = new Effect(_context, "content\\Shaders\\basicShader.hlsl");
|
||||||
|
|
||||||
|
_textureEffect = new Effect(_context, "content\\Shaders\\textureShader.hlsl");
|
||||||
|
|
||||||
|
// Create Input Layout
|
||||||
|
|
||||||
|
_vertexLayout = new VertexLayout(_context, VertexColorTexture.VertexElements, _textureEffect.VertexShader);
|
||||||
|
// Create hexagon
|
||||||
|
{
|
||||||
|
_geometryBinding = new GeometryBinding(_context);
|
||||||
|
_geometryBinding.SetPrimitiveTopology(.TriangleList);
|
||||||
|
_geometryBinding.SetVertexLayout(_vertexLayout);
|
||||||
|
|
||||||
|
float pO3 = Math.PI_f / 3.0f;
|
||||||
|
VertexColorTexture[?] vertices = .(
|
||||||
|
VertexColorTexture(.Zero, Color(255,255,255)),
|
||||||
|
VertexColorTexture(CircleCoord(0), Color(255, 0, 0)),
|
||||||
|
VertexColorTexture(CircleCoord(pO3), Color(255,255, 0)),
|
||||||
|
VertexColorTexture(CircleCoord(pO3*2), Color( 0,255, 0)),
|
||||||
|
VertexColorTexture(CircleCoord(Math.PI_f), Color( 0,255,255)),
|
||||||
|
VertexColorTexture(CircleCoord(-pO3*2), Color( 0, 0,255)),
|
||||||
|
VertexColorTexture(CircleCoord(-pO3), Color(255, 0,255)),
|
||||||
|
);
|
||||||
|
|
||||||
|
let vb = new VertexBuffer(_context, typeof(VertexColorTexture), (.)vertices.Count, .Immutable);
|
||||||
|
vb.SetData(vertices);
|
||||||
|
_geometryBinding.SetVertexBufferSlot(vb, 0);
|
||||||
|
vb.ReleaseRef();
|
||||||
|
|
||||||
|
uint16[?] indices = .(
|
||||||
|
0, 1, 2,
|
||||||
|
0, 2, 3,
|
||||||
|
0, 3, 4,
|
||||||
|
0, 4, 5,
|
||||||
|
0, 5, 6,
|
||||||
|
0, 6, 1);
|
||||||
|
|
||||||
|
let ib = new IndexBuffer(_context, (.)indices.Count, .Immutable);
|
||||||
|
ib.SetData(indices);
|
||||||
|
_geometryBinding.SetIndexBuffer(ib);
|
||||||
|
ib.ReleaseRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Quad
|
||||||
|
{
|
||||||
|
_quadGeometryBinding = new GeometryBinding(_context);
|
||||||
|
_quadGeometryBinding.SetPrimitiveTopology(.TriangleList);
|
||||||
|
_quadGeometryBinding.SetVertexLayout(_vertexLayout);
|
||||||
|
|
||||||
|
VertexColorTexture[?] vertices = .(
|
||||||
|
VertexColorTexture(Vector3(-0.75f, 0.75f, 0), Color.White, .(0, 0)),
|
||||||
|
VertexColorTexture(Vector3(-0.75f, -0.75f, 0), Color.White, .(0, 1)),
|
||||||
|
VertexColorTexture(Vector3(0.75f, -0.75f, 0), Color.White, .(1, 1)),
|
||||||
|
VertexColorTexture(Vector3(0.75f, 0.75f, 0), Color.White, .(1, 0)),
|
||||||
|
);
|
||||||
|
|
||||||
|
let qvb = new VertexBuffer(_context, typeof(VertexColorTexture), (.)vertices.Count, .Immutable);
|
||||||
|
qvb.SetData(vertices);
|
||||||
|
_quadGeometryBinding.SetVertexBufferSlot(qvb, 0);
|
||||||
|
qvb.ReleaseRef();
|
||||||
|
|
||||||
|
uint16[?] indices = .(
|
||||||
|
0, 1, 2,
|
||||||
|
2, 3, 0);
|
||||||
|
|
||||||
|
let qib = new IndexBuffer(_context, (.)indices.Count, .Immutable);
|
||||||
|
qib.SetData(indices);
|
||||||
|
_quadGeometryBinding.SetIndexBuffer(qib);
|
||||||
|
qib.ReleaseRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create rasterizer state
|
||||||
|
GlitchyEngine.Renderer.RasterizerStateDescription rsDesc = .(.Solid, .Back, true);
|
||||||
|
rsDesc.DepthClipEnabled = true;
|
||||||
|
_rasterizerState = new RasterizerState(_context, rsDesc);
|
||||||
|
|
||||||
|
// Camera
|
||||||
|
_camera = new PerspectiveCamera();
|
||||||
|
_camera.NearPlane = 0.1f;
|
||||||
|
_camera.FarPlane = 1000.0f;
|
||||||
|
_camera.FovY = Math.PI_f / 4;
|
||||||
|
_camera.Position = .(0, 128, 0);//-320
|
||||||
|
|
||||||
|
_texture = new Texture2D(_context, "content/Textures/Checkerboard.dds");
|
||||||
|
_ge_logo = new Texture2D(_context, "content/Textures/GE_Logo.dds");
|
||||||
|
|
||||||
|
let sampler = SamplerStateManager.GetSampler(
|
||||||
|
SamplerStateDescription()
|
||||||
|
{
|
||||||
|
MagFilter = .Point
|
||||||
|
});
|
||||||
|
|
||||||
|
_texture.SamplerState = sampler;
|
||||||
|
_ge_logo.SamplerState = sampler;
|
||||||
|
|
||||||
|
sampler.ReleaseRef();
|
||||||
|
|
||||||
|
BlendStateDescription blendDesc = .();
|
||||||
|
blendDesc.RenderTarget[0] = .(true, .SourceAlpha, .InvertedSourceAlpha, .Add, .SourceAlpha, .InvertedSourceAlpha, .Add, .All);
|
||||||
|
_alphaBlendState = new BlendState(_context, blendDesc);
|
||||||
|
_opaqueBlendState = new BlendState(_context, .Default);
|
||||||
|
|
||||||
|
|
||||||
|
_chunkManager = new ChunkManager(_context, _vertexLayout);
|
||||||
|
_chunkManager.Texture = _texture..AddRef();
|
||||||
|
_chunkManager.TextureEffect = _textureEffect..AddRef();
|
||||||
|
|
||||||
|
_world = new World();
|
||||||
|
if(World.CreateWorld("test", 1337, _world) case .Err(.WorldAlreadyExists))
|
||||||
|
{
|
||||||
|
World.LoadWorld("test", _world);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
void GenerateTerrain(ref VoxelChunk vc)
|
||||||
|
{
|
||||||
|
Stopwatch sw = .StartNew();
|
||||||
|
/*
|
||||||
|
float[] gradient = scope .[VoxelChunk.SizeY](?);
|
||||||
|
for(int y = 0; y < VoxelChunk.SizeY; y++)
|
||||||
|
{
|
||||||
|
gradient[y] = y / (float)(VoxelChunk.SizeY - 1);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//Random r = scope Random();
|
||||||
|
let groundNoise = scope FastNoiseLite.FastNoiseLite();
|
||||||
|
groundNoise.SetFractalOctaves(6);
|
||||||
|
groundNoise.SetFractalType(.FBm);
|
||||||
|
groundNoise.SetFrequency(0.0075f);
|
||||||
|
|
||||||
|
let perturbNoise = scope FastNoiseLite.FastNoiseLite();
|
||||||
|
perturbNoise.SetFractalOctaves(6);
|
||||||
|
perturbNoise.SetFractalType(.FBm);
|
||||||
|
perturbNoise.SetFrequency(0.005f);
|
||||||
|
|
||||||
|
for(int x < VoxelChunk.SizeX)
|
||||||
|
for(int y < VoxelChunk.SizeY)
|
||||||
|
for(int z < VoxelChunk.SizeZ)
|
||||||
|
{
|
||||||
|
//(int X, int Y, int Z) coordinate = (x, y, z);
|
||||||
|
|
||||||
|
// randomize coordinate
|
||||||
|
//coordinate.Y += (int)(groundNoise.GetNoise(x, 0, z) * VoxelChunk.SizeY / 4);//r.Next(-VoxelChunk.SizeY / 4, VoxelChunk.SizeY / 4);
|
||||||
|
|
||||||
|
|
||||||
|
//float pertubation = perturbNoise.GetNoise(y * 0.5f, -y * 0.5f) * 30;
|
||||||
|
|
||||||
|
//coordinate.Y += (int)(groundNoise.GetNoise(x + pertubation, z + pertubation) * VoxelChunk.SizeY / 4);//r.Next(-VoxelChunk.SizeY / 4, VoxelChunk.SizeY / 4);
|
||||||
|
|
||||||
|
//coordinate.Y = Math.Clamp(coordinate.Y, 0, VoxelChunk.SizeY - 1);
|
||||||
|
|
||||||
|
// get Gradient for coordinate
|
||||||
|
//float gradientValue = gradient[coordinate.Y];
|
||||||
|
|
||||||
|
float cy = (float)y;
|
||||||
|
cy += groundNoise.GetNoise(x, cy * 0.5f, z) * (VoxelChunk.SizeY / 4.0f);
|
||||||
|
|
||||||
|
float gradientValue = cy / (float)(VoxelChunk.SizeY - 1);
|
||||||
|
|
||||||
|
// determine whether or not gradient value is air
|
||||||
|
uint8 stepValue = gradientValue < 0.5f ? 1 : 0;
|
||||||
|
|
||||||
|
vc.Data[x][y][z] = stepValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sw.Stop();
|
||||||
|
|
||||||
|
Debug.WriteLine($"Terrain Generation: {sw.ElapsedMilliseconds}ms");
|
||||||
|
|
||||||
|
delete sw;
|
||||||
|
|
||||||
|
/*
|
||||||
|
let elevationNoise = scope FastNoiseLite.FastNoiseLite();
|
||||||
|
//elevationNoise.
|
||||||
|
|
||||||
|
for(int x < VoxelChunk.SizeX)
|
||||||
|
for(int y < VoxelChunk.SizeY)
|
||||||
|
for(int z < VoxelChunk.SizeZ)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
float elevation = elevationNoise.GetNoise(x, z);
|
||||||
|
|
||||||
|
int height = (int)((elevation) * 64 + 64);
|
||||||
|
|
||||||
|
for(int y < height)
|
||||||
|
{
|
||||||
|
vc.Data[x][y][z] = 1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
vc.Data[x][y][z] = ((elevationNoise.GetNoise(x, y, z) * 64) + y) < 64 ? 1 : 0;
|
||||||
|
//vc.Data[x][y][z] = elevationNoise.GetNoise(x, y, z) > 0.0f ? 1 : 0;
|
||||||
|
|
||||||
|
//vc.Data[x][y][z] = (noise.GetNoise(x, y, z) + 0.5f) < 0 ? 0 : 1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
for(int x < VoxelChunk.SizeX)
|
||||||
|
for(int z < VoxelChunk.SizeZ)
|
||||||
|
{
|
||||||
|
float f = noise.GetNoise(x, z);
|
||||||
|
|
||||||
|
int yMax = (int)(f * VoxelChunk.SizeY);
|
||||||
|
|
||||||
|
for(int y < yMax)
|
||||||
|
{
|
||||||
|
vc.Data[x][y][z] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GroundLayer
|
||||||
|
{
|
||||||
|
public int Depth;
|
||||||
|
public uint8 BlockType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroundLayers(ref VoxelChunk vc)
|
||||||
|
{
|
||||||
|
GroundLayer[3] layers;
|
||||||
|
layers[0] = .()
|
||||||
|
{
|
||||||
|
Depth = 1,
|
||||||
|
BlockType = 3
|
||||||
|
};
|
||||||
|
layers[1] = .()
|
||||||
|
{
|
||||||
|
Depth = 4,
|
||||||
|
BlockType = 2
|
||||||
|
};
|
||||||
|
layers[2] = .()
|
||||||
|
{
|
||||||
|
Depth = 0,
|
||||||
|
BlockType = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
for(int x < VoxelChunk.SizeX)
|
||||||
|
for(int z < VoxelChunk.SizeZ)
|
||||||
|
{
|
||||||
|
int currentLayer = 0;
|
||||||
|
int currentDepth = 0;
|
||||||
|
|
||||||
|
for(int y = VoxelChunk.SizeY - 1; y > 0; y--)
|
||||||
|
{
|
||||||
|
if(vc.Data[x][y][z] == 0)
|
||||||
|
{
|
||||||
|
currentDepth--;
|
||||||
|
|
||||||
|
if(currentDepth < 0)
|
||||||
|
{
|
||||||
|
currentDepth = 0;
|
||||||
|
|
||||||
|
currentLayer--;
|
||||||
|
|
||||||
|
if(currentLayer < 0)
|
||||||
|
currentLayer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vc.Data[x][y][z] = layers[currentLayer].BlockType;
|
||||||
|
|
||||||
|
currentDepth++;
|
||||||
|
|
||||||
|
if(currentDepth >= layers[currentLayer].Depth)
|
||||||
|
{
|
||||||
|
if(currentLayer >= layers.Count - 1)
|
||||||
|
{
|
||||||
|
currentLayer = layers.Count - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentDepth = 0;
|
||||||
|
currentLayer++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenTestChunk()
|
||||||
|
{
|
||||||
|
VoxelChunk* vc = new .();
|
||||||
|
|
||||||
|
GenerateTerrain(ref *vc);
|
||||||
|
GroundLayers(ref *vc);
|
||||||
|
/*
|
||||||
|
Random r = scope Random();
|
||||||
|
|
||||||
|
for(int x < VoxelChunk.SizeX)
|
||||||
|
for(int y < VoxelChunk.SizeY)
|
||||||
|
for(int z < VoxelChunk.SizeZ)
|
||||||
|
{
|
||||||
|
vc.Data[x][y][z] = (.)y;//(.)r.Next(0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int x < VoxelChunk.SizeX)
|
||||||
|
for(int y < VoxelChunk.SizeY)
|
||||||
|
for(int z < VoxelChunk.SizeZ)
|
||||||
|
{
|
||||||
|
if(vc.Data[x][y][z] < VoxelChunk.SizeY / 2)
|
||||||
|
vc.Data[x][y][z] = 1;
|
||||||
|
else
|
||||||
|
vc.Data[x][y][z] = 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
vc.Data[8][VoxelChunk.SizeY / 2][8] = 1;
|
||||||
|
vc.Data[8][VoxelChunk.SizeY / 2 + 1][8] = 1;
|
||||||
|
vc.Data[8][VoxelChunk.SizeY / 2 + 2][8] = 1;
|
||||||
|
vc.Data[8][VoxelChunk.SizeY / 2 + 3][8] = 1;
|
||||||
|
|
||||||
|
for(int x = 6; x < 11; x++)
|
||||||
|
for(int y = VoxelChunk.SizeY / 2 + 2; y < VoxelChunk.SizeY / 2 + 5; y++)
|
||||||
|
for(int z = 6; z < 11; z++)
|
||||||
|
{
|
||||||
|
vc.Data[x][y][z] = 1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
_chunkGeoBinding = voxelGeoGen.GenerateGeometry(*vc);
|
||||||
|
|
||||||
|
delete vc;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
void UpdateCamera(GameTime gameTime)
|
||||||
|
{
|
||||||
|
UpdateCameraRotation(gameTime);
|
||||||
|
UpdateCameraMovement(gameTime);
|
||||||
|
|
||||||
|
//_camera.Width = _context.SwapChain.BackbufferViewport.Width / 256;
|
||||||
|
//_camera.Height = _context.SwapChain.BackbufferViewport.Height / 256;
|
||||||
|
|
||||||
|
_camera.AspectRatio = Application.Get().Window.Context.SwapChain.BackbufferViewport.Width /
|
||||||
|
Application.Get().Window.Context.SwapChain.BackbufferViewport.Height;
|
||||||
|
|
||||||
|
_camera.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
double cameraRotationSpeedX = 0.0001f;
|
||||||
|
double cameraRotationSpeedY = 0.0001f;
|
||||||
|
|
||||||
|
bool b = true;
|
||||||
|
|
||||||
|
void UpdateCameraRotation(GameTime gameTime)
|
||||||
|
{
|
||||||
|
if(b)
|
||||||
|
{
|
||||||
|
b = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mouseMovement = Input.GetMouseMovement();
|
||||||
|
|
||||||
|
if(mouseMovement.X == 0 && mouseMovement.Y == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Vector3 rotation = _camera.Rotation;
|
||||||
|
|
||||||
|
rotation.Y = (float)(rotation.Y + mouseMovement.X * cameraRotationSpeedX * gameTime.FrameTime.TotalMilliseconds);
|
||||||
|
rotation.X = (float)(rotation.X + mouseMovement.Y * cameraRotationSpeedY * gameTime.FrameTime.TotalMilliseconds);
|
||||||
|
|
||||||
|
rotation.X = Math.Clamp(rotation.X, -Math.PI_f / 2, Math.PI_f / 2);
|
||||||
|
|
||||||
|
_camera.Rotation = rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
float movementSpeed = 2;
|
||||||
|
float movementSpeedFast = 20;
|
||||||
|
|
||||||
|
void UpdateCameraMovement(GameTime gameTime)
|
||||||
|
{
|
||||||
|
Vector3 movement = .();
|
||||||
|
|
||||||
|
if(Input.IsKeyPressed(Key.W))
|
||||||
|
{
|
||||||
|
movement.Z += 1;
|
||||||
|
}
|
||||||
|
if(Input.IsKeyPressed(Key.S))
|
||||||
|
{
|
||||||
|
movement.Z -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Input.IsKeyPressed(Key.A))
|
||||||
|
{
|
||||||
|
movement.X -= 1;
|
||||||
|
}
|
||||||
|
if(Input.IsKeyPressed(Key.D))
|
||||||
|
{
|
||||||
|
movement.X += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Input.IsKeyPressed(Key.Space))
|
||||||
|
{
|
||||||
|
movement.Y += 1;
|
||||||
|
}
|
||||||
|
if(Input.IsKeyPressed(Key.Control))
|
||||||
|
{
|
||||||
|
movement.Y -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(movement != .Zero)
|
||||||
|
movement.Normalize();
|
||||||
|
|
||||||
|
movement *= (float)(gameTime.FrameTime.TotalSeconds);
|
||||||
|
|
||||||
|
Matrix rot = .RotationY(_camera.Rotation.Y) * .RotationX(_camera.Rotation.X);
|
||||||
|
|
||||||
|
movement = ((Vector4)(rot * Vector4(movement, 1.0f))).XYZ;
|
||||||
|
|
||||||
|
float speed = Input.IsKeyPressed(Key.Shift) ? movementSpeedFast : movementSpeed;
|
||||||
|
|
||||||
|
_camera.Position += movement * speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
UpdateCamera(gameTime);
|
||||||
|
|
||||||
|
_chunkManager.Update(_camera.Position);
|
||||||
|
|
||||||
|
//RenderCommand.Clear(null, .(0.2f, 0.2f, 0.2f));
|
||||||
|
RenderCommand.Clear(null, .CornflowerBlue);
|
||||||
|
RenderCommand.Clear(_depthStencilTarget, 1.0f, 0, .Depth);
|
||||||
|
|
||||||
|
// Draw test geometry
|
||||||
|
_depthStencilTarget.Bind();
|
||||||
|
_context.SetRenderTarget(null);
|
||||||
|
_context.BindRenderTargets();
|
||||||
|
|
||||||
|
_context.SetRasterizerState(_rasterizerState);
|
||||||
|
|
||||||
|
_context.SetViewport(_context.SwapChain.BackbufferViewport);
|
||||||
|
|
||||||
|
Renderer.BeginScene(_camera);
|
||||||
|
|
||||||
|
_opaqueBlendState.Bind();
|
||||||
|
|
||||||
|
for(int x < 20)
|
||||||
|
for(int y < 20)
|
||||||
|
{
|
||||||
|
if((x + y) % 2 == 0)
|
||||||
|
_effect.Variables["BaseColor"].SetData(_squareColor0);
|
||||||
|
else
|
||||||
|
_effect.Variables["BaseColor"].SetData(_squareColor1);
|
||||||
|
|
||||||
|
Matrix transform = Matrix.Translation(x * 0.2f, y * 0.2f, 0) * Matrix.Scaling(0.1f);
|
||||||
|
Renderer.Submit(_quadGeometryBinding, _effect, transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
_effect.Variables["BaseColor"].SetData(_squareColor1);
|
||||||
|
|
||||||
|
_texture.Bind();
|
||||||
|
Renderer.Submit(_quadGeometryBinding, _textureEffect, .Scaling(1.5f));
|
||||||
|
|
||||||
|
_alphaBlendState.Bind();
|
||||||
|
|
||||||
|
_ge_logo.Bind();
|
||||||
|
Renderer.Submit(_quadGeometryBinding, _textureEffect, .Scaling(1.5f));
|
||||||
|
|
||||||
|
_chunkManager.Draw();
|
||||||
|
|
||||||
|
//_texture.Bind();
|
||||||
|
//Renderer.Submit(_chunkGeoBinding, _textureEffect, .Identity);
|
||||||
|
|
||||||
|
Renderer.EndScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGBA _squareColor0 = ColorRGBA.CornflowerBlue;
|
||||||
|
ColorRGBA _squareColor1;
|
||||||
|
|
||||||
|
public override void OnEvent(Event event)
|
||||||
|
{
|
||||||
|
EventDispatcher dispatcher = scope EventDispatcher(event);
|
||||||
|
|
||||||
|
dispatcher.Dispatch<ImGuiRenderEvent>(scope (e) => OnImGuiRender(e));
|
||||||
|
dispatcher.Dispatch<WindowResizeEvent>(scope (e) => OnWindowResize(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool OnWindowResize(WindowResizeEvent e)
|
||||||
|
{
|
||||||
|
_depthStencilTarget?.ReleaseRef();
|
||||||
|
|
||||||
|
_depthStencilTarget = new DepthStencilTarget(_context, _context.SwapChain.Width, _context.SwapChain.Height);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool OnImGuiRender(ImGuiRenderEvent e)
|
||||||
|
{
|
||||||
|
_chunkManager.OnImGuiRender();
|
||||||
|
|
||||||
|
ImGui.Begin("Test");
|
||||||
|
|
||||||
|
ImGui.DragFloat("Slow Speed", &movementSpeed, 1.0f, 0.01f, 100.0f);
|
||||||
|
ImGui.DragFloat("Fast Speed", &movementSpeedFast, 1.0f, 1f, 10000.0f);
|
||||||
|
|
||||||
|
Vector3 camPos = _camera.Position;
|
||||||
|
|
||||||
|
ImGui.DragFloat3("Position", *(float[3]*)(void*)&camPos, 1.0f, float.NegativeInfinity, float.PositiveInfinity);
|
||||||
|
|
||||||
|
_camera.Position = camPos;
|
||||||
|
|
||||||
|
ImGui.ColorEdit3("Square Color", ref _squareColor0);
|
||||||
|
|
||||||
|
_squareColor1 = ColorRGBA.White - _squareColor0;
|
||||||
|
|
||||||
|
ImGui.End();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace Sandbox.VoxelFun
|
||||||
|
{
|
||||||
|
public class World
|
||||||
|
{
|
||||||
|
public enum CreateError
|
||||||
|
{
|
||||||
|
case WorldAlreadyExists;
|
||||||
|
case CreateDirectoryError(Platform.BfpFileResult error);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum LoadError
|
||||||
|
{
|
||||||
|
case WorldDoesNotExist;
|
||||||
|
case DirectoryError(Platform.BfpFileResult error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int64 _seed;
|
||||||
|
private String _name ~ delete _;
|
||||||
|
private String _directory ~ delete _;
|
||||||
|
|
||||||
|
public int64 Seed => _seed;
|
||||||
|
public String Name => _name;
|
||||||
|
public String Directory => _directory;
|
||||||
|
|
||||||
|
const String WorldsDirectory = "worlds";
|
||||||
|
const String WorldFileName = "world.info";
|
||||||
|
|
||||||
|
public static Result<void, CreateError> CreateWorld(String name, int64 seed, World outWorld)
|
||||||
|
{
|
||||||
|
String worldPath = new String();
|
||||||
|
Path.InternalCombine(worldPath, WorldsDirectory, name);
|
||||||
|
|
||||||
|
if(Directory.Exists(worldPath))
|
||||||
|
{
|
||||||
|
delete worldPath;
|
||||||
|
return .Err(.WorldAlreadyExists);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Directory.CreateDirectory(worldPath) case .Err(let error))
|
||||||
|
{
|
||||||
|
delete worldPath;
|
||||||
|
return .Err(.CreateDirectoryError(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
String worldFilePath = Path.InternalCombine(.. scope .(), worldPath, WorldFileName);
|
||||||
|
|
||||||
|
MemoryStream str = scope MemoryStream();
|
||||||
|
str.Write(seed);
|
||||||
|
|
||||||
|
Span<uint8> data = .(str.[Friend]mMemory.Ptr, str.Length);
|
||||||
|
|
||||||
|
File.WriteAll(worldFilePath, data);
|
||||||
|
|
||||||
|
outWorld._name = new String(name);
|
||||||
|
outWorld._directory = worldPath;
|
||||||
|
outWorld._seed = seed;
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result<void, LoadError> LoadWorld(String name, World outWorld)
|
||||||
|
{
|
||||||
|
String worldPath = new String();
|
||||||
|
Path.InternalCombine(worldPath, WorldsDirectory, name);
|
||||||
|
|
||||||
|
if(!Directory.Exists(worldPath))
|
||||||
|
return .Err(.WorldDoesNotExist);
|
||||||
|
|
||||||
|
String worldFilePath = Path.InternalCombine(.. scope .(), worldPath, WorldFileName);
|
||||||
|
|
||||||
|
List<uint8> data = scope .();
|
||||||
|
|
||||||
|
File.ReadAll(worldFilePath, data);
|
||||||
|
|
||||||
|
int64 seed = *(int64*)data.Ptr;
|
||||||
|
|
||||||
|
outWorld._name = new String(name);
|
||||||
|
outWorld._directory = worldPath;
|
||||||
|
outWorld._seed = seed;
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Reference in New Issue
Block a user