Ejemplo n.º 1
0
        public Status GetPolyArea(long refId, ref short resultArea)
        {
            long salt, it, ip;

            if (refId == 0)
            {
                return(Status.Failure);
            }

            DecodePolyId(refId, out salt, out it, out ip);
            if (it >= _maxTiles)
            {
                return(Status.Failure | Status.InvalidParam);
            }
            if (_tiles[it].Salt != salt || _tiles[it].Header == null)
            {
                return(Status.Failure | Status.InvalidParam);
            }
            MeshTile tile = _tiles[it];

            if (ip >= _tiles[it].Header.PolyCount)
            {
                return(Status.Failure | Status.InvalidParam);
            }

            Poly poly = tile.Polys[ip];

            resultArea = poly.Area;

            return(Status.Success);
        }
Ejemplo n.º 2
0
        public Status RestoreTileState(MeshTile tile, TileState tileState)
        {
            if (tileState.Magic != Helper.NavMeshMagic)
            {
                return(Status.Failure | Status.WrongMagic);
            }
            if (tileState.Version != Helper.NavMeshVersion)
            {
                return(Status.Failure | Status.WrongVersion);
            }
            if (tileState.Ref != GetTileRef(tile))
            {
                return(Status.Failure | Status.InvalidParam);
            }

            for (int i = 0; i < tile.Header.PolyCount; i++)
            {
                Poly      p = tile.Polys[i];
                PolyState s = tileState.PolyStates[i];
                p.Flags = s.Flags;
                p.Area  = s.Area;
            }

            return(Status.Success);
        }
Ejemplo n.º 3
0
        public Status SetPolyFlags(long refId, int flags)
        {
            long salt, it, ip;

            if (refId == 0)
            {
                return(Status.Failure);
            }

            DecodePolyId(refId, out salt, out it, out ip);
            if (it >= _maxTiles)
            {
                return(Status.Failure | Status.InvalidParam);
            }
            if (_tiles[it].Salt != salt || _tiles[it].Header == null)
            {
                return(Status.Failure | Status.InvalidParam);
            }
            MeshTile tile = _tiles[it];

            if (ip >= _tiles[it].Header.PolyCount)
            {
                return(Status.Failure | Status.InvalidParam);
            }

            Poly poly = tile.Polys[ip];

            poly.Flags = flags;
            return(Status.Success);
        }
Ejemplo n.º 4
0
 public float GetCost(float pax, float pay, float paz, float pbx, float pby, float pbz,
                      long prevRef, MeshTile prevTile, Poly prevPoly,
                      long curRef, MeshTile curTile, Poly curPoly,
                      long nextRef, MeshTile nextTile, Poly nextPoly)
 {
     return(Helper.VDist(pax, pay, paz, pbx, pby, pbz) * _areaCost[curPoly.Area]);
 }
Ejemplo n.º 5
0
        public Status GetTileAndPolyByRef(long refid, ref MeshTile tile, ref Poly poly)
        {
            if (refid == 0)
            {
                return(Status.Failure);
            }
            long salt, it, ip;

            DecodePolyId(refid, out salt, out it, out ip);
            if (it >= _maxTiles)
            {
                return(Status.Failure | Status.InvalidParam);
            }
            if (_tiles[it].Salt != salt || _tiles[it].Header == null)
            {
                return(Status.Failure | Status.InvalidParam);
            }
            if (ip >= _tiles[it].Header.PolyCount)
            {
                return(Status.Failure | Status.InvalidParam);
            }
            tile = _tiles[it];
            poly = _tiles[it].Polys[ip];
            return(Status.Success);
        }
Ejemplo n.º 6
0
        public void GetTileAndPolyByRefUnsafe(long refId, out MeshTile tile, out Poly poly)
        {
            long salt, it, ip;

            DecodePolyId(refId, out salt, out it, out ip);
            tile = _tiles[it];
            poly = _tiles[it].Polys[ip];
        }
Ejemplo n.º 7
0
        private void BaseOffMeshLinks(MeshTile tile)
        {
            if (tile == null)
            {
                return;
            }
            long baseId = GetPolyRefBase(tile);

            for (int i = 0; i < tile.Header.OffMeshConCount; i++)
            {
                OffMeshConnection con = tile.OffMeshCons[i];
                Poly poly             = tile.Polys[con.Poly];

                float[] ext       = { con.Rad, tile.Header.WalkableClimb, con.Rad };
                int     p         = 0;
                float[] nearestPt = new float[3];
                long    refId     = FindNearestPolyInTile(tile, con.Pos[p + 0], con.Pos[p + 1], con.Pos[p + 2], ext[0], ext[1],
                                                          ext[2], ref nearestPt);
                if (refId <= 0)
                {
                    continue;
                }
                if (((nearestPt[0] - con.Pos[p + 0]) * (nearestPt[0] - con.Pos[p + 0])) +
                    ((nearestPt[2] - con.Pos[p + 2]) * (nearestPt[2] - con.Pos[p + 2])) > (con.Rad * con.Rad))
                {
                    continue;
                }

                int v = poly.Verts[0] * 3;
                Array.Copy(nearestPt, 0, tile.Verts, v, 3);

                long idx = AllocLink(tile);
                if (idx != NullLink)
                {
                    Link link = tile.Links[idx];
                    link.Ref       = refId;
                    link.Edge      = 0;
                    link.Side      = 0xff;
                    link.BMin      = link.BMax = 0;
                    link.Next      = poly.FirstLink;
                    poly.FirstLink = idx;
                }

                long tidx = AllocLink(tile);
                if (tidx != NullLink)
                {
                    int  landPolyIdx = (int)DecodePolyIdPoly(refId);
                    Poly landPoly    = tile.Polys[landPolyIdx];
                    Link link        = tile.Links[tidx];
                    link.Ref           = baseId | con.Poly;
                    link.Edge          = 0xff;
                    link.Side          = 0xff;
                    link.BMin          = link.BMax = 0;
                    link.Next          = landPoly.FirstLink;
                    landPoly.FirstLink = tidx;
                }
            }
        }
