예제 #1
0
        public Status Init(NavMeshBuilder data, int flags)
        {
            if (data.Header.Magic != Helper.NavMeshMagic)
            {
                throw new ArgumentException("Wrong Magic Number");
            }
            if (data.Header.Version != Helper.NavMeshVersion)
            {
                throw new ArgumentException("Wrong Version Number");
            }

            NavMeshParams param = new NavMeshParams();

            Array.Copy(data.Header.BMin, param.Orig, 3);
            param.TileWidth  = data.Header.BMax[0] - data.Header.BMin[0];
            param.TileHeight = data.Header.BMax[2] - data.Header.BMin[2];
            param.MaxTiles   = 1;
            param.MaxPolys   = data.Header.PolyCount;

            Status status = Init(param);

            if ((status & Status.Failure) == Status.Failure)
            {
                return(status);
            }

            long temp = 0;

            return(AddTile(data, flags, 0, ref temp));
        }
예제 #2
0
        public Status RemoveTile(long refId, out NavMeshBuilder data)
        {
            data = null;
            if (refId == 0)
            {
                return(Status.Failure | Status.InvalidParam);
            }
            long tileIndex = DecodePolyIdTile(refId);
            long tileSalt  = DecodePolyIdSalt(refId);

            if (tileIndex >= _maxTiles)
            {
                return(Status.Failure | Status.InvalidParam);
            }
            MeshTile tile = _tiles[tileIndex];

            if (tile.Salt != tileSalt)
            {
                return(Status.Failure | Status.InvalidParam);
            }

            int      h    = ComputeTileHash(tile.Header.X, tile.Header.Y, _tileLutMask);
            MeshTile prev = null;
            MeshTile cur  = _posLookup[h];

            while (cur != null)
            {
                if (cur == tile)
                {
                    if (prev != null)
                    {
                        prev.Next = cur.Next;
                    }
                    else
                    {
                        _posLookup[h] = cur.Next;
                    }
                    break;
                }
                prev = cur;
                cur  = cur.Next;
            }

            int MaxNeis = 32;

            MeshTile[] neis = new MeshTile[MaxNeis];
            int        nneis;

            nneis = GetTilesAt(tile.Header.X, tile.Header.Y, ref neis, MaxNeis);
            for (int j = 0; j < nneis; j++)
            {
                if (neis[j] == tile)
                {
                    continue;
                }
                MeshTile temp = neis[j];
                UnconnectExtLinks(ref temp, ref tile);
            }

            for (int i = 0; i < 8; i++)
            {
                nneis = GetNeighborTilesAt(tile.Header.X, tile.Header.Y, i, ref neis, MaxNeis);
                for (int j = 0; j < nneis; j++)
                {
                    MeshTile temp = neis[j];
                    UnconnectExtLinks(ref temp, ref tile);
                }
            }

            // reset tile
            if ((tile.Flags & TileFreeData) != 0)
            {
                tile.Data = null;
            }
            else
            {
                data = tile.Data;
            }

            tile.Header        = null;
            tile.Flags         = 0;
            tile.LinksFreeList = 0;
            tile.Polys         = null;
            tile.Verts         = null;
            tile.Links         = null;
            tile.DetailMeshes  = null;
            tile.DetailVerts   = null;
            tile.DetailTris    = null;
            tile.BVTree        = null;
            tile.OffMeshCons   = null;

            tile.Salt = (tile.Salt + 1) & ((1 << (int)_saltBits) - 1);
            if (tile.Salt == 0)
            {
                tile.Salt++;
            }

            tile.Next = _nextFree;
            _nextFree = tile;

            return(Status.Success);
        }
예제 #3
0
        public Status AddTile(NavMeshBuilder data, int flags, long lastRef, ref long result)
        {
            MeshHeader header = data.Header;

            if (header.Magic != Helper.NavMeshMagic)
            {
                return(Status.Failure | Status.WrongMagic);
            }
            if (header.Version != Helper.NavMeshVersion)
            {
                return(Status.Failure | Status.WrongVersion);
            }

            if (GetTileAt(header.X, header.Y, header.Layer) != null)
            {
                return(Status.Failure);
            }

            MeshTile tile = null;

            if (lastRef == 0)
            {
                if (_nextFree != null)
                {
                    tile      = _nextFree;
                    _nextFree = tile.Next;
                    tile.Next = null;
                }
            }
            else
            {
                int tileIndex = (int)DecodePolyIdTile(lastRef);
                if (tileIndex >= _maxTiles)
                {
                    return(Status.Failure | Status.OutOfMemory);
                }

                MeshTile target = _tiles[tileIndex];
                MeshTile prev   = null;
                tile = _nextFree;
                while (tile != null && tile != target)
                {
                    prev = tile;
                    tile = tile.Next;
                }

                if (tile != target)
                {
                    return(Status.Failure | Status.OutOfMemory);
                }

                if (prev != null)
                {
                    _nextFree = tile.Next;
                }
                else
                {
                    prev.Next = tile.Next;
                }

                tile.Salt = DecodePolyIdSalt(lastRef);
            }

            if (tile == null)
            {
                return(Status.Failure | Status.OutOfMemory);
            }

            // insert tile into the position
            int h = ComputeTileHash(header.X, header.Y, _tileLutMask);

            tile.Next     = _posLookup[h];
            _posLookup[h] = tile;

            tile.Verts        = data.NavVerts;
            tile.Polys        = data.NavPolys;
            tile.Links        = data.NavLinks;
            tile.DetailMeshes = data.NavDMeshes;
            tile.DetailVerts  = data.NavDVerts;
            tile.DetailTris   = data.NavDTris;
            tile.BVTree       = data.NavBvTree;
            tile.OffMeshCons  = data.OffMeshCons;

            tile.LinksFreeList = 0;
            tile.Links[header.MaxLinkCount - 1].Next = NullLink;
            for (int i = 0; i < header.MaxLinkCount - 1; i++)
            {
                tile.Links[i].Next = i + 1;
            }

            tile.Data   = data;
            tile.Header = header;
            tile.Flags  = flags;

            ConnectIntLinks(tile);
            BaseOffMeshLinks(tile);

            int MaxNeis = 32;

            MeshTile[] neis = new MeshTile[MaxNeis];
            int        nneis;

            nneis = GetTilesAt(header.X, header.Y, ref neis, MaxNeis);
            for (int j = 0; j < nneis; j++)
            {
                MeshTile temp = neis[j];
                if (neis[j] != tile)
                {
                    ConnectExtLinks(ref tile, ref temp, -1);
                    ConnectExtLinks(ref temp, ref tile, -1);
                }
                ConnectExtOffMeshLinks(ref tile, ref temp, -1);
                ConnectExtOffMeshLinks(ref temp, ref tile, -1);
            }

            for (int i = 0; i < 8; i++)
            {
                nneis = GetNeighborTilesAt(header.X, header.Y, i, ref neis, MaxNeis);
                for (int j = 0; j < nneis; j++)
                {
                    MeshTile temp = neis[j];
                    ConnectExtLinks(ref tile, ref temp, i);
                    ConnectExtLinks(ref temp, ref tile, Helper.OppositeTile(i));
                    ConnectExtOffMeshLinks(ref tile, ref temp, i);
                    ConnectExtOffMeshLinks(ref temp, ref tile, Helper.OppositeTile(i));
                }
            }

            result = GetTileRef(tile);

            return(Status.Success);
        }