// 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); }
// 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; } } }
public bool Overlaps2D(Cell cell, bool tangential_ok = false) { return(AABB.Overlaps2D(cell.AABB, tangential_ok)); }
public bool Overlaps2D(Vec3 circle_center, float radius, bool tangential_ok = false) { return(AABB.Overlaps2D(circle_center, radius, tangential_ok)); }
// 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); } }
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); } }