Implement clipping for third person camera, also fix sound selection method for blocks being wrong (Thanks 123DontMessWitMe)

This commit is contained in:
UnknownShadow200 2015-12-31 11:09:53 +11:00
parent ec4b708a84
commit f8e19afe65
15 changed files with 86 additions and 42 deletions

View File

@ -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(),

View File

@ -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;

View File

@ -55,6 +55,9 @@ namespace ClassicalSharp {
/// <summary> Accumulator for the number of chunk updates performed. Reset every second. </summary>
public int ChunkUpdates;
/// <summary> Whether the third person camera should have their camera position clipped so as to not intersect blocks. </summary>
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;

View File

@ -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 )

View File

@ -12,6 +12,9 @@ namespace ClassicalSharp {
/// <summary> Maximum world coordinates of the block's bounding box. </summary>
public Vector3 Max;
/// <summary> Exact world coordinates at which the ray intersected this block. </summary>
public Vector3 IntersectPoint;
/// <summary> Integer world coordinates of the block. </summary>
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;

View File

@ -10,7 +10,7 @@ namespace ClassicalSharp {
/// <summary> Determines the picked block based on the given origin and direction vector.<br/>
/// 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. </summary>
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.

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

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

View File

@ -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;

View File

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

View File

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

View File

@ -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

View File

@ -20,7 +20,7 @@
<ApplicationIcon>icon.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<PlatformTarget>x86</PlatformTarget>
<PlatformTarget>AnyCPU</PlatformTarget>
<BaseAddress>4194304</BaseAddress>
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>