Ejemplo n.º 8
0
        private int FindConnectingPolys(float vax, float vay, float vaz, float vbx, float vby, float vbz, MeshTile tile,
                                        int side, ref long[] con, ref float[] conarea, int maxcon)
        {
            if (tile == null)
            {
                return(0);
            }
            float[] amin = new float[2], amax = new float[2];
            Helper.CalcSlabEndPoints(vax, vay, vaz, vbx, vby, vbz, ref amin, ref amax, side);
            float apos = Helper.GetSlabCoord(vax, vay, vaz, side);

            float[] bmin   = new float[2], bmax = new float[2];
            int     m      = NavMeshBuilder.ExtLink | side;
            int     n      = 0;
            long    baseId = GetPolyRefBase(tile);

            for (int i = 0; i < tile.Header.PolyCount; i++)
            {
                Poly poly = tile.Polys[i];
                int  nv   = poly.VertCount;
                for (int j = 0; j < nv; j++)
                {
                    if (poly.Neis[j] != m)
                    {
                        continue;
                    }

                    int   vc   = poly.Verts[j] * 3;
                    int   vd   = poly.Verts[(j + 1) % nv] * 3;
                    float bpos = Helper.GetSlabCoord(tile.Verts[vc + 0], tile.Verts[vc + 1], tile.Verts[vc + 2], side);

                    if (Math.Abs(apos - bpos) > 0.01f)
                    {
                        continue;
                    }

                    Helper.CalcSlabEndPoints(tile.Verts[vc + 0], tile.Verts[vc + 1], tile.Verts[vc + 2], tile.Verts[vd + 0], tile.Verts[vd + 1], tile.Verts[vd + 2], ref bmin, ref bmax, side);

                    if (!Helper.OverlapSlabs(amin, amax, bmin, bmax, 0.01f, tile.Header.WalkableClimb))
                    {
                        continue;
                    }

                    if (n < maxcon)
                    {
                        conarea[n * 2 + 0] = Math.Max(amin[0], bmin[0]);
                        conarea[n * 2 + 1] = Math.Min(amax[0], bmax[0]);
                        con[n]             = baseId | i;
                        n++;
                    }
                    break;
                }
            }
            return(n);
        }
Ejemplo n.º 9
0
        public Status GetOffMeshConnectionPolyEndPoints(long prevRef, long polyRef, ref float[] startPos, ref float[] endPos)
        {
            long salt, it, ip;

            if (polyRef == 0)
            {
                return(Status.Failure);
            }

            DecodePolyId(polyRef, out salt, out it, out ip);
            if (it >= _maxTiles)
            {
                return(Status.Failure | Status.InvalidParam);
            }
            if (_tiles[it].Salt != salt || _tiles[it].Header == null)
            {
                return(Status.Failure | Status.InvalidParam);
            }
            MeshTile tile = _tiles[it];

            if (ip >= _tiles[it].Header.PolyCount)
            {
                return(Status.Failure | Status.InvalidParam);
            }

            Poly poly = tile.Polys[ip];

            if (poly.Type != NavMeshBuilder.PolyTypeOffMeshConnection)
            {
                return(Status.Failure);
            }

            int idx0 = 0, idx1 = 1;

            for (long i = poly.FirstLink; i != NullLink; i = tile.Links[i].Next)
            {
                if (tile.Links[i].Edge == 0)
                {
                    if (tile.Links[i].Ref != prevRef)
                    {
                        idx0 = 1;
                        idx1 = 0;
                    }
                    break;
                }
            }

            Array.Copy(tile.Verts, poly.Verts[idx0] * 3, startPos, 0, 3);
            Array.Copy(tile.Verts, poly.Verts[idx1] * 3, endPos, 0, 3);

            return(Status.Success);
        }
Ejemplo n.º 10
0
        public Status StoreTileState(MeshTile tile, out TileState tileState)
        {
            tileState            = new TileState();
            tileState.Magic      = Helper.NavMeshMagic;
            tileState.Version    = Helper.NavMeshVersion;
            tileState.Ref        = GetTileRef(tile);
            tileState.PolyStates = new PolyState[tile.Header.PolyCount];
            for (int i = 0; i < tile.Header.PolyCount; i++)
            {
                Poly p = tile.Polys[i];
                tileState.PolyStates[i]       = new PolyState();
                tileState.PolyStates[i].Flags = p.Flags;
                tileState.PolyStates[i].Area  = p.Area;
            }

            return(Status.Success);
        }
