Exemple #1
0
        public bool FindPath(Vec3 from, Vec3 to, MovementFlag flags, ref List <Vec3> path, float merge_distance = -1, bool as_close_as_possible = false, bool include_from = false, float random_coeff = 0, bool bounce = false, float shift_nodes_distance = 0, bool smoothen = true)
        {
            using (m_Navmesh.AcquireReadDataLock())
            {
                List <path_pos> tmp_path = new List <path_pos>();

                if (from.IsZero() || to.IsZero())
                {
                    return(false);
                }

                Cell start = null;
                Cell end   = null;

                bool start_on_nav_mesh = m_Navmesh.GetCellContaining(from, out start, flags, false, as_close_as_possible, -1, false, 2, null);
                bool end_on_nav_mesh   = m_Navmesh.GetCellContaining(to, out end, flags, false, as_close_as_possible, -1, false, 2, null);

                if (bounce)
                {
                    Vec3 bounce_dir = start.AABB.GetBounceDir2D(from);
                    Vec3 new_from   = from + bounce_dir * 10;
                    m_Navmesh.GetCellContaining(new_from, out start, flags, false, as_close_as_possible, -1, false, 2, null);

                    if (!Algorihms.FindPath <Cell>(start, ref end, new_from, to, flags, ref tmp_path, random_coeff, true))
                    {
                        return(false);
                    }

                    tmp_path.Insert(0, new path_pos(start.AABB.Align(from), start));
                }
                else
                {
                    if (!Algorihms.FindPath <Cell>(start, ref end, from, to, flags, ref tmp_path, random_coeff, true))
                    {
                        return(false);
                    }
                }

                if (smoothen && random_coeff == 0)
                {
                    SmoothenPath(ref tmp_path, flags, bounce ? 1 : 0);
                }

                if (DistToKeepFromEdge > 0 && random_coeff == 0)
                {
                    KeepAwayFromEdges(ref tmp_path, flags);
                }

                path = tmp_path.Select(x => x.pos).ToList();

                PostProcessPath(ref path, merge_distance, shift_nodes_distance);

                if (!include_from && start_on_nav_mesh)
                {
                    path.RemoveAt(0);
                }

                return(true);
            }
        }
Exemple #2
0
        public static List <Cell> GetCellsWithin(IEnumerable <Cell> cells, Vec3 p, float radius, MovementFlag flags, bool allow_disabled = false, bool test_2d = true, float z_tolerance = 0)
        {
            var result_cells = new List <Cell>();

            if (p.IsZero())
            {
                return(result_cells);
            }

            float radiusSqr = radius * radius;

            foreach (Cell cell in cells)
            {
                if ((!allow_disabled && cell.Disabled) || (cell.Flags & flags) != flags)
                {
                    continue;
                }

                float distSqr = test_2d ? cell.Distance2DSqr(p) : cell.DistanceSqr(p);

                if (distSqr <= radiusSqr)
                {
                    result_cells.Add(cell);
                }
            }

            return(result_cells);
        }
Exemple #3
0
        internal bool GetCellAt(Vec3 p, out ExploreCell result_cell)
        {
            using (new ReadLock(DataLock))
            {
                result_cell = null;

                if (p.IsZero())
                {
                    return(false);
                }

                foreach (var explore_cell in m_ExploreCells)
                {
                    if (explore_cell.Contains2D(p))
                    {
                        var cells = explore_cell.GetCellsAt(p, test_2d: true, z_tolerance: 0);

                        if (cells.Count() > 0)
                        {
                            result_cell = explore_cell;
                            return(true);
                        }
                    }
                }

                return(false);
            }
        }
Exemple #4
0
        public NavMeshViewer(string[] args, Navmesh navmesh = null, NavigationEngine navigator = null, ExplorationEngine explorer = null)
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            BackColor = Color.LightGray;

            m_Params = new Params(args);

            m_Navmesh   = navmesh;
            m_Navigator = navigator;
            m_Explorer  = explorer;

            CreateNavigation();
            LoadDebugConfig();

            if (m_Params.HasParam("load"))
            {
                m_Params.GetParam("load", out string file);
                LoadData(file);
            }

            if (m_Params.HasParam("start"))
            {
                m_Params.GetParam("start", out string str);
                m_Navigator.CurrentPos = new Vec3(str);
            }

            if (m_Params.HasParam("end"))
            {
                m_Params.GetParam("end", out string str);
                m_Navigator.Destination = new destination(new Vec3(str));
            }

            if (m_Params.HasParam("load_waypoints"))
            {
                m_Params.GetParam("load_waypoints", out string file);
                LoadWaypoints(file);
            }

            if (m_Params.HasParam("deserialize"))
            {
                m_Params.GetParam("deserialize", out string file);
                m_Navmesh.Deserialize(file);
                m_Navigator.Deserialize(file);
                m_Explorer.Deserialize(file);

                Vec3 initial_pos = m_Navigator.CurrentPos;
                if (initial_pos.IsZero())
                {
                    initial_pos = m_Navmesh.GetCenter();
                }
                m_RenderCenter.X = initial_pos.X;
                m_RenderCenter.Y = initial_pos.Y;
            }

            InitializeComponents();
        }
