示例#1
0
        // Return true if the given waypoints are connected by a path. O(n) (or O(1) if connected components were unchanged)
        /// <summary>This function needs to be called with EntityCloseLock already acquired, or not an issue.</summary>
        public static bool Connected(MyWayPoint v1, MyWayPoint v2)
        {
            int c1 = MyWayPointGraph.GetConnectedComponentId(v1);
            int c2 = MyWayPointGraph.GetConnectedComponentId(v2);

            return(c1 == c2 && c1 != -1);
        }
示例#2
0
 // Add a symmetric edge between two vertices. O(1)
 public static void Connect(MyWayPoint v1, MyWayPoint v2)
 {
     if (v1 == v2)
     {
         return;
     }
     using (NeighborsLock.AcquireExclusiveUsing())
     {
         MyWayPointGraph.MakeConnectedComponentsDirty();
         v1.m_neighbors.Add(v2);
         v2.m_neighbors.Add(v1);
     }
 }
示例#3
0
        // Reconstruct the path that leads to the given vertex using cameFrom links.
        private static List <MyWayPoint> ReconstructPath(MyWayPoint v)
        {
            var result = new List <MyWayPoint>();

            result.Add(v);
            while (v.m_cameFrom != v)
            {
                v = v.m_cameFrom;
                result.Add(v);
            }
            result.Reverse();
            return(result);
        }
示例#4
0
 public bool ContainsEdge(MyWayPoint v, MyWayPoint w)
 {
     using (MyEntities.EntityCloseLock.AcquireSharedUsing())
     {
         for (int i = 0; i < WayPoints.Count - 1; i++)
         {
             var subpath = WayPoints[i].GetShortestPathTo(WayPoints[i + 1]);
             for (int j = 0; j < subpath.Count - 1; j++)
             {
                 if ((subpath[j] == v && subpath[j + 1] == w) || (subpath[j] == w && subpath[j + 1] == v))
                 {
                     return(true);
                 }
             }
         }
     }
     return(false);
 }
示例#5
0
        // Add a symmetric edge between two vertices if there's nothing blocking the way.
        // Returns whether the connection exists after the raycast.
        public static bool ConnectIfVisible(MyWayPoint v1, MyWayPoint v2)
        {
            if (v1 == v2)
            {
                return(true);
            }
            if (v1.Neighbors.Contains(v2))
            {
                return(true);
            }
            if (v1.Position == v2.Position)
            {
                Connect(v1, v2);
                return(true);
            }
            var line = new MyLine(v1.Position, v2.Position, true);

            if (MyEntities.GetAnyIntersectionWithLine(ref line, null, null, true, true, true, false) == null)
            {
                Connect(v1, v2);
                return(true);
            }
            return(false);
        }
示例#6
0
        // Add a symmetric edge between two vertices if there are no AABBs blocking the way.
        // Returns whether the connection exists after the raycast.
        public static bool ConnectIfNoAABBBlockers(MyWayPoint v1, MyWayPoint v2, MyEntity ignore1 = null, MyEntity ignore2 = null)
        {
            if (v1 == v2)
            {
                return(true);
            }
            if (v1.Neighbors.Contains(v2))
            {
                return(true);
            }
            if (v1.Position == v2.Position)
            {
                Connect(v1, v2);
                return(true);
            }
            var line = new MyLine(v1.Position, v2.Position, true);

            if (!MyEntities.IsAnyIntersectionWithLineAABBOnly(ref line, ignore1, ignore2))
            {
                Connect(v1, v2);
                return(true);
            }
            return(false);
        }