Ejemplo n.º 11
0
        private void ConnectIntLinks(MeshTile tile)
        {
            if (tile == null)
            {
                return;
            }
            long baseId = GetPolyRefBase(tile);

            for (int i = 0; i < tile.Header.PolyCount; i++)
            {
                Poly poly = tile.Polys[i];
                poly.FirstLink = NullLink;

                if (poly.Type == NavMeshBuilder.PolyTypeOffMeshConnection)
                {
                    continue;
                }

                for (int j = poly.VertCount - 1; j >= 0; j--)
                {
                    if (poly.Neis[j] == 0 || (poly.Neis[j] & NavMeshBuilder.ExtLink) != 0)
                    {
                        continue;
                    }

                    long idx = AllocLink(tile);
                    if (idx != NullLink)
                    {
                        Link link = tile.Links[idx];
                        link.Ref  = baseId | (poly.Neis[j] - 1);
                        link.Edge = (short)j;
                        link.Side = 0xff;
                        link.BMin = link.BMax = 0;

                        link.Next      = poly.FirstLink;
                        poly.FirstLink = idx;
                    }
                }
            }
        }
Ejemplo n.º 12
0
        private void UnconnectExtLinks(ref MeshTile tile, ref MeshTile target)
        {
            if (tile == null || target == null)
            {
                return;
            }

            long targetNum = DecodePolyIdTile(GetTileRef(target));

            for (int i = 0; i < tile.Header.PolyCount; i++)
            {
                Poly poly = tile.Polys[i];
                long j    = poly.FirstLink;
                long pj   = NullLink;
                while (j != NullLink)
                {
                    if (tile.Links[j].Side != 0xff && DecodePolyIdTile(tile.Links[j].Ref) == targetNum)
                    {
                        long nj = tile.Links[j].Next;
                        if (pj == NullLink)
                        {
                            poly.FirstLink = nj;
                        }
                        else
                        {
                            tile.Links[pj].Next = nj;
                        }
                        FreeLink(ref tile, j);
                        j = nj;
                    }
                    else
                    {
                        pj = j;
                        j  = tile.Links[j].Next;
                    }
                }
            }
        }
Ejemplo n.º 13
0
        public OffMeshConnection GetOffMeshConnectionByRef(long refId)
        {
            long salt, it, ip;

            if (refId == 0)
            {
                return(null);
            }

            DecodePolyId(refId, out salt, out it, out ip);
            if (it >= _maxTiles)
            {
                return(null);
            }
            if (_tiles[it].Salt != salt || _tiles[it].Header == null)
            {
                return(null);
            }
            MeshTile tile = _tiles[it];

            if (ip >= _tiles[it].Header.PolyCount)
            {
                return(null);
            }

            Poly poly = tile.Polys[ip];

            if (poly.Type != NavMeshBuilder.PolyTypeOffMeshConnection)
            {
                return(null);
            }

            long idx = ip - tile.Header.OffMeshBase;

            return(tile.OffMeshCons[idx]);
        }
