Exemple #1
0
        private CompressedTile GetTileAt(int tx, int ty, int tlayer)
        {
            // Find tile based on hash.
            int h    = Detour.ComputeTileHash(tx, ty, m_tileLutMask);
            var tile = m_posLookup[h];

            while (tile != null)
            {
                if (tile.Header.TX == tx &&
                    tile.Header.TY == ty &&
                    tile.Header.TLayer == tlayer)
                {
                    return(tile);
                }
                tile = tile.Next;
            }

            return(null);
        }
Exemple #2
0
        public int GetTilesAt(int tx, int ty, out CompressedTile[] tiles, int maxTiles)
        {
            tiles = new CompressedTile[maxTiles];

            int n = 0;

            // Find tile based on hash.
            int h    = Detour.ComputeTileHash(tx, ty, m_tileLutMask);
            var tile = m_posLookup[h];

            while (tile != null)
            {
                if (tile.Header.TX == tx && tile.Header.TY == ty && n < maxTiles)
                {
                    tiles[n++] = tile;
                }

                tile = tile.Next;
            }

            return(n);
        }
Exemple #3
0
        public Status QueryTiles(Vector3 bmin, Vector3 bmax, int maxResults, out CompressedTile[] results, out int resultCount)
        {
            results = new CompressedTile[maxResults];

            int MAX_TILES = 32;

            int n = 0;

            float tw  = m_params.Width * m_params.CellSize;
            float th  = m_params.Height * m_params.CellSize;
            int   tx0 = (int)Math.Floor((bmin.X - m_params.Origin.X) / tw);
            int   tx1 = (int)Math.Floor((bmax.X - m_params.Origin.X) / tw);
            int   ty0 = (int)Math.Floor((bmin.Z - m_params.Origin.Z) / th);
            int   ty1 = (int)Math.Floor((bmax.Z - m_params.Origin.Z) / th);

            for (int ty = ty0; ty <= ty1; ++ty)
            {
                for (int tx = tx0; tx <= tx1; ++tx)
                {
                    int ntiles = GetTilesAt(tx, ty, out CompressedTile[] tiles, MAX_TILES);

                    for (int i = 0; i < ntiles; ++i)
                    {
                        var tile = tiles[i];
                        CalcTightTileBounds(tile.Header, out Vector3 tbmin, out Vector3 tbmax);

                        if (Detour.OverlapBounds(bmin, bmax, tbmin, tbmax) && n < maxResults)
                        {
                            results[n++] = tiles[i];
                        }
                    }
                }
            }

            resultCount = n;

            return(Status.DT_SUCCESS);
        }
Exemple #4
0
        public Node GetNode(int id, int state)
        {
            int bucket = Detour.HashRef(id) & (HashSize - 1);
            int i      = First[bucket];

            while (i != Detour.DT_NULL_IDX)
            {
                if (Nodes[i] != null && Nodes[i].Id == id && Nodes[i].State == state)
                {
                    return(Nodes[i]);
                }
                i = Next[i];
            }

            if (NodeCount >= MaxNodes)
            {
                return(null);
            }

            i = NodeCount;
            NodeCount++;

            // Init node
            Nodes[i] = new Node
            {
                PIdx  = 0,
                Cost  = 0,
                Total = 0,
                Id    = id,
                State = state,
                Flags = 0
            };

            Next[i]       = First[bucket];
            First[bucket] = i;

            return(Nodes[i]);
        }
Exemple #5
0
        public int FindNodes(int id, out Node[] nodes, int maxNodes)
        {
            nodes = new Node[maxNodes];

            int n      = 0;
            int bucket = Detour.HashRef(id) & (HashSize - 1);
            int i      = First[bucket];

            while (i != Detour.DT_NULL_IDX)
            {
                if (Nodes[i].Id == id)
                {
                    if (n >= maxNodes)
                    {
                        return(n);
                    }
                    nodes[n++] = Nodes[i];
                }
                i = Next[i];
            }

            return(n);
        }
