/// <summary> /// <para>Test line segment between startPosition and targetPosition for obstructing entities.</para> /// <para>Tests for obstructing voxel map, character, or grid.</para> ///// <param name="shortTest">When checking voxels, shortens the line by 1 m, needed to interact with an entity that may be on the surface of the voxel.</param> /// </summary> public static bool Obstructed <Tignore>(LineD line, IEnumerable <Tignore> ignoreList, bool checkVoxel = true, bool checkPlanet = DefaultCheckPlanet) where Tignore : IMyEntity { List <MyLineSegmentOverlapResult <MyEntity> > potentialObstruction = ResourcePool <List <MyLineSegmentOverlapResult <MyEntity> > > .Get(); MyGamePruningStructure.GetAllEntitiesInRay(ref line, potentialObstruction); bool result = Obstructed(line, potentialObstruction.Select(overlap => overlap.Element), ignoreList, checkVoxel, checkPlanet); potentialObstruction.Clear(); ResourcePool <List <MyLineSegmentOverlapResult <MyEntity> > > .Return(potentialObstruction); return(result); }
public static bool IntersectsVoxel(ref CapsuleD capsule, out MyVoxelBase hitVoxel, out Vector3D hitPosition, bool checkPlanet, double capsuleLength = -1d) { Profiler.StartProfileBlock(); if (capsuleLength < 0) { Vector3D.Distance(ref capsule.P0, ref capsule.P1, out capsuleLength); } double halfLength = capsuleLength * 0.5d; Vector3D temp; Vector3D.Add(ref capsule.P0, ref capsule.P1, out temp); Vector3D middle; Vector3D.Multiply(ref temp, 0.5d, out middle); double radius = halfLength + capsule.Radius; BoundingSphereD worldSphere = new BoundingSphereD() { Center = middle, Radius = radius }; List <MyVoxelBase> voxels = ResourcePool <List <MyVoxelBase> > .Get(); MyGamePruningStructure.GetAllVoxelMapsInSphere(ref worldSphere, voxels); foreach (MyVoxelBase voxel in voxels) { if ((voxel is MyVoxelMap || voxel is MyPlanet && checkPlanet) && Intersects(ref capsule, voxel, out hitPosition, capsuleLength)) { hitVoxel = voxel; voxels.Clear(); ResourcePool.Return(voxels); Profiler.EndProfileBlock(); return(true); } } voxels.Clear(); ResourcePool.Return(voxels); hitVoxel = null; hitPosition = Vector3.Invalid; Profiler.EndProfileBlock(); return(false); }
/// <summary> /// Estimates the proximity between a given capsule and any voxel. /// </summary> /// <param name="capsule">The capsule to test for intersection, the points must be at least one metre apart.</param> public static double ProximityToVoxel(ref CapsuleD capsule, out MyVoxelBase hitVoxel, out Vector3D hitPosition, bool checkPlanet, double capsuleLength = -1d) { Profiler.StartProfileBlock(); if (capsuleLength < 0) { Vector3D.Distance(ref capsule.P0, ref capsule.P1, out capsuleLength); } double halfLength = capsuleLength * 0.5d; Vector3D temp; Vector3D.Add(ref capsule.P0, ref capsule.P1, out temp); Vector3D middle; Vector3D.Multiply(ref temp, 0.5d, out middle); double radius = halfLength + capsule.Radius; BoundingSphereD worldSphere = new BoundingSphereD() { Center = middle, Radius = radius }; List <MyVoxelBase> voxels = ResourcePool <List <MyVoxelBase> > .Get(); MyGamePruningStructure.GetAllVoxelMapsInSphere(ref worldSphere, voxels); double closestProx = double.MaxValue; hitPosition = Globals.Invalid; foreach (MyVoxelBase voxel in voxels) { if (voxel is MyVoxelMap || voxel is MyPlanet && checkPlanet) { if (voxel is MyPlanet) { LineSegmentD line; ResourcePool.Get(out line); line.From = capsule.P0; line.To = capsule.P1; double minDistSq = line.DistanceSquared(voxel.GetCentre()); double maxPlanetRadius = ((MyPlanet)voxel).MaximumRadius; ResourcePool.Return(line); if (minDistSq > maxPlanetRadius * maxPlanetRadius) { Logger.DebugLog("Skip planet from: " + line.From + ", to: " + line.To + ", planet centre: " + voxel.GetCentre() + ", min dist sq to centre: " + minDistSq + ", max planet radius: " + maxPlanetRadius); continue; } Logger.DebugLog("Check planet from: " + line.From + ", to: " + line.To + ", planet centre: " + voxel.GetCentre() + ", min dist sq to centre: " + minDistSq + ", max planet radius: " + maxPlanetRadius); } double proximity = Proximity(ref capsule, voxel, ref hitPosition, capsuleLength); if (proximity < closestProx) { Logger.TraceLog("proximity is less than closest. proximity: " + proximity + ", closest: " + closestProx); closestProx = proximity; } if (closestProx < 1d) { Logger.TraceLog("closest under 1: " + closestProx); hitVoxel = voxel; voxels.Clear(); ResourcePool.Return(voxels); Profiler.EndProfileBlock(); return(closestProx); } } } voxels.Clear(); ResourcePool.Return(voxels); hitVoxel = null; Profiler.EndProfileBlock(); return(closestProx); }
public static void Get <T>(out T item) where T : new() { item = ResourcePool <T> .Get(); }