Exemple #5
0
        public static float GetPathLength(List <Vec3> path, Vec3 pos)
        {
            float length = 0;

            for (int i = 0; i < path.Count - 1; ++i)
            {
                length += path[i].Distance2D(path[i + 1]);
            }

            return(length + ((path.Count > 0 && !pos.IsZero()) ? path[0].Distance2D(pos) : 0));
        }
Exemple #6
0
        private static void BuildPath <T>(T start, T end, Vec3 from, Vec3 to, NodeInfo info, ref List <path_pos> path) where T : Cell
        {
            // build result path
            if (path != null)
            {
                List <Cell> cells_list = new List <Cell>();

                while (info != null)
                {
                    cells_list.Add(info.cell);
                    info = info.parent;
                }

                cells_list.Reverse();

                for (int i = 0; i < cells_list.Count; ++i)
                {
                    Cell cell = cells_list[i];

                    if (i == 0)
                    {
                        if (from.IsZero())
                        {
                            path.Add(new path_pos(cell.Center, cell));
                        }
                        else
                        {
                            path.Add(new path_pos(cell.AABB.Align(from), cell));
                        }
                    }
                    else
                    {
                        path.Add(new path_pos(cell.AABB.Align(path[path.Count - 1].pos), cell));
                    }

                    if (i == cells_list.Count - 1)
                    {
                        if (to.IsZero())
                        {
                            path.Add(new path_pos(cell.Center, cell));
                        }
                        else
                        {
                            path.Add(new path_pos(cell.AABB.Align(to), cell));
                        }
                    }
                }

                for (int k = path.Count - 2; k > 0; --k)
                {
                    path[k] = new path_pos(path[k - 1].cell.AABB.Align(path[k + 1].pos), path[k].cell);
                }
            }
        }
Exemple #7
0
        private void LoadData(string filename, bool clear = true)
        {
            m_LastDataFile = filename;

            if (m_Navmesh.Load(filename, clear, true))
            {
                Vec3 initial_pos = m_Navigator.CurrentPos;
                if (initial_pos.IsZero())
                {
                    initial_pos = m_Navmesh.GetCenter();
                }

                m_RenderCenter.X = initial_pos.X;
                m_RenderCenter.Y = initial_pos.Y;
            }
        }
Exemple #8
0
        public bool FindRoughPath(Vec3 from, Vec3 to, ref List <Vec3> path)
        {
            if (from.IsZero() || to.IsZero())
            {
                return(false);
            }

            List <path_pos> tmp_path = new List <path_pos>();

            bool start_on_nav_mesh = GetCellAt(from, out ExploreCell start);
            bool end_on_nav_mesh   = GetCellAt(to, out ExploreCell end);

            using (new ReadLock(DataLock))
                Algorihms.FindPath(start, from, new Algorihms.DestinationPathFindStrategy <ExploreCell>(to, end), MovementFlag.None, ref tmp_path, use_cell_centers: true);

            path = tmp_path.Select(x => x.pos).ToList();
            return(true);
        }
Exemple #9
0
        private void UpdateExploration()
        {
            Vec3 current_pos = m_Navigator.CurrentPos;

            if (current_pos.IsZero())
            {
                return;
            }

            if (!IsDataAvailable)
            {
                m_Navmesh.Log("[Nav] Exploration data unavailable!");
                return;
            }

            if (IsExplored())
            {
                m_Navmesh.Log("[Nav] Exploration finished!");
                m_Navigator.ClearDestination(DestType.Explore);
                return;
            }

            using (new ReadLock(DataLock, true))
            {
                if (m_Navigator.GetDestinationType() < DestType.Explore)
                {
                    m_DestCell = GetDestinationCell();
                    m_Navigator.SetDestination(GetDestinationCellPosition(), DestType.Explore, ExploreDestPrecision);
                    //m_Navmesh.Log("[Nav] Explore dest changed.");
                }

                {
                    // mark cells as explored when passing by close enough
                    ExploreCell current_explore_cell = m_ExploreCells.FirstOrDefault(x => !x.Explored && x.Position.Distance2D(current_pos) < ExploreDestPrecision);

                    if (current_explore_cell != null)
                    {
                        OnCellExplored(current_explore_cell);
                    }
                }

                OnUpdateExploration();
            }
        }
Exemple #10
0
        internal List <Cell> GetCellsWithin(Vec3 p, float radius, MovementFlag flags)
        {
            var result_cells = new List <Cell>();

            if (p.IsZero())
            {
                return(result_cells);
            }

            foreach (var cellsG in CellsGrid)
            {
                if (cellsG.Key.Distance2D(p) > radius)
                {
                    continue;
                }

                result_cells.AddRange(Algorihms.GetCellsWithin(cellsG.Value, p, radius, flags, allow_disabled: true));
            }

            return(result_cells);
        }
Exemple #11
0
        private void ReorganizeWaypoints()
        {
            Vec3 pos = CurrentPos;

            if (pos.IsZero())
            {
                return;
            }

            using (new ReadLock(InputLock, true))
            {
                if (m_Waypoints.Count == 0)
                {
                    return;
                }

                int   nearest_waypoint_index = -1;
                float nearest_waypoint_dist  = float.MaxValue;

                for (int i = 0; i < m_Waypoints.Count; ++i)
                {
                    float dist = m_Waypoints[i].Distance(pos);

                    if (dist < nearest_waypoint_dist)
                    {
                        nearest_waypoint_index = i;
                        nearest_waypoint_dist  = dist;
                    }
                }

                using (new WriteLock(InputLock))
                {
                    for (int i = 0; i < nearest_waypoint_index; ++i)
                    {
                        m_Waypoints.Add(new Vec3(m_Waypoints[0]));
                        m_Waypoints.RemoveAt(0);
                    }
                }
            }
        }
