예제 #1
0
파일: Cell.cs 프로젝트: Ifry/Nav
        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);
        }
예제 #2
0
파일: Cell.cs 프로젝트: wlastas/Nav
        // 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);
        }
예제 #3
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.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;
                }
            }
        }
예제 #4
0
        // 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));
            }
        }
예제 #5
0
파일: Cell.cs 프로젝트: rol2728/Dev.D3
        // 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);
        }
예제 #6
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);
            }
        }
예제 #7
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);
            }
        }