示例#7
0
        public override bool DebugDraw()
        {            /*
                      * int i = MyWayPointGraph.GetConnectedComponentId(this);
                      * var vertexColor = HsvToRgb((0.36f + i * 0.618034f) % 1.0f, 0.8f, 0.75f);
                      *
                      * DrawWaypointVertex(WorldMatrix.Translation, vertexColor);  // draw only edges for generated waypoints
                      *
                      *
                      * // draw edges
                      * foreach (var neighbor in Neighbors)
                      * {
                      * //DrawWaypointEdge(wp.WorldMatrix.Translation, neighbor.WorldMatrix.Translation, Color.Red, Color.Green);  // selected path: red-green edges
                      *
                      * if (neighbor.WorldMatrix.Translation != WorldMatrix.Translation)
                      * {
                      * Vector3 direction = neighbor.WorldMatrix.Translation - WorldMatrix.Translation;
                      * float lineLength = direction.Length();
                      * direction.Normalize();
                      * MyTransparentGeometry.AddLineBillboard(MyTransparentMaterialEnum.ProjectileTrailLine, Color.Yellow.ToVector4(), WorldMatrix.Translation, direction, lineLength, 0.25f);
                      * }
                      *
                      * }
                      */
            if (((MyHud.ShowDebugWaypoints) || (MyGuiScreenGamePlay.Static.IsEditorActive() && !MyGuiScreenGamePlay.Static.IsIngameEditorActive())) && (MyFakes.ENABLE_GENERATED_WAYPOINTS_IN_EDITOR || MyHud.ShowDebugGeneratedWaypoints || Save))
            {
                // color by connected components
                int i           = MyWayPointGraph.GetConnectedComponentId(this);
                var vertexColor = HsvToRgb((0.36f + i * 0.618034f) % 1.0f, 0.8f, 0.75f);

                if (MyWayPointGraph.SelectedPath != null && MyWayPointGraph.SelectedPath.WayPoints.Contains(this))
                {
                    vertexColor = Color.Orange.ToVector3();  // selected path: orange vertices
                }

                if (IsSecret)
                {
                    vertexColor *= 0.25f;
                }

                // draw vertices
                if (MyEditorGizmo.SelectedEntities.Contains(this))
                {
                    DrawWaypointVertex(WorldMatrix.Translation, vertexColor + (IsSecret ? 1 : 3) * GetHighlightColor());
                    var name = new StringBuilder();
                    if (MyWayPointGraph.SelectedPath != null && MyWayPointGraph.SelectedPath.WayPoints.Contains(this))
                    {
                        name.Append(MyWayPointGraph.SelectedPath.Name).Append(": ").Append(MyWayPointGraph.SelectedPath.WayPoints.IndexOf(this) + 1);
                    }
                    else
                    {
                        name.Append(MyWayPoint.FilterWayPoints(MyEditorGizmo.SelectedEntities).IndexOf(this) + 1);
                    }
                    MyDebugDraw.DrawText(WorldMatrix.Translation, name, Color.White, 1);
                }
                else
                {
                    if (Save)
                    {
                        DrawWaypointVertex(WorldMatrix.Translation, vertexColor);  // for generated waypoints, draw only edges
                    }
                }

                // draw edges
                if (Save || MyHud.ShowDebugGeneratedWaypoints)
                {
                    using (MyWayPoint.NeighborsLock.AcquireSharedUsing())
                    {
                        foreach (var neighbor in Neighbors)
                        {
                            if (MyWayPointGraph.SelectedPath != null && MyWayPointGraph.SelectedPath.ContainsEdge(this, neighbor))
                            {
                                DrawWaypointEdge(WorldMatrix.Translation, neighbor.WorldMatrix.Translation, Color.Yellow, Color.White);  // on selected path: yellow-white
                                continue;
                            }

                            if (neighbor.Save || MyHud.ShowDebugGeneratedWaypoints)
                            {
                                using (MyWayPoint.BlockedEdgesLock.AcquireSharedUsing())
                                {
                                    // blocked for player (by a locked indestructible door: white-gray)
                                    if (BlockedEdgesForPlayer.Contains(Tuple.Create(this, neighbor)) || BlockedEdgesForPlayer.Contains(Tuple.Create(neighbor, this)))
                                    {
                                        DrawWaypointEdge(WorldMatrix.Translation, neighbor.WorldMatrix.Translation, Color.White, Color.Gray);
                                        continue;
                                    }

                                    // blocked for bots by a locked door: black-gray
                                    if (BlockedEdgesForBots.Contains(Tuple.Create(this, neighbor)) || BlockedEdgesForBots.Contains(Tuple.Create(neighbor, this)))
                                    {
                                        DrawWaypointEdge(WorldMatrix.Translation, neighbor.WorldMatrix.Translation, Color.Black, Color.Gray);
                                        continue;
                                    }
                                }

                                // obstructed: violet-white
                                if (MyHud.ShowDebugWaypointsCollisions && Position != neighbor.Position)
                                {
                                    var line = new MyLine(Position, neighbor.Position, true);
                                    if (MyEntities.GetAnyIntersectionWithLine(ref line, null, null, true, true, true, false) != null)
                                    {
                                        DrawWaypointEdge(WorldMatrix.Translation, neighbor.WorldMatrix.Translation, Color.Violet, Color.White);
                                        continue;
                                    }
                                }

                                // normal-normal: red-green
                                // generated-normal: orange-green (normally invisible)
                                // generated-generated: yellow-green (normally invisible)
                                bool generated      = !(Save && neighbor.Save);
                                bool fullyGenerated = !Save && !neighbor.Save;
                                DrawWaypointEdge(WorldMatrix.Translation, neighbor.WorldMatrix.Translation, generated ? fullyGenerated ? Color.Yellow : Color.Orange : Color.Red, Color.Green);
                                continue;
                            }
                        }
                    }
                }
            }
            return(base.DebugDraw());
        }