Exemple #12
0
        public static Cell GetCellAt(IEnumerable <Cell> cells, Vec3 p, MovementFlag flags, bool allow_disabled = false, bool test_2d = true, float z_tolerance = 0)
        {
            if (p.IsZero())
            {
                return(null);
            }

            foreach (Cell cell in cells)
            {
                if ((!allow_disabled && cell.Disabled) || (cell.Flags & flags) != flags)
                {
                    continue;
                }

                if (test_2d ? cell.Contains2D(p) : cell.Contains(p, z_tolerance))
                {
                    return(cell);
                }
            }

            return(null);
        }
Exemple #13
0
        private static void BuildPath <T>(T start, T end, Vec3 from, Vec3 to, NodeInfo info, ref List <path_pos> path, bool use_cell_centers = false) where T : Cell
        {
            // build result path
            if (path == null)
            {
                return;
            }

            List <Cell> cells_list = new List <Cell>();

            if (info != null)
            {
                path.Add(new path_pos(to.IsZero() ? info.cell.Center : to, info.cell));
            }

            while (info != null)
            {
                path.Add(new path_pos((use_cell_centers && info.parent != null) ? info.cell.Center : info.leading_point, info.cell));
                info = info.parent;
            }

            path.Reverse();
        }
Exemple #14
0
        protected virtual void OnKey(KeyEventArgs e)
        {
            if (e.Control)
            {
                if (e.KeyCode == Keys.D0)
                {
                    m_RenderAxis = !m_RenderAxis;
                    e.Handled    = true;
                }
                if (e.KeyCode == Keys.D1)
                {
                    m_RenderPath = !m_RenderPath;
                    e.Handled    = true;
                }
                else if (e.KeyCode == Keys.D2)
                {
                    m_Navmesh.RegionsEnabled = !m_Navmesh.RegionsEnabled;
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.D3)
                {
                    m_RenderAvoidancePath = !m_RenderAvoidancePath;
                    e.Handled             = true;
                }
                else if (e.KeyCode == Keys.D4)
                {
                    m_RenderPositionsHistory = !m_RenderPositionsHistory;
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.D5)
                {
                    m_RenderRoughPath = !m_RenderRoughPath;
                    e.Handled         = true;
                }
            }
            else
            {
                if (e.KeyCode == Keys.S)
                {
                    Vec3 result = default(Vec3);
                    if (!m_Navmesh.RayTrace(new Vec3(m_RenderCenter.X, m_RenderCenter.Y, 1000),
                                            new Vec3(m_RenderCenter.X, m_RenderCenter.Y, -1000),
                                            MovementFlag.Walk,
                                            ref result))
                    {
                        result = new Vec3(m_RenderCenter.X, m_RenderCenter.Y, 0);
                    }

                    m_Navigator.CurrentPos = result;
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.E)
                {
                    Vec3 result = default(Vec3);
                    if (!m_Navmesh.RayTrace(new Vec3(m_RenderCenter.X, m_RenderCenter.Y, 1000),
                                            new Vec3(m_RenderCenter.X, m_RenderCenter.Y, -1000),
                                            MovementFlag.Walk,
                                            ref result))
                    {
                        result = new Vec3(m_RenderCenter.X, m_RenderCenter.Y, 0);
                    }

                    m_Navigator.SetCustomDestination(result);
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.R)
                {
                    Vec3 result = default(Vec3);
                    if (!m_Navmesh.RayTrace(new Vec3(m_RenderCenter.X, m_RenderCenter.Y, 1000),
                                            new Vec3(m_RenderCenter.X, m_RenderCenter.Y, -1000),
                                            MovementFlag.Walk,
                                            ref result))
                    {
                        result = new Vec3(m_RenderCenter.X, m_RenderCenter.Y, 0);
                    }

                    m_Navigator.Destination = new destination(result, DestType.Custom, m_Navigator.DefaultPrecision, m_Navigator.DefaultPrecision * 2);
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.L)
                {
                    m_RenderLegend = !m_RenderLegend;
                    e.Handled      = true;
                }
                else if (e.KeyCode == Keys.D1)
                {
                    m_RenderGrids = !m_RenderGrids;
                    e.Handled     = true;
                }
                else if (e.KeyCode == Keys.D2)
                {
                    m_RenderCells = !m_RenderCells;
                    e.Handled     = true;
                }
                else if (e.KeyCode == Keys.D3)
                {
                    m_RenderExploreCells = !m_RenderExploreCells;
                    e.Handled            = true;
                }
                else if (e.KeyCode == Keys.D4)
                {
                    m_RenderConnections = !m_RenderConnections;
                    e.Handled           = true;
                }
                else if (e.KeyCode == Keys.D5)
                {
                    m_RenderIds = !m_RenderIds;
                    e.Handled   = true;
                }
                else if (e.KeyCode == Keys.D6)
                {
                    m_RenderConnected = !m_RenderConnected;
                    e.Handled         = true;
                }
                else if (e.KeyCode == Keys.D7)
                {
                    m_RenderRegionsMode = (RegionsRenderMode)(((int)m_RenderRegionsMode + 1) % (int)RegionsRenderMode.Count);
                    e.Handled           = true;
                }
                else if (e.KeyCode == Keys.D8)
                {
                    m_RenderOriginalPath = !m_RenderOriginalPath;
                    e.Handled            = true;
                }
                else if (e.KeyCode == Keys.D9)
                {
                    m_RenderRayCast = !m_RenderRayCast;
                    e.Handled       = true;
                }
                else if (e.KeyCode == Keys.D0)
                {
                    m_RenderBacktrackPath = !m_RenderBacktrackPath;
                    e.Handled             = true;
                }
                else if (e.KeyCode == Keys.F1)
                {
                    LoadWaypoints(m_LastWaypointsFile);
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.F2)
                {
                    LoadData(m_LastDataFile ?? "nav_dump.txt");
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.F3)
                {
                    m_Navmesh.Dump("nav_dump.txt");
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.F4)
                {
                    m_Navmesh.Clear();
                    m_Navigator.Clear();
                    m_Explorer.Clear();
                    LoadDebugConfig();
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.F5)
                {
                    m_Navmesh.Serialize("nav_save");
                    m_Navigator.Serialize("nav_save");
                    m_Explorer.Serialize("nav_save");
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.F6)
                {
                    m_Navmesh.Deserialize("nav_save");
                    m_Navigator.Deserialize("nav_save");
                    m_Explorer.Deserialize("nav_save");

                    Vec3 initial_pos = m_Navigator.CurrentPos;
                    if (initial_pos.IsZero())
                    {
                        initial_pos = m_Navmesh.GetCenter();
                    }
                    m_RenderCenter.X = initial_pos.X;
                    m_RenderCenter.Y = initial_pos.Y;
                    e.Handled        = true;
                }
                else if (e.KeyCode == Keys.F7)
                {
                    LoadDebugConfig();
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.F10)
                {
                    //Thread t = new Thread(dbg_ContiniousSerialize);
                    //t.Start();

                    Thread t = new Thread(() => dbg_MovingRegions(200));
                    t.Start();

                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.F11)
                {
                    m_Navmesh.dbg_GenerateRandomAvoidAreas(100, -1, 300, 2);

                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.B)
                {
                    Vec3 result = default(Vec3);

                    if (m_Navigator.CurrentPos.IsZero())
                    {
                        m_Navmesh.RayTrace(new Vec3(m_RenderCenter.X, m_RenderCenter.Y, 1000),
                                           new Vec3(m_RenderCenter.X, m_RenderCenter.Y, -1000),
                                           MovementFlag.Fly,
                                           ref result);
                    }
                    else
                    {
                        result = m_Navigator.CurrentPos;
                    }

                    m_Bot     = new TestBot(m_Navmesh, m_Navigator, m_Explorer, result, m_BotSpeed);
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.C)
                {
                    m_CenterOnBot = !m_CenterOnBot;
                    e.Handled     = true;
                }
                else if (e.KeyCode == Keys.D)
                {
                    if (m_Bot != null)
                    {
                        m_Bot.Destination = new Vec3(m_RenderCenter.X, m_RenderCenter.Y, 0);
                    }
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.H)
                {
                    if (m_Explorer != null)
                    {
                        m_Explorer.HintPos = new Vec3(m_RenderCenter.X, m_RenderCenter.Y, 0);
                    }
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.X)
                {
                    m_Navigator.CurrentPos = new Vec3(m_RenderCenter.X, m_RenderCenter.Y, 0);
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.Space)
                {
                    if (m_Bot != null)
                    {
                        m_Bot.Paused = !m_Bot.Paused;
                    }
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.V)
                {
                    if (m_Bot != null)
                    {
                        m_Bot.BackTrace = !m_Bot.BackTrace;
                    }
                    e.Handled = true;
                }
                else if (e.KeyCode == Keys.P)
                {
                    m_RenderPatches = !m_RenderPatches;
                    e.Handled       = true;
                }
            }
        }
