예제 #1
0
        /** Generate connections between the two tiles.
         * The tiles must be adjacent.
         */
        protected void ConnectTiles(NavmeshTile tile1, NavmeshTile tile2)
        {
            if (tile1 == null)
            {
                return;                           //throw new System.ArgumentNullException ("tile1");
            }
            if (tile2 == null)
            {
                return;                           //throw new System.ArgumentNullException ("tile2");
            }
            if (tile1.nodes == null)
            {
                throw new System.ArgumentException("tile1 does not contain any nodes");
            }
            if (tile2.nodes == null)
            {
                throw new System.ArgumentException("tile2 does not contain any nodes");
            }

            int t1x = Mathf.Clamp(tile2.x, tile1.x, tile1.x + tile1.w - 1);
            int t2x = Mathf.Clamp(tile1.x, tile2.x, tile2.x + tile2.w - 1);
            int t1z = Mathf.Clamp(tile2.z, tile1.z, tile1.z + tile1.d - 1);
            int t2z = Mathf.Clamp(tile1.z, tile2.z, tile2.z + tile2.d - 1);

            int coord, altcoord;
            int t1coord, t2coord;

            float tcs;

            if (t1x == t2x)
            {
                coord    = 2;
                altcoord = 0;
                t1coord  = t1z;
                t2coord  = t2z;
                tcs      = tileSizeZ * cellSize;
            }
            else if (t1z == t2z)
            {
                coord    = 0;
                altcoord = 2;
                t1coord  = t1x;
                t2coord  = t2x;
                tcs      = tileSizeX * cellSize;
            }
            else
            {
                throw new System.ArgumentException("Tiles are not adjacent (neither x or z coordinates match)");
            }

            if (Math.Abs(t1coord - t2coord) != 1)
            {
                EB.Debug.Log("{0} {1} {2} {3}\n{5} {6} {7} {8}\n{9} {10} {11} {12}", tile1.x, tile1.z, tile1.w, tile1.d,
                             tile2.x, tile2.z, tile2.w, tile2.d, t1x, t1z, t2x, t2z);
                throw new System.ArgumentException("Tiles are not adjacent (tile coordinates must differ by exactly 1. Got '" + t1coord + "' and '" + t2coord + "')");
            }

            //Midpoint between the two tiles
            int midpoint = (int)Math.Round((Math.Max(t1coord, t2coord) * tcs + forcedBounds.min[coord]) * Int3.Precision);

#if ASTARDEBUG
            Vector3 v1 = new Vector3(-100, 0, -100);
            Vector3 v2 = new Vector3(100, 0, 100);
            v1[coord] = midpoint * Int3.PrecisionFactor;
            v2[coord] = midpoint * Int3.PrecisionFactor;

            Debug.DrawLine(v1, v2, Color.magenta);
#endif

#if BNICKSON_UPDATED
            // different triangle link height tolerance based on whether we're linking tiles generated for random levels or not
            float heightToleranceSquared = generateFromInputMesh ? GameUtils.Square(heightZoneLinkTolerance) : GameUtils.Square(walkableClimb);
#endif
            TriangleMeshNode[] nodes1 = tile1.nodes;
            TriangleMeshNode[] nodes2 = tile2.nodes;

            //Find adjacent nodes on the border between the tiles
            for (int i = 0; i < nodes1.Length; i++)
            {
                TriangleMeshNode node = nodes1[i];
                int av = node.GetVertexCount();

                for (int a = 0; a < av; a++)
                {
                    Int3 ap1 = node.GetVertex(a);
                    Int3 ap2 = node.GetVertex((a + 1) % av);
#if BNICKSON_UPDATED
                    if (ap1[coord] == midpoint && ap2[coord] == midpoint)                     // this could be given a little bit of tolerance
#else
                    if (Math.Abs(ap1[coord] - midpoint) < 2 && Math.Abs(ap2[coord] - midpoint) < 2)
#endif
                    {
#if ASTARDEBUG
                        Debug.DrawLine((Vector3)ap1, (Vector3)ap2, Color.red);
#endif

                        int minalt = Math.Min(ap1[altcoord], ap2[altcoord]);
                        int maxalt = Math.Max(ap1[altcoord], ap2[altcoord]);

                        //Degenerate edge
                        if (minalt == maxalt)
                        {
                            continue;
                        }

                        for (int j = 0; j < nodes2.Length; j++)
                        {
                            TriangleMeshNode other = nodes2[j];
                            int bv = other.GetVertexCount();
                            for (int b = 0; b < bv; b++)
                            {
                                Int3 bp1 = other.GetVertex(b);
                                Int3 bp2 = other.GetVertex((b + 1) % av);
#if BNICKSON_UPDATED
                                if (bp1[coord] == midpoint && bp2[coord] == midpoint)                                 // this could be given a little bit of tolerance
#else
                                if (Math.Abs(bp1[coord] - midpoint) < 2 && Math.Abs(bp2[coord] - midpoint) < 2)
#endif
                                {
                                    int minalt2 = Math.Min(bp1[altcoord], bp2[altcoord]);
                                    int maxalt2 = Math.Max(bp1[altcoord], bp2[altcoord]);

                                    //Degenerate edge
                                    if (minalt2 == maxalt2)
                                    {
                                        continue;
                                    }

                                    if (maxalt > minalt2 && minalt < maxalt2)
                                    {
                                        //Adjacent

                                        //Test shortest distance between the segments (first test if they are equal since that is much faster)
                                        if ((ap1 == bp1 && ap2 == bp2) || (ap1 == bp2 && ap2 == bp1) ||
#if BNICKSON_UPDATED
                                            VectorMath.SqrDistanceSegmentSegment((Vector3)ap1, (Vector3)ap2, (Vector3)bp1, (Vector3)bp2) < heightToleranceSquared)                                             // different height tolerances based on generating from input mesh or not
#else
                                            VectorMath.SqrDistanceSegmentSegment((Vector3)ap1, (Vector3)ap2, (Vector3)bp1, (Vector3)bp2) < walkableClimb * walkableClimb)
#endif
                                        {
                                            uint cost = (uint)(node.position - other.position).costMagnitude;

                                            node.AddConnection(other, cost);
                                            other.AddConnection(node, cost);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }