예제 #1
0
        /// <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;
        }
예제 #2
0
        //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;
        }