Exemple #15
0
        private void UpdateExploration(bool forceReevaluation, bool ignore_explored)
        {
            Vec3 current_pos = m_Navigator.CurrentPos;

            if (current_pos.IsZero())
            {
                return;
            }

            if (!IsDataAvailable)
            {
                m_Navmesh.Log("[Nav] Exploration data unavailable!");
                return;
            }

            if (!ignore_explored && IsExplored())
            {
                m_Navmesh.Log("[Nav] Exploration finished!");
                m_Navigator.ClearDestination(DestType.Explore);
                return;
            }

            if (m_DestCell != null)
            {
                bool validate_dest_cell         = Interlocked.CompareExchange(ref m_ValidateDestCell, 0, 1) == 1;
                bool mark_dest_cell_as_explored = false;
                // perform connection check only when reevaluation is forced (usually due to navigation data change)
                bool is_dest_cell_connected = (!forceReevaluation && !validate_dest_cell) || m_Navmesh.AreConnected(GetDestinationCellPosition(), current_pos, MovementFlag.Walk, 0, 0, out var unused1, out var unused2);

                // delay exploration of currently unconnected explore cells, unless they are already delayed (mark them as explored in that case)
                if (!is_dest_cell_connected)
                {
                    if (!m_DestCell.Delayed)
                    {
                        m_DestCell.Delayed = true;
                        forceReevaluation  = true; // this is a change to find another un-delayed explore cell
                    }
                    else
                    {
                        // looks like there are no better cells to visit, and there is no way to reach this one... so sorry but we have to mark it as explored
                        mark_dest_cell_as_explored = true;
                    }
                }

                // mark destination cell as explored when external function says so or destination cell is no longer connected (mostly due to nav blocker)
                mark_dest_cell_as_explored |= AlternativeExploredCondition?.Invoke(m_DestCell, current_pos) ?? false;

                if (mark_dest_cell_as_explored)
                {
                    Trace.WriteLine($"Explore cell GID {m_DestCell.GlobalId} considered explored by external logic.");
                    OnCellExplored(m_DestCell);
                }
            }

            using (new ReadLock(DataLock, true))
            {
                if ((Enabled && m_Navigator.GetDestinationType() < DestType.Explore) || (m_DestCell?.Explored ?? false) || forceReevaluation)
                {
                    SelectNewDestinationCell(null);
                    //m_Navmesh.Log("[Nav] Explore dest changed.");
                }

                ExploreCell travel_through_explore_cell = m_ExploreCells.FirstOrDefault(x => x.Contains2D(current_pos));

                if (travel_through_explore_cell != null && !travel_through_explore_cell.Explored)
                {
                    bool mark_explored = false;
                    if (AlternativeExploredCondition?.Invoke(travel_through_explore_cell, current_pos) ?? false)
                    {
                        Trace.WriteLine($"Explore cell GID {travel_through_explore_cell.GlobalId} considered explored by external logic.");
                        mark_explored = true;
                    }

                    // mark cells as explored when passing by close enough
                    if (travel_through_explore_cell.Position.Distance2D(current_pos) < ExploreDestPrecision)
                    {
                        Trace.WriteLine($"Explore cell GID {travel_through_explore_cell.GlobalId} considered explored because of passing by.");
                        mark_explored = true;
                    }

                    if (mark_explored)
                    {
                        OnCellExplored(travel_through_explore_cell);
                    }
                }

                OnUpdateExploration(travel_through_explore_cell);
            }
        }