示例#8
0
 // Get the distance between two vertices, no matter their parents.
 public static float Distance(MyWayPoint v1, MyWayPoint v2)
 {
     return(Vector3.Distance(v1.Position, v2.Position));
 }
示例#9
0
        // Get the shortest path to the goal vertex using the A* algorithm. Return an empty list if the goal is unreachable.
        /// <summary>This function needs to be called with EntityCloseLock already acquired, or not an issue.</summary>
        public List <MyWayPoint> GetShortestPathTo(MyWayPoint goal, HashSet <Tuple <MyWayPoint, MyWayPoint> > blockedEdges = null, bool useGeneratedWaypoints = true, bool useSecretWaypoints = true)
        {
            lock (m_shortestPathLock)
            {
                if (Connected(this, goal) && (useGeneratedWaypoints || (Save && goal.Save)) && (useSecretWaypoints || (!IsSecret && !goal.IsSecret)))
                {
                    // use next search id, handle overflow
                    m_searchId++;
                    if (m_searchId == int.MaxValue)
                    {
                        MyWayPointGraph.ResetAllVisitedSearchIds();
                        m_searchId = 1;
                    }

                    // seen but yet unvisited vertices; add start vertex
                    m_openSet.Clear();
                    m_fScore   = Distance(this, goal); // estimate distance to goal as Euclidean (= consistent)
                    m_gScore   = 0;
                    m_cameFrom = this;
                    m_openSet.Add(this);

                    int num = 0;

                    while (m_openSet.Count != 0)
                    {
                        if (num++ > MyWayPointGraph.WaypointCount() + 10)
                        {
                            int maxSearchId = 0;
                            foreach (var v in MyWayPointGraph.GetCopyOfAllWaypoints())
                            {
                                maxSearchId = Math.Max(maxSearchId, v.m_visitedSearchId);
                            }
                            Debug.Fail(string.Format(
                                           "Infinite path search... contact JanK! \nDebug info: set_count={0} start_end_connected={1} current_search_id={2} max_search_id={3}",
                                           m_openSet.Count,
                                           Connected(this, goal),
                                           m_searchId,
                                           maxSearchId
                                           ));
                            break;
                        }

                        var current = m_openSet.Min;  // get vertex with the smallest f (ties: highest g)
                        m_openSet.Remove(current);
                        if (current == goal)
                        {
                            return(ReconstructPath(goal));       // found the shortest path, return it
                        }
                        current.m_visitedSearchId = m_searchId;  // mark current as visited

                        using (NeighborsLock.AcquireSharedUsing())
                        {
                            // look at all neighbors
                            foreach (var neighbor in current.m_neighbors)
                            {
                                if (!useGeneratedWaypoints && !neighbor.Save)
                                {
                                    continue;                                            // generated
                                }
                                if (!useSecretWaypoints && neighbor.IsSecret)
                                {
                                    continue;                                            // secret
                                }
                                if (neighbor.m_visitedSearchId == m_searchId)
                                {
                                    continue;                                            // already visited
                                }
                                if (blockedEdges != null && blockedEdges.Contains(Tuple.Create(current, neighbor)))
                                {
                                    continue;                                                                                  // blocked
                                }
                                var gScoreThroughCurrent = current.m_gScore + Distance(current, neighbor);

                                if (m_openSet.Contains(neighbor))  // already seen
                                {
                                    if (gScoreThroughCurrent < neighbor.m_gScore)
                                    {
                                        m_openSet.Remove(neighbor);                                            // path through current is better: remove neighbor and put it back with updated score
                                    }
                                    else
                                    {
                                        continue;
                                    }
                                }

                                neighbor.m_fScore   = gScoreThroughCurrent + Distance(neighbor, goal);
                                neighbor.m_gScore   = gScoreThroughCurrent;
                                neighbor.m_cameFrom = current;
                                m_openSet.Add(neighbor);
                            }
                        }
                    }
                }
            }
            return(new List <MyWayPoint>());  // unreachable
        }
