Fix highlighted block, add crosshairs

This commit is contained in:
Drew DeVault 2015-09-27 17:14:04 -04:00
parent 6066db0bd7
commit 02146108ba
14 changed files with 204 additions and 210 deletions

View File

@ -79,6 +79,14 @@ namespace TrueCraft.API
return new Vector3(Math.Floor(X), Math.Floor(Y), Math.Floor(Z)); return new Vector3(Math.Floor(X), Math.Floor(Y), Math.Floor(Z));
} }
/// <summary>
/// Rounds the decimal component of each part of this Vector3.
/// </summary>
public Vector3 Round()
{
return new Vector3(Math.Round(X), Math.Round(Y), Math.Round(Z));
}
/// <summary> /// <summary>
/// Clamps the vector to within the specified value. /// Clamps the vector to within the specified value.
/// </summary> /// </summary>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -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();
}
}
}

View File

@ -3,6 +3,9 @@ using Microsoft.Xna.Framework.Graphics;
using TrueCraft.API; using TrueCraft.API;
using TrueCraft.Client.Rendering; using TrueCraft.Client.Rendering;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using XVector3 = Microsoft.Xna.Framework.Vector3;
using TVector3 = TrueCraft.API.Vector3;
using TRay = TrueCraft.API.Ray;
namespace TrueCraft.Client.Modules namespace TrueCraft.Client.Modules
{ {
@ -10,51 +13,37 @@ namespace TrueCraft.Client.Modules
{ {
public TrueCraftGame Game { get; set; } public TrueCraftGame Game { get; set; }
private Texture2D HighlightTexture { get; set; }
private Coordinates3D HighlightedBlock { get; set; } private Coordinates3D HighlightedBlock { get; set; }
private Mesh HighlightMesh { get; set; }
private BasicEffect HighlightEffect { 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) public HighlightModule(TrueCraftGame game)
{ {
Game = 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<Color>(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 = 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; HighlightEffect.VertexColorEnabled = true;
} }
@ -66,18 +55,19 @@ namespace TrueCraft.Client.Modules
Matrix.CreateRotationY(MathHelper.ToRadians(Game.Client.Yaw))); Matrix.CreateRotationY(MathHelper.ToRadians(Game.Client.Yaw)));
var cast = VoxelCast.Cast(Game.Client.World, var cast = VoxelCast.Cast(Game.Client.World,
new TrueCraft.API.Ray(Game.Camera.Position, new TRay(Game.Camera.Position, new TVector3(direction.X, direction.Y, direction.Z)),
new TrueCraft.API.Vector3(direction.X, direction.Y, direction.Z)), Game.BlockRepository, (int)TrueCraftGame.Reach);
Game.BlockRepository, TrueCraftGame.Reach);
if (cast == null) if (cast == null)
HighlightedBlock = -Coordinates3D.One; HighlightedBlock = -Coordinates3D.One;
else else
{ {
HighlightedBlock = cast.Item1; HighlightedBlock = cast.Item1;
HighlightEffect.World = Matrix.CreateScale(1.02f) * HighlightEffect.World =
Matrix.CreateTranslation(new Microsoft.Xna.Framework.Vector3( Matrix.CreateTranslation(new XVector3(-0.5f)) *
cast.Item1.X, cast.Item1.Y, cast.Item1.Z)); 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) if (HighlightedBlock != -Coordinates3D.One)
{ {
Game.GraphicsDevice.DepthStencilState = DepthStencilState.None; foreach (var pass in HighlightEffect.CurrentTechnique.Passes)
HighlightMesh.Draw(HighlightEffect); {
pass.Apply();
HighlightEffect.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>(
PrimitiveType.LineList, CubeVerticies, 0,
CubeVerticies.Length, CubeIndicies, 0, CubeIndicies.Length / 2);
}
} }
} }
} }

View File