Exemple #16
0
        // Everything inside this method is rendered with transformation resulting from ModifyRenderMatrix.
        protected virtual void OnRenderData(PaintEventArgs e)
        {
            try
            {
                int cells_count      = 0;
                int grid_cells_count = 0;

                if (m_RenderGrids || m_RenderCells)
                {
                    using (m_Navmesh.AcquireReadDataLock())
                    {
                        var grid_cells = m_Navmesh.dbg_GetGridCells();

                        if (m_RenderGrids)
                        {
                            foreach (Nav.GridCell grid_cell in grid_cells)
                            {
                                RenderHelper.Render(grid_cell, m_RenderCenter, e, m_RenderConnections, m_RenderIds);
                            }

                            grid_cells_count = grid_cells.Count;
                        }

                        if (m_RenderCells)
                        {
                            foreach (Nav.GridCell grid_cell in grid_cells)
                            {
                                foreach (Nav.Cell cell in grid_cell.GetCells())
                                {
                                    RenderHelper.Render(cell, m_RenderCenter, e, m_RenderConnections, m_RenderIds, m_RenderRegionsMode == RegionsRenderMode.MoveCostMult, m_RenderRegionsMode == RegionsRenderMode.Threat);
                                }

                                cells_count += grid_cell.GetCellsCount();
                            }
                        }
                    }
                }

                if (m_RenderExploreCells || m_RenderExploreArea)
                {
                    using (m_Explorer.AquireReadDataLock())
                    {
                        var explore_cells = m_Explorer.dbg_GetExploreCells();

                        foreach (Nav.ExploreCell explore_cell in explore_cells)
                        {
                            RenderHelper.Render(explore_cell, m_Explorer.ExploreDestPrecision, m_RenderCenter, e, m_RenderConnections, m_RenderIds);

                            if (m_RenderExploreArea)
                            {
                                RenderHelper.DrawString(e.Graphics, explore_cell.Small ? Brushes.DarkRed : Brushes.Black, m_RenderCenter, explore_cell.Position, explore_cell.CellsArea().ToString(), 12);
                            }
                        }
                    }
                }

                if (m_RenderPatches)
                {
                    using (m_Navmesh.AcquireReadDataLock())
                    {
                        int id = 0;
                        foreach (var patch in m_Navmesh.m_CellsPatches)
                        {
                            var   rng = new Random(id++);
                            Color c   = Color.FromArgb(rng.Next(255), rng.Next(255), rng.Next(255));

                            foreach (var cell in patch.Cells)
                            {
                                RenderHelper.Render(cell, m_RenderCenter, e, draw_connections: false, draw_id: false, render_move_cost_mult: false, render_threat: false, render_outline: false, render_disabled: true, force_color: c);
                            }
                        }
                    }
                }

                if (m_RenderRegionsMode == RegionsRenderMode.Outline)
                {
                    var regions = m_Navmesh.Regions;

                    foreach (var region in regions)
                    {
                        RenderHelper.DrawRectangle(e.Graphics, Pens.Black, m_RenderCenter, region.Area.Min, region.Area.Max);
                    }

                    //Vec3 safe_point = m_Navigator.GetNearestGridCellOutsideAvoidAreas();

                    //if (!safe_point.IsEmpty)
                    //    RenderHelper.DrawPoint(e.Graphics, Pens.Green, render_center, safe_point);
                }

                if (m_RenderAxis)
                {
                    e.Graphics.DrawString("X", new Font("Arial", 6 / m_RenderScale), Brushes.Black, 25 / m_RenderScale, 0);
                    e.Graphics.DrawLine(RenderHelper.AXIS_PEN, -25 / m_RenderScale, 0, 25 / m_RenderScale, 0);
                    e.Graphics.DrawString("Y", new Font("Arial", 6 / m_RenderScale), Brushes.Black, 0, 25 / m_RenderScale);
                    e.Graphics.DrawLine(RenderHelper.AXIS_PEN, 0, -25 / m_RenderScale, 0, 25 / m_RenderScale);
                }

                if (!m_RenderOriginalPath && m_RenderPath)
                {
                    destination last_path_dest = default(destination);
                    if (m_Navigator.TryGetPath(ref m_LastPath, ref last_path_dest))
                    {
                        m_LastPath.Insert(0, m_Navigator.CurrentPos);
                    }
                    RenderHelper.DrawLines(e.Graphics, RenderHelper.PATH_PEN, m_RenderCenter, m_LastPath, 1, true);

                    if (!m_Navigator.PathRecalcTriggerPosition.IsZero())
                    {
                        RenderHelper.DrawCircle(e.Graphics, Pens.DarkRed, m_RenderCenter, m_Navigator.PathRecalcTriggerPosition, m_Navigator.PathRecalcTriggerPrecision);
                    }
                }

                if (m_RenderBacktrackPath)
                {
                    if (m_Navigator.TryGetBackTrackPath(ref m_LastBacktrackPath))
                    {
                        m_LastBacktrackPath.Insert(0, m_Navigator.CurrentPos);
                    }
                    RenderHelper.DrawLines(e.Graphics, Pens.Blue, m_RenderCenter, m_LastBacktrackPath, 1);
                }

                if (m_RenderPositionsHistory)
                {
                    m_Navigator.TryGetDebugPositionsHistory(ref m_LastPositionsHistory);
                    RenderHelper.DrawLines(e.Graphics, Pens.Green, m_RenderCenter, m_LastPositionsHistory, 1, true);
                }

                Vec3 curr      = m_Navigator.CurrentPos;
                Vec3 dest      = m_Navigator.Destination.pos;
                var  ring_dest = m_Navigator.RingDestination;

                if (!curr.IsZero())
                {
                    RenderHelper.DrawPoint(e.Graphics, Pens.Blue, m_RenderCenter, curr);
                }

                if (!dest.IsZero())
                {
                    RenderHelper.DrawPoint(e.Graphics, Pens.LightBlue, m_RenderCenter, dest);
                }

                if (!ring_dest.pos.IsZero())
                {
                    RenderHelper.DrawPoint(e.Graphics, Pens.LightBlue, m_RenderCenter, ring_dest.pos);
                    RenderHelper.DrawCircle(e.Graphics, Pens.LightBlue, m_RenderCenter, ring_dest.pos, ring_dest.precision);
                    RenderHelper.DrawCircle(e.Graphics, Pens.LightBlue, m_RenderCenter, ring_dest.pos, ring_dest.precision_max);
                }

                if (!curr.IsZero() && !dest.IsZero())
                {
                    if (m_RenderOriginalPath)
                    {
                        List <Vec3> path = new List <Vec3>();
                        m_Navigator.FindPath(curr, dest, MovementFlag.Walk, ref path, out var path_recalc_trigger_position, out var path_recalc_trigger_precision, -1, false, false, 0, false, 0, smoothen_distance: 0);
                        path.Insert(0, curr);
                        RenderHelper.DrawLines(e.Graphics, Pens.Black, m_RenderCenter, path, 1);
                    }

                    if (m_RenderRoughPath)
                    {
                        List <Vec3> rought_path = new List <Vec3>();

                        if (m_Navigator.m_RoughtPathEstimator != null)
                        {
                            m_Navigator.m_RoughtPathEstimator.FindRoughPath(curr, dest, ref rought_path);
                        }

                        rought_path.Insert(0, curr);
                        RenderHelper.DrawLines(e.Graphics, RenderHelper.EXPLORE_PATH_PEN, m_RenderCenter, rought_path, 1, true);
                    }

                    if (m_RenderRayCast)
                    {
                        var result = m_Navmesh.RayCast2D(curr, dest, MovementFlag.Walk);
                        RenderHelper.DrawLine(e.Graphics, result ? Pens.Green : Pens.Red, m_RenderCenter, curr, result.End);
                    }

                    if (m_RenderConnected)
                    {
                        bool connected = m_Navmesh.AreConnected(curr, dest, MovementFlag.Walk, 100, 400, out var curr_on_nav, out var dest_on_nav);
                        RenderHelper.DrawLine(e.Graphics, connected ? Pens.Green : Pens.Red, m_RenderCenter, curr, dest);
                        RenderHelper.DrawLine(e.Graphics, Pens.Lavender, m_RenderCenter, curr, curr_on_nav);
                        RenderHelper.DrawLine(e.Graphics, Pens.Lavender, m_RenderCenter, dest, dest_on_nav);
                        RenderHelper.DrawString(e.Graphics, connected ? Brushes.Green : Brushes.Red, m_RenderCenter, dest, connected ? "connected" : "not connected", 4);
                    }
                }

                if (!curr.IsZero() && dest.IsZero())
                {
                    if (m_RenderAvoidancePath)
                    {
                        List <Vec3> path = new List <Vec3>();
                        m_Navigator.FindAvoidancePath(curr, 0, MovementFlag.Walk, ref path, Vec3.ZERO, false, 0, float.MaxValue);
                        path.Insert(0, curr);
                        RenderHelper.DrawLines(e.Graphics, Pens.Black, m_RenderCenter, path, 1);
                    }
                }

                var waypoints = m_Navigator.Waypoints;
                if (waypoints.Count > 0)
                {
                    RenderHelper.DrawLines(e.Graphics, Pens.Red, m_RenderCenter, waypoints, 1);
                }

                if (m_Bot != null)
                {
                    //if (!m_Bot.Paused && m_CenterOnBot)
                    //    m_RenderCenter = new PointF(m_Bot.Position.X, m_Bot.Position.Y);
                    m_Bot.Render(e.Graphics, m_RenderCenter);
                }
            }
            catch (Exception)
            {
            }
        }
