mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-13 01:26:50 -04:00
Reduce memory pressure on GC even more.
This commit is contained in:
parent
c235286b94
commit
0118370400
@ -6,43 +6,8 @@ namespace ClassicalSharp {
|
|||||||
|
|
||||||
public static class Picking {
|
public static class Picking {
|
||||||
|
|
||||||
public static PickedPos GetPickedBlockPos( Game window, Vector3 origin, Vector3 dir, float reach ) {
|
|
||||||
Map map = window.Map;
|
|
||||||
BlockInfo info = window.BlockInfo;
|
|
||||||
float reachSquared = reach * reach;
|
|
||||||
|
|
||||||
int iterations = 0;
|
|
||||||
foreach( Vector3I cell in GetCellsOnRay( origin, dir ) ) {
|
|
||||||
Vector3 pos = new Vector3( cell.X, cell.Y, cell.Z );
|
|
||||||
if( Utils.DistanceSquared( pos, origin ) >= reachSquared ) return null;
|
|
||||||
iterations++;
|
|
||||||
|
|
||||||
if( iterations > 10000 ) {
|
|
||||||
throw new InvalidOperationException(
|
|
||||||
"did over 10000 iterations in Picking.GetPickedBlockPos(). " +
|
|
||||||
"Something has gone wrong. (dir: " + dir + ")" );
|
|
||||||
}
|
|
||||||
|
|
||||||
int x = cell.X, y = cell.Y, z = cell.Z;
|
|
||||||
byte block;
|
|
||||||
if( map.IsValidPos( x, y, z ) && ( block = map.GetBlock( x, y, z ) ) != 0 ) {
|
|
||||||
if( !window.CanPlace[block] && !window.CanDelete[block] && info.IsLiquid( block ) ) continue;
|
|
||||||
// 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 height = info.BlockHeight( block );
|
|
||||||
Vector3 min = new Vector3( x, y, z );
|
|
||||||
Vector3 max = new Vector3( x + 1, y + height, z + 1 );
|
|
||||||
float t0, t1;
|
|
||||||
if( IntersectionUtils.RayIntersectsBox( origin, dir, min, max, out t0, out t1 ) ) {
|
|
||||||
return new PickedPos( min, max, origin, dir, t0, t1 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// http://www.xnawiki.com/index.php/Voxel_traversal
|
// http://www.xnawiki.com/index.php/Voxel_traversal
|
||||||
public static IEnumerable<Vector3I> GetCellsOnRay( Vector3 origin, Vector3 dir ) {
|
public static PickedPos GetPickedBlockPos( Game window, Vector3 origin, Vector3 dir, float reach ) {
|
||||||
// Implementation is based on:
|
// Implementation is based on:
|
||||||
// "A Fast Voxel Traversal Algorithm for Ray Tracing"
|
// "A Fast Voxel Traversal Algorithm for Ray Tracing"
|
||||||
// John Amanatides, Andrew Woo
|
// John Amanatides, Andrew Woo
|
||||||
@ -97,11 +62,34 @@ namespace ClassicalSharp {
|
|||||||
if( Single.IsNaN( tDelta.X ) ) tDelta.X = Single.PositiveInfinity;
|
if( Single.IsNaN( tDelta.X ) ) tDelta.X = Single.PositiveInfinity;
|
||||||
if( Single.IsNaN( tDelta.Y ) ) tDelta.Y = Single.PositiveInfinity;
|
if( Single.IsNaN( tDelta.Y ) ) tDelta.Y = Single.PositiveInfinity;
|
||||||
if( Single.IsNaN( tDelta.Z ) ) tDelta.Z = Single.PositiveInfinity;
|
if( Single.IsNaN( tDelta.Z ) ) tDelta.Z = Single.PositiveInfinity;
|
||||||
|
|
||||||
|
Map map = window.Map;
|
||||||
|
BlockInfo info = window.BlockInfo;
|
||||||
|
float reachSquared = reach * reach;
|
||||||
|
int iterations = 0;
|
||||||
|
|
||||||
// For each step, determine which distance to the next voxel boundary is lowest (i.e.
|
// For each step, determine which distance to the next voxel boundary is lowest (i.e.
|
||||||
// which voxel boundary is nearest) and walk that way.
|
// which voxel boundary is nearest) and walk that way.
|
||||||
while( true ) {
|
while( iterations < 10000 ) {
|
||||||
yield return new Vector3I( x, y, z );
|
Vector3 pos = new Vector3( x, y, z );
|
||||||
|
if( Utils.DistanceSquared( pos, origin ) >= reachSquared ) return null;
|
||||||
|
iterations++;
|
||||||
|
|
||||||
|
byte block;
|
||||||
|
if( map.IsValidPos( x, y, z ) && ( block = map.GetBlock( x, y, z ) ) != 0 ) {
|
||||||
|
bool cantPickBlock = !window.CanPlace[block] && !window.CanDelete[block] && info.IsLiquid( block );
|
||||||
|
if( !cantPickBlock ) {
|
||||||
|
// 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 height = info.BlockHeight( block );
|
||||||
|
Vector3 min = new Vector3( x, y, z );
|
||||||
|
Vector3 max = new Vector3( x + 1, y + height, z + 1 );
|
||||||
|
float t0, t1;
|
||||||
|
if( IntersectionUtils.RayIntersectsBox( origin, dir, min, max, out t0, out t1 ) ) {
|
||||||
|
return new PickedPos( min, max, origin, dir, t0, t1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( tMax.X < tMax.Y && tMax.X < tMax.Z ) {
|
if( tMax.X < tMax.Y && tMax.X < tMax.Z ) {
|
||||||
// tMax.X is the lowest, an YZ cell boundary plane is nearest.
|
// tMax.X is the lowest, an YZ cell boundary plane is nearest.
|
||||||
@ -117,6 +105,8 @@ namespace ClassicalSharp {
|
|||||||
tMax.Z += tDelta.Z;
|
tMax.Z += tDelta.Z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
throw new InvalidOperationException( "did over 10000 iterations in GetPickedBlockPos(). " +
|
||||||
|
"Something has gone wrong. (dir: " + dir + ")" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user