Ejemplo n.º 14
0
        public NavMeshBuilder(NavMeshCreateParams param)
        {
            if (param.Nvp > VertsPerPoly)
            {
                throw new ArgumentException("Too many Verts per Poly for NavMeshBuilder");
            }
            if (param.VertCount >= 0xffff)
            {
                throw new ArgumentException("Too many total verticies for NavMeshBuilder");
            }
            if (param.VertCount == 0 || param.Verts == null)
            {
                throw new ArgumentException("No vertices, cannot generate nav mesh");
            }
            if (param.PolyCount == 0 || param.Polys == null)
            {
                throw new ArgumentException("No Polygons, cannot generate nav mesh");
            }

            int nvp = param.Nvp;

            short[] offMeshConClass       = new short[0];
            int     storedOffMeshConCount = 0;
            int     offMeshConLinkCount   = 0;

            if (param.OffMeshConCount > 0)
            {
                offMeshConClass = new short[param.OffMeshConCount * 2];

                float hmin = float.MaxValue;
                float hmax = float.MinValue;

                if (param.DetailVerts != null && param.DetailVertsCount > 0)
                {
                    for (int i = 0; i < param.DetailVertsCount; i++)
                    {
                        int h = i * 3 + 1;
                        hmin = Math.Min(hmin, param.DetailVerts[h]);
                        hmax = Math.Max(hmax, param.DetailVerts[h]);
                    }
                }
                else
                {
                    for (int i = 0; i < param.VertCount; i++)
                    {
                        int   iv = i * 3;
                        float h  = param.BMin[1] + param.Verts[iv + 1] * param.Ch;
                        hmin = Math.Min(hmin, h);
                        hmax = Math.Max(hmax, h);
                    }
                }
                hmin -= param.WalkableClimb;
                hmax += param.WalkableClimb;
                float[] bmin = new float[3], bmax = new float[3];
                Array.Copy(param.BMin, bmin, 3);
                Array.Copy(param.BMax, bmax, 3);

                bmin[1] = hmin;
                bmax[1] = hmax;

                for (int i = 0; i < param.OffMeshConCount; i++)
                {
                    int p0 = (i * 2 + 0) * 3;
                    int p1 = (i * 2 + 1) * 3;
                    offMeshConClass[i * 2 + 0] = ClassifyOffMeshPoint(param.OffMeshConVerts[p0 + 0],
                                                                      param.OffMeshConVerts[p0 + 1],
                                                                      param.OffMeshConVerts[p0 + 2], bmin, bmax);
                    offMeshConClass[i * 2 + 1] = ClassifyOffMeshPoint(param.OffMeshConVerts[p1 + 0],
                                                                      param.OffMeshConVerts[p1 + 1],
                                                                      param.OffMeshConVerts[p1 + 2], bmin, bmax);

                    if (offMeshConClass[i * 2 + 0] == 0xff)
                    {
                        if (param.OffMeshConVerts[p0 + 1] < bmin[1] || param.OffMeshConVerts[p0 + 1] > bmax[1])
                        {
                            offMeshConClass[i * 2 + 0] = 0;
                        }
                    }

                    if (offMeshConClass[i * 2 + 0] == 0xff)
                    {
                        offMeshConLinkCount++;
                    }
                    if (offMeshConClass[i * 2 + 1] == 0xff)
                    {
                        offMeshConLinkCount++;
                    }

                    if (offMeshConClass[i * 2 + 0] == 0xff)
                    {
                        storedOffMeshConCount++;
                    }
                }
            }

            int totPolyCount = param.PolyCount + storedOffMeshConCount;
            int totVertCount = param.VertCount + storedOffMeshConCount * 2;

            int edgeCount   = 0;
            int portalCount = 0;

            for (int i = 0; i < param.PolyCount; i++)
            {
                int p = i * 2 * nvp;
                for (int j = 0; j < nvp; j++)
                {
                    if (param.Polys[p + j] == PolyMesh.MeshNullIdx)
                    {
                        break;
                    }
                    edgeCount++;

                    if ((param.Polys[p + nvp + j] & 0x8000) != 0)
                    {
                        int dir = param.Polys[p + nvp + j] & 0xf;
                        if (dir != 0xf)
                        {
                            portalCount++;
                        }
                    }
                }
            }

            int maxLinkCount = edgeCount + portalCount * 2 + offMeshConLinkCount * 2;

            int uniqueDetailVertCount = 0;
            int detailTryCount        = 0;

            if (param.DetailMeshes != null)
            {
                detailTryCount = param.DetailTriCount;
                for (int i = 0; i < param.PolyCount; i++)
                {
                    int p   = i * nvp * 2;
                    int ndv = (int)param.DetailMeshes[i * 4 + 1];
                    int nv  = 0;
                    for (int j = 0; j < nvp; j++)
                    {
                        if (param.Polys[p + j] == PolyMesh.MeshNullIdx)
                        {
                            break;
                        }
                        nv++;
                    }
                    ndv -= nv;
                    uniqueDetailVertCount += ndv;
                }
            }
            else
            {
                uniqueDetailVertCount = 0;
                detailTryCount        = 0;
                for (int i = 0; i < param.PolyCount; i++)
                {
                    int p  = i * nvp * 2;
                    int nv = 0;
                    for (int j = 0; j < nvp; j++)
                    {
                        if (param.Polys[p + j] == PolyMesh.MeshNullIdx)
                        {
                            break;
                        }
                        nv++;
                    }
                    detailTryCount += nv - 2;
                }
            }

            // Initialize the header and all nav data.
            Header = new MeshHeader
            {
                Magic           = Helper.NavMeshMagic,
                Version         = Helper.NavMeshVersion,
                X               = param.TileX,
                Y               = param.TileY,
                Layer           = param.TileLayer,
                UserId          = param.UserId,
                PolyCount       = totPolyCount,
                VertCount       = totVertCount,
                MaxLinkCount    = maxLinkCount,
                DetailMeshCount = param.PolyCount,
                DetailVertCount = uniqueDetailVertCount,
                DetailTriCount  = detailTryCount,
                BVQuantFactor   = 1.0f / param.Cs,
                OffMeshBase     = param.PolyCount,
                WalkableHeight  = param.WalkableHeight,
                WalkableRadius  = param.WalkableRadius,
                WalkableClimb   = param.WalkableClimb,
                OffMeshConCount = storedOffMeshConCount,
                BVNodeCount     = param.BuildBvTree ? param.PolyCount * 2 : 0,
                BMin            = new float[3],
                BMax            = new float[3]
            };
            Array.Copy(param.BMin, Header.BMin, 3);
            Array.Copy(param.BMax, Header.BMax, 3);

            NavVerts = new float[totVertCount * 3];
            NavPolys = new Poly[totPolyCount];
            for (int i = 0; i < totPolyCount; i++)
            {
                NavPolys[i] = new Poly();
            }
            NavLinks = new Link[maxLinkCount];
            for (int i = 0; i < maxLinkCount; i++)
            {
                NavLinks[i] = new Link();
            }
            NavDMeshes = new PolyDetail[param.PolyCount];
            for (int i = 0; i < param.PolyCount; i++)
            {
                NavDMeshes[i] = new PolyDetail();
            }
            NavDVerts = new float[3 * uniqueDetailVertCount];
            NavDTris  = new short[4 * detailTryCount];
            NavBvTree = param.BuildBvTree ? new BVNode[param.PolyCount * 2] : new BVNode[0];
            if (param.BuildBvTree)
            {
                for (int i = 0; i < param.PolyCount * 2; i++)
                {
                    NavBvTree[i] = new BVNode();
                }
            }
            OffMeshCons = new OffMeshConnection[storedOffMeshConCount];
            for (int i = 0; i < storedOffMeshConCount; i++)
            {
                OffMeshCons[i] = new OffMeshConnection();
            }


            int offMeshVertsBase = param.VertCount;
            int offMeshPolyBase  = param.PolyCount;

            // store vertices
            // Mesh
            for (int i = 0; i < param.VertCount; i++)
            {
                int iv = i * 3;
                int v  = i * 3;
                NavVerts[v + 0] = param.BMin[0] + param.Verts[iv + 0] * param.Cs;
                NavVerts[v + 1] = param.BMin[1] + param.Verts[iv + 1] * param.Ch;
                NavVerts[v + 2] = param.BMin[2] + param.Verts[iv + 2] * param.Cs;
            }
            // off-link
            int n = 0;

            for (int i = 0; i < param.OffMeshConCount; i++)
            {
                if (offMeshConClass[i * 2 + 0] == 0xff)
                {
                    int linkv = i * 2 * 3;
                    int v     = (offMeshVertsBase + n * 2) * 3;
                    Array.Copy(param.OffMeshConVerts, linkv, NavVerts, v, 3);
                    Array.Copy(param.OffMeshConVerts, linkv + 3, NavVerts, v + 3, 3);
                    n++;
                }
            }

            // store polygons
            // mesh
            int src = 0;

            for (int i = 0; i < param.PolyCount; i++)
            {
                Poly p = NavPolys[i];
                p.VertCount = 0;
                p.Flags     = param.PolyFlags[i];
                p.Area      = param.PolyAreas[i];
                p.Type      = PolyTypeGround;
                for (int j = 0; j < nvp; j++)
                {
                    if (param.Polys[src + j] == PolyMesh.MeshNullIdx)
                    {
                        break;
                    }
                    p.Verts[j] = param.Polys[src + j];
                    if ((param.Polys[src + nvp + j] & 0x8000) != 0)
                    {
                        int dir = param.Polys[src + nvp + j] & 0xf;
                        if (dir == 0xf)
                        {
                            p.Neis[j] = 0;
                        }
                        else if (dir == 0)
                        {
                            p.Neis[j] = ExtLink | 4;
                        }
                        else if (dir == 1)
                        {
                            p.Neis[j] = ExtLink | 2;
                        }
                        else if (dir == 2)
                        {
                            p.Neis[j] = ExtLink | 0;
                        }
                        else if (dir == 3)
                        {
                            p.Neis[j] = ExtLink | 6;
                        }
                    }
                    else
                    {
                        p.Neis[j] = param.Polys[src + nvp + j] + 1;
                    }
                    p.VertCount++;
                }
                src += nvp * 2;
            }
            // off mesh
            n = 0;
            for (int i = 0; i < param.OffMeshConCount; i++)
            {
                if (offMeshConClass[i * 2 + 0] == 0xff)
                {
                    Poly p = NavPolys[offMeshPolyBase + n];
                    p.VertCount = 2;
                    p.Verts[0]  = (offMeshVertsBase + n * 2 + 0);
                    p.Verts[1]  = (offMeshVertsBase + n * 2 + 1);
                    p.Flags     = param.OffMeshConFlags[i];
                    p.Area      = (short)param.OffMeshConAreas[i];
                    p.Type      = PolyTypeOffMeshConnection;
                    n++;
                }
            }

            // Store detail meshes and verts
            if (param.DetailMeshes != null)
            {
                int vbase = 0;
                for (int i = 0; i < param.PolyCount; i++)
                {
                    PolyDetail dtl = NavDMeshes[i];
                    int        vb  = (int)param.DetailMeshes[i * 4 + 0];
                    int        ndv = (int)param.DetailMeshes[i * 4 + 1];
                    int        nv  = NavPolys[i].VertCount;
                    dtl.VertBase  = vbase;
                    dtl.VertCount = (short)(ndv - nv);
                    dtl.TriBase   = param.DetailMeshes[i * 4 + 2];
                    dtl.TriCount  = (short)param.DetailMeshes[i * 4 + 3];
                    if (ndv - nv > 0)
                    {
                        Array.Copy(param.DetailVerts, (vb + nv) * 3, NavDVerts, vbase * 3, (ndv - nv) * 3);
                        vbase += (short)(ndv - nv);
                    }
                }
                Array.Copy(param.DetailTris, NavDTris, param.DetailTriCount * 4);
            }
            else
            {
                // Create dummy detail mesh
                int tbase = 0;
                for (int i = 0; i < param.PolyCount; i++)
                {
                    PolyDetail dtl = NavDMeshes[i];
                    int        nv  = NavPolys[i].VertCount;
                    dtl.VertBase  = 0;
                    dtl.VertCount = 0;
                    dtl.TriBase   = tbase;
                    dtl.TriCount  = (short)(nv - 2);
                    for (int j = 2; j < nv; j++)
                    {
                        int t = tbase * 4;
                        NavDTris[t + 0] = 0;
                        NavDTris[t + 1] = (short)(j - 1);
                        NavDTris[t + 2] = (short)j;
                        NavDTris[t + 3] = (1 << 2);
                        if (j == 2)
                        {
                            NavDTris[t + 3] |= (1 << 0);
                        }
                        if (j == nv - 1)
                        {
                            NavDTris[t + 3] |= (1 << 4);
                        }
                        tbase++;
                    }
                }
            }

            // Store and create BVTree
            if (param.BuildBvTree)
            {
                CreateBVTree(param.Verts, param.VertCount, param.Polys, param.PolyCount, nvp, param.Cs, param.Ch, param.PolyCount * 2);
            }

            // store off-mesh connections
            n = 0;
            for (int i = 0; i < param.OffMeshConCount; i++)
            {
                if (offMeshConClass[i * 2 + 0] == 0xff)
                {
                    OffMeshConnection con = OffMeshCons[n];
                    con.Poly = offMeshPolyBase + n;
                    int endPts = i * 2 * 3;
                    Array.Copy(param.OffMeshConVerts, endPts, con.Pos, 0, 3);
                    Array.Copy(param.OffMeshConVerts, endPts + 3, con.Pos, 3, 3);
                    con.Rad   = param.OffMeshConRad[i];
                    con.Flags = param.OffMeshConDir[i] > 0 ? OffMeshConBiDir : (short)0;
                    con.Side  = offMeshConClass[i * 2 + 1];
                    if (param.OffMeshConUserId != null)
                    {
                        con.UserId = param.OffMeshConUserId[i];
                    }
                    n++;
                }
            }
        }
