mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Added voxel raycasting and voxel chunk access
This commit is contained in:
@@ -5,18 +5,18 @@ namespace GlitchyEngine.Math
|
||||
[SwizzleVector(3)]
|
||||
public struct Vector3
|
||||
{
|
||||
public const Vector3 Zero = .(0f, 0f, 0f);
|
||||
public const Vector3 UnitX = .(1f, 0f, 0f);
|
||||
public const Vector3 UnitY = .(0f, 1f, 0f);
|
||||
public const Vector3 UnitZ = .(0f, 0f, 1f);
|
||||
public const Vector3 One = .(1f, 1f, 1f);
|
||||
public const Vector3 Zero = .(0f, 0f, 0f);
|
||||
public const Vector3 UnitX = .(1f, 0f, 0f);
|
||||
public const Vector3 UnitY = .(0f, 1f, 0f);
|
||||
public const Vector3 UnitZ = .(0f, 0f, 1f);
|
||||
public const Vector3 One = .(1f, 1f, 1f);
|
||||
|
||||
public const Vector3 Forward = .(0f, 0f, 1f);
|
||||
public const Vector3 Forward = .(0f, 0f, 1f);
|
||||
public const Vector3 Backward = .(0f, 0f, -1f);
|
||||
public const Vector3 Left = .(-1f, 0f, 0f);
|
||||
public const Vector3 Right = .(1f, 0f, 0f);
|
||||
public const Vector3 Up = .(0f, 1f, 0f);
|
||||
public const Vector3 Down = .(0f, -1f, 0f);
|
||||
public const Vector3 Left = .(-1f, 0f, 0f);
|
||||
public const Vector3 Right = .(1f, 0f, 0f);
|
||||
public const Vector3 Up = .(0f, 1f, 0f);
|
||||
public const Vector3 Down = .(0f, -1f, 0f);
|
||||
|
||||
public float X, Y, Z;
|
||||
|
||||
@@ -77,6 +77,9 @@ namespace GlitchyEngine.Math
|
||||
return X * X + Y * Y + Z * Z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes this vector.
|
||||
*/
|
||||
[Checked]
|
||||
public void Normalize() mut
|
||||
{
|
||||
@@ -86,11 +89,34 @@ namespace GlitchyEngine.Math
|
||||
this /= Magnitude();
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes this vector.
|
||||
*/
|
||||
public void Normalize() mut
|
||||
{
|
||||
this /= Magnitude();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this Vector with a magnitude of 1.
|
||||
*/
|
||||
[Checked]
|
||||
public Vector3 Normalized()
|
||||
{
|
||||
if(this == .Zero)
|
||||
return .Zero;
|
||||
|
||||
return this / Magnitude();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this Vector with a magnitude of 1.
|
||||
*/
|
||||
public Vector3 Normalized()
|
||||
{
|
||||
return this / Magnitude();
|
||||
}
|
||||
|
||||
public static Vector3 Normalize(Vector3 v)
|
||||
{
|
||||
return v / v.Magnitude();
|
||||
@@ -125,6 +151,11 @@ namespace GlitchyEngine.Math
|
||||
return (a - b * (Dot(a, b) / Dot(b, b)));
|
||||
}
|
||||
|
||||
public static Vector3 Floor(Vector3 value)
|
||||
{
|
||||
return .(Math.Floor(value.X), Math.Floor(value.Y), Math.Floor(value.Z));
|
||||
}
|
||||
|
||||
//
|
||||
// Assignment operators
|
||||
//
|
||||
@@ -239,6 +270,14 @@ namespace GlitchyEngine.Math
|
||||
|
||||
public static Vector3 operator /(float scalar, Vector3 value) => Vector3(scalar / value.X, scalar / value.Y, scalar / value.Z);
|
||||
|
||||
// Modulo
|
||||
|
||||
public static Vector3 operator %(Vector3 left, Vector3 right) => Vector3(left.X % right.X, left.Y % right.Y, left.Z % right.Z);
|
||||
|
||||
public static Vector3 operator %(Vector3 value, float scalar) => Vector3(value.X % scalar, value.Y % scalar, value.Z % scalar);
|
||||
|
||||
public static Vector3 operator %(float scalar, Vector3 value) => Vector3(scalar % value.X, scalar % value.Y, scalar % value.Z);
|
||||
|
||||
// Equality
|
||||
|
||||
public static bool operator ==(Vector3 left, Vector3 right) => left.X == right.X && left.Y == right.Y && left.Z == right.Z;
|
||||
|
||||
@@ -111,6 +111,7 @@ namespace Sandbox.VoxelFun
|
||||
|
||||
chunkLoader = new Thread(new => ChunkLoaderThread_Entry);
|
||||
chunkLoader.Start();
|
||||
|
||||
}
|
||||
|
||||
public ~this()
|
||||
@@ -209,21 +210,22 @@ namespace Sandbox.VoxelFun
|
||||
// Wait for chunkPos to change
|
||||
chunkPosChanged.Enter();
|
||||
|
||||
chunkPosLock.Enter();
|
||||
curChunkPosition = chunkPosition;
|
||||
chunkPosLock.Exit();
|
||||
using(chunkPosLock.Enter())
|
||||
{
|
||||
curChunkPosition = chunkPosition;
|
||||
}
|
||||
|
||||
// Position didn't change -> skip
|
||||
if(curChunkPosition == oldChunkPosition)
|
||||
continue;
|
||||
|
||||
GenerateChunks(curChunkPosition);
|
||||
ChunkLoaderThread_GenerateChunks(curChunkPosition);
|
||||
|
||||
oldChunkPosition = curChunkPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public void GenerateChunks(Point3 chunkPos)
|
||||
public void ChunkLoaderThread_GenerateChunks(Point3 chunkPos)
|
||||
{
|
||||
for(var chunk in _chunks)
|
||||
{
|
||||
@@ -231,13 +233,44 @@ namespace Sandbox.VoxelFun
|
||||
|
||||
if(dist.X > _viewDistance || dist.Z > _viewDistance)
|
||||
{
|
||||
chunkListLock.Enter();
|
||||
delete chunk.value;
|
||||
_chunks.Remove(chunk.key);
|
||||
chunkListLock.Exit();
|
||||
using(chunkListLock.Enter())
|
||||
{
|
||||
delete chunk.value;
|
||||
_chunks.Remove(chunk.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int x = 0;
|
||||
int z = 0;
|
||||
for(int r = 1; r < _viewDistance; r++)
|
||||
{
|
||||
for(; x < r; x++)
|
||||
{
|
||||
Point3 chunkCoordinate = (Point3)chunkPos + .(x, 0, z);
|
||||
LoadChunk(chunkCoordinate);
|
||||
}
|
||||
|
||||
for(; z < r; z++)
|
||||
{
|
||||
Point3 chunkCoordinate = (Point3)chunkPos + .(x, 0, z);
|
||||
LoadChunk(chunkCoordinate);
|
||||
}
|
||||
|
||||
for(; x > -r; x--)
|
||||
{
|
||||
Point3 chunkCoordinate = (Point3)chunkPos + .(x, 0, z);
|
||||
LoadChunk(chunkCoordinate);
|
||||
}
|
||||
|
||||
for(; z > -r; z--)
|
||||
{
|
||||
Point3 chunkCoordinate = (Point3)chunkPos + .(x, 0, z);
|
||||
LoadChunk(chunkCoordinate);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for(int x = -_viewDistance; x < _viewDistance; x++)
|
||||
//for(int y = -_viewDistance; y < _viewDistance; y++)
|
||||
for(int z = -_viewDistance; z < _viewDistance; z++)
|
||||
@@ -247,6 +280,7 @@ namespace Sandbox.VoxelFun
|
||||
|
||||
LoadChunk(chunkCoordinate);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
Result<void> LoadChunkFromFile(Point3 chunkCoordinate, Chunk outChunk)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using GlitchyEngine.Math;
|
||||
|
||||
namespace Sandbox.VoxelFun
|
||||
{
|
||||
public struct VoxelChunk
|
||||
@@ -7,6 +9,7 @@ namespace Sandbox.VoxelFun
|
||||
public const int SizeZ = 16;
|
||||
|
||||
public const Point3 Size = .(SizeX, SizeY, SizeZ);
|
||||
public const Vector3 VectorSize = .(SizeX, SizeY, SizeZ);
|
||||
|
||||
public uint8[SizeX][SizeY][SizeZ] Data;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,8 @@ namespace Sandbox.VoxelFun
|
||||
|
||||
GeometryBinding _quadGeometryBinding ~ _?.ReleaseRef();
|
||||
|
||||
GeometryBinding _lineGeometryBinding ~ _?.ReleaseRef();
|
||||
|
||||
RasterizerState _rasterizerState ~ delete _;
|
||||
|
||||
Effect _effect ~ _?.ReleaseRef();
|
||||
@@ -185,6 +187,30 @@ namespace Sandbox.VoxelFun
|
||||
qib.ReleaseRef();
|
||||
}
|
||||
|
||||
// Create Line
|
||||
{
|
||||
_lineGeometryBinding = new GeometryBinding(_context);
|
||||
_lineGeometryBinding.SetPrimitiveTopology(.LineList);
|
||||
_lineGeometryBinding.SetVertexLayout(_vertexLayout);
|
||||
|
||||
VertexColorTexture[?] vertices = .(
|
||||
VertexColorTexture(Vector3(0, 0, 0), Color.White, .(0, 0)),
|
||||
VertexColorTexture(Vector3(0, 0, 10), Color.White, .(0, 1)),
|
||||
);
|
||||
|
||||
let qvb = new VertexBuffer(_context, typeof(VertexColorTexture), (.)vertices.Count, .Immutable);
|
||||
qvb.SetData(vertices);
|
||||
_lineGeometryBinding.SetVertexBufferSlot(qvb, 0);
|
||||
qvb.ReleaseRef();
|
||||
|
||||
uint16[?] indices = .(0, 1);
|
||||
|
||||
let qib = new IndexBuffer(_context, (.)indices.Count, .Immutable);
|
||||
qib.SetData(indices);
|
||||
_lineGeometryBinding.SetIndexBuffer(qib);
|
||||
qib.ReleaseRef();
|
||||
}
|
||||
|
||||
// Create rasterizer state
|
||||
GlitchyEngine.Renderer.RasterizerStateDescription rsDesc = .(.Solid, .Back, true);
|
||||
rsDesc.DepthClipEnabled = true;
|
||||
@@ -226,219 +252,7 @@ namespace Sandbox.VoxelFun
|
||||
_world.ChunkManager.Texture = _texture..AddRef();
|
||||
_world.ChunkManager.TextureEffect = _textureEffect..AddRef();
|
||||
}
|
||||
/*
|
||||
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);
|
||||
@@ -529,6 +343,8 @@ namespace Sandbox.VoxelFun
|
||||
_camera.Position += movement * speed;
|
||||
}
|
||||
|
||||
Ray ray = .(.(0, 128, 0), .UnitZ);
|
||||
|
||||
public override void Update(GameTime gameTime)
|
||||
{
|
||||
UpdateCamera(gameTime);
|
||||
@@ -574,13 +390,33 @@ namespace Sandbox.VoxelFun
|
||||
_ge_logo.Bind();
|
||||
Renderer.Submit(_quadGeometryBinding, _textureEffect, .Scaling(1.5f));
|
||||
|
||||
Ray ray = .(_camera.Position, _camera.Transform.Forward);
|
||||
|
||||
Point3 lookedAtBlock = _world.RaycastBlock(ray, 10);
|
||||
//Ray ray = .(.(0.5f, 128.5f, 0.5f), .(0, -0.1f, -0.1f));
|
||||
|
||||
_effect.Variables["BaseColor"].SetData(.Red);
|
||||
|
||||
_texture.Bind();
|
||||
|
||||
Matrix mat = .Translation(ray.Start);
|
||||
|
||||
Matrix mat2 = .Identity;
|
||||
mat2.Up = .(0, 1, 0);
|
||||
|
||||
mat2.Forward = ray.Direction;
|
||||
mat2.Forward.Normalize();
|
||||
|
||||
mat2.Right = Vector3.Cross(mat2.Up, mat2.Forward);
|
||||
mat2.Right.Normalize();
|
||||
|
||||
mat2.Up = Vector3.Cross(mat2.Forward, mat2.Right);
|
||||
mat2.Up.Normalize();
|
||||
|
||||
Matrix mat3 = mat * mat2;
|
||||
|
||||
Renderer.Submit(_lineGeometryBinding, _textureEffect, mat3);
|
||||
|
||||
//Point3 lookedAtBlock = _world.RaycastBlock(ray, 10, _cubeGeo, _textureEffect);
|
||||
Point3 lookedAtBlock = _world.RaycastBlock(.(_camera.Position, _camera.Transform.Forward), 10, _cubeGeo, _textureEffect);
|
||||
|
||||
Renderer.Submit(_cubeGeo, _textureEffect, .Translation((Vector3)lookedAtBlock));
|
||||
|
||||
_world.ChunkManager.Draw();
|
||||
@@ -631,6 +467,16 @@ namespace Sandbox.VoxelFun
|
||||
|
||||
_squareColor1 = ColorRGBA.White - _squareColor0;
|
||||
|
||||
|
||||
ImGui.DragFloat3("Ray Position", *(float[3]*)(void*)&ray.Start, 0.1f, float.NegativeInfinity, float.PositiveInfinity);
|
||||
|
||||
ImGui.DragFloat3("Ray Direction", *(float[3]*)(void*)&ray.Direction, 0.001f, -1f, 1.0f);
|
||||
|
||||
_camera.Position = camPos;
|
||||
|
||||
|
||||
|
||||
|
||||
ImGui.End();
|
||||
|
||||
return false;
|
||||
|
||||
+149
-28
@@ -3,6 +3,7 @@ using System.IO;
|
||||
using System.Collections;
|
||||
using GlitchyEngine.Math;
|
||||
using GlitchyEngine;
|
||||
using GlitchyEngine.Renderer;
|
||||
|
||||
namespace Sandbox.VoxelFun
|
||||
{
|
||||
@@ -111,49 +112,169 @@ namespace Sandbox.VoxelFun
|
||||
}
|
||||
*/
|
||||
|
||||
public Point3 GetChunkCoordinate(Point3 blockCoordinate)
|
||||
/**
|
||||
* Returs the coordinate of the chunk that contains the given coordinate.
|
||||
*/
|
||||
public Vector3 GetChunkCoordinate(Vector3 blockCoordinate)
|
||||
{
|
||||
Point3 p = blockCoordinate;
|
||||
if(p.X < 0)
|
||||
p.X -= VoxelChunk.Size.X;
|
||||
if(p.Y < 0)
|
||||
p.Y -= VoxelChunk.Size.Y;
|
||||
if(p.Z < 0)
|
||||
p.Z -= VoxelChunk.Size.Z;
|
||||
Vector3 chunkPosition = blockCoordinate / VoxelChunk.VectorSize;
|
||||
|
||||
return .(p.X / VoxelChunk.Size.X, 0, p.Z / VoxelChunk.Size.Z);//p.Y / VoxelChunk.Size.Y
|
||||
return Vector3.Floor(chunkPosition);
|
||||
}
|
||||
|
||||
public Point3 RaycastBlock(Ray ray, float maxDistance)
|
||||
/**
|
||||
* Calculates the coordinate of the chunk that contains the given block coordinate.
|
||||
*/
|
||||
public Point3 ChunkCoordFromBlockCoord(Point3 blockCoordinate)
|
||||
{
|
||||
Vector3 rayWalker = ray.Start;
|
||||
Vector3 direction = ray.Direction.Normalized();
|
||||
Point3 coordinate = blockCoordinate;
|
||||
|
||||
for(float walkedLength = 0; walkedLength < maxDistance; rayWalker += direction, walkedLength++)
|
||||
if(coordinate.X < 0)
|
||||
coordinate.X -= VoxelChunk.Size.X;
|
||||
|
||||
if(coordinate.Y < 0)
|
||||
coordinate.Y -= VoxelChunk.Size.Y;
|
||||
|
||||
if(coordinate.Z < 0)
|
||||
coordinate.Z -= VoxelChunk.Size.Z;
|
||||
|
||||
return coordinate / VoxelChunk.Size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the block coordinate relative to its chunk.
|
||||
* 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)
|
||||
*/
|
||||
public Point3 BlockCoordInChunk(Point3 blockCoordinate)
|
||||
{
|
||||
Point3 chunkPosition = blockCoordinate % VoxelChunk.Size;
|
||||
|
||||
if(chunkPosition.X < 0)
|
||||
chunkPosition.X += VoxelChunk.Size.X;
|
||||
|
||||
if(chunkPosition.Y < 0)
|
||||
chunkPosition.Y += VoxelChunk.Size.Y;
|
||||
|
||||
if(chunkPosition.Z < 0)
|
||||
chunkPosition.Z += VoxelChunk.Size.Z;
|
||||
|
||||
return chunkPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returs the coordinate of the block relative to the chunk.
|
||||
*/
|
||||
public Vector3 GetPositionInChunk(Vector3 position)
|
||||
{
|
||||
Vector3 chunkPosition = position % VoxelChunk.VectorSize;
|
||||
|
||||
if(chunkPosition.X < 0)
|
||||
chunkPosition.X += VoxelChunk.VectorSize.X;
|
||||
|
||||
if(chunkPosition.Y < 0)
|
||||
chunkPosition.Y += VoxelChunk.VectorSize.Y;
|
||||
|
||||
if(chunkPosition.Z < 0)
|
||||
chunkPosition.Z += VoxelChunk.VectorSize.Z;
|
||||
|
||||
return Vector3.Floor(chunkPosition);
|
||||
}
|
||||
|
||||
public Point3 RaycastBlock(Ray ray, float maxDistance, GeometryBinding geo, Effect effect)
|
||||
{
|
||||
Vector3 start = ray.Start;
|
||||
Vector3 dir = ray.Direction.Normalized();
|
||||
|
||||
Vector3 unitStepSize = .((dir / dir.X).Magnitude(), (dir / dir.Y).Magnitude(), (dir / dir.Z).Magnitude());
|
||||
|
||||
Point3 walker = (Point3)Vector3.Floor(start);
|
||||
|
||||
Vector3 rayLengths = .();
|
||||
|
||||
Point3 step;
|
||||
|
||||
if(dir.X < 0)
|
||||
{
|
||||
Point3 blockCoordinate = (.)rayWalker;
|
||||
step.X = -1;
|
||||
rayLengths.X = (start.X - (float)(walker.X)) * unitStepSize.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
step.X = 1;
|
||||
rayLengths.X = ((float)(walker.X + 1) - start.X) * unitStepSize.X;
|
||||
}
|
||||
|
||||
Point3 chunkCoordinate = GetChunkCoordinate(blockCoordinate);
|
||||
if(dir.Y < 0)
|
||||
{
|
||||
step.Y = -1;
|
||||
rayLengths.Y = (start.Y - (float)(walker.Y)) * unitStepSize.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
step.Y = 1;
|
||||
rayLengths.Y = ((float)(walker.Y + 1) - start.Y) * unitStepSize.Y;
|
||||
}
|
||||
|
||||
if(dir.Z < 0)
|
||||
{
|
||||
step.Z = -1;
|
||||
rayLengths.Z = (start.Z - (float)(walker.Z)) * unitStepSize.Z;
|
||||
}
|
||||
else
|
||||
{
|
||||
step.Z = 1;
|
||||
rayLengths.Z = ((float)(walker.Z + 1) - start.Z) * unitStepSize.Z;
|
||||
}
|
||||
|
||||
float distance = 0.0f;
|
||||
while(distance < maxDistance)
|
||||
{
|
||||
// Walk
|
||||
if(rayLengths.X < rayLengths.Y)
|
||||
{
|
||||
if(rayLengths.X < rayLengths.Z)
|
||||
{
|
||||
walker.X += step.X;
|
||||
distance = rayLengths.X;
|
||||
rayLengths.X += unitStepSize.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
walker.Z += step.Z;
|
||||
distance = rayLengths.Z;
|
||||
rayLengths.Z += unitStepSize.Z;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rayLengths.Y < rayLengths.Z)
|
||||
{
|
||||
walker.Y += step.Y;
|
||||
distance = rayLengths.Y;
|
||||
rayLengths.Y += unitStepSize.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
walker.Z += step.Z;
|
||||
distance = rayLengths.Z;
|
||||
rayLengths.Z += unitStepSize.Z;
|
||||
}
|
||||
}
|
||||
|
||||
Point3 chunkCoordinate = ChunkCoordFromBlockCoord(walker);
|
||||
|
||||
Chunk chunk = _chunkManager.LoadChunk(chunkCoordinate);
|
||||
|
||||
Point3 coordInChunk = blockCoordinate - chunkCoordinate * VoxelChunk.Size;
|
||||
Point3 coordInChunk = BlockCoordInChunk(walker);
|
||||
|
||||
int blockData = chunk.Data.Data[coordInChunk.X][coordInChunk.Y][coordInChunk.Z];
|
||||
uint8 blockData = chunk.Data.Data[coordInChunk.X][coordInChunk.Y][coordInChunk.Z];
|
||||
|
||||
if(blockData != 0)
|
||||
return blockCoordinate;
|
||||
{
|
||||
return walker;
|
||||
}
|
||||
|
||||
//Point3 chunkCoordinate = GetChunkCoordinate(rayWalker);
|
||||
|
||||
//Chunk chunk = _chunkManager.LoadChunk(chunkCoordinate);
|
||||
|
||||
//Point3 blockIndex = (Point3)rayWalker - chunkCoordinate * VoxelChunk.Size;
|
||||
|
||||
//int blockData = chunk.Data.Data[blockIndex.X][blockIndex.Y][blockIndex.Z];
|
||||
|
||||
//if(blockData != 0)
|
||||
// return blockIndex;
|
||||
}
|
||||
|
||||
return .(int.MaxValue, int.MaxValue, int.MaxValue);
|
||||
|
||||
Reference in New Issue
Block a user