Пример #1
0
        /// <summary>
        /// Find the closest polygon possible in the tile under certain constraints.
        /// </summary>
        /// <param name="tile">Current tile</param>
        /// <param name="center">Center starting point</param>
        /// <param name="extents">Range of search</param>
        /// <param name="nearestPt">Resulting nearest point</param>
        /// <returns>Polygon Reference which contains nearest point</returns>
        public PolyId FindNearestPolyInTile(MeshTile tile, Vector3 center, Vector3 extents, ref Vector3 nearestPt)
        {
            BBox3 bounds;

            bounds.Min = center - extents;
            bounds.Max = center + extents;

            //Get nearby polygons from proximity grid
            List <PolyId> polys     = new List <PolyId>(128);
            int           polyCount = QueryPolygonsInTile(tile, bounds, polys);

            //Find nearest polygon amongst the nearby polygons
            PolyId nearest            = PolyId.Null;
            float  nearestDistanceSqr = float.MaxValue;

            //Iterate throuh all the polygons
            for (int i = 0; i < polyCount; i++)
            {
                PolyId  reference     = polys[i];
                Vector3 closestPtPoly = new Vector3();
                tile.ClosestPointOnPoly(reference.DecodePolyIndex(polyBits), center, ref closestPtPoly);
                float d = (center - closestPtPoly).LengthSquared();
                if (d < nearestDistanceSqr)
                {
                    nearestPt          = closestPtPoly;
                    nearestDistanceSqr = d;
                    nearest            = reference;
                }
            }

            return(nearest);
        }
Пример #2
0
        /// <summary>
        /// Connect Off-Mesh links between polygons from two different tiles.
        /// </summary>
        /// <param name="tile">Current Tile</param>
        /// <param name="target">Target Tile</param>
        /// <param name="side">Polygon edge</param>
        public void ConnectExtOffMeshLinks(ref MeshTile tile, ref MeshTile target, BoundarySide side)
        {
            if (tile == null)
            {
                return;
            }

            //Connect off-mesh links, specifically links which land from target tile to this tile
            BoundarySide oppositeSide = side.GetOpposite();

            //Iterate through all the off-mesh connections of target tile
            for (int i = 0; i < target.Header.OffMeshConCount; i++)
            {
                OffMeshConnection targetCon = target.OffMeshConnections[i];
                if (targetCon.Side != oppositeSide)
                {
                    continue;
                }

                Poly targetPoly = target.Polys[targetCon.Poly];

                //Skip off-mesh connections which start location could not be connected at all
                if (!IsLinkAllocated(targetPoly.FirstLink))
                {
                    continue;
                }

                Vector3 extents = new Vector3(targetCon.Radius, target.Header.WalkableClimb, targetCon.Radius);

                //Find polygon to connect to
                Vector3 p         = targetCon.Pos1;
                Vector3 nearestPt = new Vector3();
                PolyId  reference = FindNearestPolyInTile(tile, p, extents, ref nearestPt);
                if (reference == PolyId.Null)
                {
                    continue;
                }

                //Further checks
                if ((nearestPt.X - p.X) * (nearestPt.X - p.X) + (nearestPt.Z - p.Z) * (nearestPt.Z - p.Z) >
                    (targetCon.Radius * targetCon.Radius))
                {
                    continue;
                }

                //Make sure the location is on the current mesh
                target.Verts[targetPoly.Verts[1]] = nearestPt;

                //Link off-mesh connection to target poly
                int idx = AllocLink(target);
                if (IsLinkAllocated(idx))
                {
                    target.Links[idx].Reference = reference;
                    target.Links[idx].Edge      = i;
                    target.Links[idx].Side      = oppositeSide;
                    target.Links[idx].BMin      = target.Links[idx].BMax = 0;

                    //add to linked list
                    target.Links[idx].Next    = target.Polys[i].FirstLink;
                    target.Polys[i].FirstLink = idx;
                }

                //link target poly to off-mesh connection
                if ((targetCon.Flags & OffMeshConnectionFlags.Bidirectional) != 0)
                {
                    int tidx = AllocLink(tile);
                    if (IsLinkAllocated(tidx))
                    {
                        int    landPolyIdx = reference.DecodePolyIndex(polyBits);
                        PolyId id;
                        id = GetPolyRefBase(target);
                        PolyId.SetPolyIndex(ref id, targetCon.Poly, out id);
                        tile.Links[tidx].Reference = id;
                        tile.Links[tidx].Edge      = 0xff;
                        tile.Links[tidx].Side      = side;
                        tile.Links[tidx].BMin      = tile.Links[tidx].BMax = 0;

                        //add to linked list
                        tile.Links[tidx].Next             = tile.Polys[landPolyIdx].FirstLink;
                        tile.Polys[landPolyIdx].FirstLink = tidx;
                    }
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Begin creating off-mesh links between the tile polygons.
        /// </summary>
        /// <param name="tile">Current Tile</param>
        public void BaseOffMeshLinks(ref MeshTile tile)
        {
            if (tile == null)
            {
                return;
            }

            PolyId polyBase = GetPolyRefBase(tile);

            //Base off-mesh connection start points
            for (int i = 0; i < tile.Header.OffMeshConCount; i++)
            {
                int con  = i;
                int poly = tile.OffMeshConnections[con].Poly;

                Vector3 extents = new Vector3(tile.OffMeshConnections[con].Radius, tile.Header.WalkableClimb, tile.OffMeshConnections[con].Radius);

                //Find polygon to connect to
                Vector3 p         = tile.OffMeshConnections[con].Pos0;
                Vector3 nearestPt = new Vector3();
                PolyId  reference = FindNearestPolyInTile(tile, p, extents, ref nearestPt);
                if (reference == PolyId.Null)
                {
                    continue;
                }

                //Do extra checks
                if ((nearestPt.X - p.X) * (nearestPt.X - p.X) + (nearestPt.Z - p.Z) * (nearestPt.Z - p.Z) >
                    tile.OffMeshConnections[con].Radius * tile.OffMeshConnections[con].Radius)
                {
                    continue;
                }

                //Make sure location is on current mesh
                tile.Verts[tile.Polys[poly].Verts[0]] = nearestPt;

                //Link off-mesh connection to target poly
                int idx = AllocLink(tile);
                if (IsLinkAllocated(idx))
                {
                    //Initialize a new link
                    tile.Links[idx].Reference = reference;
                    tile.Links[idx].Edge      = 0;
                    tile.Links[idx].Side      = BoundarySide.Internal;
                    tile.Links[idx].BMin      = tile.Links[idx].BMax = 0;

                    //Add to polygon's links list
                    tile.Links[idx].Next       = tile.Polys[poly].FirstLink;
                    tile.Polys[poly].FirstLink = idx;
                }

                //Start end-point always conects back to off-mesh connection
                int tidx = AllocLink(tile);
                if (IsLinkAllocated(tidx))
                {
                    //Initialize a new link
                    int    landPolyIdx = reference.DecodePolyIndex(polyBits);
                    PolyId id;
                    PolyId.SetPolyIndex(ref polyBase, tile.OffMeshConnections[con].Poly, out id);
                    tile.Links[idx].Reference = id;
                    tile.Links[idx].Edge      = 0xff;
                    tile.Links[idx].Side      = BoundarySide.Internal;
                    tile.Links[idx].BMin      = tile.Links[idx].BMax = 0;

                    //Add to polygon's links list
                    tile.Links[idx].Next = tile.Polys[landPolyIdx].FirstLink;
                    tile.Polys[landPolyIdx].FirstLink = tidx;
                }
            }
        }