Geometry Generation now in Block

This commit is contained in:
Simon Lübeß
2021-03-18 17:22:41 +01:00
parent 4e87f5f144
commit 8320689d3e
8 changed files with 280 additions and 126 deletions
@@ -33,8 +33,7 @@ namespace GlitchyEngine.Math
[Comptime] [Comptime]
public void ApplyToType(Type type) public void ApplyToType(Type type)
{ {
// TODO: report bug... sized array not working String[4] componentNames = .("X", "Y", "Z", "W");
String[] componentNames = scope String[]("X", "Y", "Z", "W");
for(int swizzleCount = 2; swizzleCount <= 4; swizzleCount++) for(int swizzleCount = 2; swizzleCount <= 4; swizzleCount++)
{ {
@@ -50,7 +49,7 @@ namespace GlitchyEngine.Math
{ {
String swizzleName = scope String(swizzleCount); String swizzleName = scope String(swizzleCount);
String swizzleConstructor = scope String(swizzleCount * 3); String swizzleConstructor = scope String(swizzleCount * 3);
String setter = scope String(128); String setter = scope String();
bool setterInvalid = invalidSetter(cmp, swizzleCount); bool setterInvalid = invalidSetter(cmp, swizzleCount);
@@ -64,7 +63,7 @@ namespace GlitchyEngine.Math
} }
swizzleConstructor.Append(componentNames[cmp[c]]); swizzleConstructor.Append(componentNames[cmp[c]]);
if(!setterInvalid && c < _vectorSize) // if(!setterInvalid && c < _vectorSize)
{ {
setter.AppendF($"\n\t\t{componentNames[cmp[c]]} = value.{componentNames[c]};"); setter.AppendF($"\n\t\t{componentNames[cmp[c]]} = value.{componentNames[c]};");
} }
+23 -3
View File
@@ -1,20 +1,40 @@
using GlitchyEngine.Math; using GlitchyEngine.Math;
using GlitchyEngine;
namespace Sandbox.VoxelFun namespace Sandbox.VoxelFun
{ {
class Block class Block
{ {
private Model _model;
private uint16 _blockID; private uint16 _blockID;
public uint16 ID => _blockID; public uint16 ID => _blockID;
public Color Color {get;} public Model Model => _model;
public BlockFace VisibleNeighbors {get;} public BlockFace VisibleNeighbors {get;}
public this(Color color, BlockFace visibleNeighbors = .None) public this(BlockFace visibleNeighbors = .None)
{ {
Color = color;
VisibleNeighbors = visibleNeighbors; VisibleNeighbors = visibleNeighbors;
} }
/**
* This method will be called when the block is being destroyed by the player.
* @param blockCoordinate The coordinate the block is at.
*/
public virtual void OnBreaking(Int32_3 blockCoordinate)
{
Log.ClientLogger.Info($"I broke. {{{blockCoordinate}}}");
}
/**
* This method will be called when the block is being placed by the player.
* @param blockCoordinate The coordinate the block is at.
*/
public virtual void OnPlacing(Int32_3 blockCoordinate)
{
Log.ClientLogger.Info($"I broke. {{{blockCoordinate}}}");
}
} }
} }
+98
View File
@@ -0,0 +1,98 @@
using System.Collections;
using GlitchyEngine.Math;
using static Sandbox.VoxelFun.VoxelTestLayer;
namespace Sandbox.VoxelFun
{
abstract class Model
{
public abstract void GenerateGeometry(Block block, Vector3 blockPosition, BlockFace visibleFaces, List<VertexColorTexture> vertices, List<uint32> indices, ref uint32 lastIndex);
protected static 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;
}
}
class BlockModel : Model
{
Color _color;
public this(Color color)
{
_color = color;
}
public override void GenerateGeometry(Block block, Vector3 blockPosition, BlockFace visibleFaces, List<VertexColorTexture> vertices, List<uint32> indices, ref uint32 lastIndex)
{
if(visibleFaces.HasFlag(.Back))
{
vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 0), _color, .UnitY));
vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 0), _color, .One));
vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 0), _color, .UnitX));
vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 0), _color, .Zero));
AddQuadIndices(ref lastIndex, indices);
}
if(visibleFaces.HasFlag(.Top))
{
vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 0), _color, .UnitY));
vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 0), _color, .One));
vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 1), _color, .UnitX));
vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 1), _color, .Zero));
AddQuadIndices(ref lastIndex, indices);
}
if(visibleFaces.HasFlag(.Bottom))
{
vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 1), _color, .UnitY));
vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 1), _color, .One));
vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 0), _color, .UnitX));
vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 0), _color, .Zero));
AddQuadIndices(ref lastIndex, indices);
}
if(visibleFaces.HasFlag(.Front))
{
vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 1), _color, .UnitY));
vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 1), _color, .One));
vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 1), _color, .UnitX));
vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 1), _color, .Zero));
AddQuadIndices(ref lastIndex, indices);
}
if(visibleFaces.HasFlag(.Right))
{
vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 0), _color, .UnitY));
vertices.Add(VertexColorTexture(blockPosition + .(1, 0, 1), _color, .One));
vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 1), _color, .UnitX));
vertices.Add(VertexColorTexture(blockPosition + .(1, 1, 0), _color, .Zero));
AddQuadIndices(ref lastIndex, indices);
}
if(visibleFaces.HasFlag(.Left))
{
vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 1), _color, .UnitY));
vertices.Add(VertexColorTexture(blockPosition + .(0, 0, 0), _color, .One));
vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 0), _color, .UnitX));
vertices.Add(VertexColorTexture(blockPosition + .(0, 1, 1), _color, .Zero));
AddQuadIndices(ref lastIndex, indices);
}
}
}
}
+12 -4
View File
@@ -8,11 +8,19 @@ namespace Sandbox.VoxelFun
static List<Block> _blocks = new List<Block>() ~ DeleteContainerAndItems!(_); static List<Block> _blocks = new List<Block>() ~ DeleteContainerAndItems!(_);
/// Air is a special Block. It defines the absence of a block. /// Air is a special Block. It defines the absence of a block.
public static Block Air = RegisterBlock(.. new Block(.White, .All)); public static Block Air;
public static Block Stone = RegisterBlock(.. new Block(.Gray)); public static Block Stone;
public static Block Grass = RegisterBlock(.. new Block(.Green)); public static Block Grass;
public static Block Dirt = RegisterBlock(.. new Block(.Brown)); public static Block Dirt;
public static void Init()
{
Air = RegisterBlock(.. new Block(.All));
Stone = RegisterBlock(.. new Block());
Grass = RegisterBlock(.. new Block());
Dirt = RegisterBlock(.. new Block());
}
private static void RegisterBlock(Block block) private static void RegisterBlock(Block block)
{ {
+27
View File
@@ -0,0 +1,27 @@
using System;
using System.Collections;
namespace Sandbox.VoxelFun
{
static class Models
{
static List<Model> _models = new List<Model>() ~ DeleteContainerAndItems!(_);
public static Model Stone;
public static Model Grass;
public static Model Dirt;
public static void Init()
{
Stone = RegisterModel(Blocks.Stone, .. new BlockModel(.Gray));
Grass = RegisterModel(Blocks.Grass, .. new BlockModel(.Green));
Dirt = RegisterModel(Blocks.Dirt, .. new BlockModel(.Brown));
}
public static void RegisterModel(Block block, Model model)
{
_models.Add(model);
block.[Friend]_model = model;
}
}
}
+1 -84
View File
@@ -90,7 +90,7 @@ namespace Sandbox.VoxelFun
BlockFace visibleFaces = GetVisibleFaces(chunk, x, y, z); BlockFace visibleFaces = GetVisibleFaces(chunk, x, y, z);
if(visibleFaces != .None) if(visibleFaces != .None)
GenerateBlockModel(block, blockPos, visibleFaces, vertices, indices, ref lastIndex); block.Model.GenerateGeometry(block, blockPos, visibleFaces, vertices, indices, ref lastIndex);
} }
} }
@@ -126,88 +126,5 @@ namespace Sandbox.VoxelFun
return gb; return gb;
} }
Random r = new Random(1337) ~ delete _;
float f = 0.0f;
public static void GenerateBlockModel(Block block, Vector3 blockPosition, BlockFace visibleFaces, List<VertexColorTexture> vertices, List<uint32> indices, ref uint32 lastIndex)
{
Color c = block.Color;
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);
}
}
static 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;
}
} }
} }
+11 -22
View File
@@ -88,6 +88,9 @@ namespace Sandbox.VoxelFun
[AllowAppend] [AllowAppend]
public this() : base("VoxelTest") public this() : base("VoxelTest")
{ {
Blocks.Init();
Models.Init();
_context = Application.Get().Window.Context..AddRef(); _context = Application.Get().Window.Context..AddRef();
_effectLibrary = new EffectLibrary(_context); _effectLibrary = new EffectLibrary(_context);
@@ -178,7 +181,7 @@ namespace Sandbox.VoxelFun
uint32 i = 0; uint32 i = 0;
VoxelGeometryGenerator.GenerateBlockModel(Blocks.Stone, .Zero, .All, vertices, indices, ref i); (scope BlockModel(.HotPink)).GenerateGeometry(Blocks.Air, .Zero, .All, vertices, indices, ref i);
let qvb = new VertexBuffer(_context, typeof(VertexColorTexture), (.)vertices.Count, .Immutable); let qvb = new VertexBuffer(_context, typeof(VertexColorTexture), (.)vertices.Count, .Immutable);
qvb.SetData<VertexColorTexture>(vertices); qvb.SetData<VertexColorTexture>(vertices);
@@ -406,31 +409,15 @@ namespace Sandbox.VoxelFun
{ {
if(Input.IsMouseButtonPressing(.LeftButton)) if(Input.IsMouseButtonPressing(.LeftButton))
{ {
_world.SetBlock(intersectInfo.Coordinate, Blocks.Air); _world.BreakBlock(intersectInfo.Coordinate);
} }
else if(Input.IsMouseButtonPressing(.RightButton)) else if(Input.IsMouseButtonPressing(.RightButton))
{ {
var newBlockCoord = intersectInfo.Coordinate; _world.PlaceBlock(intersectInfo.Coordinate, rightHandBlock, intersectInfo.Face);
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.");
} }
else if(Input.IsMouseButtonPressing(.MiddleButton))
_world.SetBlock(newBlockCoord, Blocks.Stone); {
rightHandBlock = _world.GetBlock(intersectInfo.Coordinate);
} }
} }
@@ -439,6 +426,8 @@ namespace Sandbox.VoxelFun
Renderer.EndScene(); Renderer.EndScene();
} }
Block rightHandBlock = Blocks.Stone;
struct IntersectionInfo struct IntersectionInfo
{ {
public Int32_3 Coordinate; public Int32_3 Coordinate;
+103 -7
View File
@@ -115,7 +115,7 @@ namespace Sandbox.VoxelFun
/** /**
* Returs the coordinate of the chunk that contains the given coordinate. * Returs the coordinate of the chunk that contains the given coordinate.
*/ */
public Vector3 GetChunkCoordinate(Vector3 blockCoordinate) public static Vector3 GetChunkCoordinate(Vector3 blockCoordinate)
{ {
Vector3 chunkPosition = blockCoordinate / VoxelChunk.VectorSize; Vector3 chunkPosition = blockCoordinate / VoxelChunk.VectorSize;
@@ -125,18 +125,18 @@ namespace Sandbox.VoxelFun
/** /**
* Calculates the coordinate of the chunk that contains the given block coordinate. * Calculates the coordinate of the chunk that contains the given block coordinate.
*/ */
public Int32_3 ChunkCoordFromBlockCoord(Int32_3 blockCoordinate) public static Int32_3 ChunkCoordFromBlockCoord(Int32_3 blockCoordinate)
{ {
Int32_3 coordinate = blockCoordinate; Int32_3 coordinate = blockCoordinate;
if(coordinate.X < 0) if(coordinate.X < 0)
coordinate.X -= VoxelChunk.Size.X; coordinate.X -= VoxelChunk.Size.X - 1;
if(coordinate.Y < 0) if(coordinate.Y < 0)
coordinate.Y -= VoxelChunk.Size.Y; coordinate.Y -= VoxelChunk.Size.Y - 1;
if(coordinate.Z < 0) if(coordinate.Z < 0)
coordinate.Z -= VoxelChunk.Size.Z; coordinate.Z -= VoxelChunk.Size.Z - 1;
return coordinate / VoxelChunk.Size; return coordinate / VoxelChunk.Size;
} }
@@ -146,7 +146,7 @@ namespace Sandbox.VoxelFun
* For Example: Consider the block at the global location of (25, 17, -12) * For Example: Consider the block at the global location of (25, 17, -12)
* The coordinate of this block inside its chunk would be (9, 17, 4) because the chunk starts at (16, 0, -16) * The coordinate of this block inside its chunk would be (9, 17, 4) because the chunk starts at (16, 0, -16)
*/ */
public Int32_3 BlockCoordInChunk(Int32_3 blockCoordinate) public static Int32_3 BlockCoordInChunk(Int32_3 blockCoordinate)
{ {
Int32_3 chunkPosition = blockCoordinate % VoxelChunk.Size; Int32_3 chunkPosition = blockCoordinate % VoxelChunk.Size;
@@ -165,7 +165,7 @@ namespace Sandbox.VoxelFun
/** /**
* Returs the coordinate of the block relative to the chunk. * Returs the coordinate of the block relative to the chunk.
*/ */
public Vector3 GetPositionInChunk(Vector3 position) public static Vector3 GetPositionInChunk(Vector3 position)
{ {
Vector3 chunkPosition = position % VoxelChunk.VectorSize; Vector3 chunkPosition = position % VoxelChunk.VectorSize;
@@ -301,6 +301,71 @@ namespace Sandbox.VoxelFun
return .(int32.MaxValue, int32.MaxValue, int32.MaxValue); return .(int32.MaxValue, int32.MaxValue, int32.MaxValue);
} }
/**
* Breaks the block at the given coordinates.
*/
public void BreakBlock(Int32_3 blockCoordinate)
{
Int32_3 chunkCoordinate = ChunkCoordFromBlockCoord(blockCoordinate);
Chunk chunk = _chunkManager.LoadChunk(chunkCoordinate);
Int32_3 coordInChunk = BlockCoordInChunk(blockCoordinate);
Block block = chunk.GetBlock(coordInChunk);
block.OnBreaking(blockCoordinate);
chunk.SetBlock(coordInChunk, Blocks.Air);
}
/**
* Places a block at the given coordinates.
*/
public void PlaceBlock(Int32_3 blockCoordinate, Block block)
{
Int32_3 chunkCoordinate = ChunkCoordFromBlockCoord(blockCoordinate);
Chunk chunk = _chunkManager.LoadChunk(chunkCoordinate);
Int32_3 coordInChunk = BlockCoordInChunk(blockCoordinate);
// Todo: we will also be able to place block in fluids and some other blocks.
Log.ClientLogger.AssertDebug(chunk.GetBlock(coordInChunk) == Blocks.Air, "A block can only be placed in air (atm)");
block.OnPlacing(blockCoordinate);
chunk.SetBlock(coordInChunk, block);
}
/**
* Places a block on the given face of the block at the specified coordinates.
*/
public void PlaceBlock(Int32_3 blockCoordinate, Block block, BlockFace face)
{
var blockCoordinate;
switch(face)
{
case .Front:
blockCoordinate.Z--;
case .Back:
blockCoordinate.Z++;
case .Left:
blockCoordinate.X--;
case .Right:
blockCoordinate.X++;
case .Bottom:
blockCoordinate.Y--;
case .Top:
blockCoordinate.Y++;
default:
Log.ClientLogger.AssertDebug(false, "Unexpected block face.");
}
PlaceBlock(blockCoordinate, block);
}
/** /**
* Gets the block at the specified coordinate. * Gets the block at the specified coordinate.
* @remarks If the blocks chunk is not loaded it will be loaded from the disk. * @remarks If the blocks chunk is not loaded it will be loaded from the disk.
@@ -330,5 +395,36 @@ namespace Sandbox.VoxelFun
return chunk.GetBlock(coordInChunk); return chunk.GetBlock(coordInChunk);
} }
[Test]
static void TestWorld()
{
// ChunkCoordFromBlockCoord
{
Int32_3 block = .(0, 0, 0);
Int32_3 expectedChunk = .(0, 0, 0);
Test.Assert(expectedChunk == ChunkCoordFromBlockCoord(block));
block = .(5, 0, 0);
expectedChunk = .(0, 0, 0);
Test.Assert(expectedChunk == ChunkCoordFromBlockCoord(block));
block = .(45, 80, 12);
expectedChunk = .(2, 0, 0);
Test.Assert(expectedChunk == ChunkCoordFromBlockCoord(block));
block = .(0, 0, -1);
expectedChunk = .(0, 0, -1);
Test.Assert(expectedChunk == ChunkCoordFromBlockCoord(block));
block = .(0, 0, -16);
expectedChunk = .(0, 0, -1);
Test.Assert(expectedChunk == ChunkCoordFromBlockCoord(block));
block = .(0, 0, -17);
expectedChunk = .(0, 0, -2);
Test.Assert(expectedChunk == ChunkCoordFromBlockCoord(block));
}
}
} }
} }