Exemplo n.º 1
0
        /// <summary>
        /// Insert a segment into the array
        /// </summary>
        /// <param name="ints">The array of segments</param>
        /// <param name="nints">The number of segments</param>
        /// <param name="maxInts">The maximium number of segments allowed</param>
        /// <param name="tmin">Parameter t minimum</param>
        /// <param name="tmax">Parameter t maximum</param>
        /// <param name="reference">Polygon reference</param>
        public void InsertInterval(SegInterval[] ints, ref int nints, int maxInts, int tmin, int tmax, PolyId reference)
        {
            if (nints + 1 > maxInts)
                return;

            //find insertion point
            int idx = 0;
            while (idx < nints)
            {
                if (tmax <= ints[idx].TMin)
                    break;
                idx++;
            }

            //move current results
            if (nints - idx > 0)
            {
                for (int i = 0; i < nints - idx; i++)
                    ints[idx + 1 + i] = ints[idx + i];
            }

            //store
            ints[idx].Reference = reference;
            ints[idx].TMin = tmin;
            ints[idx].TMax = tmax;
            nints++;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Collect all the edges from a polygon.
        /// </summary>
        /// <param name="reference">The polygon reference</param>
        /// <param name="segmentVerts">Segment vertices</param>
        /// <param name="segmentRefs">The polygon reference containing the segment</param>
        /// <param name="segmentCount">The number of segments stored</param>
        /// <param name="maxSegments">The maximum number of segments allowed</param>
        /// <returns>True, unless the polygon reference is invalid</returns>
        public bool GetPolyWallSegments(PolyId reference, Crowds.LocalBoundary.Segment[] segmentVerts, PolyId[] segmentRefs, ref int segmentCount, int maxSegments)
        {
            segmentCount = 0;

            MeshTile tile;
            Poly poly;
            if (nav.TryGetTileAndPolyByRef(reference, out tile, out poly) == false)
                return false;

            int n = 0;
            int MAX_INTERVAL = 16;
            SegInterval[] ints = new SegInterval[MAX_INTERVAL];
            int nints;

            bool storePortals = segmentRefs.Length != 0;

            for (int i = 0, j = poly.VertCount - 1; i < poly.VertCount; j = i++)
            {
                //skip non-solid edges
                nints = 0;
                if ((poly.Neis[j] & Link.External) != 0)
                {
                    //tile border
                    for (int k = poly.FirstLink; k != Link.Null; k = tile.Links[k].Next)
                    {
                        Link link = tile.Links[k];
                        if (link.Edge == j)
                        {
                            if (link.Reference != PolyId.Null)
                            {
                                MeshTile neiTile;
                                Poly neiPoly;
                                nav.TryGetTileAndPolyByRefUnsafe(link.Reference, out neiTile, out neiPoly);
                                InsertInterval(ints, ref nints, MAX_INTERVAL, link.BMin, link.BMax, link.Reference);
                            }
                        }
                    }
                }
                else
                {
                    //internal edge
                    PolyId neiRef = PolyId.Null;
                    if (poly.Neis[j] != 0)
                    {
                        int idx = poly.Neis[j] - 1;
                        PolyId id = nav.GetPolyRefBase(tile);
                        PolyId.SetPolyIndex(ref id, idx, out neiRef);
                    }

                    //if the edge leads to another polygon and portals are not stored, skip
                    if (neiRef != PolyId.Null && !storePortals)
                        continue;

                    if (n < maxSegments)
                    {
                        Vector3 vj = tile.Verts[poly.Verts[j]];
                        Vector3 vi = tile.Verts[poly.Verts[i]];
                        segmentVerts[n].Start = vj;
                        segmentVerts[n].End = vi;
                        segmentRefs[n] = neiRef;
                        n++; //could be n += 2, since segments have 2 vertices
                    }

                    continue;
                }

                //add sentinels
                InsertInterval(ints, ref nints, MAX_INTERVAL, -1, 0, PolyId.Null);
                InsertInterval(ints, ref nints, MAX_INTERVAL, 255, 256, PolyId.Null);

                //store segments
                Vector3 vj2 = tile.Verts[poly.Verts[j]];
                Vector3 vi2 = tile.Verts[poly.Verts[i]];
                for (int k = 1; k < nints; k++)
                {
                    //portal segment
                    if (storePortals && ints[k].Reference != PolyId.Null)
                    {
                        float tmin = ints[k].TMin / 255.0f;
                        float tmax = ints[k].TMax / 255.0f;
                        if (n < maxSegments)
                        {
                            Vector3.Lerp(ref vj2, ref vi2, tmin, out segmentVerts[n].Start);
                            Vector3.Lerp(ref vj2, ref vi2, tmax, out segmentVerts[n].End);
                            segmentRefs[n] = ints[k].Reference;
                            n++;
                        }
                    }

                    //wall segment
                    int imin = ints[k - 1].TMax;
                    int imax = ints[k].TMin;
                    if (imin != imax)
                    {
                        float tmin = imin / 255.0f;
                        float tmax = imax / 255.0f;
                        if (n < maxSegments)
                        {
                            Vector3.Lerp(ref vj2, ref vi2, tmin, out segmentVerts[n].Start);
                            Vector3.Lerp(ref vj2, ref vi2, tmax, out segmentVerts[n].End);
                            segmentRefs[n] = PolyId.Null;
                            n++;
                        }
                    }
                }
            }

            segmentCount = n;

            return true;
        }