diff --git a/ClassicalSharp/2D/Screens/Menu/HacksSettingsScreen.cs b/ClassicalSharp/2D/Screens/Menu/HacksSettingsScreen.cs
index 07f00a7a6..9724cf878 100644
--- a/ClassicalSharp/2D/Screens/Menu/HacksSettingsScreen.cs
+++ b/ClassicalSharp/2D/Screens/Menu/HacksSettingsScreen.cs
@@ -27,6 +27,11 @@ namespace ClassicalSharp {
(g, v) => { g.LocalPlayer.SpeedMultiplier = Single.Parse( v );
Options.Set( OptionsKey.Speed, v ); } ),
+ Make( -140, 0, "Camera clipping", OnWidgetClick,
+ g => g.CameraClipping ? "yes" : "no",
+ (g, v) => { g.CameraClipping = v == "yes";
+ Options.Set( OptionsKey.CameraClipping, v == "yes" ); } ),
+
// Column 2
Make( 140, -100, "Liquids breakable", OnWidgetClick,
g => g.LiquidsBreakable ? "yes" : "no",
@@ -56,6 +61,7 @@ namespace ClassicalSharp {
validators = new MenuInputValidator[] {
new BooleanValidator(),
new RealValidator( 0.1f, 50 ),
+ new BooleanValidator(),
new BooleanValidator(),
new BooleanValidator(),
diff --git a/ClassicalSharp/Entities/LocalPlayer.cs b/ClassicalSharp/Entities/LocalPlayer.cs
index da5b33e4c..d9ffaaa04 100644
--- a/ClassicalSharp/Entities/LocalPlayer.cs
+++ b/ClassicalSharp/Entities/LocalPlayer.cs
@@ -142,16 +142,7 @@ namespace ClassicalSharp {
SoundType type = SoundType.None;
bool nonAir = false;
- // first check block standing on
- byte blockUnder = (byte)BlockUnderFeet;
- SoundType typeUnder = game.BlockInfo.StepSounds[blockUnder];
- BlockCollideType collideType = game.BlockInfo.CollideType[blockUnder];
- if( collideType == BlockCollideType.Solid && typeUnder != SoundType.None ) {
- nonAir = true;
- return typeUnder;
- }
-
- // then check surrounding liquids/gas for sounds
+ // first check surrounding liquids/gas for sounds
TouchesAny( bounds, b => {
SoundType newType = game.BlockInfo.StepSounds[b];
BlockCollideType collide = game.BlockInfo.CollideType[b];
@@ -163,6 +154,15 @@ namespace ClassicalSharp {
if( type != SoundType.None )
return type;
+ // then check block standing on
+ byte blockUnder = (byte)BlockUnderFeet;
+ SoundType typeUnder = game.BlockInfo.StepSounds[blockUnder];
+ BlockCollideType collideType = game.BlockInfo.CollideType[blockUnder];
+ if( collideType == BlockCollideType.Solid && typeUnder != SoundType.None ) {
+ nonAir = true;
+ return typeUnder;
+ }
+
// then check all solid blocks at feet
pos.Y -= 0.01f;
bounds.Max.Y = bounds.Min.Y = pos.Y;
diff --git a/ClassicalSharp/Game/Game.Properties.cs b/ClassicalSharp/Game/Game.Properties.cs
index 458c5f742..41f4fd33a 100644
--- a/ClassicalSharp/Game/Game.Properties.cs
+++ b/ClassicalSharp/Game/Game.Properties.cs
@@ -55,6 +55,9 @@ namespace ClassicalSharp {
/// Accumulator for the number of chunk updates performed. Reset every second.
public int ChunkUpdates;
+ /// Whether the third person camera should have their camera position clipped so as to not intersect blocks.
+ public bool CameraClipping = true;
+
public MapRenderer MapRenderer;
public MapBordersRenderer MapBordersRenderer;
public EnvRenderer EnvRenderer;
@@ -66,7 +69,7 @@ namespace ClassicalSharp {
public SelectionManager SelectionManager;
public ParticleManager ParticleManager;
public PickingRenderer Picking;
- public PickedPos SelectedPos = new PickedPos();
+ public PickedPos SelectedPos = new PickedPos(), CameraClipPos = new PickedPos();
public ModelCache ModelCache;
internal string skinServer, chatInInputBuffer = null;
internal int defaultIb;
@@ -126,6 +129,8 @@ namespace ClassicalSharp {
public bool ViewBobbing, ShowBlockInHand;
public bool UseSound, UseMusic, LiquidsBreakable;
+ public Vector3 CurrentCameraPos;
+
public Animations Animations;
internal int CloudsTexId, RainTexId, SnowTexId, GuiTexId;
internal bool screenshotRequested;
diff --git a/ClassicalSharp/Game/Game.cs b/ClassicalSharp/Game/Game.cs
index f0b3132a4..ede2c2a6e 100644
--- a/ClassicalSharp/Game/Game.cs
+++ b/ClassicalSharp/Game/Game.cs
@@ -44,6 +44,7 @@ namespace ClassicalSharp {
Options.Load();
AcceptedUrls.Load();
ViewDistance = Options.GetInt( OptionsKey.ViewDist, 16, 4096, 512 );
+ CameraClipping = Options.GetBool( OptionsKey.CameraClipping, true );
InputHandler = new InputHandler( this );
Chat = new ChatLog( this );
ParticleManager = new ParticleManager( this );
@@ -185,10 +186,12 @@ namespace ClassicalSharp {
Culling.CalcFrustumEquations( ref Projection, ref modelView );
bool visible = activeScreen == null || !activeScreen.BlocksWorld;
- if( visible ) {
+ if( visible ) {
AxisLinesRenderer.Render( e.Time );
Players.RenderModels( Graphics, e.Time, t );
Players.RenderNames( Graphics, e.Time, t );
+ CurrentCameraPos = Camera.GetCameraPos( LocalPlayer.EyePosition );
+
ParticleManager.Render( e.Time, t );
Camera.GetPickedBlock( SelectedPos ); // TODO: only pick when necessary
EnvRenderer.Render( e.Time );
@@ -351,7 +354,7 @@ namespace ClassicalSharp {
PerspectiveCamera oldCam = (PerspectiveCamera)Camera;
if( Camera == firstPersonCam ) Camera = thirdPersonCam;
else if( Camera == thirdPersonCam ) Camera = forwardThirdPersonCam;
- else if( Camera == forwardThirdPersonCam ) Camera = firstPersonZoomCam;
+ //else if( Camera == forwardThirdPersonCam ) Camera = firstPersonZoomCam;
else Camera = firstPersonCam;
if( !LocalPlayer.CanUseThirdPersonCamera )
diff --git a/ClassicalSharp/Physics/PickedPos.cs b/ClassicalSharp/Physics/PickedPos.cs
index be4e8005e..cae6a9ce5 100644
--- a/ClassicalSharp/Physics/PickedPos.cs
+++ b/ClassicalSharp/Physics/PickedPos.cs
@@ -12,6 +12,9 @@ namespace ClassicalSharp {
/// Maximum world coordinates of the block's bounding box.
public Vector3 Max;
+ /// Exact world coordinates at which the ray intersected this block.
+ public Vector3 IntersectPoint;
+
/// Integer world coordinates of the block.
public Vector3I BlockPos;
@@ -36,6 +39,7 @@ namespace ClassicalSharp {
BlockPos = new Vector3I( x, y, z );
Valid = true;
BlockType = block;
+ IntersectPoint = intersect;
Vector3I normal = Vector3I.Zero;
float dist = float.PositiveInfinity;
diff --git a/ClassicalSharp/Physics/Picking.cs b/ClassicalSharp/Physics/Picking.cs
index 65a75e0a3..3a09f3a1a 100644
--- a/ClassicalSharp/Physics/Picking.cs
+++ b/ClassicalSharp/Physics/Picking.cs
@@ -10,7 +10,7 @@ namespace ClassicalSharp {
/// Determines the picked block based on the given origin and direction vector.
/// Marks pickedPos as invalid if a block could not be found due to going outside map boundaries
/// or not being able to find a suitable candiate within the given reach distance.
- public static void CalculatePickedBlock( Game window, Vector3 origin, Vector3 dir, float reach, PickedPos pickedPos ) {
+ public static void CalculatePickedBlock( Game game, Vector3 origin, Vector3 dir, float reach, PickedPos pickedPos ) {
// Implementation based on: "A Fast Voxel Traversal Algorithm for Ray Tracing"
// John Amanatides, Andrew Woo
// http://www.cse.yorku.ca/~amana/research/grid.pdf
@@ -21,10 +21,10 @@ namespace ClassicalSharp {
int x = start.X, y = start.Y, z = start.Z;
Vector3I step, cellBoundary;
Vector3 tMax, tDelta;
- CalculateTimes( origin, dir, out step, out cellBoundary, out tMax, out tDelta );
+ CalcVectors( origin, dir, out step, out cellBoundary, out tMax, out tDelta );
- Map map = window.Map;
- BlockInfo info = window.BlockInfo;
+ Map map = game.Map;
+ BlockInfo info = game.BlockInfo;
float reachSquared = reach * reach;
int iterations = 0;
@@ -44,7 +44,7 @@ namespace ClassicalSharp {
return;
}
- if( window.CanPick( block ) ) {
+ if( game.CanPick( block ) ) {
// This cell falls on the path of the ray. Now perform an additional bounding box test,
// since some blocks do not occupy a whole cell.
float t0, t1;
@@ -61,15 +61,20 @@ namespace ClassicalSharp {
"Something has gone wrong. (dir: " + dir + ")" );
}
- public static void ClipCameraPos( Game window, Vector3 origin, Vector3 dir, float reach, PickedPos pickedPos ) {
+ public static void ClipCameraPos( Game game, Vector3 origin, Vector3 dir, float reach, PickedPos pickedPos ) {
+ if( !game.CameraClipping ) {
+ pickedPos.SetAsInvalid();
+ pickedPos.IntersectPoint = origin + dir * reach;
+ return;
+ }
Vector3I start = Vector3I.Floor( origin );
int x = start.X, y = start.Y, z = start.Z;
Vector3I step, cellBoundary;
Vector3 tMax, tDelta;
- CalculateTimes( origin, dir, out step, out cellBoundary, out tMax, out tDelta );
+ CalcVectors( origin, dir, out step, out cellBoundary, out tMax, out tDelta );
- Map map = window.Map;
- BlockInfo info = window.BlockInfo;
+ Map map = game.Map;
+ BlockInfo info = game.BlockInfo;
float reachSquared = reach * reach;
int iterations = 0;
@@ -84,25 +89,42 @@ namespace ClassicalSharp {
if( dx * dx + dy * dy + dz * dz > reachSquared ) {
pickedPos.SetAsInvalid();
+ pickedPos.IntersectPoint = origin + dir * reach;
return;
}
if( info.CollideType[block] == BlockCollideType.Solid && !info.IsAir[block] ) {
float t0, t1;
+ const float adjust = 0.1f;
if( Intersection.RayIntersectsBox( origin, dir, min, max, out t0, out t1 ) ) {
Vector3 intersect = origin + dir * t0;
pickedPos.SetAsValid( x, y, z, min, max, block, intersect );
+
+ switch( pickedPos.BlockFace) {
+ case CpeBlockFace.XMin:
+ pickedPos.IntersectPoint.X -= adjust; break;
+ case CpeBlockFace.XMax:
+ pickedPos.IntersectPoint.X += adjust; break;
+ case CpeBlockFace.YMin:
+ pickedPos.IntersectPoint.Y -= adjust; break;
+ case CpeBlockFace.YMax:
+ pickedPos.IntersectPoint.Y += adjust; break;
+ case CpeBlockFace.ZMin:
+ pickedPos.IntersectPoint.Z -= adjust; break;
+ case CpeBlockFace.ZMax:
+ pickedPos.IntersectPoint.Z += adjust; break;
+ }
return;
}
}
Step( ref tMax, ref tDelta, ref step, ref x, ref y, ref z );
iterations++;
}
- throw new InvalidOperationException( "did over 10000 iterations in GetPickedBlockPos(). " +
+ throw new InvalidOperationException( "did over 10000 iterations in ClipCameraPos(). " +
"Something has gone wrong. (dir: " + dir + ")" );
}
- static void CalculateTimes( Vector3 origin, Vector3 dir, out Vector3I step,
+ static void CalcVectors( Vector3 origin, Vector3 dir, out Vector3I step,
out Vector3I cellBoundary, out Vector3 tMax, out Vector3 tDelta ) {
Vector3I start = Vector3I.Floor( origin );
// Determine which way we go.
diff --git a/ClassicalSharp/Rendering/MapBordersRenderer.cs b/ClassicalSharp/Rendering/MapBordersRenderer.cs
index 147b1a3fd..9bcfda4db 100644
--- a/ClassicalSharp/Rendering/MapBordersRenderer.cs
+++ b/ClassicalSharp/Rendering/MapBordersRenderer.cs
@@ -57,9 +57,8 @@ namespace ClassicalSharp {
// Do not draw water when we cannot see it.
// Fixes some 'depth bleeding through' issues with 16 bit depth buffers on large maps.
- Vector3 eyePos = game.LocalPlayer.EyePosition;
float yVisible = Math.Min( 0, map.SidesHeight );
- if( game.Map.EdgeBlock != Block.Air && game.Camera.GetCameraPos( eyePos ).Y >= yVisible ) {
+ if( game.Map.EdgeBlock != Block.Air && game.CurrentCameraPos.Y >= yVisible ) {
graphics.DrawIndexedVb_TrisT2fC4b( edgesVertices * 6 / 4, 0 );
}
graphics.AlphaBlending = false;
diff --git a/ClassicalSharp/Rendering/MapRenderer.cs b/ClassicalSharp/Rendering/MapRenderer.cs
index 8880379cc..fc3d6582a 100644
--- a/ClassicalSharp/Rendering/MapRenderer.cs
+++ b/ClassicalSharp/Rendering/MapRenderer.cs
@@ -224,8 +224,7 @@ namespace ClassicalSharp {
int[] distances;
void UpdateSortOrder() {
- Player p = game.LocalPlayer;
- Vector3 cameraPos = game.Camera.GetCameraPos( p.EyePosition );
+ Vector3 cameraPos = game.CurrentCameraPos;
Vector3I newChunkPos = Vector3I.Floor( cameraPos );
newChunkPos.X = (newChunkPos.X & ~0x0F) + 8;
newChunkPos.Y = (newChunkPos.Y & ~0x0F) + 8;
diff --git a/ClassicalSharp/Rendering/PickingRenderer.cs b/ClassicalSharp/Rendering/PickingRenderer.cs
index 0c96291c9..6fcaffda0 100644
--- a/ClassicalSharp/Rendering/PickingRenderer.cs
+++ b/ClassicalSharp/Rendering/PickingRenderer.cs
@@ -24,8 +24,7 @@ namespace ClassicalSharp.Renderers {
public void Render( double delta, PickedPos pickedPos ) {
index = 0;
- Player player = game.LocalPlayer;
- Vector3 camPos = game.Camera.GetCameraPos( player.EyePosition );
+ Vector3 camPos = game.CurrentCameraPos;
float dist = (camPos - pickedPos.Min).LengthSquared;
float size = dist < 12 * 12 ? 1/64f : 1/32f;
diff --git a/ClassicalSharp/Rendering/StandardEnvRenderer.cs b/ClassicalSharp/Rendering/StandardEnvRenderer.cs
index 46c3e8dde..6fcc563f5 100644
--- a/ClassicalSharp/Rendering/StandardEnvRenderer.cs
+++ b/ClassicalSharp/Rendering/StandardEnvRenderer.cs
@@ -23,8 +23,7 @@ namespace ClassicalSharp.Renderers {
public override void Render( double deltaTime ) {
if( skyVb == -1 || cloudsVb == -1 ) return;
- Vector3 eyePos = game.LocalPlayer.EyePosition;
- Vector3 pos = game.Camera.GetCameraPos( eyePos );
+ Vector3 pos = game.CurrentCameraPos;
float normalY = map.Height + 8;
float skyY = Math.Max( pos.Y + 8, normalY );
diff --git a/ClassicalSharp/Rendering/WeatherRenderer.cs b/ClassicalSharp/Rendering/WeatherRenderer.cs
index 053453ef5..5138b553e 100644
--- a/ClassicalSharp/Rendering/WeatherRenderer.cs
+++ b/ClassicalSharp/Rendering/WeatherRenderer.cs
@@ -32,8 +32,7 @@ namespace ClassicalSharp {
graphics.Texturing = true;
graphics.BindTexture( weather == Weather.Rainy ? game.RainTexId : game.SnowTexId );
- Vector3 eyePos = game.LocalPlayer.EyePosition;
- Vector3 camPos = game.Camera.GetCameraPos( eyePos );
+ Vector3 camPos = game.CurrentCameraPos;
Vector3I pos = Vector3I.Floor( camPos );
bool moved = pos != lastPos;
lastPos = pos;
diff --git a/ClassicalSharp/Selections/SelectionManager.cs b/ClassicalSharp/Selections/SelectionManager.cs
index a545ffd13..24d945a00 100644
--- a/ClassicalSharp/Selections/SelectionManager.cs
+++ b/ClassicalSharp/Selections/SelectionManager.cs
@@ -38,12 +38,11 @@ namespace ClassicalSharp.Selections {
SelectionBoxComparer comparer = new SelectionBoxComparer();
public void Render( double delta ) {
- Player player = game.LocalPlayer;
if( selections.Count == 0 ) return;
// TODO: Proper selection box sorting. But this is very difficult because
// we can have boxes within boxes, intersecting boxes, etc. Probably not worth it.
- Vector3 camPos = game.Camera.GetCameraPos( player.EyePosition );
+ Vector3 camPos = game.CurrentCameraPos;
for( int i = 0; i < selections.Count; i++ )
comparer.Intersect( selections[i], camPos );
selections.Sort( comparer );
diff --git a/ClassicalSharp/Utils/Camera.cs b/ClassicalSharp/Utils/Camera.cs
index 871d24d08..60d21efbf 100644
--- a/ClassicalSharp/Utils/Camera.cs
+++ b/ClassicalSharp/Utils/Camera.cs
@@ -143,8 +143,10 @@ namespace ClassicalSharp {
CalcViewBobbing( delta );
Vector3 eyePos = player.EyePosition;
eyePos.Y += bobYOffset;
- Vector3 cameraPos = eyePos - Utils.GetDirVector( player.YawRadians, player.PitchRadians ) * distance;
- //Vector3 cameraPos = Picking.ClipCameraPos( game, eyePos, -Utils.GetDirVector( player.YawRadians, player.PitchRadians ), distance );
+
+ Vector3 dir = -Utils.GetDirVector( player.YawRadians, player.PitchRadians );
+ Picking.ClipCameraPos( game, eyePos, dir, distance, game.CameraClipPos );
+ Vector3 cameraPos = game.CameraClipPos.IntersectPoint;
return Matrix4.LookAt( cameraPos, eyePos, Vector3.UnitY ) * tiltMatrix;
}
@@ -153,7 +155,9 @@ namespace ClassicalSharp {
}
public override Vector3 GetCameraPos( Vector3 eyePos ) {
- return eyePos - Utils.GetDirVector( player.YawRadians, player.PitchRadians ) * distance;
+ Vector3 dir = -Utils.GetDirVector( player.YawRadians, player.PitchRadians );
+ Picking.ClipCameraPos( game, eyePos, dir, distance, game.CameraClipPos );
+ return game.CameraClipPos.IntersectPoint;
}
}
@@ -173,7 +177,10 @@ namespace ClassicalSharp {
CalcViewBobbing( delta );
Vector3 eyePos = player.EyePosition;
eyePos.Y += bobYOffset;
- Vector3 cameraPos = eyePos + Utils.GetDirVector( player.YawRadians, player.PitchRadians ) * distance;
+
+ Vector3 dir = Utils.GetDirVector( player.YawRadians, player.PitchRadians );
+ Picking.ClipCameraPos( game, eyePos, dir, distance, game.CameraClipPos );
+ Vector3 cameraPos = game.CameraClipPos.IntersectPoint;
return Matrix4.LookAt( cameraPos, eyePos, Vector3.UnitY ) * tiltMatrix;
}
@@ -182,7 +189,9 @@ namespace ClassicalSharp {
}
public override Vector3 GetCameraPos( Vector3 eyePos ) {
- return eyePos + Utils.GetDirVector( player.YawRadians, player.PitchRadians ) * distance;
+ Vector3 dir = Utils.GetDirVector( player.YawRadians, player.PitchRadians );
+ Picking.ClipCameraPos( game, eyePos, dir, distance, game.CameraClipPos );
+ return game.CameraClipPos.IntersectPoint;
}
}
diff --git a/ClassicalSharp/Utils/Options.cs b/ClassicalSharp/Utils/Options.cs
index 33338a590..9069fc72d 100644
--- a/ClassicalSharp/Utils/Options.cs
+++ b/ClassicalSharp/Utils/Options.cs
@@ -36,6 +36,7 @@ namespace ClassicalSharp {
public const string PushbackPlacing = "pushbackplacing";
public const string InvertMouse = "invertmouse";
public const string NoclipSlide = "noclipslide";
+ public const string CameraClipping = "cameraclipping";
}
// TODO: implement this
diff --git a/Launcher2/Launcher2.csproj b/Launcher2/Launcher2.csproj
index 020d45cca..5bd5daedb 100644
--- a/Launcher2/Launcher2.csproj
+++ b/Launcher2/Launcher2.csproj
@@ -20,7 +20,7 @@
icon.ico
- x86
+ AnyCPU
4194304
False
Auto