Ejemplo n.º 15
0
 public bool PassFilter(long refId, MeshTile tile, Poly poly)
 {
     return((poly.Flags & IncludeFlags) != 0 && (poly.Flags & ExcludeFlags) == 0);
 }
Ejemplo n.º 16
0
        private void ConnectExtOffMeshLinks(ref MeshTile tile, ref MeshTile target, int side)
        {
            if (tile == null)
            {
                return;
            }

            short oppositeSide = (side == -1) ? (short)0xff : (short)Helper.OppositeTile(side);

            for (int i = 0; i < target.Header.OffMeshConCount; i++)
            {
                OffMeshConnection targetCon = target.OffMeshCons[i];
                if (targetCon.Side != oppositeSide)
                {
                    continue;
                }

                Poly targetPoly = target.Polys[targetCon.Poly];
                if (targetPoly.FirstLink == NullLink)
                {
                    continue;
                }

                float[] ext = { targetCon.Rad, target.Header.WalkableClimb, targetCon.Rad };

                int     p         = 3;
                float[] nearestPt = new float[3];
                long    refId     = FindNearestPolyInTile(tile, targetCon.Pos[p + 0], targetCon.Pos[p + 1], targetCon.Pos[p + 2],
                                                          ext[0], ext[1], ext[2], ref nearestPt);
                if (refId <= 0)
                {
                    continue;
                }

                if (((nearestPt[0] - targetCon.Pos[p + 0]) * (nearestPt[0] - targetCon.Pos[p + 0])) + ((nearestPt[2] - targetCon.Pos[p + 2]) * (nearestPt[2] - targetCon.Pos[p + 2])) > (targetCon.Rad * targetCon.Rad))
                {
                    continue;
                }

                int v = targetPoly.Verts[1] * 3;
                Array.Copy(nearestPt, 0, target.Verts, v, 3);

                long idx = AllocLink(target);
                if (idx != NullLink)
                {
                    Link link = target.Links[idx];
                    link.Ref  = refId;
                    link.Edge = 1;
                    link.Side = oppositeSide;
                    link.BMin = link.BMax = 0;

                    link.Next            = targetPoly.FirstLink;
                    targetPoly.FirstLink = idx;
                }

                if ((targetCon.Flags & NavMeshBuilder.OffMeshConBiDir) != 0)
                {
                    long tidx = AllocLink(tile);
                    if (tidx != NullLink)
                    {
                        int  landPolyIdx = (int)DecodePolyIdPoly(refId);
                        Poly landPoly    = tile.Polys[landPolyIdx];
                        Link link        = tile.Links[tidx];
                        link.Ref           = GetPolyRefBase(target) | (targetCon.Poly);
                        link.Edge          = 0xff;
                        link.Side          = side == -1 ? (short)0xff : (short)side;
                        link.BMin          = link.BMax = 0;
                        link.Next          = landPoly.FirstLink;
                        landPoly.FirstLink = tidx;
                    }
                }
            }
        }