Exemple #17
0
        // Everything inside this method is rendered with transformation resulting from ModifyRenderMatrix.
        protected virtual void OnRenderData(PaintEventArgs e)
        {
            try
            {
                int cells_count      = 0;
                int grid_cells_count = 0;

                if (m_RenderGrids || m_RenderCells)
                {
                    using (m_Navmesh.AcquireReadDataLock())
                    {
                        var grid_cells = m_Navmesh.dbg_GetGridCells();

                        if (m_RenderGrids)
                        {
                            foreach (Nav.GridCell grid_cell in grid_cells)
                            {
                                RenderHelper.Render(grid_cell, m_RenderCenter, e, m_RenderConnections, m_RenderIds);
                            }

                            grid_cells_count = grid_cells.Count;
                        }

                        if (m_RenderCells)
                        {
                            foreach (Nav.GridCell grid_cell in grid_cells)
                            {
                                foreach (Nav.Cell cell in grid_cell.GetCells())
                                {
                                    RenderHelper.Render(cell, m_RenderCenter, e, m_RenderConnections, m_RenderIds, m_RenderRegionsMode == RegionsRenderMode.MoveCostMult, m_RenderRegionsMode == RegionsRenderMode.Threat);
                                }

                                cells_count += grid_cell.GetCellsCount();
                            }
                        }
                    }
                }

                if (m_RenderExploreCells || m_RenderExploreArea)
                {
                    using (m_Explorer.AquireReadDataLock())
                    {
                        var explore_cells = m_Explorer.dbg_GetExploreCells();

                        foreach (Nav.ExploreCell explore_cell in explore_cells)
                        {
                            RenderHelper.Render(explore_cell, m_Explorer.ExploreDestPrecision, m_RenderCenter, e, m_RenderConnections, m_RenderIds);

                            if (m_RenderExploreArea)
                            {
                                RenderHelper.DrawString(e.Graphics, Brushes.Black, m_RenderCenter, explore_cell.Position, explore_cell.CellsArea().ToString(), 5);
                            }
                        }
                    }
                }

                if (m_RenderRegionsMode == RegionsRenderMode.Outline)
                {
                    var regions = m_Navmesh.Regions;

                    foreach (var region in regions)
                    {
                        RenderHelper.DrawRectangle(e.Graphics, Pens.Black, m_RenderCenter, region.Area.Min, region.Area.Max);
                    }

                    //Vec3 safe_point = m_Navigator.GetNearestGridCellOutsideAvoidAreas();

                    //if (!safe_point.IsEmpty)
                    //    RenderHelper.DrawPoint(e.Graphics, Pens.Green, render_center, safe_point);
                }

                if (m_RenderAxis)
                {
                    e.Graphics.DrawString("X", new Font("Arial", 6 / m_RenderScale), Brushes.Black, 25 / m_RenderScale, 0);
                    e.Graphics.DrawLine(RenderHelper.AXIS_PEN, -25 / m_RenderScale, 0, 25 / m_RenderScale, 0);
                    e.Graphics.DrawString("Y", new Font("Arial", 6 / m_RenderScale), Brushes.Black, 0, 25 / m_RenderScale);
                    e.Graphics.DrawLine(RenderHelper.AXIS_PEN, 0, -25 / m_RenderScale, 0, 25 / m_RenderScale);
                }

                if (!m_RenderOriginalPath && m_RenderPath)
                {
                    DestType last_path_dest_type = DestType.None;
                    if (m_Navigator.TryGetPath(ref m_LastPath, ref last_path_dest_type))
                    {
                        m_LastPath.Insert(0, m_Navigator.CurrentPos);
                    }
                    RenderHelper.DrawLines(e.Graphics, RenderHelper.PATH_PEN, m_RenderCenter, m_LastPath, 1, true);
                }

                if (m_RenderBacktrackPath)
                {
                    if (m_Navigator.TryGetBackTrackPath(ref m_LastBacktrackPath))
                    {
                        m_LastBacktrackPath.Insert(0, m_Navigator.CurrentPos);
                    }
                    RenderHelper.DrawLines(e.Graphics, Pens.Blue, m_RenderCenter, m_LastBacktrackPath, 1);
                }

                if (m_RenderPositionsHistory)
                {
                    m_Navigator.TryGetDebugPositionsHistory(ref m_LastPositionsHistory);
                    RenderHelper.DrawLines(e.Graphics, Pens.Green, m_RenderCenter, m_LastPositionsHistory, 1);
                }

                Vec3 curr = m_Navigator.CurrentPos;
                Vec3 dest = m_Navigator.Destination;

                if (!curr.IsZero())
                {
                    RenderHelper.DrawPoint(e.Graphics, Pens.Blue, m_RenderCenter, curr);
                }

                if (!dest.IsZero())
                {
                    RenderHelper.DrawPoint(e.Graphics, Pens.LightBlue, m_RenderCenter, dest);
                }

                if (!curr.IsZero() && !dest.IsZero())
                {
                    if (m_RenderOriginalPath)
                    {
                        List <Vec3> path = new List <Vec3>();
                        m_Navigator.FindPath(curr, dest, MovementFlag.Walk, ref path, -1, false, false, 0, false, 0, false);
                        path.Insert(0, curr);
                        RenderHelper.DrawLines(e.Graphics, Pens.Black, m_RenderCenter, path, 1);
                    }

                    if (m_RenderRayCast)
                    {
                        var result = m_Navmesh.RayCast2D(curr, dest, MovementFlag.Walk);
                        RenderHelper.DrawLine(e.Graphics, result ? Pens.Green : Pens.Red, m_RenderCenter, curr, result.End);
                    }

                    if (m_RenderConnected)
                    {
                        bool connected = m_Navmesh.AreConnected(curr, dest, MovementFlag.Walk, 40);
                        RenderHelper.DrawLine(e.Graphics, connected ? Pens.Green : Pens.Red, m_RenderCenter, curr, dest);
                        RenderHelper.DrawString(e.Graphics, connected ? Brushes.Green : Brushes.Red, m_RenderCenter, dest, connected ? "connected" : "not connected", 4);
                    }
                }

                if (!curr.IsZero() && dest.IsZero())
                {
                    if (m_RenderAvoidancePath)
                    {
                        List <Vec3> path = new List <Vec3>();
                        m_Navigator.FindAvoidancePath(curr, 0, MovementFlag.Walk, ref path, Vec3.ZERO, false, 0, true);
                        path.Insert(0, curr);
                        RenderHelper.DrawLines(e.Graphics, Pens.Black, m_RenderCenter, path, 1);
                    }
                }

                var waypoints = m_Navigator.Waypoints;
                if (waypoints.Count > 0)
                {
                    RenderHelper.DrawLines(e.Graphics, Pens.Red, m_RenderCenter, waypoints, 1);
                }

                if (m_Bot != null)
                {
                    //if (!m_Bot.Paused && m_CenterOnBot)
                    //    m_RenderCenter = new PointF(m_Bot.Position.X, m_Bot.Position.Y);
                    m_Bot.Render(e.Graphics, m_RenderCenter);
                }
            }
            catch (Exception)
            {
            }
        }
