/// <summary> /// Tries to retrieve targeted <see cref="IMyTerminalBlock"/> on a grid within a given distance. /// </summary> private bool TryGetTargetedBlockInternal(double maxDist, out IMyTerminalBlock target) { IMyCubeGrid cubeGrid; IHitInfo rayInfo; MatrixD transform = MyAPIGateway.Session.Camera.WorldMatrix; Vector3D headPos = transform.Translation, forward = transform.Forward; if (!LocalPlayer.IsSpectating) { headPos += (headPos - LocalPlayer.Position).Length() * forward; } LineD line = new LineD(headPos, headPos + forward * maxDist); target = null; if ((LocalPlayer.IsControllingCharacter || LocalPlayer.IsSpectating) && LocalPlayer.TryGetTargetedGrid(line, out cubeGrid, out rayInfo)) { // Retrieve blocks within about half a block of the ray intersection point. var sphere = new BoundingSphereD(rayInfo.Position, (cubeGrid.GridSizeEnum == MyCubeSize.Large) ? 1.3 : .3); double currentDist = double.PositiveInfinity, currentCenterDist = double.PositiveInfinity; tempGrid.SetGrid(cubeGrid, true); targetBuffer.Clear(); tempGrid.GetBlocksInsideSphere(cubeGrid, targetBuffer, ref sphere); foreach (IMySlimBlock slimBlock in targetBuffer) { IMyCubeBlock cubeBlock = slimBlock?.FatBlock; if (cubeBlock != null) { var topBlock = cubeBlock as IMyAttachableTopBlock; if (topBlock != null) { cubeBlock = topBlock.Base; } } var tBlock = cubeBlock as IMyTerminalBlock; if (tBlock != null) { // Find shortest dist between the bb and the intersection. BoundingBoxD box = cubeBlock.WorldAABB; double newDist = Math.Round(box.DistanceSquared(rayInfo.Position), 3), newCenterDist = Math.Round(Vector3D.DistanceSquared(box.Center, rayInfo.Position), 3); // If this is a terminal block, check to see if this block is any closer than the last. // If the distance to the bb is zero, use the center dist, favoring smaller blocks. if ( (currentDist > 0d && newDist < currentDist) || (Math.Abs(currentDist - newDist) < 0.02 && newCenterDist < currentCenterDist) ) { target = tBlock; currentDist = newDist; currentCenterDist = newCenterDist; } } } } tempGrid.Reset(); return(target != null); }
public static double Distance(this BoundingBoxD first, BoundingBoxD second) { return(Math.Sqrt(first.DistanceSquared(second))); }