@ -11,10 +11,12 @@ namespace TrueCraft.Client.Modules
{ {
private TrueCraftGame Game { get; set; } private TrueCraftGame Game { get; set; }
private Vector3 Delta { get; set; } private Vector3 Delta { get; set; }
private bool Capture { get; set; }
public PlayerControlModule(TrueCraftGame game) public PlayerControlModule(TrueCraftGame game)
{ {
Game = game; Game = game;
Capture = true;
} }
public bool KeyDown(GameTime gameTime, KeyboardKeyEventArgs e) public bool KeyDown(GameTime gameTime, KeyboardKeyEventArgs e)
@ -55,6 +57,14 @@ namespace TrueCraft.Client.Modules
Delta += Vector3.Backward; Delta += Vector3.Backward;
return true; return true;
case Keys.I:
Game.Client.Position = Game.Client.Position.Floor();
return true;
case Keys.Tab:
Capture = !Capture;
return true;
case Keys.Space: case Keys.Space:
if (Math.Floor(Game.Client.Position.Y) == Game.Client.Position.Y) if (Math.Floor(Game.Client.Position.Y) == Game.Client.Position.Y)
Game.Client.Velocity += TrueCraft.API.Vector3.Up * 0.3; Game.Client.Velocity += TrueCraft.API.Vector3.Up * 0.3;
@ -96,6 +106,8 @@ namespace TrueCraft.Client.Modules
public void MouseMove(GameTime gameTime, MouseMoveEventArgs e) public void MouseMove(GameTime gameTime, MouseMoveEventArgs e)
{ {
if (!Capture)
return;
var centerX = Game.GraphicsDevice.Viewport.Width / 2; var centerX = Game.GraphicsDevice.Viewport.Width / 2;
var centerY = Game.GraphicsDevice.Viewport.Height / 2; var centerY = Game.GraphicsDevice.Viewport.Height / 2;
Mouse.SetPosition(centerX, centerY); Mouse.SetPosition(centerX, centerY);

View File

@ -256,7 +256,8 @@ namespace TrueCraft.Client
{ {
get get
{ {
return new BoundingBox(Position, Position + Size); var pos = Position - new Vector3(Width / 2, 0, Depth / 2);
return new BoundingBox(pos, pos + Size);
} }
} }

View File

@ -147,50 +147,50 @@ namespace TrueCraft.Client.Rendering
CubeMesh[0] = new[] // Positive Z face CubeMesh[0] = new[] // Positive Z face
{ {
new Vector3(0.5f, -0.5f, 0.5f), new Vector3(1, 0, 1),
new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(0, 0, 1),
new Vector3(-0.5f, 0.5f, 0.5f), new Vector3(0, 1, 1),
new Vector3(0.5f, 0.5f, 0.5f) new Vector3(1, 1, 1)
}; };
CubeMesh[1] = new[] // Negative Z face CubeMesh[1] = new[] // Negative Z face
{ {
new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(0, 0, 0),
new Vector3(0.5f, -0.5f, -0.5f), new Vector3(1, 0, 0),
new Vector3(0.5f, 0.5f, -0.5f), new Vector3(1, 1, 0),
new Vector3(-0.5f, 0.5f, -0.5f) new Vector3(0, 1, 0)
}; };
CubeMesh[2] = new[] // Positive X face CubeMesh[2] = new[] // Positive X face
{ {
new Vector3(0.5f, -0.5f, -0.5f), new Vector3(1, 0, 0),
new Vector3(0.5f, -0.5f, 0.5f), new Vector3(1, 0, 1),
new Vector3(0.5f, 0.5f, 0.5f), new Vector3(1, 1, 1),
new Vector3(0.5f, 0.5f, -0.5f) new Vector3(1, 1, 0)
}; };
CubeMesh[3] = new[] // Negative X face CubeMesh[3] = new[] // Negative X face
{ {
new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(0, 0, 1),
new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(0, 0, 0),
new Vector3(-0.5f, 0.5f, -0.5f), new Vector3(0, 1, 0),
new Vector3(-0.5f, 0.5f, 0.5f) new Vector3(0, 1, 1)
}; };
CubeMesh[4] = new[] // Positive Y face CubeMesh[4] = new[] // Positive Y face
{ {
new Vector3(0.5f, 0.5f, 0.5f), new Vector3(1, 1, 1),
new Vector3(-0.5f, 0.5f, 0.5f), new Vector3(0, 1, 1),
new Vector3(-0.5f, 0.5f, -0.5f), new Vector3(0, 1, 0),
new Vector3(0.5f, 0.5f, -0.5f) new Vector3(1, 1, 0)
}; };
CubeMesh[5] = new[] // Negative Y face CubeMesh[5] = new[] // Negative Y face
{ {
new Vector3(0.5f, -0.5f, -0.5f), new Vector3(1, 0, 0),
new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(0, 0, 0),
new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(0, 0, 1),
new Vector3(0.5f, -0.5f, 0.5f) new Vector3(1, 0, 1)
}; };
} }
} }

View File

@ -27,17 +27,13 @@ namespace TrueCraft.Client.Rendering.Blocks
public override VertexPositionNormalColorTexture[] Render(BlockDescriptor descriptor, Vector3 offset, public override VertexPositionNormalColorTexture[] Render(BlockDescriptor descriptor, Vector3 offset,
VisibleFaces faces, Tuple<int, int> textureMap, int indiciesOffset, out int[] indicies) VisibleFaces faces, Tuple<int, int> textureMap, int indiciesOffset, out int[] indicies)
{ {
var overhead = new Vector3(0.5f, 0.5f, 0.5f); var cube = CreateUniformCube(Vector3.Zero, Texture, faces, indiciesOffset, out indicies, Color.White);
var cube = CreateUniformCube(overhead, Texture, faces, indiciesOffset, out indicies, Color.White);
var heightMultiplier = new Vector3(1, ((descriptor.Metadata + 1) / 16f), 1); var heightMultiplier = new Vector3(1, ((descriptor.Metadata + 1) / 16f), 1);
for (int i = 0; i < cube.Length; i++) for (int i = 0; i < cube.Length; i++)
{ {
if (cube[i].Position.Y > 0) if (cube[i].Position.Y > 0)
{
cube[i].Position *= heightMultiplier; cube[i].Position *= heightMultiplier;
}
cube[i].Position += offset; cube[i].Position += offset;
cube[i].Position -= overhead;
} }
return cube; return cube;
} }

