Пример #1
0
        // This function will return list of cells pairs that should be connected
        public List <(Cell, Cell, Vec3)> CheckNeighbour(GridCell grid_cell, out MovementFlag connection_flags)
        {
            var result = new List <(Cell, Cell, Vec3)>();

            connection_flags = MovementFlag.None;

            if (GlobalId == grid_cell.GlobalId || !AABB.Overlaps2D(grid_cell.AABB, true))
            {
                return(result);
            }

            foreach (Cell our_cell in Cells)
            {
                foreach (Cell other_cell in grid_cell.Cells)
                {
                    Vec3 border_point        = default(Vec3);
                    bool should_be_connected = our_cell.ShouldBecomeNeighbours(other_cell, ref border_point);

                    if (should_be_connected)
                    {
                        result.Add((our_cell, other_cell, border_point));

                        MovementFlag flags = our_cell.Flags & other_cell.Flags;

                        if (flags > connection_flags)
                        {
                            connection_flags = flags;
                        }
                    }
                }
            }

            return(result);
        }
Пример #2
0
        // Try to connect grid_cell with this cell. Connection can be established only when any two cells of both grid cells are connected. This function should behave
        // properly when called multiple times for the same pair of grid cells!
        public void AddNeighbour(GridCell grid_cell)
        {
            if (GlobalId == grid_cell.GlobalId || !AABB.Overlaps2D(grid_cell.AABB, true))
            {
                return;
            }

            // this is removed to properly handle merging
            //if (Neighbours.Exists(x => x.cell.Equals(grid_cell)))
            //    return;

            bool         any_cells_connected = false;
            MovementFlag connection_flags    = MovementFlag.None;

            foreach (Cell our_cell in Cells)
            {
                foreach (Cell other_cell in grid_cell.Cells)
                {
                    Vec3 border_point    = default(Vec3);
                    bool cells_connected = our_cell.AddNeighbour(other_cell, ref border_point);

                    if (cells_connected)
                    {
                        any_cells_connected = true;
                        MovementFlag flags = our_cell.Flags & other_cell.Flags;

                        if (flags > connection_flags)
                        {
                            connection_flags = flags;
                        }
                    }
                }
            }

            if (any_cells_connected)
            {
                Neighbour n1 = Neighbours.FirstOrDefault(x => x.cell.GlobalId == grid_cell.GlobalId);

                // if they were not connected before, simply connect them
                if (n1 == null)
                {
                    Neighbours.Add(new Neighbour(grid_cell, Vec3.ZERO, connection_flags));
                    grid_cell.Neighbours.Add(new Neighbour(this, Vec3.ZERO, connection_flags));
                }
                // otherwise verify connection flags
                else if (n1.connection_flags < connection_flags)
                {
                    Neighbour n2 = grid_cell.Neighbours.FirstOrDefault(x => x.cell.GlobalId == GlobalId);

                    n1.connection_flags = connection_flags;
                    n2.connection_flags = connection_flags;
                }
            }
        }
Пример #3
0
 public bool Overlaps2D(Cell cell, bool tangential_ok = false)
 {
     return(AABB.Overlaps2D(cell.AABB, tangential_ok));
 }
Пример #4
0
 public bool Overlaps2D(Vec3 circle_center, float radius, bool tangential_ok = false)
 {
     return(AABB.Overlaps2D(circle_center, radius, tangential_ok));
 }
