bool GetBorderSegmentWith(AABB aabb, ref Vec3 v1, ref Vec3 v2) { AABB intersection = default(AABB); if (AABB.Intersect(aabb, ref intersection, true)) { // find widest vector inside intersection AABB along X or Y axis Vec3 dimentions = intersection.Dimensions; Tuple <Vec3, Vec3> border_segment; //if (intersection.Dimensions.Z < 3 && (Math.Abs(intersection.Center.Z - cell.AABB.Max.Z) < 1f || Math.Abs(intersection.Center.Z - cell.AABB.Min.Z) < 1f)) if (aabb.Dimensions.Z < 3 || AABB.Dimensions.Z < 3) { Vec3 intersection_center = intersection.Center; if (dimentions.X > dimentions.Y) { border_segment = new Tuple <Vec3, Vec3>(new Vec3(intersection.Min.X, intersection_center.Y, intersection_center.Z), new Vec3(intersection.Max.X, intersection_center.Y, intersection_center.Z)); } else { border_segment = new Tuple <Vec3, Vec3>(new Vec3(intersection_center.X, intersection.Min.Y, intersection_center.Z), new Vec3(intersection_center.X, intersection.Max.Y, intersection_center.Z)); } return(true); } } return(false); }
// Try to add given cell as neighbour. Returns true when actually added. public bool AddNeighbour(Cell cell, ref Vec3 border_point) { // should not happen - removed due to performance impact - deep down it only checks global ID matching if (cell.Equals(this)) { return(false); } AABB intersection = default(AABB); if (AABB.Intersect(cell.AABB, ref intersection, true)) { if (Neighbours.Exists(x => x.cell.GlobalId == cell.GlobalId)) { return(false); } AddNeighbour(cell, intersection.Center); cell.AddNeighbour(this, intersection.Center); border_point = new Vec3(intersection.Center); return(true); } return(false); }
// 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.Intersect(grid_cell.AABB, true) == null) { 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 = null; 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, null, null, connection_flags)); grid_cell.Neighbours.Add(new Neighbour(this, null, null, 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; } } }
// Only grid cells connected vis cells with Walk movement flags will be treated as neighbours public void AddNeighbour(GridCell grid_cell) { if (AABB.Intersect(grid_cell.AABB, true) == null) { return; } 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) { bool cells_connected = our_cell.AddNeighbour(other_cell); 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) { Neighbours.Add(new Neighbour(grid_cell, null, connection_flags)); grid_cell.Neighbours.Add(new Neighbour(this, null, connection_flags)); } }
// Try to add given cell as neighbour. Returns true when actually added. public bool AddNeighbour(Cell cell) { if (cell.Equals(this)) { return(false); } AABB intersection = AABB.Intersect(cell.AABB, true); if (intersection != null) { if (Neighbours.Exists(x => x.cell.GlobalId == cell.GlobalId)) { return(false); } AddNeighbour(cell, intersection.Center); cell.AddNeighbour(this, intersection.Center); return(true); } return(false); }
// 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); } }