From cd7190e9ebbe1fa08196ef5f9e2b204a32916e3e Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 21 Oct 2015 07:37:18 +1100 Subject: [PATCH] Fix bugs with third person camera over-aggressively culling, add forward facing third person camera, slightly decrease selection box for sprites. --- ClassicalSharp/Entities/Player.Rendering.cs | 13 ++++-- ClassicalSharp/Game/Game.cs | 7 +++- ClassicalSharp/Game/InputHandler.cs | 2 +- ClassicalSharp/Physics/Picking.cs | 7 +++- ClassicalSharp/Rendering/MapEnvRenderer.cs | 4 +- ClassicalSharp/Rendering/MapRenderer.cs | 3 +- ClassicalSharp/Rendering/PickingRenderer.cs | 6 +++ .../Rendering/StandardEnvRenderer.cs | 3 +- ClassicalSharp/Utils/Camera.cs | 42 +++++++++++++++++++ 9 files changed, 75 insertions(+), 12 deletions(-) diff --git a/ClassicalSharp/Entities/Player.Rendering.cs b/ClassicalSharp/Entities/Player.Rendering.cs index b7569f0ef..1ec04dd81 100644 --- a/ClassicalSharp/Entities/Player.Rendering.cs +++ b/ClassicalSharp/Entities/Player.Rendering.cs @@ -45,11 +45,16 @@ namespace ClassicalSharp { Vector3 pos = Position; pos.Y += Model.NameYOffset; + float u1 = nameTex.U1, u2 = nameTex.U2; + if( game.Camera is ForwardThirdPersonCamera ) { + u1 = nameTex.U2; u2 = nameTex.U1; + } + FastColour col = FastColour.White; - api.texVerts[0] = new VertexPos3fTex2fCol4b( Utils.RotateY( x1, y1, 0, cosA, sinA ) + pos, nameTex.U1, nameTex.V1, col ); - api.texVerts[1] = new VertexPos3fTex2fCol4b( Utils.RotateY( x2, y1, 0, cosA, sinA ) + pos, nameTex.U2, nameTex.V1, col ); - api.texVerts[2] = new VertexPos3fTex2fCol4b( Utils.RotateY( x2, y2, 0, cosA, sinA ) + pos, nameTex.U2, nameTex.V2, col ); - api.texVerts[3] = new VertexPos3fTex2fCol4b( Utils.RotateY( x1, y2, 0, cosA, sinA ) + pos, nameTex.U1, nameTex.V2, col ); + api.texVerts[0] = new VertexPos3fTex2fCol4b( Utils.RotateY( x1, y1, 0, cosA, sinA ) + pos, u1, nameTex.V1, col ); + api.texVerts[1] = new VertexPos3fTex2fCol4b( Utils.RotateY( x2, y1, 0, cosA, sinA ) + pos, u2, nameTex.V1, col ); + api.texVerts[2] = new VertexPos3fTex2fCol4b( Utils.RotateY( x2, y2, 0, cosA, sinA ) + pos, u2, nameTex.V2, col ); + api.texVerts[3] = new VertexPos3fTex2fCol4b( Utils.RotateY( x1, y2, 0, cosA, sinA ) + pos, u1, nameTex.V2, col ); api.BeginVbBatch( VertexFormat.Pos3fTex2fCol4b ); api.DrawDynamicIndexedVb( DrawMode.Triangles, api.texVb, api.texVerts, 4, 6 ); diff --git a/ClassicalSharp/Game/Game.cs b/ClassicalSharp/Game/Game.cs index 3b8572bc4..188803b2d 100644 --- a/ClassicalSharp/Game/Game.cs +++ b/ClassicalSharp/Game/Game.cs @@ -27,7 +27,7 @@ namespace ClassicalSharp { public CpeListInfo[] CpePlayersList = new CpeListInfo[256]; public LocalPlayer LocalPlayer; public Camera Camera; - Camera firstPersonCam, thirdPersonCam; + Camera firstPersonCam, thirdPersonCam, forwardThirdPersonCam; public BlockInfo BlockInfo; public double accumulator; public TerrainAtlas2D TerrainAtlas; @@ -153,6 +153,7 @@ namespace ClassicalSharp { firstPersonCam = new FirstPersonCamera( this ); thirdPersonCam = new ThirdPersonCamera( this ); + forwardThirdPersonCam = new ForwardThirdPersonCamera( this ); Camera = firstPersonCam; CommandManager = new CommandManager(); CommandManager.Init( this ); @@ -332,7 +333,9 @@ namespace ClassicalSharp { public void SetCamera( bool thirdPerson ) { PerspectiveCamera oldCam = (PerspectiveCamera)Camera; - Camera = ( thirdPerson && CanUseThirdPersonCamera ) ? thirdPersonCam : firstPersonCam; + Camera = (thirdPerson && CanUseThirdPersonCamera) ? + (Camera is FirstPersonCamera ? thirdPersonCam : forwardThirdPersonCam ) : + firstPersonCam; PerspectiveCamera newCam = (PerspectiveCamera)Camera; newCam.delta = oldCam.delta; newCam.previous = oldCam.previous; diff --git a/ClassicalSharp/Game/InputHandler.cs b/ClassicalSharp/Game/InputHandler.cs index 614de5f6d..b0757a961 100644 --- a/ClassicalSharp/Game/InputHandler.cs +++ b/ClassicalSharp/Game/InputHandler.cs @@ -194,7 +194,7 @@ namespace ClassicalSharp { WindowState.Normal : WindowState.Fullscreen; } } else if( key == game.Keys[KeyMapping.ThirdPersonCamera] ) { - bool useThirdPerson = game.Camera is FirstPersonCamera; + bool useThirdPerson = !(game.Camera is ForwardThirdPersonCamera); game.SetCamera( useThirdPerson ); } else if( key == game.Keys[KeyMapping.ViewDistance] ) { if( game.IsKeyDown( Key.ShiftLeft ) || game.IsKeyDown( Key.ShiftRight ) ) { diff --git a/ClassicalSharp/Physics/Picking.cs b/ClassicalSharp/Physics/Picking.cs index bb3a6562c..12dd950a8 100644 --- a/ClassicalSharp/Physics/Picking.cs +++ b/ClassicalSharp/Physics/Picking.cs @@ -90,7 +90,7 @@ namespace ClassicalSharp { float t0, t1; if( Intersection.RayIntersectsBox( origin, dir, min, max, out t0, out t1 ) ) { Vector3 intersect = origin + dir * t0; - pickedPos.SetAsValid( min, max, intersect ); + pickedPos.SetAsValid( min, max, block, intersect ); return; } } @@ -122,12 +122,14 @@ namespace ClassicalSharp { public Vector3I TranslatedPos; public bool Valid = true; public CpeBlockFace BlockFace; + public byte BlockType; - public void SetAsValid( Vector3 min, Vector3 max, Vector3 intersect ) { + public void SetAsValid( Vector3 min, Vector3 max, byte block, Vector3 intersect ) { Min = min; Max = max; BlockPos = Vector3I.Truncate( Min ); Valid = true; + BlockType = block; Vector3I normal = Vector3I.Zero; float dist = float.PositiveInfinity; @@ -144,6 +146,7 @@ namespace ClassicalSharp { Valid = false; BlockPos = TranslatedPos = Vector3I.MinusOne; BlockFace = (CpeBlockFace)255; + BlockType = 0; } void TestAxis( float dAxis, ref float dist, Vector3I nAxis, ref Vector3I normal, diff --git a/ClassicalSharp/Rendering/MapEnvRenderer.cs b/ClassicalSharp/Rendering/MapEnvRenderer.cs index 84e768f34..c5a13850f 100644 --- a/ClassicalSharp/Rendering/MapEnvRenderer.cs +++ b/ClassicalSharp/Rendering/MapEnvRenderer.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Drawing; using ClassicalSharp.GraphicsAPI; +using OpenTK; namespace ClassicalSharp { @@ -54,7 +55,8 @@ namespace ClassicalSharp { graphics.BindVb( edgesVb ); // Do not draw water when we cannot see it. // Fixes some 'depth bleeding through' issues with 16 bit depth buffers on large maps. - if( game.LocalPlayer.EyePosition.Y >= 0 ) { + Vector3 eyePos = game.LocalPlayer.EyePosition; + if( game.Camera.GetCameraPos( eyePos ).Y >= 0 ) { graphics.DrawIndexedVb_TrisT2fC4b( edgesVertices * 6 / 4, 0 ); } else { graphics.DrawIndexedVb_TrisT2fC4b( edgesVerVertices * 6 / 4, edgesBaseVertices * 6 / 4 ); diff --git a/ClassicalSharp/Rendering/MapRenderer.cs b/ClassicalSharp/Rendering/MapRenderer.cs index 46211c127..e9d6c5108 100644 --- a/ClassicalSharp/Rendering/MapRenderer.cs +++ b/ClassicalSharp/Rendering/MapRenderer.cs @@ -225,7 +225,8 @@ namespace ClassicalSharp { int[] distances; void UpdateSortOrder() { Player p = game.LocalPlayer; - Vector3I newChunkPos = Vector3I.Floor( p.EyePosition ); + Vector3 cameraPos = game.Camera.GetCameraPos( p.EyePosition ); + Vector3I newChunkPos = Vector3I.Floor( cameraPos ); newChunkPos.X = (newChunkPos.X & ~0x0F) + 8; newChunkPos.Y = (newChunkPos.Y & ~0x0F) + 8; newChunkPos.Z = (newChunkPos.Z & ~0x0F) + 8; diff --git a/ClassicalSharp/Rendering/PickingRenderer.cs b/ClassicalSharp/Rendering/PickingRenderer.cs index 938eadbb9..e0deacd5e 100644 --- a/ClassicalSharp/Rendering/PickingRenderer.cs +++ b/ClassicalSharp/Rendering/PickingRenderer.cs @@ -7,11 +7,13 @@ namespace ClassicalSharp.Renderers { public class PickingRenderer { IGraphicsApi graphics; + BlockInfo info; int vb; public PickingRenderer( Game window ) { graphics = window.Graphics; vb = graphics.CreateDynamicVb( VertexFormat.Pos3fCol4b, verticesCount ); + info = window.BlockInfo; } FastColour col = FastColour.Black; @@ -27,6 +29,10 @@ namespace ClassicalSharp.Renderers { Vector3 p2 = pickedPos.Max + new Vector3( offset, offset, offset ); col.A = 150; graphics.AlphaBlending = true; + if( info.IsSprite[pickedPos.BlockType] ) { + p1.X += 2.50f/16f; p1.Z += 2.50f/16f; + p2.X -= 2.50f/16f; p2.Z -= 2.50f/16f; + } // bottom face DrawYPlane( p1.Y, p1.X, p1.Z, p1.X + size, p2.Z ); diff --git a/ClassicalSharp/Rendering/StandardEnvRenderer.cs b/ClassicalSharp/Rendering/StandardEnvRenderer.cs index 422cf6f5e..a169cb9c0 100644 --- a/ClassicalSharp/Rendering/StandardEnvRenderer.cs +++ b/ClassicalSharp/Rendering/StandardEnvRenderer.cs @@ -25,7 +25,8 @@ namespace ClassicalSharp.Renderers { public override void Render( double deltaTime ) { if( skyVb == -1 || cloudsVb == -1 ) return; - Vector3 pos = game.LocalPlayer.EyePosition; + Vector3 eyePos = game.LocalPlayer.EyePosition; + Vector3 pos = game.Camera.GetCameraPos( eyePos ); if( pos.Y < map.CloudHeight + 8 ) { graphics.BeginVbBatch( VertexFormat.Pos3fCol4b ); graphics.BindVb( skyVb ); diff --git a/ClassicalSharp/Utils/Camera.cs b/ClassicalSharp/Utils/Camera.cs index 57001988c..7fd93efae 100644 --- a/ClassicalSharp/Utils/Camera.cs +++ b/ClassicalSharp/Utils/Camera.cs @@ -12,6 +12,12 @@ namespace ClassicalSharp { public abstract Matrix4 GetView(); + /// Calculates the location of the camera's position in the world + /// based on the entity's eye position. + public abstract Vector3 GetCameraPos( Vector3 eyePos ); + + /// Whether this camera is using a third person perspective. + /// This causes the local player to be renderered if true. public abstract bool IsThirdPerson { get; } public virtual void Tick( double elapsed ) { @@ -23,6 +29,7 @@ namespace ClassicalSharp { public abstract void RegrabMouse(); + /// Calculates the picked block based on the camera's current position. public virtual void GetPickedBlock( PickedPos pos ) { } } @@ -112,6 +119,37 @@ namespace ClassicalSharp { public override bool IsThirdPerson { get { return true; } } + + public override Vector3 GetCameraPos( Vector3 eyePos ) { + return eyePos - Utils.GetDirVector( player.YawRadians, player.PitchRadians ) * distance; + } + } + + public class ForwardThirdPersonCamera : PerspectiveCamera { + + public ForwardThirdPersonCamera( Game window ) : base( window ) { + } + + float distance = 3; + public override bool MouseZoom( MouseWheelEventArgs e ) { + distance -= e.DeltaPrecise; + if( distance < 2 ) distance = 2; + return true; + } + + public override Matrix4 GetView() { + Vector3 eyePos = player.EyePosition; + Vector3 cameraPos = eyePos + Utils.GetDirVector( player.YawRadians, player.PitchRadians ) * distance; + return Matrix4.LookAt( cameraPos, eyePos, Vector3.UnitY ); + } + + public override bool IsThirdPerson { + get { return true; } + } + + public override Vector3 GetCameraPos( Vector3 eyePos ) { + return eyePos + Utils.GetDirVector( player.YawRadians, player.PitchRadians ) * distance; + } } public class FirstPersonCamera : PerspectiveCamera { @@ -128,5 +166,9 @@ namespace ClassicalSharp { public override bool IsThirdPerson { get { return false; } } + + public override Vector3 GetCameraPos( Vector3 eyePos ) { + return eyePos; + } } }