Ejemplo n.º 17
0
        private int QueryPolygonsInTile(MeshTile tile, float qminx, float qminy, float qminz, float qmaxx, float qmaxy,
                                        float qmaxz, ref long[] polys, int maxPolys)
        {
            if (tile.BVTree != null)
            {
                int     node  = 0;
                int     end   = tile.Header.BVNodeCount;
                float[] tbmin = tile.Header.BMin;
                float[] tbmax = tile.Header.BMax;
                float   qfac  = tile.Header.BVQuantFactor;

                int[] bmin = new int[3], bmax = new int[3];

                float minx = Math.Min(tbmax[0], Math.Max(qminx, tbmin[0])) - tbmin[0];
                float miny = Math.Min(tbmax[1], Math.Max(qminy, tbmin[1])) - tbmin[1];
                float minz = Math.Min(tbmax[2], Math.Max(qminz, tbmin[2])) - tbmin[2];
                float maxx = Math.Min(tbmax[0], Math.Max(qmaxx, tbmin[0])) - tbmin[0];
                float maxy = Math.Min(tbmax[1], Math.Max(qmaxy, tbmin[1])) - tbmin[1];
                float maxz = Math.Min(tbmax[2], Math.Max(qmaxz, tbmin[2])) - tbmin[2];

                bmin[0] = (int)(qfac * minx) & 0xfffe;
                bmin[1] = (int)(qfac * miny) & 0xfffe;
                bmin[2] = (int)(qfac * minz) & 0xfffe;
                bmax[0] = (int)(qfac * maxx + 1) | 1;
                bmax[1] = (int)(qfac * maxy + 1) | 1;
                bmax[2] = (int)(qfac * maxz + 1) | 1;

                long baseId = GetPolyRefBase(tile);
                int  n      = 0;
                while (node < end)
                {
                    bool overlap    = Helper.OverlapQuantBounds(bmin, bmax, tile.BVTree[node].BMin, tile.BVTree[node].BMax);
                    bool isLeafNode = tile.BVTree[node].I >= 0;

                    if (isLeafNode && overlap)
                    {
                        if (n < maxPolys)
                        {
                            polys[n++] = baseId | tile.BVTree[node].I;
                        }
                    }

                    if (overlap || isLeafNode)
                    {
                        node++;
                    }
                    else
                    {
                        int escapeIndex = -tile.BVTree[node].I;
                        node += escapeIndex;
                    }
                }
                return(n);
            }
            else
            {
                float[] bmin   = new float[3], bmax = new float[3];
                int     n      = 0;
                long    baseId = GetPolyRefBase(tile);
                for (int i = 0; i < tile.Header.PolyCount; i++)
                {
                    Poly p = tile.Polys[i];
                    if (p.Type == NavMeshBuilder.PolyTypeOffMeshConnection)
                    {
                        continue;
                    }

                    int v = p.Verts[0 * 3];
                    Array.Copy(tile.Verts, v, bmin, 0, 3);
                    Array.Copy(tile.Verts, v, bmax, 0, 3);
                    for (int j = 1; j < p.VertCount; j++)
                    {
                        v = p.Verts[j] * 3;
                        Helper.VMin(ref bmin, tile.Verts[v + 0], tile.Verts[v + 1], tile.Verts[v + 2]);
                        Helper.VMax(ref bmax, tile.Verts[v + 0], tile.Verts[v + 1], tile.Verts[v + 2]);
                    }
                    if (Helper.OverlapBounds(qminx, qminy, qminz, qmaxx, qmaxy, qmaxz, bmin[0], bmin[1], bmin[2],
                                             bmax[0], bmax[1], bmax[2]))
                    {
                        if (n < maxPolys)
                        {
                            polys[n++] = baseId | i;
                        }
                    }
                }
                return(n);
            }
        }
