/// <summary> /// Tests for path intersection with voxel. /// </summary> /// <returns>True iff path is clear; voxel does not intersect path.</returns> private bool TestVoxel(MyVoxelBase voxel, Capsule path, out Vector3? pointOfObstruction) { if (m_ignoreAsteroid) { m_logger.debugLog("Ignoring asteroid: " + voxel.getBestName()); pointOfObstruction = null; return true; } Vector3[] intersection = new Vector3[2]; if (!path.IntersectsAABB(voxel, out intersection[0])) { m_logger.debugLog("path does not intersect AABB. " + voxel.getBestName(), Logger.severity.TRACE); pointOfObstruction = null; return true; } if (!path.get_Reverse().IntersectsAABB(voxel, out intersection[1])) { m_logger.debugLog("Reversed path does not intersect AABB, perhaps it moved? " + voxel.getBestName(), Logger.severity.WARNING); pointOfObstruction = null; return true; } Capsule testSection = new Capsule(intersection[0], intersection[1], path.Radius); IMyVoxelMap asteroid = voxel as IMyVoxelMap; if (asteroid != null) { if (testSection.Intersects(asteroid, out pointOfObstruction)) return false; } // planet test is done by PlanetChecker m_logger.debugLog("Does not intersect path: " + voxel.getBestName(), Logger.severity.TRACE); pointOfObstruction = null; return true; }
//public bool GravityTest(LineSegmentD line, Vector3D finalDestination, out MyEntity blockingPath, out Vector3? pointOfObstruction) //{ // if (Vector3.DistanceSquared(line.From, line.To) > 10000f) // { // BoundingBoxD box = line.BoundingBox; // m_voxels.Clear(); // MyGamePruningStructure.GetAllVoxelMapsInBox(ref box, m_voxels); // foreach (MyEntity entity in m_voxels) // { // MyPlanet planet = entity as MyPlanet; // if (planet == null) // continue; // Vector3D planetCentre = planet.GetCentre(); // Vector3D closestPoint = line.ClosestPoint(planetCentre); // if (!planet.IsPositionInGravityWell(closestPoint)) // continue; // m_logger.debugLog("path: " + line.From + " to " + line.To + ", final: " + finalDestination + ", closest point: " + closestPoint + ", planet @ " + planetCentre + " : " + planet.getBestName(), "GravityTest()"); // if (closestPoint == line.From) // { // m_logger.debugLog("closest point is start", "GravityTest()"); // continue; // } // if (closestPoint == line.To) // { // if (line.To == finalDestination ) // { // m_logger.debugLog("closest point is final", "GravityTest()"); // continue; // } // if (Vector3D.DistanceSquared(planetCentre, closestPoint) < Vector3D.DistanceSquared(planetCentre, finalDestination)) // { // m_logger.debugLog("closest point is end, which is closer to planet than final dest is", "GravityTest()"); // blockingPath = entity; // pointOfObstruction = closestPoint; // return false; // } // m_logger.debugLog("closest point is end", "GravityTest()"); // continue; // } // //float startGravity = planet.GetWorldGravityGrid( line.From).LengthSquared(); // //float closestGravity = planet.GetWorldGravityGrid(closestPoint).LengthSquared(); // //double toDistSq = Vector3D.DistanceSquared(planetCentre, line.To); // //if (closestPoint == line.To && (line.To == finalDestination || )) // //{ // // m_logger.debugLog("path: " + line.From + " to " + line.To + ", closest point: " + closestPoint + ", planet @ " + planetCentre + " : " + planet.getBestName(), "GravityTest()"); // // m_logger.debugLog("closest point is end", "GravityTest()"); // // continue; // //} // //m_logger.debugLog("path: " + line.From + " to " + line.To + ", closest point: " + closestPoint + ", planet @ " + planetCentre + " : " + planet.getBestName(), "GravityTest()", Logger.severity.DEBUG); // double closestDistSq = Vector3D.DistanceSquared(planetCentre, closestPoint) + 1f; // if (closestDistSq < Vector3D.DistanceSquared(planetCentre, line.From) || closestDistSq < Vector3D.DistanceSquared(planetCentre, line.To)) // { // m_logger.debugLog("path moves ship closer to planet. closestDistSq: " + closestDistSq + ", from dist sq: " + Vector3D.DistanceSquared(planetCentre, line.From) + ", to dist sq: " + Vector3D.DistanceSquared(planetCentre, line.To), "GravityTest()", Logger.severity.INFO); // blockingPath = entity; // pointOfObstruction = closestPoint; // return false; // } // } // } // blockingPath = null; // pointOfObstruction = null; // return true; //} /// <summary> /// How far long the line would the ship be able to travel? Uses a capsule derived from previously calculated path. /// </summary> /// <param name="canTravel">Line along which navigation block would travel</param> /// <remarks> /// Capsule only test because the ship will not be oriented correctly /// </remarks> /// <returns>distance from the destination that can be reached</returns> public float distanceCanTravel(LineSegment canTravel) { BoundingBoxD atFrom = m_grid.WorldAABB.Translate(canTravel.From - m_grid.GetPosition()); BoundingBoxD atTo = m_grid.WorldAABB.Translate(canTravel.To - m_grid.GetPosition()); ICollection<MyEntity> offenders = EntitiesInLargeAABB(atFrom, atTo); if (offenders.Count == 0) { m_logger.debugLog("AABB is empty"); return 0; } m_logger.debugLog("collected entities to test: " + offenders.Count); IOrderedEnumerable<MyEntity> ordered = offenders.OrderBy(entity => Vector3D.Distance(canTravel.From, entity.GetCentre())); Capsule path = new Capsule(canTravel.From, canTravel.To, m_path.Radius); Vector3? pointOfObstruction = null; foreach (MyEntity entity in ordered) if (path.IntersectsAABB(entity)) { MyVoxelBase voxel = entity as MyVoxelBase; if (voxel != null) if (!TestVoxel(voxel, path, out pointOfObstruction)) { m_logger.debugLog("obstruction at " + pointOfObstruction + " distance from dest is " + Vector3.Distance(canTravel.To, (Vector3)pointOfObstruction)); return Vector3.Distance(canTravel.To, (Vector3)pointOfObstruction); } IMyCubeGrid grid = entity as IMyCubeGrid; if (grid != null) { float minDistSq = (m_grid.GridSize + grid.GridSize) * (m_grid.GridSize + grid.GridSize); GridCellCache cache = GridCellCache.GetCellCache(grid); cache.ForEach(cell => { Vector3 cellPos = grid.GridIntegerToWorld(cell); if (canTravel.PointInCylinder(minDistSq, ref cellPos)) { pointOfObstruction = cellPos; return true; } return false; }); if (pointOfObstruction.HasValue) return Vector3.Distance(canTravel.To, (Vector3)pointOfObstruction); } m_logger.debugLog("not a grid, testing bounds"); if (!m_path.IntersectsVolume(entity)) continue; m_logger.debugLog("no more tests for non-grids are implemented", Logger.severity.DEBUG); pointOfObstruction = m_path.get_Line().ClosestPoint(entity.GetCentre()); return Vector3.Distance(canTravel.To, (Vector3)pointOfObstruction); } // no obstruction m_logger.debugLog("no obstruction"); return 0f; }