View File

@ -46,10 +46,11 @@ namespace TrueCraft.Client.Rendering
indicies = new int[4 * 2 * 6]; indicies = new int[4 * 2 * 6];
var verticies = new VertexPositionNormalColorTexture[4 * 2 * 6]; var verticies = new VertexPositionNormalColorTexture[4 * 2 * 6];
int[] _indicies; 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 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 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) if (side == CubeFace.NegativeX || side == CubeFace.PositiveX)
{ {
for (int i = 0; i < quad.Length; i++) for (int i = 0; i < quad.Length; i++)
@ -73,7 +74,7 @@ namespace TrueCraft.Client.Rendering
for (int _side = 0; _side < 4; _side++) for (int _side = 0; _side < 4; _side++)
{ {
var side = (CubeFace)_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) if (side == CubeFace.NegativeX || side == CubeFace.PositiveX)
{ {
for (int i = 0; i < quad.Length; i++) for (int i = 0; i < quad.Length; i++)
@ -98,6 +99,7 @@ namespace TrueCraft.Client.Rendering
for (int i = 0; i < verticies.Length; i++) for (int i = 0; i < verticies.Length; i++)
{ {
verticies[i].Position.Y -= 1 / 16f; verticies[i].Position.Y -= 1 / 16f;
verticies[i].Position -= center;
} }
return verticies; return verticies;
} }

View File

@ -80,34 +80,34 @@ namespace TrueCraft.Client.Rendering
QuadMesh[0] = new[] QuadMesh[0] = new[]
{ {
new Vector3(0.5f, -0.5f, 0.5f), new Vector3(1, 0, 1),
new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(0, 0, 0),
new Vector3(-0.5f, 0.5f, -0.5f), new Vector3(0, 1, 0),
new Vector3(0.5f, 0.5f, 0.5f) new Vector3(1, 1, 1)
}; };
QuadMesh[1] = new[] QuadMesh[1] = new[]
{ {
new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(0, 0, 0),
new Vector3(0.5f, -0.5f, 0.5f), new Vector3(1, 0, 1),
new Vector3(0.5f, 0.5f, 0.5f), new Vector3(1, 1, 1),
new Vector3(-0.5f, 0.5f, -0.5f) new Vector3(0, 1, 0)
}; };
QuadMesh[2] = new[] QuadMesh[2] = new[]
{ {
new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(0, 0, 1),
new Vector3(0.5f, -0.5f, -0.5f), new Vector3(1, 0, 0),
new Vector3(0.5f, 0.5f, -0.5f), new Vector3(1, 1, 0),
new Vector3(-0.5f, 0.5f, 0.5f) new Vector3(0, 1, 1)
}; };
QuadMesh[3] = new[] QuadMesh[3] = new[]
{ {
new Vector3(0.5f, -0.5f, -0.5f), new Vector3(1, 0, 0),
new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(0, 0, 1),
new Vector3(-0.5f, 0.5f, 0.5f), new Vector3(0, 1, 1),
new Vector3(0.5f, 0.5f, -0.5f) new Vector3(1, 1, 0)
}; };
} }
} }

View File

@ -31,6 +31,8 @@ namespace TrueCraft.Client.Rendering
Defaults.Add("items.png", new PngReader().Read(File.OpenRead("Content/items.png"), graphicsDevice)); 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("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));
} }
/// <summary> /// <summary>

View File