Ejemplo n.º 18
0
        private void ClosestPointOnPolyInTile(MeshTile tile, long ip, float posx, float posy, float posz, ref float[] closestPt)
        {
            Poly poly = tile.Polys[ip];

            if (poly.Type == NavMeshBuilder.PolyTypeOffMeshConnection)
            {
                int   v0 = poly.Verts[0] * 3;
                int   v1 = poly.Verts[1] * 3;
                float d0 = Helper.VDist(posx, posy, posz, tile.Verts[v0 + 0], tile.Verts[v0 + 1], tile.Verts[v0 + 2]);
                float d1 = Helper.VDist(posx, posy, posz, tile.Verts[v1 + 0], tile.Verts[v1 + 1], tile.Verts[v1 + 2]);
                float u  = d0 / (d0 + d1);
                Helper.VLerp(ref closestPt, tile.Verts[v0 + 0], tile.Verts[v0 + 1], tile.Verts[v0 + 2], tile.Verts[v1 + 0], tile.Verts[v1 + 1], tile.Verts[v1 + 2], u);
                return;
            }

            PolyDetail pd = tile.DetailMeshes[ip];

            float[] verts = new float[NavMeshBuilder.VertsPerPoly * 3];
            float[] edged = new float[NavMeshBuilder.VertsPerPoly];
            float[] edget = new float[NavMeshBuilder.VertsPerPoly];
            int     nv    = poly.VertCount;

            for (int i = 0; i < nv; i++)
            {
                Array.Copy(tile.Verts, poly.Verts[i] * 3, verts, i * 3, 3);
            }

            closestPt[0] = posx;
            closestPt[1] = posy;
            closestPt[2] = posz;

            if (!Helper.DistancePtPolyEdgesSqr(posx, posy, posz, verts, nv, ref edged, ref edget))
            {
                float dmin = float.MaxValue;
                int   imin = -1;
                for (int i = 0; i < nv; i++)
                {
                    if (edged[i] < dmin)
                    {
                        dmin = edged[i];
                        imin = i;
                    }
                }
                int va = imin * 3;
                int vb = ((imin + 1) % nv) * 3;
                Helper.VLerp(ref closestPt, verts[va + 0], verts[va + 1], verts[va + 2], verts[vb + 0], verts[vb + 1], verts[vb + 2], edget[imin]);
            }

            for (int j = 0; j < pd.TriCount; j++)
            {
                int     t = (int)(pd.TriBase + j) * 4;
                float[] v = new float[9];
                for (int k = 0; k < 3; k++)
                {
                    if (tile.DetailTris[t + k] < poly.VertCount)
                    {
                        Array.Copy(tile.Verts, poly.Verts[tile.DetailTris[t + k]] * 3, v, k * 3, 3);
                        //v[k] = tile.Verts[poly.Verts[tile.DetailTris[t + k]]*3];
                    }
                    else
                    {
                        Array.Copy(tile.DetailVerts, (pd.VertBase + (tile.DetailTris[t + k] - poly.VertCount)) * 3, v, k * 3, 3);
                        //v[k] = tile.DetailVerts[(pd.VertBase + (tile.DetailTris[t + k] - poly.VertCount))*3];
                    }
                }
                float h = 0;
                if (Helper.ClosestHeightPointTriangle(posx, posy, posz, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], ref h))
                {
                    closestPt[1] = h;
                    break;
                }
            }
        }