Пример #5
0
        // assume Navmesh data lock is aquired
        private int GenerateExploreCells(AABB cell_aabb)
        {
            // should not happen
            //if (m_ExploreCells.Exists(x => x.AABB.Equals(cell_aabb)))
            //    return;

            MovementFlag movement_flags = m_Navigator.MovementFlags;

            //using (new Profiler("[Nav] Nav data generated [%t]"))
            //using (m_Navmesh.AquireReadDataLock())
            {
                List <Cell> cells = new List <Cell>();

                // i'm interested in unique list
                HashSet <int> tmp_overlapping_grid_cells = new HashSet <int>();

                // find all cells inside cell_aabb
                using (m_Navmesh.AcquireReadDataLock())
                {
                    foreach (GridCell grid_cell in m_Navmesh.m_GridCells.Where(x => x.AABB.Overlaps2D(cell_aabb)))
                    {
                        tmp_overlapping_grid_cells.Add(grid_cell.Id);

                        cells.AddRange(grid_cell.GetCells(x => x.HasFlags(movement_flags) && cell_aabb.Overlaps2D(x.AABB), false));
                    }
                }

                // for traversing purposes list will be faster
                List <int> overlapping_grid_cells = tmp_overlapping_grid_cells.ToList();

                //create ExploreCell for each interconnected group of cells
                HashSet <Cell> cells_copy = new HashSet <Cell>(cells);
                int            last_explore_cells_count = m_ExploreCells.Count;

                while (cells_copy.Count > 0)
                {
                    HashSet <Cell> visited = new HashSet <Cell>();

                    using (m_Navmesh.AcquireReadDataLock())
                        Algorihms.Visit(cells_copy.First(), ref visited, movement_flags, true, 1, -1, cells_copy);

                    List <AABB> intersections      = new List <AABB>();
                    AABB        intersections_aabb = new AABB();

                    AABB intersection = default(AABB);

                    foreach (Cell c in visited)
                    {
                        if (cell_aabb.Intersect(c.AABB, ref intersection))
                        {
                            intersections.Add(intersection);
                            intersections_aabb = intersections_aabb.Extend(intersection);
                        }
                    }

                    ExploreCell ex_cell = new ExploreCell(cell_aabb, visited.ToList(), overlapping_grid_cells, m_LastExploreCellId++);
                    Add(ex_cell);

                    ex_cell.Small = (ex_cell.CellsArea < MaxAreaToMarkAsSmall) || (ex_cell.CellsAABB.Dimensions.Max() < MaxDimensionToMarkAsSmall);

                    cells_copy.RemoveWhere(x => visited.Contains(x));
                }

                return(m_ExploreCells.Count - last_explore_cells_count);
            }
        }
Пример #6
0
        private int GenerateExploreCells(AABB cell_aabb)
        {
            // should not happen
            //if (m_ExploreCells.Exists(x => x.AABB.Equals(cell_aabb)))
            //    return;

            MovementFlag movement_flags = Navmesh.Navigator.MovementFlags;

            //using (new Profiler("[Nav] Nav data generated [{t}]"))
            using (Navmesh.AquireReadDataLock())
            {
                List <Cell> cells = new List <Cell>();

                // find all cells inside cell_aabb
                foreach (GridCell grid_cell in Navmesh.m_GridCells)
                {
                    if (!cell_aabb.Overlaps2D(grid_cell.AABB))
                    {
                        continue;
                    }

                    cells.AddRange(grid_cell.Cells.FindAll(x => !x.Replacement && x.HasFlags(movement_flags) && cell_aabb.Overlaps2D(x.AABB)));
                }

                // add all replaced cells overlapped by explore cell
                //cells.AddRange(Navmesh.GetReplacedCells().FindAll(x => x.HasFlags(movement_flags) && cell_aabb.Overlaps2D(x.AABB)));

                //create ExploreCell for each interconnected group of cells
                List <Cell> cells_copy = new List <Cell>(cells);
                int         last_explore_cells_count = m_ExploreCells.Count;

                while (cells_copy.Count > 0)
                {
                    List <Cell> visited = new List <Cell>();

                    Algorihms.Visit(cells_copy[0], ref visited, movement_flags, true, 1, -1, cells_copy);

                    List <AABB> intersections      = new List <AABB>();
                    AABB        intersections_aabb = new AABB();

                    foreach (Cell c in visited)
                    {
                        AABB intersection = cell_aabb.Intersect(c.AABB);

                        intersections.Add(intersection);
                        intersections_aabb.Extend(intersection);
                    }

                    Vec3  nearest_intersection_center = Vec3.Empty;
                    float nearest_intersection_dist   = float.MaxValue;

                    foreach (AABB inter_aabb in intersections)
                    {
                        float dist = inter_aabb.Center.Distance2D(intersections_aabb.Center);

                        if (dist < nearest_intersection_dist)
                        {
                            nearest_intersection_center = inter_aabb.Center;
                            nearest_intersection_dist   = dist;
                        }
                    }

                    ExploreCell ex_cell = new ExploreCell(cell_aabb, visited, nearest_intersection_center, m_LastExploreCellId++);
                    Add(ex_cell);

                    ex_cell.Small = (ex_cell.CellsArea() < MAX_AREA_TO_MARK_AS_SMALL);

                    cells_copy.RemoveAll(x => visited.Contains(x));
                }

                return(m_ExploreCells.Count - last_explore_cells_count);
            }
        }