mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-16 19:15:14 -04:00
Implement clipping for third person camera, also fix sound selection method for blocks being wrong (Thanks 123DontMessWitMe)
This commit is contained in:
parent
ec4b708a84
commit
f8e19afe65
@ -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(),
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 )
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 );
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user