@ -132,6 +132,7 @@
<Compile Include="Modules\HighlightModule.cs" /> <Compile Include="Modules\HighlightModule.cs" />
<Compile Include="Modules\PlayerControlModule.cs" /> <Compile Include="Modules\PlayerControlModule.cs" />
<Compile Include="Modules\DebugInfoModule.cs" /> <Compile Include="Modules\DebugInfoModule.cs" />
<Compile Include="Modules\HUDModule.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup> <ItemGroup>
@ -230,8 +231,11 @@
<Content Include="Content\gui.png"> <Content Include="Content\gui.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Content\icons.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Modules\" /> <Folder Include="Modules\" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -28,6 +28,7 @@ namespace TrueCraft.Client
public ConcurrentBag<Action> PendingMainThreadActions { get; set; } public ConcurrentBag<Action> PendingMainThreadActions { get; set; }
public double Bobbing { get; set; } public double Bobbing { get; set; }
public ChunkModule ChunkModule { get; set; } public ChunkModule ChunkModule { get; set; }
public float ScaleFactor { get; set; }
private List<IGameplayModule> Modules { get; set; } private List<IGameplayModule> Modules { get; set; }
private SpriteBatch SpriteBatch { get; set; } private SpriteBatch SpriteBatch { get; set; }
@ -43,7 +44,7 @@ namespace TrueCraft.Client
private GameTime GameTime { get; set; } private GameTime GameTime { get; set; }
private DebugInfoModule DebugInfoModule { get; set; } private DebugInfoModule DebugInfoModule { get; set; }
public static readonly int Reach = 5; public static readonly double Reach = 3;
public IBlockRepository BlockRepository public IBlockRepository BlockRepository
{ {
@ -63,6 +64,7 @@ namespace TrueCraft.Client
Graphics.PreferredBackBufferWidth = UserSettings.Local.WindowResolution.Width; Graphics.PreferredBackBufferWidth = UserSettings.Local.WindowResolution.Width;
Graphics.PreferredBackBufferHeight = UserSettings.Local.WindowResolution.Height; Graphics.PreferredBackBufferHeight = UserSettings.Local.WindowResolution.Height;
Graphics.ApplyChanges(); Graphics.ApplyChanges();
Window.ClientSizeChanged += Window_ClientSizeChanged;
Client = client; Client = client;
EndPoint = endPoint; EndPoint = endPoint;
LastPhysicsUpdate = DateTime.MinValue; LastPhysicsUpdate = DateTime.MinValue;
@ -80,6 +82,16 @@ namespace TrueCraft.Client
Components.Add(mouseComponent); 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() protected override void Initialize()
{ {
Modules = new List<IGameplayModule>(); Modules = new List<IGameplayModule>();
@ -92,6 +104,7 @@ namespace TrueCraft.Client
Modules.Add(ChunkModule); Modules.Add(ChunkModule);
Modules.Add(new HighlightModule(this)); Modules.Add(new HighlightModule(this));
Modules.Add(new PlayerControlModule(this)); Modules.Add(new PlayerControlModule(this));
Modules.Add(new HUDModule(this));
Modules.Add(DebugInfoModule); Modules.Add(DebugInfoModule);
Client.PropertyChanged += HandleClientPropertyChanged; Client.PropertyChanged += HandleClientPropertyChanged;
@ -111,6 +124,8 @@ namespace TrueCraft.Client
Window.ClientSizeChanged += (sender, e) => CreateRenderTarget(); Window.ClientSizeChanged += (sender, e) => CreateRenderTarget();
CreateRenderTarget(); CreateRenderTarget();
SpriteBatch = new SpriteBatch(GraphicsDevice); SpriteBatch = new SpriteBatch(GraphicsDevice);
Window_ClientSizeChanged(null, null);
} }
private void CreateRenderTarget() private void CreateRenderTarget()
@ -235,9 +250,10 @@ namespace TrueCraft.Client
var bobbing = Bobbing * 1.5; var bobbing = Bobbing * 1.5;
var xbob = Math.Cos(bobbing + Math.PI / 2) * bobbingMultiplier; var xbob = Math.Cos(bobbing + Math.PI / 2) * bobbingMultiplier;
var ybob = Math.Sin(Math.PI / 2 - (2 * bobbing)) * bobbingMultiplier; var ybob = Math.Sin(Math.PI / 2 - (2 * bobbing)) * bobbingMultiplier;
Camera.Position = new TrueCraft.API.Vector3( Camera.Position = new TrueCraft.API.Vector3(
Client.Position.X + xbob - (Client.Size.Width / 2), 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)); Client.Position.Z - (Client.Size.Depth / 2));
Camera.Pitch = Client.Pitch; Camera.Pitch = Client.Pitch;

View File

@ -15,122 +15,42 @@ namespace TrueCraft.Client
// Thanks to http://gamedev.stackexchange.com/questions/47362/cast-ray-to-select-block-in-voxel-game // Thanks to http://gamedev.stackexchange.com/questions/47362/cast-ray-to-select-block-in-voxel-game
public static Tuple<Coordinates3D, BlockFace> Cast(ReadOnlyWorld world, public static Tuple<Coordinates3D, BlockFace> Cast(ReadOnlyWorld world,
Ray ray, IBlockRepository repository, double max) Ray ray, IBlockRepository repository, int max)
{ {
var origin = ray.Position.Floor(); // TODO: There are more efficient ways of doing this, fwiw
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;
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; return null;
return new Tuple<Coordinates3D, BlockFace>(pick, BlockFace.PositiveY);
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, BlockFace>((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;
} }
} }
} }