Ejemplo n.º 19
0
        private void ConnectExtLinks(ref MeshTile tile, ref MeshTile target, int side)
        {
            if (tile == null)
            {
                return;
            }

            for (int i = 0; i < tile.Header.PolyCount; i++)
            {
                Poly poly = tile.Polys[i];

                int nv = poly.VertCount;
                for (int j = 0; j < nv; j++)
                {
                    if ((poly.Neis[j] & NavMeshBuilder.ExtLink) == 0)
                    {
                        continue;
                    }

                    int dir = (int)(poly.Neis[j] & 0xff);
                    if (side != -1 && dir != side)
                    {
                        continue;
                    }

                    int     va   = poly.Verts[j] * 3;
                    int     vb   = poly.Verts[(j + 1) % nv] * 3;
                    long[]  nei  = new long[4];
                    float[] neia = new float[4 * 2];
                    int     nnei = FindConnectingPolys(tile.Verts[va + 0], tile.Verts[va + 1], tile.Verts[va + 2],
                                                       tile.Verts[vb + 0], tile.Verts[vb + 1], tile.Verts[vb + 2], target,
                                                       Helper.OppositeTile(dir), ref nei, ref neia, 4);
                    for (int k = 0; k < nnei; k++)
                    {
                        long idx = AllocLink(tile);
                        if (idx != NullLink)
                        {
                            Link link = tile.Links[idx];
                            link.Ref  = nei[k];
                            link.Edge = (short)j;
                            link.Side = (short)dir;

                            link.Next      = poly.FirstLink;
                            poly.FirstLink = idx;

                            if (dir == 0 || dir == 4)
                            {
                                float tmin = (neia[k * 2 + 0] - tile.Verts[va + 2]) /
                                             (tile.Verts[vb + 2] - tile.Verts[va + 2]);
                                float tmax = (neia[k * 2 + 1] - tile.Verts[va + 2]) /
                                             (tile.Verts[vb + 2] - tile.Verts[va + 2]);
                                if (tmin > tmax)
                                {
                                    float temp = tmin;
                                    tmin = tmax;
                                    tmax = temp;
                                }
                                link.BMin = (short)(Math.Min(1.0f, Math.Max(tmin, 0.0f)) * 255.0f);
                                link.BMax = (short)(Math.Min(1.0f, Math.Max(tmax, 0.0f)) * 255.0f);
                            }
                            else if (dir == 2 || dir == 6)
                            {
                                float tmin = (neia[k * 2 + 0] - tile.Verts[va + 0]) /
                                             (tile.Verts[vb + 0] - tile.Verts[va + 0]);
                                float tmax = (neia[k * 2 + 1] - tile.Verts[va + 0]) /
                                             (tile.Verts[vb + 0] - tile.Verts[va + 0]);
                                if (tmin > tmax)
                                {
                                    float temp = tmin;
                                    tmin = tmax;
                                    tmax = temp;
                                }
                                link.BMin = (short)(Math.Min(1.0f, Math.Max(tmin, 0.0f)) * 255.0f);
                                link.BMax = (short)(Math.Min(1.0f, Math.Max(tmax, 0.0f)) * 255.0f);
                            }
                        }
                    }
                }
            }
        }