Exemple #18
0
        private void UpdateExploration()
        {
            Vec3 current_pos = m_Navigator.CurrentPos;

            if (current_pos.IsZero())
            {
                return;
            }

            if (!IsDataAvailable)
            {
                m_Navmesh.Log("[Nav] Exploration data unavailable!");
                return;
            }

            if (IsExplored())
            {
                m_Navmesh.Log("[Nav] Exploration finished!");
                m_Navigator.ClearDestination(DestType.Explore);
                return;
            }

            if (m_DestCell != null)
            {
                bool mark_dest_cell_as_explored = false;
                // perform connection check only when reevaluation is forced (usually due to navigation data change)
                bool is_dest_cell_connected = (!m_ForceReevaluation && !m_ValidateDestCell) || m_Navmesh.AreConnected(GetDestinationCellPosition(), current_pos, MovementFlag.Walk, ExploreDestPrecision, 0, out var unused1, out var unused2);

                // delay exploration of currently unconnected explore cells, unless they are already delayed (mark them as explored in that case)
                if (!is_dest_cell_connected)
                {
                    if (!m_DestCell.Delayed)
                    {
                        m_DestCell.Delayed  = true;
                        m_ForceReevaluation = true; // this is a change to find another un-delayed explore cell
                    }
                    else
                    {
                        // looks like there are no better cells to visit, and there is no way to reach this one... so sorry but we have to mark it as explored
                        mark_dest_cell_as_explored = true;
                    }
                }

                m_ValidateDestCell = false;

                // mark destination cell as explored when external function says so or destination cell is no longer connected (mostly due to nav blocker)
                mark_dest_cell_as_explored |= AlternativeExploredCondition?.Invoke(m_DestCell, current_pos) ?? false;

                if (mark_dest_cell_as_explored)
                {
                    OnCellExplored(m_DestCell);
                }
            }

            using (new ReadLock(DataLock, true))
            {
                if (m_Navigator.GetDestinationType() < DestType.Explore || (m_DestCell?.Explored ?? false) || m_ForceReevaluation)
                {
                    SelectNewDestinationCell();
                    //m_Navmesh.Log("[Nav] Explore dest changed.");
                }

                // mark cells as explored when passing by close enough
                ExploreCell current_explore_cell = m_ExploreCells.FirstOrDefault(x => !x.Explored && x.Position.Distance2D(current_pos) < ExploreDestPrecision);

                if (current_explore_cell != null)
                {
                    OnCellExplored(current_explore_cell);
                }

                OnUpdateExploration();
            }
        }