Exemple #6
0
        public bool BuildNavMeshTile(CompressedTile tile, NavMesh navmesh)
        {
            NavMeshTileBuildContext bc = new NavMeshTileBuildContext();
            int walkableClimbVx        = (int)(m_params.WalkableClimb / m_params.CellHeight);

            // Decompress tile layer data.
            if (!DetourTileCache.DecompressTileCacheLayer(tile.Header, tile.Data, 0, out var layer))
            {
                return(false);
            }
            bc.Layer = layer;

            // Rasterize obstacles.
            for (int i = 0; i < m_params.MaxObstacles; ++i)
            {
                var ob = m_obstacles[i];

                if (ob.State == ObstacleState.DT_OBSTACLE_EMPTY || ob.State == ObstacleState.DT_OBSTACLE_REMOVING)
                {
                    continue;
                }

                if (DetourTileCache.Contains(ob.Touched, ob.NTouched, tile))
                {
                    if (ob.Type == ObstacleType.DT_OBSTACLE_CYLINDER)
                    {
                        DetourTileCache.MarkCylinderArea(bc,
                                                         tile.Header.BBox.Minimum, m_params.CellSize, m_params.CellHeight,
                                                         ob.Cylinder.Pos, ob.Cylinder.Radius, ob.Cylinder.Height, 0);
                    }
                    else if (ob.Type == ObstacleType.DT_OBSTACLE_BOX)
                    {
                        DetourTileCache.MarkBoxArea(bc,
                                                    tile.Header.BBox.Minimum, m_params.CellSize, m_params.CellHeight,
                                                    ob.Box.BMin, ob.Box.BMax, 0);
                    }
                    else if (ob.Type == ObstacleType.DT_OBSTACLE_ORIENTED_BOX)
                    {
                        DetourTileCache.MarkBoxArea(bc,
                                                    tile.Header.BBox.Minimum, m_params.CellSize, m_params.CellHeight,
                                                    ob.OrientedBox.Center, ob.OrientedBox.HalfExtents, ob.OrientedBox.RotAux, 0);
                    }
                }
            }

            // Build navmesh
            if (!DetourTileCache.BuildTileCacheRegions(bc, walkableClimbVx))
            {
                return(false);
            }

            if (!DetourTileCache.BuildTileCacheContours(bc, walkableClimbVx, m_params.MaxSimplificationError))
            {
                return(false);
            }

            if (!DetourTileCache.BuildTileCachePolyMesh(bc))
            {
                return(false);
            }

            // Early out if the mesh tile is empty.
            if (bc.LMesh.NPolys == 0)
            {
                // Remove existing tile.
                navmesh.RemoveTile(navmesh.GetTileRefAt(tile.Header.TX, tile.Header.TY, tile.Header.TLayer), null, 0);
                return(true);
            }

            var param = new NavMeshCreateParams
            {
                Verts          = bc.LMesh.Verts,
                VertCount      = bc.LMesh.NVerts,
                Polys          = bc.LMesh.Polys,
                PolyAreas      = bc.LMesh.Areas,
                PolyFlags      = bc.LMesh.Flags,
                polyCount      = bc.LMesh.NPolys,
                nvp            = Detour.DT_VERTS_PER_POLYGON,
                walkableHeight = m_params.WalkableHeight,
                walkableRadius = m_params.WalkableRadius,
                walkableClimb  = m_params.WalkableClimb,
                tileX          = tile.Header.TX,
                tileY          = tile.Header.TY,
                tileLayer      = tile.Header.TLayer,
                cs             = m_params.CellSize,
                ch             = m_params.CellHeight,
                buildBvTree    = false,
                bmin           = tile.Header.BBox.Minimum,
                bmax           = tile.Header.BBox.Maximum,
            };

            if (m_tmproc != null)
            {
                m_tmproc.Process(ref param, bc);
            }

            if (!Detour.CreateNavMeshData(param, out MeshData navData))
            {
                return(false);
            }

            // Remove existing tile.
            navmesh.RemoveTile(navmesh.GetTileRefAt(tile.Header.TX, tile.Header.TY, tile.Header.TLayer), null, 0);

            // Add new tile, or leave the location empty.
            if (navData != null && !navmesh.AddTile(navData, TileFlagTypes.DT_TILE_FREE_DATA, 0, out int result))
            {
                // Let the navmesh own the data.
                navData = null;

                return(false);
            }

            return(true);
        }