diff --git a/TrueCraft.API/Vector3.cs b/TrueCraft.API/Vector3.cs
index 26970ef..8b878a3 100644
--- a/TrueCraft.API/Vector3.cs
+++ b/TrueCraft.API/Vector3.cs
@@ -79,6 +79,14 @@ namespace TrueCraft.API
return new Vector3(Math.Floor(X), Math.Floor(Y), Math.Floor(Z));
}
+ ///
+ /// Rounds the decimal component of each part of this Vector3.
+ ///
+ public Vector3 Round()
+ {
+ return new Vector3(Math.Round(X), Math.Round(Y), Math.Round(Z));
+ }
+
///
/// Clamps the vector to within the specified value.
///
diff --git a/TrueCraft.Client/Content/icons.png b/TrueCraft.Client/Content/icons.png
new file mode 100644
index 0000000..590a89e
Binary files /dev/null and b/TrueCraft.Client/Content/icons.png differ
diff --git a/TrueCraft.Client/Modules/HUDModule.cs b/TrueCraft.Client/Modules/HUDModule.cs
new file mode 100644
index 0000000..1a9a574
--- /dev/null
+++ b/TrueCraft.Client/Modules/HUDModule.cs
@@ -0,0 +1,38 @@
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+namespace TrueCraft.Client.Modules
+{
+ public class HUDModule : IGraphicalModule
+ {
+ private TrueCraftGame Game { get; set; }
+ private SpriteBatch SpriteBatch { get; set; }
+ private Texture2D GUI { get; set; }
+ private Texture2D Icons { get; set; }
+
+ public HUDModule(TrueCraftGame game)
+ {
+ Game = game;
+ SpriteBatch = new SpriteBatch(game.GraphicsDevice);
+ GUI = game.TextureMapper.GetTexture("gui/gui.png");
+ Icons = game.TextureMapper.GetTexture("gui/icons.png");
+ }
+
+ public void Update(GameTime gameTime)
+ {
+ }
+
+ static readonly Color CrosshairColor = new Color(255, 255, 255, 70);
+
+ public void Draw(GameTime gameTime)
+ {
+ SpriteBatch.Begin(samplerState: SamplerState.PointClamp);
+ SpriteBatch.Draw(Icons, new Vector2(
+ Game.GraphicsDevice.Viewport.Width / 2 - (8 * Game.ScaleFactor * 2),
+ Game.GraphicsDevice.Viewport.Height / 2 - (8 * Game.ScaleFactor * 2)),
+ new Rectangle(0, 0, 16, 16), CrosshairColor,
+ 0, Vector2.Zero, Game.ScaleFactor * 2, SpriteEffects.None, 1);
+ SpriteBatch.End();
+ }
+ }
+}
diff --git a/TrueCraft.Client/Modules/HighlightModule.cs b/TrueCraft.Client/Modules/HighlightModule.cs
index d38523e..fd750e7 100644
--- a/TrueCraft.Client/Modules/HighlightModule.cs
+++ b/TrueCraft.Client/Modules/HighlightModule.cs
@@ -3,6 +3,9 @@ using Microsoft.Xna.Framework.Graphics;
using TrueCraft.API;
using TrueCraft.Client.Rendering;
using Microsoft.Xna.Framework;
+using XVector3 = Microsoft.Xna.Framework.Vector3;
+using TVector3 = TrueCraft.API.Vector3;
+using TRay = TrueCraft.API.Ray;
namespace TrueCraft.Client.Modules
{
@@ -10,51 +13,37 @@ namespace TrueCraft.Client.Modules
{
public TrueCraftGame Game { get; set; }
- private Texture2D HighlightTexture { get; set; }
private Coordinates3D HighlightedBlock { get; set; }
- private Mesh HighlightMesh { get; set; }
private BasicEffect HighlightEffect { get; set; }
+ private static readonly VertexPositionColor[] CubeVerticies;
+ private static readonly short[] CubeIndicies;
+
+ static HighlightModule()
+ {
+ var color = Color.Black;
+ CubeVerticies = new[]
+ {
+ new VertexPositionColor(new XVector3(0, 0, 1), color),
+ new VertexPositionColor(new XVector3(1, 0, 1), color),
+ new VertexPositionColor(new XVector3(1, 1, 1), color),
+ new VertexPositionColor(new XVector3(0, 1, 1), color),
+ new VertexPositionColor(new XVector3(0, 0, 0), color),
+ new VertexPositionColor(new XVector3(1, 0, 0), color),
+ new VertexPositionColor(new XVector3(1, 1, 0), color),
+ new VertexPositionColor(new XVector3(0, 1, 0), color)
+ };
+ CubeIndicies = new short[]
+ {
+ 0, 1, 1, 2, 2, 3, 3, 0,
+ 0, 4, 4, 7, 7, 6, 6, 2,
+ 1, 5, 5, 4, 3, 7, 6, 5
+ };
+ }
public HighlightModule(TrueCraftGame game)
{
Game = game;
-
- const int size = 64;
- HighlightedBlock = -Coordinates3D.One;
- HighlightTexture = new Texture2D(Game.GraphicsDevice, size, size);
-
- var colors = new Color[size * size];
- for (int i = 0; i < colors.Length; i++)
- colors[i] = Color.Transparent;
- for (int x = 0; x < size; x++)
- colors[x] = Color.Black; // Top
- for (int x = 0; x < size; x++)
- colors[x + (size - 1) * size] = Color.Black; // Bottom
- for (int y = 0; y < size; y++)
- colors[y * size] = Color.Black; // Left
- for (int y = 0; y < size; y++)
- colors[y * size + (size - 1)] = Color.Black; // Right
-
- HighlightTexture.SetData(colors);
- var texcoords = new[]
- {
- Vector2.UnitX + Vector2.UnitY,
- Vector2.UnitY,
- Vector2.Zero,
- Vector2.UnitX
- };
- int[] indicies;
- var verticies = BlockRenderer.CreateUniformCube(Microsoft.Xna.Framework.Vector3.Zero,
- texcoords, VisibleFaces.All, 0, out indicies, Color.White);
- HighlightMesh = new Mesh(Game, verticies, indicies);
-
HighlightEffect = new BasicEffect(Game.GraphicsDevice);
- HighlightEffect.EnableDefaultLighting();
- HighlightEffect.DirectionalLight0.SpecularColor = Color.Black.ToVector3();
- HighlightEffect.DirectionalLight1.SpecularColor = Color.Black.ToVector3();
- HighlightEffect.DirectionalLight2.SpecularColor = Color.Black.ToVector3();
- HighlightEffect.TextureEnabled = true;
- HighlightEffect.Texture = HighlightTexture;
HighlightEffect.VertexColorEnabled = true;
}
@@ -66,18 +55,19 @@ namespace TrueCraft.Client.Modules
Matrix.CreateRotationY(MathHelper.ToRadians(Game.Client.Yaw)));
var cast = VoxelCast.Cast(Game.Client.World,
- new TrueCraft.API.Ray(Game.Camera.Position,
- new TrueCraft.API.Vector3(direction.X, direction.Y, direction.Z)),
- Game.BlockRepository, TrueCraftGame.Reach);
+ new TRay(Game.Camera.Position, new TVector3(direction.X, direction.Y, direction.Z)),
+ Game.BlockRepository, (int)TrueCraftGame.Reach);
if (cast == null)
HighlightedBlock = -Coordinates3D.One;
else
{
HighlightedBlock = cast.Item1;
- HighlightEffect.World = Matrix.CreateScale(1.02f) *
- Matrix.CreateTranslation(new Microsoft.Xna.Framework.Vector3(
- cast.Item1.X, cast.Item1.Y, cast.Item1.Z));
+ HighlightEffect.World =
+ Matrix.CreateTranslation(new XVector3(-0.5f)) *
+ Matrix.CreateScale(1.01f) *
+ Matrix.CreateTranslation(new XVector3(0.5f)) *
+ Matrix.CreateTranslation(new XVector3(cast.Item1.X, cast.Item1.Y, cast.Item1.Z));
}
}
@@ -87,8 +77,13 @@ namespace TrueCraft.Client.Modules
if (HighlightedBlock != -Coordinates3D.One)
{
- Game.GraphicsDevice.DepthStencilState = DepthStencilState.None;
- HighlightMesh.Draw(HighlightEffect);
+ foreach (var pass in HighlightEffect.CurrentTechnique.Passes)
+ {
+ pass.Apply();
+ HighlightEffect.GraphicsDevice.DrawUserIndexedPrimitives(
+ PrimitiveType.LineList, CubeVerticies, 0,
+ CubeVerticies.Length, CubeIndicies, 0, CubeIndicies.Length / 2);
+ }
}
}
}
diff --git a/TrueCraft.Client/Modules/PlayerControlModule.cs b/TrueCraft.Client/Modules/PlayerControlModule.cs
index af9aea1..c844f3d 100644
--- a/TrueCraft.Client/Modules/PlayerControlModule.cs
+++ b/TrueCraft.Client/Modules/PlayerControlModule.cs
@@ -11,10 +11,12 @@ namespace TrueCraft.Client.Modules
{
private TrueCraftGame Game { get; set; }
private Vector3 Delta { get; set; }
+ private bool Capture { get; set; }
public PlayerControlModule(TrueCraftGame game)
{
Game = game;
+ Capture = true;
}
public bool KeyDown(GameTime gameTime, KeyboardKeyEventArgs e)
@@ -55,6 +57,14 @@ namespace TrueCraft.Client.Modules
Delta += Vector3.Backward;
return true;
+ case Keys.I:
+ Game.Client.Position = Game.Client.Position.Floor();
+ return true;
+
+ case Keys.Tab:
+ Capture = !Capture;
+ return true;
+
case Keys.Space:
if (Math.Floor(Game.Client.Position.Y) == Game.Client.Position.Y)
Game.Client.Velocity += TrueCraft.API.Vector3.Up * 0.3;
@@ -96,6 +106,8 @@ namespace TrueCraft.Client.Modules
public void MouseMove(GameTime gameTime, MouseMoveEventArgs e)
{
+ if (!Capture)
+ return;
var centerX = Game.GraphicsDevice.Viewport.Width / 2;
var centerY = Game.GraphicsDevice.Viewport.Height / 2;
Mouse.SetPosition(centerX, centerY);
diff --git a/TrueCraft.Client/MultiplayerClient.cs b/TrueCraft.Client/MultiplayerClient.cs
index 0d6ce0b..eb74f92 100644
--- a/TrueCraft.Client/MultiplayerClient.cs
+++ b/TrueCraft.Client/MultiplayerClient.cs
@@ -256,7 +256,8 @@ namespace TrueCraft.Client
{
get
{
- return new BoundingBox(Position, Position + Size);
+ var pos = Position - new Vector3(Width / 2, 0, Depth / 2);
+ return new BoundingBox(pos, pos + Size);
}
}
diff --git a/TrueCraft.Client/Rendering/BlockRenderer.cs b/TrueCraft.Client/Rendering/BlockRenderer.cs
index 8a27cda..f8b6ca5 100644
--- a/TrueCraft.Client/Rendering/BlockRenderer.cs
+++ b/TrueCraft.Client/Rendering/BlockRenderer.cs
@@ -147,50 +147,50 @@ namespace TrueCraft.Client.Rendering
CubeMesh[0] = new[] // Positive Z face
{
- new Vector3(0.5f, -0.5f, 0.5f),
- new Vector3(-0.5f, -0.5f, 0.5f),
- new Vector3(-0.5f, 0.5f, 0.5f),
- new Vector3(0.5f, 0.5f, 0.5f)
+ new Vector3(1, 0, 1),
+ new Vector3(0, 0, 1),
+ new Vector3(0, 1, 1),
+ new Vector3(1, 1, 1)
};
CubeMesh[1] = new[] // Negative Z face
{
- new Vector3(-0.5f, -0.5f, -0.5f),
- new Vector3(0.5f, -0.5f, -0.5f),
- new Vector3(0.5f, 0.5f, -0.5f),
- new Vector3(-0.5f, 0.5f, -0.5f)
+ new Vector3(0, 0, 0),
+ new Vector3(1, 0, 0),
+ new Vector3(1, 1, 0),
+ new Vector3(0, 1, 0)
};
CubeMesh[2] = new[] // Positive X face
{
- new Vector3(0.5f, -0.5f, -0.5f),
- new Vector3(0.5f, -0.5f, 0.5f),
- new Vector3(0.5f, 0.5f, 0.5f),
- new Vector3(0.5f, 0.5f, -0.5f)
+ new Vector3(1, 0, 0),
+ new Vector3(1, 0, 1),
+ new Vector3(1, 1, 1),
+ new Vector3(1, 1, 0)
};
CubeMesh[3] = new[] // Negative X face
{
- new Vector3(-0.5f, -0.5f, 0.5f),
- new Vector3(-0.5f, -0.5f, -0.5f),
- new Vector3(-0.5f, 0.5f, -0.5f),
- new Vector3(-0.5f, 0.5f, 0.5f)
+ new Vector3(0, 0, 1),
+ new Vector3(0, 0, 0),
+ new Vector3(0, 1, 0),
+ new Vector3(0, 1, 1)
};
CubeMesh[4] = new[] // Positive Y face
{
- new Vector3(0.5f, 0.5f, 0.5f),
- new Vector3(-0.5f, 0.5f, 0.5f),
- new Vector3(-0.5f, 0.5f, -0.5f),
- new Vector3(0.5f, 0.5f, -0.5f)
+ new Vector3(1, 1, 1),
+ new Vector3(0, 1, 1),
+ new Vector3(0, 1, 0),
+ new Vector3(1, 1, 0)
};
CubeMesh[5] = new[] // Negative Y face
{
- new Vector3(0.5f, -0.5f, -0.5f),
- new Vector3(-0.5f, -0.5f, -0.5f),
- new Vector3(-0.5f, -0.5f, 0.5f),
- new Vector3(0.5f, -0.5f, 0.5f)
+ new Vector3(1, 0, 0),
+ new Vector3(0, 0, 0),
+ new Vector3(0, 0, 1),
+ new Vector3(1, 0, 1)
};
}
}
diff --git a/TrueCraft.Client/Rendering/Blocks/SnowRenderer.cs b/TrueCraft.Client/Rendering/Blocks/SnowRenderer.cs
index 6a16e2a..a8eff25 100644
--- a/TrueCraft.Client/Rendering/Blocks/SnowRenderer.cs
+++ b/TrueCraft.Client/Rendering/Blocks/SnowRenderer.cs
@@ -27,17 +27,13 @@ namespace TrueCraft.Client.Rendering.Blocks
public override VertexPositionNormalColorTexture[] Render(BlockDescriptor descriptor, Vector3 offset,
VisibleFaces faces, Tuple textureMap, int indiciesOffset, out int[] indicies)
{
- var overhead = new Vector3(0.5f, 0.5f, 0.5f);
- var cube = CreateUniformCube(overhead, Texture, faces, indiciesOffset, out indicies, Color.White);
+ var cube = CreateUniformCube(Vector3.Zero, Texture, faces, indiciesOffset, out indicies, Color.White);
var heightMultiplier = new Vector3(1, ((descriptor.Metadata + 1) / 16f), 1);
for (int i = 0; i < cube.Length; i++)
{
if (cube[i].Position.Y > 0)
- {
cube[i].Position *= heightMultiplier;
- }
cube[i].Position += offset;
- cube[i].Position -= overhead;
}
return cube;
}
diff --git a/TrueCraft.Client/Rendering/Blocks/WheatRenderer.cs b/TrueCraft.Client/Rendering/Blocks/WheatRenderer.cs
index debaf0c..2f75b09 100644
--- a/TrueCraft.Client/Rendering/Blocks/WheatRenderer.cs
+++ b/TrueCraft.Client/Rendering/Blocks/WheatRenderer.cs
@@ -46,10 +46,11 @@ namespace TrueCraft.Client.Rendering
indicies = new int[4 * 2 * 6];
var verticies = new VertexPositionNormalColorTexture[4 * 2 * 6];
int[] _indicies;
+ var center = new Vector3(-0.5f, -0.5f, -0.5f);
for (int _side = 0; _side < 4; _side++) // Y faces are the last two in the CubeFace enum, so we can just iterate to 4
{
var side = (CubeFace)_side;
- var quad = CreateQuad(side, Vector3.Zero, texture, 0, indiciesOffset, out _indicies, Color.White);
+ var quad = CreateQuad(side, center, texture, 0, indiciesOffset, out _indicies, Color.White);
if (side == CubeFace.NegativeX || side == CubeFace.PositiveX)
{
for (int i = 0; i < quad.Length; i++)
@@ -73,7 +74,7 @@ namespace TrueCraft.Client.Rendering
for (int _side = 0; _side < 4; _side++)
{
var side = (CubeFace)_side;
- var quad = CreateQuad(side, Vector3.Zero, texture, 0, indiciesOffset, out _indicies, Color.White);
+ var quad = CreateQuad(side, center, texture, 0, indiciesOffset, out _indicies, Color.White);
if (side == CubeFace.NegativeX || side == CubeFace.PositiveX)
{
for (int i = 0; i < quad.Length; i++)
@@ -98,6 +99,7 @@ namespace TrueCraft.Client.Rendering
for (int i = 0; i < verticies.Length; i++)
{
verticies[i].Position.Y -= 1 / 16f;
+ verticies[i].Position -= center;
}
return verticies;
}
diff --git a/TrueCraft.Client/Rendering/FlatQuadRenderer.cs b/TrueCraft.Client/Rendering/FlatQuadRenderer.cs
index d53106e..94da96d 100644
--- a/TrueCraft.Client/Rendering/FlatQuadRenderer.cs
+++ b/TrueCraft.Client/Rendering/FlatQuadRenderer.cs
@@ -80,34 +80,34 @@ namespace TrueCraft.Client.Rendering
QuadMesh[0] = new[]
{
- new Vector3(0.5f, -0.5f, 0.5f),
- new Vector3(-0.5f, -0.5f, -0.5f),
- new Vector3(-0.5f, 0.5f, -0.5f),
- new Vector3(0.5f, 0.5f, 0.5f)
+ new Vector3(1, 0, 1),
+ new Vector3(0, 0, 0),
+ new Vector3(0, 1, 0),
+ new Vector3(1, 1, 1)
};
QuadMesh[1] = new[]
{
- new Vector3(-0.5f, -0.5f, -0.5f),
- new Vector3(0.5f, -0.5f, 0.5f),
- new Vector3(0.5f, 0.5f, 0.5f),
- new Vector3(-0.5f, 0.5f, -0.5f)
+ new Vector3(0, 0, 0),
+ new Vector3(1, 0, 1),
+ new Vector3(1, 1, 1),
+ new Vector3(0, 1, 0)
};
QuadMesh[2] = new[]
{
- new Vector3(-0.5f, -0.5f, 0.5f),
- new Vector3(0.5f, -0.5f, -0.5f),
- new Vector3(0.5f, 0.5f, -0.5f),
- new Vector3(-0.5f, 0.5f, 0.5f)
+ new Vector3(0, 0, 1),
+ new Vector3(1, 0, 0),
+ new Vector3(1, 1, 0),
+ new Vector3(0, 1, 1)
};
QuadMesh[3] = new[]
{
- new Vector3(0.5f, -0.5f, -0.5f),
- new Vector3(-0.5f, -0.5f, 0.5f),
- new Vector3(-0.5f, 0.5f, 0.5f),
- new Vector3(0.5f, 0.5f, -0.5f)
+ new Vector3(1, 0, 0),
+ new Vector3(0, 0, 1),
+ new Vector3(0, 1, 1),
+ new Vector3(1, 1, 0)
};
}
}
diff --git a/TrueCraft.Client/Rendering/TextureMapper.cs b/TrueCraft.Client/Rendering/TextureMapper.cs
index 0e0486c..a6557d1 100644
--- a/TrueCraft.Client/Rendering/TextureMapper.cs
+++ b/TrueCraft.Client/Rendering/TextureMapper.cs
@@ -31,6 +31,8 @@ namespace TrueCraft.Client.Rendering
Defaults.Add("items.png", new PngReader().Read(File.OpenRead("Content/items.png"), graphicsDevice));
Defaults.Add("terrain.png", new PngReader().Read(File.OpenRead("Content/terrain.png"), graphicsDevice));
+ Defaults.Add("gui/gui.png", new PngReader().Read(File.OpenRead("Content/gui.png"), graphicsDevice));
+ Defaults.Add("gui/icons.png", new PngReader().Read(File.OpenRead("Content/icons.png"), graphicsDevice));
}
///
diff --git a/TrueCraft.Client/TrueCraft.Client.csproj b/TrueCraft.Client/TrueCraft.Client.csproj
index 47c8691..3655bf5 100644
--- a/TrueCraft.Client/TrueCraft.Client.csproj
+++ b/TrueCraft.Client/TrueCraft.Client.csproj
@@ -132,6 +132,7 @@
+
@@ -230,8 +231,11 @@
PreserveNewest
+
+ PreserveNewest
+
-
+
\ No newline at end of file
diff --git a/TrueCraft.Client/TrueCraftGame.cs b/TrueCraft.Client/TrueCraftGame.cs
index 2e0adbe..4fcb959 100644
--- a/TrueCraft.Client/TrueCraftGame.cs
+++ b/TrueCraft.Client/TrueCraftGame.cs
@@ -28,6 +28,7 @@ namespace TrueCraft.Client
public ConcurrentBag PendingMainThreadActions { get; set; }
public double Bobbing { get; set; }
public ChunkModule ChunkModule { get; set; }
+ public float ScaleFactor { get; set; }
private List Modules { get; set; }
private SpriteBatch SpriteBatch { get; set; }
@@ -43,7 +44,7 @@ namespace TrueCraft.Client
private GameTime GameTime { get; set; }
private DebugInfoModule DebugInfoModule { get; set; }
- public static readonly int Reach = 5;
+ public static readonly double Reach = 3;
public IBlockRepository BlockRepository
{
@@ -63,6 +64,7 @@ namespace TrueCraft.Client
Graphics.PreferredBackBufferWidth = UserSettings.Local.WindowResolution.Width;
Graphics.PreferredBackBufferHeight = UserSettings.Local.WindowResolution.Height;
Graphics.ApplyChanges();
+ Window.ClientSizeChanged += Window_ClientSizeChanged;
Client = client;
EndPoint = endPoint;
LastPhysicsUpdate = DateTime.MinValue;
@@ -80,6 +82,16 @@ namespace TrueCraft.Client
Components.Add(mouseComponent);
}
+ void Window_ClientSizeChanged(object sender, EventArgs e)
+ {
+ if (GraphicsDevice.Viewport.Width < 640 || GraphicsDevice.Viewport.Height < 480)
+ ScaleFactor = 0.5f;
+ else if (GraphicsDevice.Viewport.Width < 978 || GraphicsDevice.Viewport.Height < 720)
+ ScaleFactor = 1.0f;
+ else
+ ScaleFactor = 1.5f;
+ }
+
protected override void Initialize()
{
Modules = new List();
@@ -92,6 +104,7 @@ namespace TrueCraft.Client
Modules.Add(ChunkModule);
Modules.Add(new HighlightModule(this));
Modules.Add(new PlayerControlModule(this));
+ Modules.Add(new HUDModule(this));
Modules.Add(DebugInfoModule);
Client.PropertyChanged += HandleClientPropertyChanged;
@@ -111,6 +124,8 @@ namespace TrueCraft.Client
Window.ClientSizeChanged += (sender, e) => CreateRenderTarget();
CreateRenderTarget();
SpriteBatch = new SpriteBatch(GraphicsDevice);
+
+ Window_ClientSizeChanged(null, null);
}
private void CreateRenderTarget()
@@ -235,9 +250,10 @@ namespace TrueCraft.Client
var bobbing = Bobbing * 1.5;
var xbob = Math.Cos(bobbing + Math.PI / 2) * bobbingMultiplier;
var ybob = Math.Sin(Math.PI / 2 - (2 * bobbing)) * bobbingMultiplier;
+
Camera.Position = new TrueCraft.API.Vector3(
Client.Position.X + xbob - (Client.Size.Width / 2),
- Client.Position.Y + (Client.Size.Height - 0.5) + ybob,
+ Client.Position.Y + Client.Size.Height + ybob,
Client.Position.Z - (Client.Size.Depth / 2));
Camera.Pitch = Client.Pitch;
diff --git a/TrueCraft.Client/VoxelCast.cs b/TrueCraft.Client/VoxelCast.cs
index 0ac6efb..9fdb467 100644
--- a/TrueCraft.Client/VoxelCast.cs
+++ b/TrueCraft.Client/VoxelCast.cs
@@ -15,122 +15,42 @@ namespace TrueCraft.Client
// Thanks to http://gamedev.stackexchange.com/questions/47362/cast-ray-to-select-block-in-voxel-game
public static Tuple Cast(ReadOnlyWorld world,
- Ray ray, IBlockRepository repository, double max)
+ Ray ray, IBlockRepository repository, int max)
{
- var origin = ray.Position.Floor();
- var direction = ray.Direction;
- var step = new Vector3(SigNum(ray.Direction.X), SigNum(ray.Direction.Y), SigNum(ray.Direction.Z));
- var tMax = new Vector3(
- IntBound(origin.X, direction.X),
- IntBound(origin.Y, direction.Y),
- IntBound(origin.Z, direction.Z));
- var tDelta = new Vector3(
- step.X / direction.X,
- step.Y / direction.Y,
- step.Z / direction.Z);
- BlockFace face = BlockFace.PositiveY;
+ // TODO: There are more efficient ways of doing this, fwiw
- if (ray.Direction == Vector3.Zero)
+ double min = max * 2;
+ var pick = -Coordinates3D.One;
+ for (int x = -max; x <= max; x++)
+ {
+ for (int y = -max; y <= max; y++)
+ {
+ for (int z = -max; z <= max; z++)
+ {
+ var coords = (Coordinates3D)(new Vector3(x, y, z) + ray.Position).Round();
+ if (!world.IsValidPosition(coords))
+ continue;
+ var id = world.GetBlockID(coords);
+ if (id != 0)
+ {
+ var provider = repository.GetBlockProvider(id);
+ var box = provider.BoundingBox;
+ if (box != null)
+ {
+ var distance = ray.Intersects(box.Value.OffsetBy(coords));
+ if (distance != null && distance.Value < min)
+ {
+ min = distance.Value;
+ pick = coords;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (pick == -Coordinates3D.One)
return null;
-
- max /= Math.Sqrt(ray.Direction.X * ray.Direction.X
- + ray.Direction.Y * ray.Direction.Y
- + ray.Direction.Z * ray.Direction.Z);
-
- while (world.IsValidPosition((Coordinates3D)origin))
- {
- var provider = repository.GetBlockProvider(world.GetBlockID((Coordinates3D)origin));
- var _box = provider.BoundingBox;
- if (_box != null)
- {
- var box = _box.Value.OffsetBy((Coordinates3D)origin);
- if (ray.Intersects(box) != null)
- return new Tuple((Coordinates3D)origin, face);
- }
-
- if (tMax.X < tMax.Y)
- {
- if (tMax.X < tMax.Z)
- {
- if (tMax.X > max)
- return null;
- // Update which cube we are now in.
- origin.X += step.X;
- // Adjust tMaxX to the next X-oriented boundary crossing.
- tMax.X += tDelta.X;
- // Record the normal vector of the cube face we entered.
- if (step.X < 0)
- face = BlockFace.PositiveX;
- else
- face = BlockFace.NegativeX;
- }
- else
- {
- if (tMax.Z > max)
- return null;
- origin.Z += step.Z;
- tMax.Z += tDelta.Z;
- if (step.Z < 0)
- face = BlockFace.PositiveZ;
- else
- face = BlockFace.NegativeZ;
- }
- }
- else
- {
- if (tMax.Y < tMax.Z)
- {
- if (tMax.Y > max)
- return null;
- origin.Y += step.Y;
- tMax.Y += tDelta.Y;
- if (step.Y < 0)
- face = BlockFace.PositiveY;
- else
- face = BlockFace.NegativeY;
- }
- else
- {
- // Identical to the second case, repeated for simplicity in
- // the conditionals.
- if (tMax.Z > max)
- break;
- origin.Z += step.Z;
- tMax.Z += tDelta.Z;
- if (step.Z < 0)
- face = BlockFace.PositiveZ;
- else
- face = BlockFace.NegativeZ;
- }
- }
- }
-
- return null;
- }
-
- private static double IntBound(double s, double ds)
- {
- // Find the smallest positive t such that s+t*ds is an integer.
- if (ds < 0)
- {
- return IntBound(-s, -ds);
- }
- else
- {
- s = Mod(s, 1);
- // problem is now s+t*ds = 1
- return (1 - s) / ds;
- }
- }
-
- private static int SigNum(double x)
- {
- return x > 0 ? 1 : x < 0 ? -1 : 0;
- }
-
- private static double Mod(double value, double modulus)
- {
- return (value % modulus + modulus) % modulus;
+ return new Tuple(pick, BlockFace.PositiveY);
}
}
}