private void TestPlanet() { MyPlanet planet = m_closestPlanet; if (planet == null) { return; } IMyCubeGrid grid = m_block.CubeGrid; Vector3D myPos = grid.GetCentre(); Vector3D planetCentre = planet.GetCentre(); double distSqToPlanet = Vector3D.DistanceSquared(myPos, planetCentre); if (distSqToPlanet > planet.MaximumRadius * planet.MaximumRadius) { Log.DebugLog("higher than planet maximum"); m_planetObstruction = false; return; } Vector3D closestPoint = planet.GetClosestSurfacePointGlobal(ref myPos); if (distSqToPlanet < Vector3D.DistanceSquared(closestPoint, planetCentre)) { Log.DebugLog("below surface"); return; } float longest = grid.GetLongestDim(); if (Vector3D.DistanceSquared(myPos, closestPoint) < longest * longest) { Log.DebugLog("near surface"); m_planetObstruction = true; return; } Log.DebugLog("clear"); m_planetObstruction = false; return; }
public static bool IsNearVoxel(IMyCubeGrid grid, double lengthMulti = 1d) { BoundingSphereD surround = new BoundingSphereD(grid.GetCentre(), grid.GetLongestDim() * lengthMulti); List<MyVoxelBase> voxels = new List<MyVoxelBase>(); MyGamePruningStructure.GetAllVoxelMapsInSphere(ref surround, voxels); if (voxels != null) foreach (IMyVoxelBase vox in voxels) { if (vox is IMyVoxelMap) { if (vox.GetIntersectionWithSphere(ref surround)) return true; } else { MyPlanet planet = vox as MyPlanet; if (planet != null && planet.Intersects(ref surround)) return true; } } return false; }
/// <summary> /// Test if it is safe for the grid to rotate. /// </summary> /// <param name="axis">Normalized axis of rotation in world space.</param> /// <returns>True iff the path is clear.</returns> private bool in_TestRotate(Vector3 axis) { IMyCubeGrid myGrid = m_block.CubeGrid; Vector3 centreOfMass = myGrid.Physics.CenterOfMassWorld; float longestDim = myGrid.GetLongestDim(); // calculate height Matrix toMyLocal = myGrid.WorldMatrixNormalizedInv; Vector3 myLocalCoM = Vector3.Transform(centreOfMass, toMyLocal); Vector3 myLocalAxis = Vector3.Transform(axis, toMyLocal.GetOrientation()); Vector3 myLocalCentre = myGrid.LocalAABB.Center; // CoM may not be on ship (it now considers mass from attached grids) Ray upper = new Ray(myLocalCentre + myLocalAxis * longestDim * 2f, -myLocalAxis); float? upperBound = myGrid.LocalAABB.Intersects(upper); if (!upperBound.HasValue) { Log.AlwaysLog("Math fail, upperBound does not have a value", Logger.severity.FATAL); } Ray lower = new Ray(myLocalCentre - myLocalAxis * longestDim * 2f, myLocalAxis); float?lowerBound = myGrid.LocalAABB.Intersects(lower); if (!lowerBound.HasValue) { Log.AlwaysLog("Math fail, lowerBound does not have a value", Logger.severity.FATAL); } //Log.DebugLog("LocalAABB: " + myGrid.LocalAABB + ", centre: " + myLocalCentre + ", axis: " + myLocalAxis + ", longest dimension: " + longestDim + ", upper ray: " + upper + ", lower ray: " + lower); float height = longestDim * 4f - upperBound.Value - lowerBound.Value; float furthest = 0f; foreach (IMyCubeGrid grid in AttachedGrid.AttachedGrids(myGrid, Attached.AttachedGrid.AttachmentKind.Physics, true)) { CubeGridCache cache = CubeGridCache.GetFor(grid); if (cache == null) { return(false); } foreach (Vector3I cell in cache.OccupiedCells()) { Vector3 rejection = Vector3.Reject(cell * myGrid.GridSize, myLocalAxis); float cellDistSquared = Vector3.DistanceSquared(myLocalCoM, rejection); if (cellDistSquared > furthest) { furthest = cellDistSquared; } } } float length = (float)Math.Sqrt(furthest) + myGrid.GridSize; //Log.DebugLog("height: " + height + ", length: " + length); BoundingSphereD surroundingSphere = new BoundingSphereD(centreOfMass, Math.Max(length, height) * MathHelper.Sqrt2); m_obstructions.Clear(); MyGamePruningStructure.GetAllTopMostEntitiesInSphere(ref surroundingSphere, m_obstructions); LineSegment axisSegment = new LineSegment(); m_closestPlanet = null; foreach (MyEntity entity in m_collector.Invoke(m_obstructions)) { if (entity is IMyVoxelBase) { IMyVoxelMap voxel = entity as IMyVoxelMap; if (voxel != null) { if (voxel.GetIntersectionWithSphere(ref surroundingSphere)) { Log.DebugLog("Too close to " + voxel.getBestName() + ", CoM: " + centreOfMass.ToGpsTag("Centre of Mass") + ", required distance: " + surroundingSphere.Radius); ObstructingEntity = voxel; return(false); } continue; } if (m_closestPlanet == null) { MyPlanet planet = entity as MyPlanet; if (planet == null) { continue; } double distToPlanetSq = Vector3D.DistanceSquared(centreOfMass, planet.PositionComp.GetPosition()); if (distToPlanetSq < planet.MaximumRadius * planet.MaximumRadius) { m_closestPlanet = planet; if (m_planetObstruction) { Log.DebugLog("planet blocking"); ObstructingEntity = m_closestPlanet; return(false); } } } continue; } IMyCubeGrid grid = entity as IMyCubeGrid; if (grid != null) { Matrix toLocal = grid.WorldMatrixNormalizedInv; Vector3 localAxis = Vector3.Transform(axis, toLocal.GetOrientation()); Vector3 localCentre = Vector3.Transform(centreOfMass, toLocal); axisSegment.From = localCentre - localAxis * height; axisSegment.To = localCentre + localAxis * height; CubeGridCache cache = CubeGridCache.GetFor(grid); if (cache == null) { return(false); } foreach (Vector3I cell in cache.OccupiedCells()) { if (axisSegment.PointInCylinder(length, cell * grid.GridSize)) { Log.DebugLog("axis segment: " + axisSegment.From + " to " + axisSegment.To + ", radius: " + length + ", hit " + grid.nameWithId() + " at " + cell); ObstructingEntity = grid; return(false); } } continue; } Log.DebugLog("No tests for object: " + entity.getBestName(), Logger.severity.INFO); ObstructingEntity = entity; return(false); } MyAPIGateway.Utilities.TryInvokeOnGameThread(TestPlanet); ObstructingEntity = null; return(true); }
public static bool IsNearVoxel(IMyCubeGrid grid, double lengthMulti = 0.5d) { BoundingSphereD surround = new BoundingSphereD(grid.GetCentre(), grid.GetLongestDim() * lengthMulti); List<MyVoxelBase> voxels = new List<MyVoxelBase>(); MyGamePruningStructure.GetAllVoxelMapsInSphere(ref surround, voxels); if (voxels != null) foreach (IMyVoxelMap vox in voxels) if (vox.GetIntersectionWithSphere(ref surround)) return true; return false; }
/// <summary> /// Test if it is safe for the grid to rotate. /// </summary> /// <param name="axis">Normalized axis of rotation in world space.</param> /// <param name="ignoreAsteroids"></param> /// <returns>True iff the path is clear.</returns> public bool TestRotate(Vector3 axis, bool ignoreAsteroids, out IMyEntity obstruction) { Vector3 centreOfMass = m_grid.Physics.CenterOfMassWorld; float longestDim = m_grid.GetLongestDim(); // calculate height Matrix toMyLocal = m_grid.WorldMatrixNormalizedInv; Vector3 myLocalCoM = Vector3.Transform(centreOfMass, toMyLocal); Vector3 myLocalAxis = Vector3.Transform(axis, toMyLocal.GetOrientation()); Vector3 myLocalCentre = m_grid.LocalAABB.Center; // CoM may not be on ship (it now considers mass from attached grids) Ray upper = new Ray(myLocalCentre + myLocalAxis * longestDim * 2f, -myLocalAxis); float? upperBound = m_grid.LocalAABB.Intersects(upper); if (!upperBound.HasValue) { m_logger.alwaysLog("Math fail, upperBound does not have a value", Logger.severity.FATAL); } Ray lower = new Ray(myLocalCentre - myLocalAxis * longestDim * 2f, myLocalAxis); float?lowerBound = m_grid.LocalAABB.Intersects(lower); if (!lowerBound.HasValue) { m_logger.alwaysLog("Math fail, lowerBound does not have a value", Logger.severity.FATAL); } m_logger.debugLog("LocalAABB: " + m_grid.LocalAABB + ", centre: " + myLocalCentre + ", axis: " + myLocalAxis + ", longest dimension: " + longestDim + ", upper ray: " + upper + ", lower ray: " + lower); float height = longestDim * 4f - upperBound.Value - lowerBound.Value; float furthest = 0f; m_cells.ForEach(cell => { Vector3 rejection = Vector3.Reject(cell * m_grid.GridSize, myLocalAxis); float cellDistSquared = Vector3.DistanceSquared(myLocalCoM, rejection); if (cellDistSquared > furthest) { furthest = cellDistSquared; } }); float length = (float)Math.Sqrt(furthest) + m_grid.GridSize * 0.5f; m_logger.debugLog("height: " + height + ", length: " + length); BoundingSphereD surroundingSphere = new BoundingSphereD(centreOfMass, Math.Max(length, height)); m_obstructions.Clear(); MyGamePruningStructure.GetAllTopMostEntitiesInSphere(ref surroundingSphere, m_obstructions); LineSegment axisSegment = new LineSegment(); ClosestPlanet = MyPlanetExtensions.GetClosestPlanet(centreOfMass); MyAPIGateway.Utilities.TryInvokeOnGameThread(TestPlanet); foreach (MyEntity entity in m_obstructions) { if (PathChecker.collect_Entity(m_grid, entity)) { if (entity is IMyVoxelBase) { if (ignoreAsteroids) { continue; } IMyVoxelMap voxel = entity as IMyVoxelMap; if (voxel != null) { if (voxel.GetIntersectionWithSphere(ref surroundingSphere)) { m_logger.debugLog("Too close to " + voxel.getBestName() + ", CoM: " + centreOfMass.ToGpsTag("Centre of Mass") + ", required distance: " + surroundingSphere.Radius); obstruction = voxel; return(false); } continue; } if (PlanetState != Pathfinder.PathState.No_Obstruction) { m_logger.debugLog("planet blocking"); obstruction = ClosestPlanet; return(false); } continue; } IMyCubeGrid grid = entity as IMyCubeGrid; if (grid != null) { Matrix toLocal = grid.WorldMatrixNormalizedInv; Vector3 localAxis = Vector3.Transform(axis, toLocal.GetOrientation()); Vector3 localCentre = Vector3.Transform(centreOfMass, toLocal); axisSegment.From = localCentre - localAxis * height; axisSegment.To = localCentre + localAxis * height; bool found = false; GridCellCache.GetCellCache(grid).ForEach(cell => { if (axisSegment.PointInCylinder(length, cell * grid.GridSize)) { found = true; return(true); } return(false); }); if (found) { obstruction = grid; return(false); } continue; } m_logger.debugLog("No tests for object: " + entity.getBestName(), Logger.severity.INFO); obstruction = entity; return(false); } } obstruction = null; return(true); }