示例#10
0
        // Return the complete shortest path between vertices in a list.
        public List <MyWayPoint> CompletePath(HashSet <Tuple <MyWayPoint, MyWayPoint> > blockedEdges, MyWayPoint currentWayPoint, bool useGeneratedWaypoints = true, bool cycle = false, bool cachedIsOk = true)
        {
            if (!cachedIsOk || m_cachedCompletePath == null)
            {
                using (MyEntities.EntityCloseLock.AcquireSharedUsing())
                {
                    m_cachedCompletePath = new List <MyWayPoint>();
                    if (WayPoints == null || WayPoints.Count == 0)
                    {
                        return(m_cachedCompletePath);
                    }

                    int currentIndex = currentWayPoint != null?WayPoints.IndexOf(currentWayPoint) : 0;

                    m_cachedCompletePath.Add(WayPoints[0]);
                    //for (int i = 0; i < WayPoints.Count - 1; i++)
                    //{
                    //    var subpath = WayPoints[i].GetShortestPathTo(WayPoints[i + 1], blockedEdges, useGeneratedWaypoints);
                    //    if (subpath.Count == 0)
                    //        m_cachedCompletePath.Add(WayPoints[i + 1]);  // no path: add straight line to next waypoint
                    //    else
                    //        m_cachedCompletePath.AddRange(subpath.GetRange(1, subpath.Count - 1));  // the first point was the last point of the previous segment
                    //}
                    //if (cycle)
                    //{
                    //    var subpath = WayPoints[WayPoints.Count - 1].GetShortestPathTo(WayPoints[0], blockedEdges, useGeneratedWaypoints);
                    //    if (subpath.Count > 2)
                    //        m_cachedCompletePath.AddRange(subpath.GetRange(1, subpath.Count - 2));  // the first point was the last point of the previous segment, the last point was point 0
                    //}
                    for (int i = 0; i < WayPoints.Count - 1; i++)
                    {
                        var subpath = WayPoints[i].GetShortestPathTo(WayPoints[i + 1], blockedEdges, useGeneratedWaypoints);
                        if (subpath.Count == 0)
                        {
                            if (blockedEdges != null && blockedEdges.Contains(Tuple.Create(WayPoints[i], WayPoints[i + 1])))
                            {
                                // this part of the path is unreachable
                                if (currentIndex > i)
                                {
                                    m_cachedCompletePath.Clear();
                                    m_cachedCompletePath.Add(WayPoints[i + 1]);
                                }
                                else
                                {
                                    break;
                                }
                            }
                            else
                            {
                                m_cachedCompletePath.Add(WayPoints[i + 1]);  // no path: add straight line to next waypoint
                            }
                        }
                        else
                        {
                            m_cachedCompletePath.AddRange(subpath.GetRange(1, subpath.Count - 1));  // the first point was the last point of the previous segment
                        }
                    }

                    if (cycle)
                    {
                        var subpath = WayPoints[WayPoints.Count - 1].GetShortestPathTo(WayPoints[0], blockedEdges, useGeneratedWaypoints);
                        if (subpath.Count > 2)
                        {
                            m_cachedCompletePath.AddRange(subpath.GetRange(1, subpath.Count - 2));  // the first point was the last point of the previous segment, the last point was point 0
                        }
                    }
                }
            }
            return(m_cachedCompletePath);
        }