예제 #1
0
        /** Rebuilds the tree using the specified nodes.
         * This is faster and gives better quality results compared to calling Insert with all nodes
         */
        public void RebuildFrom(NavMeshNode[] nodes)
        {
            Clear();

            if (nodes.Length == 0)
            {
                return;
            }

            // We will use approximately 2N tree nodes
            EnsureCapacity(Mathf.CeilToInt(nodes.Length * 2.1f));

            // This will store the order of the nodes while the tree is being built
            // It turns out that it is a lot faster to do this than to actually modify
            // the nodes and nodeBounds arrays (presumably since that involves shuffling
            // around 20 bytes of memory (sizeof(pointer) + sizeof(IntRect)) per node
            // instead of 4 bytes (sizeof(int)).
            // It also means we don't have to make a copy of the nodes array since
            // we do not modify it
            var permutation = new int[nodes.Length];

            for (int i = 0; i < nodes.Length; i++)
            {
                permutation[i] = i;
            }

            // Precalculate the bounds of the nodes in XZ space.
            // It turns out that calculating the bounds is a bottleneck and precalculating
            // the bounds makes it around 3 times faster to build a tree
            var nodeBounds = new IntRect[nodes.Length];

            for (int i = 0; i < nodes.Length; i++)
            {
                var node = nodes[i];
                var v0   = node.GetVertex(0);
                var v1   = node.GetVertex(1);
                var v2   = node.GetVertex(2);

                var r = new IntRect(v0.x, v0.z, v0.x, v0.z);
                r             = r.ExpandToContain(v1.x, v1.z);
                r             = r.ExpandToContain(v2.x, v2.z);
                nodeBounds[i] = r;
            }

            RebuildFromInternal(nodes, permutation, nodeBounds, 0, nodes.Length, false);
        }
예제 #2
0
        private static List <TileHandler.Cut> PrepareNavmeshCutsForCutting(List <NavmeshCut> navmeshCuts, GraphTransform transform, IntRect cutSpaceBounds, int perturbate, bool anyNavmeshAdds)
        {
            System.Random random = null;
            if (perturbate > 0)
            {
                random = new System.Random();
            }
            List <List <Vector3> > list = ListPool <List <Vector3> > .Claim();

            List <TileHandler.Cut> list2 = ListPool <TileHandler.Cut> .Claim();

            for (int i = 0; i < navmeshCuts.Count; i++)
            {
                Int2 @int = new Int2(0, 0);
                if (perturbate > 0)
                {
                    @int.x = random.Next() % 6 * perturbate - 3 * perturbate;
                    if (@int.x >= 0)
                    {
                        @int.x++;
                    }
                    @int.y = random.Next() % 6 * perturbate - 3 * perturbate;
                    if (@int.y >= 0)
                    {
                        @int.y++;
                    }
                }
                list.Clear();
                navmeshCuts[i].GetContour(list);
                int num = (int)(navmeshCuts[i].GetY(transform) * 1000f);
                for (int j = 0; j < list.Count; j++)
                {
                    List <Vector3> list3 = list[j];
                    if (list3.Count == 0)
                    {
                        Debug.LogError("A NavmeshCut component had a zero length contour. Ignoring that contour.");
                    }
                    else
                    {
                        List <IntPoint> list4 = ListPool <IntPoint> .Claim(list3.Count);

                        for (int k = 0; k < list3.Count; k++)
                        {
                            Int3 int2 = (Int3)transform.InverseTransform(list3[k]);
                            if (perturbate > 0)
                            {
                                int2.x += @int.x;
                                int2.z += @int.y;
                            }
                            list4.Add(new IntPoint((long)int2.x, (long)int2.z));
                        }
                        IntRect bounds = new IntRect((int)list4[0].X, (int)list4[0].Y, (int)list4[0].X, (int)list4[0].Y);
                        for (int l = 0; l < list4.Count; l++)
                        {
                            IntPoint intPoint = list4[l];
                            bounds = bounds.ExpandToContain((int)intPoint.X, (int)intPoint.Y);
                        }
                        TileHandler.Cut cut  = new TileHandler.Cut();
                        int             num2 = (int)(navmeshCuts[i].height * 0.5f * 1000f);
                        cut.boundsY       = new Int2(num - num2, num + num2);
                        cut.bounds        = bounds;
                        cut.isDual        = navmeshCuts[i].isDual;
                        cut.cutsAddedGeom = navmeshCuts[i].cutsAddedGeom;
                        cut.contour       = list4;
                        list2.Add(cut);
                    }
                }
            }
            ListPool <List <Vector3> > .Release(list);

            return(list2);
        }
예제 #3
0
        private TileHandler.CuttingResult CutPoly(Int3[] verts, int[] tris, Int3[] extraShape, GraphTransform graphTransform, IntRect tiles, TileHandler.CutMode mode = TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual, int perturbate = -1)
        {
            if (verts.Length == 0 || tris.Length == 0)
            {
                return(new TileHandler.CuttingResult
                {
                    verts = ArrayPool <Int3> .Claim(0),
                    tris = ArrayPool <int> .Claim(0)
                });
            }
            if (perturbate > 10)
            {
                Debug.LogError("Too many perturbations aborting.\nThis may cause a tile in the navmesh to become empty. Try to see see if any of your NavmeshCut or NavmeshAdd components use invalid custom meshes.");
                return(new TileHandler.CuttingResult
                {
                    verts = verts,
                    tris = tris
                });
            }
            List <IntPoint> list = null;

            if (extraShape == null && (mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0)
            {
                throw new Exception("extraShape is null and the CutMode specifies that it should be used. Cannot use null shape.");
            }
            Bounds         tileBoundsInGraphSpace = this.graph.GetTileBoundsInGraphSpace(tiles);
            Vector3        min             = tileBoundsInGraphSpace.min;
            GraphTransform graphTransform2 = graphTransform * Matrix4x4.TRS(min, Quaternion.identity, Vector3.one);
            Vector2        v = new Vector2(tileBoundsInGraphSpace.size.x, tileBoundsInGraphSpace.size.z);

            if ((mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0)
            {
                list = ListPool <IntPoint> .Claim(extraShape.Length);

                for (int i = 0; i < extraShape.Length; i++)
                {
                    Int3 @int = graphTransform2.InverseTransform(extraShape[i]);
                    list.Add(new IntPoint((long)@int.x, (long)@int.z));
                }
            }
            IntRect cutSpaceBounds = new IntRect(verts[0].x, verts[0].z, verts[0].x, verts[0].z);

            for (int j = 0; j < verts.Length; j++)
            {
                cutSpaceBounds = cutSpaceBounds.ExpandToContain(verts[j].x, verts[j].z);
            }
            List <NavmeshCut> list2;

            if (mode == TileHandler.CutMode.CutExtra)
            {
                list2 = ListPool <NavmeshCut> .Claim();
            }
            else
            {
                list2 = this.cuts.QueryRect <NavmeshCut>(tiles);
            }
            List <NavmeshAdd> list3 = this.cuts.QueryRect <NavmeshAdd>(tiles);
            List <int>        list4 = ListPool <int> .Claim();

            List <TileHandler.Cut> list5 = TileHandler.PrepareNavmeshCutsForCutting(list2, graphTransform2, cutSpaceBounds, perturbate, list3.Count > 0);
            List <Int3>            list6 = ListPool <Int3> .Claim(verts.Length * 2);

            List <int> list7 = ListPool <int> .Claim(tris.Length);

            if (list2.Count == 0 && list3.Count == 0 && (mode & ~(TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual)) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0)
            {
                TileHandler.CopyMesh(verts, tris, list6, list7);
            }
            else
            {
                List <IntPoint> list8 = ListPool <IntPoint> .Claim();

                Dictionary <TriangulationPoint, int> dictionary = new Dictionary <TriangulationPoint, int>();
                List <PolygonPoint> list9 = ListPool <PolygonPoint> .Claim();

                PolyTree polyTree = new PolyTree();
                List <List <IntPoint> > list10 = ListPool <List <IntPoint> > .Claim();

                Stack <Polygon> stack = StackPool <Polygon> .Claim();

                this.clipper.StrictlySimple  = (perturbate > -1);
                this.clipper.ReverseSolution = true;
                Int3[] array   = null;
                Int3[] clipOut = null;
                Int2   size    = default(Int2);
                if (list3.Count > 0)
                {
                    array   = new Int3[7];
                    clipOut = new Int3[7];
                    size    = new Int2(((Int3)v).x, ((Int3)v).y);
                }
                Int3[] array2 = null;
                for (int k = -1; k < list3.Count; k++)
                {
                    Int3[] array3;
                    int[]  array4;
                    if (k == -1)
                    {
                        array3 = verts;
                        array4 = tris;
                    }
                    else
                    {
                        list3[k].GetMesh(ref array2, out array4, graphTransform2);
                        array3 = array2;
                    }
                    for (int l = 0; l < array4.Length; l += 3)
                    {
                        Int3 int2 = array3[array4[l]];
                        Int3 int3 = array3[array4[l + 1]];
                        Int3 int4 = array3[array4[l + 2]];
                        if (VectorMath.IsColinearXZ(int2, int3, int4))
                        {
                            Debug.LogWarning("Skipping degenerate triangle.");
                        }
                        else
                        {
                            IntRect a = new IntRect(int2.x, int2.z, int2.x, int2.z);
                            a = a.ExpandToContain(int3.x, int3.z);
                            a = a.ExpandToContain(int4.x, int4.z);
                            int num  = Math.Min(int2.y, Math.Min(int3.y, int4.y));
                            int num2 = Math.Max(int2.y, Math.Max(int3.y, int4.y));
                            list4.Clear();
                            bool flag = false;
                            for (int m = 0; m < list5.Count; m++)
                            {
                                int x = list5[m].boundsY.x;
                                int y = list5[m].boundsY.y;
                                if (IntRect.Intersects(a, list5[m].bounds) && y >= num && x <= num2 && (list5[m].cutsAddedGeom || k == -1))
                                {
                                    Int3 int5 = int2;
                                    int5.y = x;
                                    Int3 int6 = int2;
                                    int6.y = y;
                                    list4.Add(m);
                                    flag |= list5[m].isDual;
                                }
                            }
                            if (list4.Count == 0 && (mode & TileHandler.CutMode.CutExtra) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0 && k == -1)
                            {
                                list7.Add(list6.Count);
                                list7.Add(list6.Count + 1);
                                list7.Add(list6.Count + 2);
                                list6.Add(int2);
                                list6.Add(int3);
                                list6.Add(int4);
                            }
                            else
                            {
                                list8.Clear();
                                if (k == -1)
                                {
                                    list8.Add(new IntPoint((long)int2.x, (long)int2.z));
                                    list8.Add(new IntPoint((long)int3.x, (long)int3.z));
                                    list8.Add(new IntPoint((long)int4.x, (long)int4.z));
                                }
                                else
                                {
                                    array[0] = int2;
                                    array[1] = int3;
                                    array[2] = int4;
                                    int num3 = this.ClipAgainstRectangle(array, clipOut, size);
                                    if (num3 == 0)
                                    {
                                        goto IL_9D3;
                                    }
                                    for (int n = 0; n < num3; n++)
                                    {
                                        list8.Add(new IntPoint((long)array[n].x, (long)array[n].z));
                                    }
                                }
                                dictionary.Clear();
                                for (int num4 = 0; num4 < 16; num4++)
                                {
                                    if ((mode >> (num4 & 31) & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0)
                                    {
                                        if (1 << num4 == 1)
                                        {
                                            this.CutAll(list8, list4, list5, polyTree);
                                        }
                                        else if (1 << num4 == 2)
                                        {
                                            if (!flag)
                                            {
                                                goto IL_9C4;
                                            }
                                            this.CutDual(list8, list4, list5, flag, list10, polyTree);
                                        }
                                        else if (1 << num4 == 4)
                                        {
                                            this.CutExtra(list8, list, polyTree);
                                        }
                                        for (int num5 = 0; num5 < polyTree.ChildCount; num5++)
                                        {
                                            PolyNode        polyNode = polyTree.Childs[num5];
                                            List <IntPoint> contour  = polyNode.Contour;
                                            List <PolyNode> childs   = polyNode.Childs;
                                            if (childs.Count == 0 && contour.Count == 3 && k == -1)
                                            {
                                                for (int num6 = 0; num6 < 3; num6++)
                                                {
                                                    Int3 int7 = new Int3((int)contour[num6].X, 0, (int)contour[num6].Y);
                                                    int7.y = TileHandler.SampleYCoordinateInTriangle(int2, int3, int4, int7);
                                                    list7.Add(list6.Count);
                                                    list6.Add(int7);
                                                }
                                            }
                                            else
                                            {
                                                Polygon polygon = null;
                                                int     num7    = -1;
                                                for (List <IntPoint> list11 = contour; list11 != null; list11 = ((num7 >= childs.Count) ? null : childs[num7].Contour))
                                                {
                                                    list9.Clear();
                                                    for (int num8 = 0; num8 < list11.Count; num8++)
                                                    {
                                                        PolygonPoint polygonPoint = new PolygonPoint((double)list11[num8].X, (double)list11[num8].Y);
                                                        list9.Add(polygonPoint);
                                                        Int3 int8 = new Int3((int)list11[num8].X, 0, (int)list11[num8].Y);
                                                        int8.y = TileHandler.SampleYCoordinateInTriangle(int2, int3, int4, int8);
                                                        dictionary[polygonPoint] = list6.Count;
                                                        list6.Add(int8);
                                                    }
                                                    Polygon polygon2;
                                                    if (stack.Count > 0)
                                                    {
                                                        polygon2 = stack.Pop();
                                                        polygon2.AddPoints(list9);
                                                    }
                                                    else
                                                    {
                                                        polygon2 = new Polygon(list9);
                                                    }
                                                    if (num7 == -1)
                                                    {
                                                        polygon = polygon2;
                                                    }
                                                    else
                                                    {
                                                        polygon.AddHole(polygon2);
                                                    }
                                                    num7++;
                                                }
                                                try
                                                {
                                                    P2T.Triangulate(polygon);
                                                }
                                                catch (PointOnEdgeException)
                                                {
                                                    Debug.LogWarning("PointOnEdgeException, perturbating vertices slightly.\nThis is usually fine. It happens sometimes because of rounding errors. Cutting will be retried a few more times.");
                                                    return(this.CutPoly(verts, tris, extraShape, graphTransform, tiles, mode, perturbate + 1));
                                                }
                                                try
                                                {
                                                    for (int num9 = 0; num9 < polygon.Triangles.Count; num9++)
                                                    {
                                                        DelaunayTriangle delaunayTriangle = polygon.Triangles[num9];
                                                        list7.Add(dictionary[delaunayTriangle.Points._0]);
                                                        list7.Add(dictionary[delaunayTriangle.Points._1]);
                                                        list7.Add(dictionary[delaunayTriangle.Points._2]);
                                                    }
                                                }
                                                catch (KeyNotFoundException)
                                                {
                                                    Debug.LogWarning("KeyNotFoundException, perturbating vertices slightly.\nThis is usually fine. It happens sometimes because of rounding errors. Cutting will be retried a few more times.");
                                                    return(this.CutPoly(verts, tris, extraShape, graphTransform, tiles, mode, perturbate + 1));
                                                }
                                                TileHandler.PoolPolygon(polygon, stack);
                                            }
                                        }
                                    }
                                    IL_9C4 :;
                                }
                            }
                        }
                        IL_9D3 :;
                    }
                }
                if (array2 != null)
                {
                    ArrayPool <Int3> .Release(ref array2, false);
                }
                StackPool <Polygon> .Release(stack);

                ListPool <List <IntPoint> > .Release(list10);

                ListPool <IntPoint> .Release(list8);

                ListPool <PolygonPoint> .Release(list9);
            }
            TileHandler.CuttingResult result = default(TileHandler.CuttingResult);
            Polygon.CompressMesh(list6, list7, out result.verts, out result.tris);
            for (int num10 = 0; num10 < list2.Count; num10++)
            {
                list2[num10].UsedForCut();
            }
            ListPool <Int3> .Release(list6);

            ListPool <int> .Release(list7);

            ListPool <int> .Release(list4);

            for (int num11 = 0; num11 < list5.Count; num11++)
            {
                ListPool <IntPoint> .Release(list5[num11].contour);
            }
            ListPool <TileHandler.Cut> .Release(list5);

            ListPool <NavmeshCut> .Release(list2);

            return(result);
        }
예제 #4
0
        // Token: 0x060005E2 RID: 1506 RVA: 0x000360CC File Offset: 0x000344CC
        private void CutPoly(Int3[] verts, int[] tris, ref Int3[] outVertsArr, ref int[] outTrisArr, out int outVCount, out int outTCount, Int3[] extraShape, Int3 cuttingOffset, Bounds realBounds, TileHandler.CutMode mode = (TileHandler.CutMode) 3, int perturbate = 0)
        {
            if (verts.Length == 0 || tris.Length == 0)
            {
                outVCount   = 0;
                outTCount   = 0;
                outTrisArr  = new int[0];
                outVertsArr = new Int3[0];
                return;
            }
            List <IntPoint> list = null;

            if (extraShape == null && (mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0)
            {
                throw new Exception("extraShape is null and the CutMode specifies that it should be used. Cannot use null shape.");
            }
            if ((mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0)
            {
                list = new List <IntPoint>(extraShape.Length);
                for (int i = 0; i < extraShape.Length; i++)
                {
                    list.Add(new IntPoint((long)(extraShape[i].x + cuttingOffset.x), (long)(extraShape[i].z + cuttingOffset.z)));
                }
            }
            List <IntPoint> list2 = new List <IntPoint>(5);
            Dictionary <TriangulationPoint, int> dictionary = new Dictionary <TriangulationPoint, int>();
            List <PolygonPoint> list3 = new List <PolygonPoint>();
            IntRect             b     = new IntRect(verts[0].x, verts[0].z, verts[0].x, verts[0].z);

            for (int j = 0; j < verts.Length; j++)
            {
                b = b.ExpandToContain(verts[j].x, verts[j].z);
            }
            List <Int3> list4 = ListPool <Int3> .Claim(verts.Length * 2);

            List <int> list5 = ListPool <int> .Claim(tris.Length);

            PolyTree polyTree             = new PolyTree();
            List <List <IntPoint> > list6 = new List <List <IntPoint> >();
            Stack <Polygon>         stack = new Stack <Polygon>();

            if (this.clipper == null)
            {
                this.clipper = new Clipper(0);
            }
            this.clipper.ReverseSolution = true;
            List <NavmeshCut> list7;

            if (mode == TileHandler.CutMode.CutExtra)
            {
                list7 = ListPool <NavmeshCut> .Claim();
            }
            else
            {
                list7 = NavmeshCut.GetAllInRange(realBounds);
            }
            List <int> list8 = ListPool <int> .Claim();

            List <IntRect> list9 = ListPool <IntRect> .Claim();

            List <Int2> list10 = ListPool <Int2> .Claim();

            List <List <IntPoint> > list11 = new List <List <IntPoint> >();
            List <bool>             list12 = ListPool <bool> .Claim();

            List <bool> list13 = ListPool <bool> .Claim();

            if (perturbate > 10)
            {
                Debug.LogError("Too many perturbations aborting : " + mode);
                Debug.Break();
                outVCount   = verts.Length;
                outTCount   = tris.Length;
                outTrisArr  = tris;
                outVertsArr = verts;
                return;
            }
            System.Random random = null;
            if (perturbate > 0)
            {
                random = new System.Random();
            }
            for (int k = 0; k < list7.Count; k++)
            {
                Bounds  bounds = list7[k].GetBounds();
                Int3    @int   = (Int3)bounds.min + cuttingOffset;
                Int3    int2   = (Int3)bounds.max + cuttingOffset;
                IntRect a      = new IntRect(@int.x, @int.z, int2.x, int2.z);
                if (IntRect.Intersects(a, b))
                {
                    Int2 int3 = new Int2(0, 0);
                    if (perturbate > 0)
                    {
                        int3.x = random.Next() % 6 * perturbate - 3 * perturbate;
                        if (int3.x >= 0)
                        {
                            int3.x++;
                        }
                        int3.y = random.Next() % 6 * perturbate - 3 * perturbate;
                        if (int3.y >= 0)
                        {
                            int3.y++;
                        }
                    }
                    int count = list11.Count;
                    list7[k].GetContour(list11);
                    for (int l = count; l < list11.Count; l++)
                    {
                        List <IntPoint> list14 = list11[l];
                        if (list14.Count == 0)
                        {
                            Debug.LogError("Zero Length Contour");
                            list9.Add(default(IntRect));
                            list10.Add(new Int2(0, 0));
                        }
                        else
                        {
                            IntRect item = new IntRect((int)list14[0].X + cuttingOffset.x, (int)list14[0].Y + cuttingOffset.y, (int)list14[0].X + cuttingOffset.x, (int)list14[0].Y + cuttingOffset.y);
                            for (int m = 0; m < list14.Count; m++)
                            {
                                IntPoint value = list14[m];
                                value.X += (long)cuttingOffset.x;
                                value.Y += (long)cuttingOffset.z;
                                if (perturbate > 0)
                                {
                                    value.X += (long)int3.x;
                                    value.Y += (long)int3.y;
                                }
                                list14[m] = value;
                                item      = item.ExpandToContain((int)value.X, (int)value.Y);
                            }
                            list10.Add(new Int2(@int.y, int2.y));
                            list9.Add(item);
                            list12.Add(list7[k].isDual);
                            list13.Add(list7[k].cutsAddedGeom);
                        }
                    }
                }
            }
            List <NavmeshAdd> allInRange = NavmeshAdd.GetAllInRange(realBounds);

            Int3[] array  = verts;
            int[]  array2 = tris;
            int    num    = -1;
            int    n      = -3;

            Int3[] array3 = null;
            Int3[] array4 = null;
            Int3   int4   = Int3.zero;

            if (allInRange.Count > 0)
            {
                array3 = new Int3[7];
                array4 = new Int3[7];
                int4   = (Int3)realBounds.extents;
            }
            for (;;)
            {
                n += 3;
                while (n >= array2.Length)
                {
                    num++;
                    n = 0;
                    if (num >= allInRange.Count)
                    {
                        array = null;
                        break;
                    }
                    if (array == verts)
                    {
                        array = null;
                    }
                    allInRange[num].GetMesh(cuttingOffset, ref array, out array2);
                }
                if (array == null)
                {
                    break;
                }
                Int3    int5 = array[array2[n]];
                Int3    int6 = array[array2[n + 1]];
                Int3    int7 = array[array2[n + 2]];
                IntRect a2   = new IntRect(int5.x, int5.z, int5.x, int5.z);
                a2 = a2.ExpandToContain(int6.x, int6.z);
                a2 = a2.ExpandToContain(int7.x, int7.z);
                int num2 = Math.Min(int5.y, Math.Min(int6.y, int7.y));
                int num3 = Math.Max(int5.y, Math.Max(int6.y, int7.y));
                list8.Clear();
                bool flag = false;
                for (int num4 = 0; num4 < list11.Count; num4++)
                {
                    int x = list10[num4].x;
                    int y = list10[num4].y;
                    if (IntRect.Intersects(a2, list9[num4]) && y >= num2 && x <= num3 && (list13[num4] || num == -1))
                    {
                        Int3 int8 = int5;
                        int8.y = x;
                        Int3 int9 = int5;
                        int9.y = y;
                        list8.Add(num4);
                        flag |= list12[num4];
                    }
                }
                if (list8.Count == 0 && (mode & TileHandler.CutMode.CutExtra) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0 && num == -1)
                {
                    list5.Add(list4.Count);
                    list5.Add(list4.Count + 1);
                    list5.Add(list4.Count + 2);
                    list4.Add(int5);
                    list4.Add(int6);
                    list4.Add(int7);
                }
                else
                {
                    list2.Clear();
                    if (num == -1)
                    {
                        list2.Add(new IntPoint((long)int5.x, (long)int5.z));
                        list2.Add(new IntPoint((long)int6.x, (long)int6.z));
                        list2.Add(new IntPoint((long)int7.x, (long)int7.z));
                    }
                    else
                    {
                        array3[0] = int5;
                        array3[1] = int6;
                        array3[2] = int7;
                        int num5 = Utility.ClipPolygon(array3, 3, array4, 1, 0, 0);
                        if (num5 == 0)
                        {
                            continue;
                        }
                        num5 = Utility.ClipPolygon(array4, num5, array3, -1, 2 * int4.x, 0);
                        if (num5 == 0)
                        {
                            continue;
                        }
                        num5 = Utility.ClipPolygon(array3, num5, array4, 1, 0, 2);
                        if (num5 == 0)
                        {
                            continue;
                        }
                        num5 = Utility.ClipPolygon(array4, num5, array3, -1, 2 * int4.z, 2);
                        if (num5 == 0)
                        {
                            continue;
                        }
                        for (int num6 = 0; num6 < num5; num6++)
                        {
                            list2.Add(new IntPoint((long)array3[num6].x, (long)array3[num6].z));
                        }
                    }
                    dictionary.Clear();
                    Int3 int10 = int6 - int5;
                    Int3 int11 = int7 - int5;
                    Int3 int12 = int10;
                    Int3 int13 = int11;
                    int12.y = 0;
                    int13.y = 0;
                    for (int num7 = 0; num7 < 16; num7++)
                    {
                        if ((mode >> (num7 & 31) & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0)
                        {
                            if (1 << num7 == 1)
                            {
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, PolyType.ptSubject);
                                for (int num8 = 0; num8 < list8.Count; num8++)
                                {
                                    this.clipper.AddPolygon(list11[list8[num8]], PolyType.ptClip);
                                }
                                polyTree.Clear();
                                this.clipper.Execute(ClipType.ctDifference, polyTree, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero);
                            }
                            else if (1 << num7 == 2)
                            {
                                if (!flag)
                                {
                                    goto IL_1161;
                                }
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, PolyType.ptSubject);
                                for (int num9 = 0; num9 < list8.Count; num9++)
                                {
                                    if (list12[list8[num9]])
                                    {
                                        this.clipper.AddPolygon(list11[list8[num9]], PolyType.ptClip);
                                    }
                                }
                                list6.Clear();
                                this.clipper.Execute(ClipType.ctIntersection, list6, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero);
                                this.clipper.Clear();
                                for (int num10 = 0; num10 < list6.Count; num10++)
                                {
                                    this.clipper.AddPolygon(list6[num10], (!Clipper.Orientation(list6[num10])) ? PolyType.ptSubject : PolyType.ptClip);
                                }
                                for (int num11 = 0; num11 < list8.Count; num11++)
                                {
                                    if (!list12[list8[num11]])
                                    {
                                        this.clipper.AddPolygon(list11[list8[num11]], PolyType.ptClip);
                                    }
                                }
                                polyTree.Clear();
                                this.clipper.Execute(ClipType.ctDifference, polyTree, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero);
                            }
                            else if (1 << num7 == 4)
                            {
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, PolyType.ptSubject);
                                this.clipper.AddPolygon(list, PolyType.ptClip);
                                polyTree.Clear();
                                this.clipper.Execute(ClipType.ctIntersection, polyTree, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero);
                            }
                            for (int num12 = 0; num12 < polyTree.ChildCount; num12++)
                            {
                                PolyNode        polyNode = polyTree.Childs[num12];
                                List <IntPoint> contour  = polyNode.Contour;
                                List <PolyNode> childs   = polyNode.Childs;
                                if (childs.Count == 0 && contour.Count == 3 && num == -1)
                                {
                                    for (int num13 = 0; num13 < contour.Count; num13++)
                                    {
                                        Int3   item2 = new Int3((int)contour[num13].X, 0, (int)contour[num13].Y);
                                        double num14 = (double)(int6.z - int7.z) * (double)(int5.x - int7.x) + (double)(int7.x - int6.x) * (double)(int5.z - int7.z);
                                        if (num14 == 0.0)
                                        {
                                            Debug.LogWarning("Degenerate triangle");
                                        }
                                        else
                                        {
                                            double num15 = ((double)(int6.z - int7.z) * (double)(item2.x - int7.x) + (double)(int7.x - int6.x) * (double)(item2.z - int7.z)) / num14;
                                            double num16 = ((double)(int7.z - int5.z) * (double)(item2.x - int7.x) + (double)(int5.x - int7.x) * (double)(item2.z - int7.z)) / num14;
                                            item2.y = (int)Math.Round(num15 * (double)int5.y + num16 * (double)int6.y + (1.0 - num15 - num16) * (double)int7.y);
                                            list5.Add(list4.Count);
                                            list4.Add(item2);
                                        }
                                    }
                                }
                                else
                                {
                                    Polygon polygon = null;
                                    int     num17   = -1;
                                    for (List <IntPoint> list15 = contour; list15 != null; list15 = ((num17 >= childs.Count) ? null : childs[num17].Contour))
                                    {
                                        list3.Clear();
                                        for (int num18 = 0; num18 < list15.Count; num18++)
                                        {
                                            PolygonPoint polygonPoint = new PolygonPoint((double)list15[num18].X, (double)list15[num18].Y);
                                            list3.Add(polygonPoint);
                                            Int3   item3 = new Int3((int)list15[num18].X, 0, (int)list15[num18].Y);
                                            double num19 = (double)(int6.z - int7.z) * (double)(int5.x - int7.x) + (double)(int7.x - int6.x) * (double)(int5.z - int7.z);
                                            if (num19 == 0.0)
                                            {
                                                Debug.LogWarning("Degenerate triangle");
                                            }
                                            else
                                            {
                                                double num20 = ((double)(int6.z - int7.z) * (double)(item3.x - int7.x) + (double)(int7.x - int6.x) * (double)(item3.z - int7.z)) / num19;
                                                double num21 = ((double)(int7.z - int5.z) * (double)(item3.x - int7.x) + (double)(int5.x - int7.x) * (double)(item3.z - int7.z)) / num19;
                                                item3.y = (int)Math.Round(num20 * (double)int5.y + num21 * (double)int6.y + (1.0 - num20 - num21) * (double)int7.y);
                                                dictionary[polygonPoint] = list4.Count;
                                                list4.Add(item3);
                                            }
                                        }
                                        Polygon polygon2;
                                        if (stack.Count > 0)
                                        {
                                            polygon2 = stack.Pop();
                                            polygon2.AddPoints(list3);
                                        }
                                        else
                                        {
                                            polygon2 = new Polygon(list3);
                                        }
                                        if (polygon == null)
                                        {
                                            polygon = polygon2;
                                        }
                                        else
                                        {
                                            polygon.AddHole(polygon2);
                                        }
                                        num17++;
                                    }
                                    try
                                    {
                                        P2T.Triangulate(polygon);
                                    }
                                    catch (PointOnEdgeException)
                                    {
                                        Debug.LogWarning(string.Concat(new object[]
                                        {
                                            "PointOnEdgeException, perturbating vertices slightly ( at ",
                                            num7,
                                            " in ",
                                            mode,
                                            ")"
                                        }));
                                        this.CutPoly(verts, tris, ref outVertsArr, ref outTrisArr, out outVCount, out outTCount, extraShape, cuttingOffset, realBounds, mode, perturbate + 1);
                                        return;
                                    }
                                    for (int num22 = 0; num22 < polygon.Triangles.Count; num22++)
                                    {
                                        DelaunayTriangle delaunayTriangle = polygon.Triangles[num22];
                                        list5.Add(dictionary[delaunayTriangle.Points._0]);
                                        list5.Add(dictionary[delaunayTriangle.Points._1]);
                                        list5.Add(dictionary[delaunayTriangle.Points._2]);
                                    }
                                    if (polygon.Holes != null)
                                    {
                                        for (int num23 = 0; num23 < polygon.Holes.Count; num23++)
                                        {
                                            polygon.Holes[num23].Points.Clear();
                                            polygon.Holes[num23].ClearTriangles();
                                            if (polygon.Holes[num23].Holes != null)
                                            {
                                                polygon.Holes[num23].Holes.Clear();
                                            }
                                            stack.Push(polygon.Holes[num23]);
                                        }
                                    }
                                    polygon.ClearTriangles();
                                    if (polygon.Holes != null)
                                    {
                                        polygon.Holes.Clear();
                                    }
                                    polygon.Points.Clear();
                                    stack.Push(polygon);
                                }
                            }
                        }
                        IL_1161 :;
                    }
                }
            }
            Dictionary <Int3, int> dictionary2 = this.cached_Int3_int_dict;

            dictionary2.Clear();
            if (this.cached_int_array.Length < list4.Count)
            {
                this.cached_int_array = new int[Math.Max(this.cached_int_array.Length * 2, list4.Count)];
            }
            int[] array5 = this.cached_int_array;
            int   num24  = 0;

            for (int num25 = 0; num25 < list4.Count; num25++)
            {
                int num26;
                if (!dictionary2.TryGetValue(list4[num25], out num26))
                {
                    dictionary2.Add(list4[num25], num24);
                    array5[num25] = num24;
                    list4[num24]  = list4[num25];
                    num24++;
                }
                else
                {
                    array5[num25] = num26;
                }
            }
            outTCount = list5.Count;
            if (outTrisArr == null || outTrisArr.Length < outTCount)
            {
                outTrisArr = new int[outTCount];
            }
            for (int num27 = 0; num27 < outTCount; num27++)
            {
                outTrisArr[num27] = array5[list5[num27]];
            }
            outVCount = num24;
            if (outVertsArr == null || outVertsArr.Length < outVCount)
            {
                outVertsArr = new Int3[outVCount];
            }
            for (int num28 = 0; num28 < outVCount; num28++)
            {
                outVertsArr[num28] = list4[num28];
            }
            for (int num29 = 0; num29 < list7.Count; num29++)
            {
                list7[num29].UsedForCut();
            }
            ListPool <Int3> .Release(list4);

            ListPool <int> .Release(list5);

            ListPool <int> .Release(list8);

            ListPool <Int2> .Release(list10);

            ListPool <bool> .Release(list12);

            ListPool <bool> .Release(list13);

            ListPool <IntRect> .Release(list9);

            ListPool <NavmeshCut> .Release(list7);
        }
예제 #5
0
        private static List <TileHandler.Cut> PrepareNavmeshCutsForCutting(List <NavmeshCut> navmeshCuts, Int3 cuttingOffset, IntRect bounds, int perturbate, bool anyNavmeshAdds)
        {
            System.Random random = null;
            if (perturbate > 0)
            {
                random = new System.Random();
            }
            List <List <IntPoint> > list = ListPool <List <IntPoint> > .Claim();

            List <TileHandler.Cut> list2 = ListPool <TileHandler.Cut> .Claim();

            for (int i = 0; i < navmeshCuts.Count; i++)
            {
                Bounds  bounds2 = navmeshCuts[i].GetBounds();
                Int3    @int    = (Int3)bounds2.min + cuttingOffset;
                Int3    int2    = (Int3)bounds2.max + cuttingOffset;
                IntRect a       = new IntRect(@int.x, @int.z, int2.x, int2.z);
                if (IntRect.Intersects(a, bounds) || anyNavmeshAdds)
                {
                    Int2 int3 = new Int2(0, 0);
                    if (perturbate > 0)
                    {
                        int3.x = random.Next() % 6 * perturbate - 3 * perturbate;
                        if (int3.x >= 0)
                        {
                            int3.x++;
                        }
                        int3.y = random.Next() % 6 * perturbate - 3 * perturbate;
                        if (int3.y >= 0)
                        {
                            int3.y++;
                        }
                    }
                    list.Clear();
                    navmeshCuts[i].GetContour(list);
                    for (int j = 0; j < list.Count; j++)
                    {
                        List <IntPoint> list3 = list[j];
                        if (list3.Count == 0)
                        {
                            Debug.LogError("Zero Length Contour");
                        }
                        else
                        {
                            IntRect bounds3 = new IntRect((int)list3[0].X + cuttingOffset.x, (int)list3[0].Y + cuttingOffset.z, (int)list3[0].X + cuttingOffset.x, (int)list3[0].Y + cuttingOffset.z);
                            for (int k = 0; k < list3.Count; k++)
                            {
                                IntPoint intPoint = list3[k];
                                intPoint.X += (long)cuttingOffset.x;
                                intPoint.Y += (long)cuttingOffset.z;
                                if (perturbate > 0)
                                {
                                    intPoint.X += (long)int3.x;
                                    intPoint.Y += (long)int3.y;
                                }
                                bounds3  = bounds3.ExpandToContain((int)intPoint.X, (int)intPoint.Y);
                                list3[k] = new IntPoint(intPoint.X, intPoint.Y);
                            }
                            list2.Add(new TileHandler.Cut
                            {
                                boundsY       = new Int2(@int.y, int2.y),
                                bounds        = bounds3,
                                isDual        = navmeshCuts[i].isDual,
                                cutsAddedGeom = navmeshCuts[i].cutsAddedGeom,
                                contour       = list3
                            });
                        }
                    }
                }
            }
            ListPool <List <IntPoint> > .Release(list);

            return(list2);
        }
예제 #6
0
        private void CutPoly(Int3[] verts, int[] tris, ref Int3[] outVertsArr, ref int[] outTrisArr, out int outVCount, out int outTCount, Int3[] extraShape, Int3 cuttingOffset, Bounds realBounds, TileHandler.CutMode mode = TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual, int perturbate = -1)
        {
            if (verts.Length == 0 || tris.Length == 0)
            {
                outVCount   = 0;
                outTCount   = 0;
                outTrisArr  = new int[0];
                outVertsArr = new Int3[0];
                return;
            }
            if (perturbate > 10)
            {
                Debug.LogError("Too many perturbations aborting.\nThis may cause a tile in the navmesh to become empty. Try to see see if any of your NavmeshCut or NavmeshAdd components use invalid custom meshes.");
                outVCount   = verts.Length;
                outTCount   = tris.Length;
                outTrisArr  = tris;
                outVertsArr = verts;
                return;
            }
            List <IntPoint> list = null;

            if (extraShape == null && (mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0)
            {
                throw new Exception("extraShape is null and the CutMode specifies that it should be used. Cannot use null shape.");
            }
            if ((mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0)
            {
                list = ListPool <IntPoint> .Claim(extraShape.Length);

                for (int i = 0; i < extraShape.Length; i++)
                {
                    list.Add(new IntPoint((long)(extraShape[i].x + cuttingOffset.x), (long)(extraShape[i].z + cuttingOffset.z)));
                }
            }
            IntRect bounds = new IntRect(verts[0].x, verts[0].z, verts[0].x, verts[0].z);

            for (int j = 0; j < verts.Length; j++)
            {
                bounds = bounds.ExpandToContain(verts[j].x, verts[j].z);
            }
            List <NavmeshCut> list2;

            if (mode == TileHandler.CutMode.CutExtra)
            {
                list2 = ListPool <NavmeshCut> .Claim();
            }
            else
            {
                list2 = NavmeshCut.GetAllInRange(realBounds);
            }
            List <NavmeshAdd> allInRange = NavmeshAdd.GetAllInRange(realBounds);
            List <int>        list3      = ListPool <int> .Claim();

            List <TileHandler.Cut> list4 = TileHandler.PrepareNavmeshCutsForCutting(list2, cuttingOffset, bounds, perturbate, allInRange.Count > 0);
            List <Int3>            list5 = ListPool <Int3> .Claim(verts.Length * 2);

            List <int> list6 = ListPool <int> .Claim(tris.Length);

            Int3[] array  = verts;
            int[]  array2 = tris;
            if (list2.Count == 0 && allInRange.Count == 0 && (mode & ~(TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual)) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0)
            {
                this.CopyMesh(array, array2, list5, list6);
            }
            else
            {
                List <IntPoint> list7 = ListPool <IntPoint> .Claim();

                Dictionary <TriangulationPoint, int> dictionary = new Dictionary <TriangulationPoint, int>();
                List <PolygonPoint> list8 = ListPool <PolygonPoint> .Claim();

                PolyTree polyTree = new PolyTree();
                List <List <IntPoint> > intermediateResult = new List <List <IntPoint> >();
                Stack <Polygon>         stack = new Stack <Polygon>();
                this.clipper.StrictlySimple  = (perturbate > -1);
                this.clipper.ReverseSolution = true;
                Int3[] array3  = null;
                Int3[] clipOut = null;
                Int2   @int    = default(Int2);
                if (allInRange.Count > 0)
                {
                    array3  = new Int3[7];
                    clipOut = new Int3[7];
                    @int    = new Int2(((Int3)realBounds.extents).x, ((Int3)realBounds.extents).z);
                }
                int num = -1;
                int k   = -3;
                for (;;)
                {
                    k += 3;
                    while (k >= array2.Length)
                    {
                        num++;
                        k = 0;
                        if (num >= allInRange.Count)
                        {
                            array = null;
                            break;
                        }
                        if (array == verts)
                        {
                            array = null;
                        }
                        allInRange[num].GetMesh(cuttingOffset, ref array, out array2);
                    }
                    if (array == null)
                    {
                        break;
                    }
                    Int3 int2 = array[array2[k]];
                    Int3 int3 = array[array2[k + 1]];
                    Int3 int4 = array[array2[k + 2]];
                    if (VectorMath.IsColinearXZ(int2, int3, int4))
                    {
                        Debug.LogWarning("Skipping degenerate triangle.");
                    }
                    else
                    {
                        IntRect a = new IntRect(int2.x, int2.z, int2.x, int2.z);
                        a = a.ExpandToContain(int3.x, int3.z);
                        a = a.ExpandToContain(int4.x, int4.z);
                        int num2 = Math.Min(int2.y, Math.Min(int3.y, int4.y));
                        int num3 = Math.Max(int2.y, Math.Max(int3.y, int4.y));
                        list3.Clear();
                        bool flag = false;
                        for (int l = 0; l < list4.Count; l++)
                        {
                            int x = list4[l].boundsY.x;
                            int y = list4[l].boundsY.y;
                            if (IntRect.Intersects(a, list4[l].bounds) && y >= num2 && x <= num3 && (list4[l].cutsAddedGeom || num == -1))
                            {
                                Int3 int5 = int2;
                                int5.y = x;
                                Int3 int6 = int2;
                                int6.y = y;
                                list3.Add(l);
                                flag |= list4[l].isDual;
                            }
                        }
                        if (list3.Count == 0 && (mode & TileHandler.CutMode.CutExtra) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0 && num == -1)
                        {
                            list6.Add(list5.Count);
                            list6.Add(list5.Count + 1);
                            list6.Add(list5.Count + 2);
                            list5.Add(int2);
                            list5.Add(int3);
                            list5.Add(int4);
                        }
                        else
                        {
                            list7.Clear();
                            if (num == -1)
                            {
                                list7.Add(new IntPoint((long)int2.x, (long)int2.z));
                                list7.Add(new IntPoint((long)int3.x, (long)int3.z));
                                list7.Add(new IntPoint((long)int4.x, (long)int4.z));
                            }
                            else
                            {
                                array3[0] = int2;
                                array3[1] = int3;
                                array3[2] = int4;
                                int num4 = this.ClipAgainstRectangle(array3, clipOut, new Int2(@int.x * 2, @int.y * 2));
                                if (num4 == 0)
                                {
                                    continue;
                                }
                                for (int m = 0; m < num4; m++)
                                {
                                    list7.Add(new IntPoint((long)array3[m].x, (long)array3[m].z));
                                }
                            }
                            dictionary.Clear();
                            for (int n = 0; n < 16; n++)
                            {
                                if ((mode >> (n & 31) & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0)
                                {
                                    if (1 << n == 1)
                                    {
                                        this.CutAll(list7, list3, list4, polyTree);
                                    }
                                    else if (1 << n == 2)
                                    {
                                        if (!flag)
                                        {
                                            goto IL_9A0;
                                        }
                                        this.CutDual(list7, list3, list4, flag, intermediateResult, polyTree);
                                    }
                                    else if (1 << n == 4)
                                    {
                                        this.CutExtra(list7, list, polyTree);
                                    }
                                    for (int num5 = 0; num5 < polyTree.ChildCount; num5++)
                                    {
                                        PolyNode        polyNode = polyTree.Childs[num5];
                                        List <IntPoint> contour  = polyNode.Contour;
                                        List <PolyNode> childs   = polyNode.Childs;
                                        if (childs.Count == 0 && contour.Count == 3 && num == -1)
                                        {
                                            for (int num6 = 0; num6 < 3; num6++)
                                            {
                                                Int3 int7 = new Int3((int)contour[num6].X, 0, (int)contour[num6].Y);
                                                int7.y = TileHandler.SampleYCoordinateInTriangle(int2, int3, int4, int7);
                                                list6.Add(list5.Count);
                                                list5.Add(int7);
                                            }
                                        }
                                        else
                                        {
                                            Polygon polygon = null;
                                            int     num7    = -1;
                                            for (List <IntPoint> list9 = contour; list9 != null; list9 = ((num7 >= childs.Count) ? null : childs[num7].Contour))
                                            {
                                                list8.Clear();
                                                for (int num8 = 0; num8 < list9.Count; num8++)
                                                {
                                                    PolygonPoint polygonPoint = new PolygonPoint((double)list9[num8].X, (double)list9[num8].Y);
                                                    list8.Add(polygonPoint);
                                                    Int3 int8 = new Int3((int)list9[num8].X, 0, (int)list9[num8].Y);
                                                    int8.y = TileHandler.SampleYCoordinateInTriangle(int2, int3, int4, int8);
                                                    dictionary[polygonPoint] = list5.Count;
                                                    list5.Add(int8);
                                                }
                                                Polygon polygon2;
                                                if (stack.Count > 0)
                                                {
                                                    polygon2 = stack.Pop();
                                                    polygon2.AddPoints(list8);
                                                }
                                                else
                                                {
                                                    polygon2 = new Polygon(list8);
                                                }
                                                if (num7 == -1)
                                                {
                                                    polygon = polygon2;
                                                }
                                                else
                                                {
                                                    polygon.AddHole(polygon2);
                                                }
                                                num7++;
                                            }
                                            try
                                            {
                                                P2T.Triangulate(polygon);
                                            }
                                            catch (PointOnEdgeException)
                                            {
                                                Debug.LogWarning("PointOnEdgeException, perturbating vertices slightly.\nThis is usually fine. It happens sometimes because of rounding errors. Cutting will be retried a few more times.");
                                                this.CutPoly(verts, tris, ref outVertsArr, ref outTrisArr, out outVCount, out outTCount, extraShape, cuttingOffset, realBounds, mode, perturbate + 1);
                                                return;
                                            }
                                            try
                                            {
                                                for (int num9 = 0; num9 < polygon.Triangles.Count; num9++)
                                                {
                                                    DelaunayTriangle delaunayTriangle = polygon.Triangles[num9];
                                                    list6.Add(dictionary[delaunayTriangle.Points._0]);
                                                    list6.Add(dictionary[delaunayTriangle.Points._1]);
                                                    list6.Add(dictionary[delaunayTriangle.Points._2]);
                                                }
                                            }
                                            catch (KeyNotFoundException)
                                            {
                                                Debug.LogWarning("KeyNotFoundException, perturbating vertices slightly.\nThis is usually fine. It happens sometimes because of rounding errors. Cutting will be retried a few more times.");
                                                this.CutPoly(verts, tris, ref outVertsArr, ref outTrisArr, out outVCount, out outTCount, extraShape, cuttingOffset, realBounds, mode, perturbate + 1);
                                                return;
                                            }
                                            TileHandler.PoolPolygon(polygon, stack);
                                        }
                                    }
                                }
                                IL_9A0 :;
                            }
                        }
                    }
                }
                ListPool <IntPoint> .Release(list7);

                ListPool <PolygonPoint> .Release(list8);
            }
            this.CompressMesh(list5, list6, ref outVertsArr, ref outTrisArr, out outVCount, out outTCount);
            for (int num10 = 0; num10 < list2.Count; num10++)
            {
                list2[num10].UsedForCut();
            }
            ListPool <Int3> .Release(list5);

            ListPool <int> .Release(list6);

            ListPool <int> .Release(list3);

            for (int num11 = 0; num11 < list4.Count; num11++)
            {
                ListPool <IntPoint> .Release(list4[num11].contour);
            }
            ListPool <TileHandler.Cut> .Release(list4);

            ListPool <NavmeshCut> .Release(list2);
        }
예제 #7
0
        private void CutPoly(ListView <NavmeshCut> InNavmeshCuts, VInt3[] verts, int[] tris, ref VInt3[] outVertsArr, ref int[] outTrisArr, out int outVCount, out int outTCount, VInt3[] extraShape, VInt3 cuttingOffset, Bounds realBounds, SGameTileHandler.CutMode mode = (SGameTileHandler.CutMode) 3, int perturbate = 0)
        {
            if (verts.Length == 0 || tris.Length == 0)
            {
                outVCount   = 0;
                outTCount   = 0;
                outTrisArr  = new int[0];
                outVertsArr = new VInt3[0];
                return;
            }
            List <IntPoint> list = null;

            if (extraShape == null && (mode & SGameTileHandler.CutMode.CutExtra) != (SGameTileHandler.CutMode) 0)
            {
                throw new Exception("extraShape is null and the CutMode specifies that it should be used. Cannot use null shape.");
            }
            if ((mode & SGameTileHandler.CutMode.CutExtra) != (SGameTileHandler.CutMode) 0)
            {
                list = new List <IntPoint>(extraShape.Length);
                for (int i = 0; i < extraShape.Length; i++)
                {
                    list.Add(new IntPoint((long)(extraShape[i].x + cuttingOffset.x), (long)(extraShape[i].z + cuttingOffset.z)));
                }
            }
            List <IntPoint> list2 = new List <IntPoint>(5);
            Dictionary <TriangulationPoint, int> dictionary = new Dictionary <TriangulationPoint, int>();
            List <PolygonPoint> list3 = new List <PolygonPoint>();
            IntRect             b     = new IntRect(verts[0].x, verts[0].z, verts[0].x, verts[0].z);

            for (int j = 0; j < verts.Length; j++)
            {
                b = b.ExpandToContain(verts[j].x, verts[j].z);
            }
            List <VInt3> list4 = ListPool <VInt3> .Claim(verts.Length * 2);

            List <int> list5 = ListPool <int> .Claim(tris.Length);

            PolyTree polyTree             = new PolyTree();
            List <List <IntPoint> > list6 = new List <List <IntPoint> >();
            Stack <Polygon>         stack = new Stack <Polygon>();

            if (this.clipper == null)
            {
                this.clipper = new Clipper(0);
            }
            this.clipper.set_ReverseSolution(true);
            this.clipper.set_StrictlySimple(true);
            ListView <NavmeshCut> listView;

            if (mode == SGameTileHandler.CutMode.CutExtra)
            {
                listView = new ListView <NavmeshCut>();
            }
            else
            {
                listView = new ListView <NavmeshCut>(InNavmeshCuts);
            }
            List <int> list7 = ListPool <int> .Claim();

            List <IntRect> list8 = ListPool <IntRect> .Claim();

            List <VInt2> list9 = ListPool <VInt2> .Claim();

            List <List <IntPoint> > list10 = new List <List <IntPoint> >();
            List <bool>             list11 = ListPool <bool> .Claim();

            List <bool> list12 = ListPool <bool> .Claim();

            if (perturbate > 10)
            {
                Debug.LogError("Too many perturbations aborting : " + mode);
                Debug.Break();
                outVCount   = verts.Length;
                outTCount   = tris.Length;
                outTrisArr  = tris;
                outVertsArr = verts;
                return;
            }
            Random random = null;

            if (perturbate > 0)
            {
                random = new Random();
            }
            for (int k = 0; k < listView.Count; k++)
            {
                Bounds  bounds = listView[k].GetBounds();
                VInt3   vInt   = (VInt3)bounds.min + cuttingOffset;
                VInt3   vInt2  = (VInt3)bounds.max + cuttingOffset;
                IntRect a      = new IntRect(vInt.x, vInt.z, vInt2.x, vInt2.z);
                if (IntRect.Intersects(a, b))
                {
                    VInt2 vInt3 = new VInt2(0, 0);
                    if (perturbate > 0)
                    {
                        vInt3.x = random.Next() % 6 * perturbate - 3 * perturbate;
                        if (vInt3.x >= 0)
                        {
                            vInt3.x++;
                        }
                        vInt3.y = random.Next() % 6 * perturbate - 3 * perturbate;
                        if (vInt3.y >= 0)
                        {
                            vInt3.y++;
                        }
                    }
                    int count = list10.get_Count();
                    listView[k].GetContour(list10);
                    for (int l = count; l < list10.get_Count(); l++)
                    {
                        List <IntPoint> list13 = list10.get_Item(l);
                        if (list13.get_Count() == 0)
                        {
                            Debug.LogError("Zero Length Contour");
                            list8.Add(default(IntRect));
                            list9.Add(new VInt2(0, 0));
                        }
                        else
                        {
                            IntRect intRect = new IntRect((int)list13.get_Item(0).X + cuttingOffset.x, (int)list13.get_Item(0).Y + cuttingOffset.y, (int)list13.get_Item(0).X + cuttingOffset.x, (int)list13.get_Item(0).Y + cuttingOffset.y);
                            for (int m = 0; m < list13.get_Count(); m++)
                            {
                                IntPoint intPoint = list13.get_Item(m);
                                intPoint.X += (long)cuttingOffset.x;
                                intPoint.Y += (long)cuttingOffset.z;
                                if (perturbate > 0)
                                {
                                    intPoint.X += (long)vInt3.x;
                                    intPoint.Y += (long)vInt3.y;
                                }
                                list13.set_Item(m, intPoint);
                                intRect = intRect.ExpandToContain((int)intPoint.X, (int)intPoint.Y);
                            }
                            list9.Add(new VInt2(vInt.y, vInt2.y));
                            list8.Add(intRect);
                            list11.Add(listView[k].isDual);
                            list12.Add(listView[k].cutsAddedGeom);
                        }
                    }
                }
            }
            ListView <NavmeshAdd> listView2 = new ListView <NavmeshAdd>();

            VInt3[] array  = verts;
            int[]   array2 = tris;
            int     num    = -1;
            int     n      = -3;

            VInt3[] array3 = null;
            VInt3[] array4 = null;
            VInt3   vInt4  = VInt3.zero;

            if (listView2.Count > 0)
            {
                array3 = new VInt3[7];
                array4 = new VInt3[7];
                vInt4  = (VInt3)realBounds.extents;
            }
            while (true)
            {
                n += 3;
                while (n >= array2.Length)
                {
                    num++;
                    n = 0;
                    if (num >= listView2.Count)
                    {
                        array = null;
                        break;
                    }
                    if (array == verts)
                    {
                        array = null;
                    }
                    listView2[num].GetMesh(cuttingOffset, ref array, out array2);
                }
                if (array == null)
                {
                    break;
                }
                VInt3   vInt5 = array[array2[n]];
                VInt3   vInt6 = array[array2[n + 1]];
                VInt3   vInt7 = array[array2[n + 2]];
                IntRect a2    = new IntRect(vInt5.x, vInt5.z, vInt5.x, vInt5.z);
                a2 = a2.ExpandToContain(vInt6.x, vInt6.z);
                a2 = a2.ExpandToContain(vInt7.x, vInt7.z);
                int num2 = Math.Min(vInt5.y, Math.Min(vInt6.y, vInt7.y));
                int num3 = Math.Max(vInt5.y, Math.Max(vInt6.y, vInt7.y));
                list7.Clear();
                bool flag = false;
                for (int num4 = 0; num4 < list10.get_Count(); num4++)
                {
                    int x = list9.get_Item(num4).x;
                    int y = list9.get_Item(num4).y;
                    if (IntRect.Intersects(a2, list8.get_Item(num4)) && y >= num2 && x <= num3 && (list12.get_Item(num4) || num == -1))
                    {
                        VInt3 vInt8 = vInt5;
                        vInt8.y = x;
                        VInt3 vInt9 = vInt5;
                        vInt9.y = y;
                        list7.Add(num4);
                        flag |= list11.get_Item(num4);
                    }
                }
                if (list7.get_Count() == 0 && (mode & SGameTileHandler.CutMode.CutExtra) == (SGameTileHandler.CutMode) 0 && (mode & SGameTileHandler.CutMode.CutAll) != (SGameTileHandler.CutMode) 0 && num == -1)
                {
                    list5.Add(list4.get_Count());
                    list5.Add(list4.get_Count() + 1);
                    list5.Add(list4.get_Count() + 2);
                    list4.Add(vInt5);
                    list4.Add(vInt6);
                    list4.Add(vInt7);
                }
                else
                {
                    list2.Clear();
                    if (num == -1)
                    {
                        list2.Add(new IntPoint((long)vInt5.x, (long)vInt5.z));
                        list2.Add(new IntPoint((long)vInt6.x, (long)vInt6.z));
                        list2.Add(new IntPoint((long)vInt7.x, (long)vInt7.z));
                    }
                    else
                    {
                        array3[0] = vInt5;
                        array3[1] = vInt6;
                        array3[2] = vInt7;
                        int num5 = Utility.ClipPolygon(array3, 3, array4, 1, 0, 0);
                        if (num5 == 0)
                        {
                            continue;
                        }
                        num5 = Utility.ClipPolygon(array4, num5, array3, -1, 2 * vInt4.x, 0);
                        if (num5 == 0)
                        {
                            continue;
                        }
                        num5 = Utility.ClipPolygon(array3, num5, array4, 1, 0, 2);
                        if (num5 == 0)
                        {
                            continue;
                        }
                        num5 = Utility.ClipPolygon(array4, num5, array3, -1, 2 * vInt4.z, 2);
                        if (num5 == 0)
                        {
                            continue;
                        }
                        for (int num6 = 0; num6 < num5; num6++)
                        {
                            list2.Add(new IntPoint((long)array3[num6].x, (long)array3[num6].z));
                        }
                    }
                    dictionary.Clear();
                    VInt3 vInt10 = vInt6 - vInt5;
                    VInt3 vInt11 = vInt7 - vInt5;
                    VInt3 vInt12 = vInt10;
                    VInt3 vInt13 = vInt11;
                    vInt12.y = 0;
                    vInt13.y = 0;
                    for (int num7 = 0; num7 < 16; num7++)
                    {
                        if ((mode >> (num7 & 31) & SGameTileHandler.CutMode.CutAll) != (SGameTileHandler.CutMode) 0)
                        {
                            if (1 << num7 == 1)
                            {
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, 0);
                                for (int num8 = 0; num8 < list7.get_Count(); num8++)
                                {
                                    this.clipper.AddPolygon(list10.get_Item(list7.get_Item(num8)), 1);
                                }
                                polyTree.Clear();
                                this.clipper.Execute(2, polyTree, 0, 1);
                            }
                            else if (1 << num7 == 2)
                            {
                                if (!flag)
                                {
                                    goto IL_1173;
                                }
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, 0);
                                for (int num9 = 0; num9 < list7.get_Count(); num9++)
                                {
                                    if (list11.get_Item(list7.get_Item(num9)))
                                    {
                                        this.clipper.AddPolygon(list10.get_Item(list7.get_Item(num9)), 1);
                                    }
                                }
                                list6.Clear();
                                this.clipper.Execute(0, list6, 0, 1);
                                this.clipper.Clear();
                                for (int num10 = 0; num10 < list6.get_Count(); num10++)
                                {
                                    this.clipper.AddPolygon(list6.get_Item(num10), (!Clipper.Orientation(list6.get_Item(num10))) ? 0 : 1);
                                }
                                for (int num11 = 0; num11 < list7.get_Count(); num11++)
                                {
                                    if (!list11.get_Item(list7.get_Item(num11)))
                                    {
                                        this.clipper.AddPolygon(list10.get_Item(list7.get_Item(num11)), 1);
                                    }
                                }
                                polyTree.Clear();
                                this.clipper.Execute(2, polyTree, 0, 1);
                            }
                            else if (1 << num7 == 4)
                            {
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, 0);
                                this.clipper.AddPolygon(list, 1);
                                polyTree.Clear();
                                this.clipper.Execute(0, polyTree, 0, 1);
                            }
                            for (int num12 = 0; num12 < polyTree.get_ChildCount(); num12++)
                            {
                                PolyNode        polyNode = polyTree.get_Childs().get_Item(num12);
                                List <IntPoint> contour  = polyNode.get_Contour();
                                List <PolyNode> childs   = polyNode.get_Childs();
                                if (childs.get_Count() == 0 && contour.get_Count() == 3 && num == -1)
                                {
                                    for (int num13 = 0; num13 < contour.get_Count(); num13++)
                                    {
                                        VInt3  vInt14 = new VInt3((int)contour.get_Item(num13).X, 0, (int)contour.get_Item(num13).Y);
                                        double num14  = (double)(vInt6.z - vInt7.z) * (double)(vInt5.x - vInt7.x) + (double)(vInt7.x - vInt6.x) * (double)(vInt5.z - vInt7.z);
                                        if (num14 == 0.0)
                                        {
                                            Debug.LogWarning("Degenerate triangle");
                                        }
                                        else
                                        {
                                            double num15 = ((double)(vInt6.z - vInt7.z) * (double)(vInt14.x - vInt7.x) + (double)(vInt7.x - vInt6.x) * (double)(vInt14.z - vInt7.z)) / num14;
                                            double num16 = ((double)(vInt7.z - vInt5.z) * (double)(vInt14.x - vInt7.x) + (double)(vInt5.x - vInt7.x) * (double)(vInt14.z - vInt7.z)) / num14;
                                            vInt14.y = (int)Math.Round(num15 * (double)vInt5.y + num16 * (double)vInt6.y + (1.0 - num15 - num16) * (double)vInt7.y);
                                            list5.Add(list4.get_Count());
                                            list4.Add(vInt14);
                                        }
                                    }
                                }
                                else
                                {
                                    Polygon polygon = null;
                                    int     num17   = -1;
                                    for (List <IntPoint> list14 = contour; list14 != null; list14 = ((num17 >= childs.get_Count()) ? null : childs.get_Item(num17).get_Contour()))
                                    {
                                        list3.Clear();
                                        for (int num18 = 0; num18 < list14.get_Count(); num18++)
                                        {
                                            PolygonPoint polygonPoint = new PolygonPoint((double)list14.get_Item(num18).X, (double)list14.get_Item(num18).Y);
                                            list3.Add(polygonPoint);
                                            VInt3  vInt15 = new VInt3((int)list14.get_Item(num18).X, 0, (int)list14.get_Item(num18).Y);
                                            double num19  = (double)(vInt6.z - vInt7.z) * (double)(vInt5.x - vInt7.x) + (double)(vInt7.x - vInt6.x) * (double)(vInt5.z - vInt7.z);
                                            if (num19 == 0.0)
                                            {
                                                Debug.LogWarning("Degenerate triangle");
                                            }
                                            else
                                            {
                                                double num20 = ((double)(vInt6.z - vInt7.z) * (double)(vInt15.x - vInt7.x) + (double)(vInt7.x - vInt6.x) * (double)(vInt15.z - vInt7.z)) / num19;
                                                double num21 = ((double)(vInt7.z - vInt5.z) * (double)(vInt15.x - vInt7.x) + (double)(vInt5.x - vInt7.x) * (double)(vInt15.z - vInt7.z)) / num19;
                                                vInt15.y = (int)Math.Round(num20 * (double)vInt5.y + num21 * (double)vInt6.y + (1.0 - num20 - num21) * (double)vInt7.y);
                                                dictionary.set_Item(polygonPoint, list4.get_Count());
                                                list4.Add(vInt15);
                                            }
                                        }
                                        Polygon polygon2;
                                        if (stack.get_Count() > 0)
                                        {
                                            polygon2 = stack.Pop();
                                            polygon2.AddPoints(list3);
                                        }
                                        else
                                        {
                                            polygon2 = new Polygon(list3);
                                        }
                                        if (polygon == null)
                                        {
                                            polygon = polygon2;
                                        }
                                        else
                                        {
                                            polygon.AddHole(polygon2);
                                        }
                                        num17++;
                                    }
                                    try
                                    {
                                        P2T.Triangulate(polygon);
                                    }
                                    catch (PointOnEdgeException)
                                    {
                                        Debug.LogWarning(string.Concat(new object[]
                                        {
                                            "PointOnEdgeException, perturbating vertices slightly ( at ",
                                            num7,
                                            " in ",
                                            mode,
                                            ")"
                                        }));
                                        this.CutPoly(InNavmeshCuts, verts, tris, ref outVertsArr, ref outTrisArr, out outVCount, out outTCount, extraShape, cuttingOffset, realBounds, mode, perturbate + 1);
                                        return;
                                    }
                                    for (int num22 = 0; num22 < polygon.get_Triangles().get_Count(); num22++)
                                    {
                                        DelaunayTriangle delaunayTriangle = polygon.get_Triangles().get_Item(num22);
                                        list5.Add(dictionary.get_Item(delaunayTriangle.Points._0));
                                        list5.Add(dictionary.get_Item(delaunayTriangle.Points._1));
                                        list5.Add(dictionary.get_Item(delaunayTriangle.Points._2));
                                    }
                                    if (polygon.get_Holes() != null)
                                    {
                                        for (int num23 = 0; num23 < polygon.get_Holes().get_Count(); num23++)
                                        {
                                            polygon.get_Holes().get_Item(num23).get_Points().Clear();
                                            polygon.get_Holes().get_Item(num23).ClearTriangles();
                                            if (polygon.get_Holes().get_Item(num23).get_Holes() != null)
                                            {
                                                polygon.get_Holes().get_Item(num23).get_Holes().Clear();
                                            }
                                            stack.Push(polygon.get_Holes().get_Item(num23));
                                        }
                                    }
                                    polygon.ClearTriangles();
                                    if (polygon.get_Holes() != null)
                                    {
                                        polygon.get_Holes().Clear();
                                    }
                                    polygon.get_Points().Clear();
                                    stack.Push(polygon);
                                }
                            }
                        }
                        IL_1173 :;
                    }
                }
            }
            Dictionary <VInt3, int> dictionary2 = this.cached_Int3_int_dict;

            dictionary2.Clear();
            if (this.cached_int_array.Length < list4.get_Count())
            {
                this.cached_int_array = new int[Math.Max(this.cached_int_array.Length * 2, list4.get_Count())];
            }
            int[] array5 = this.cached_int_array;
            int   num24  = 0;

            for (int num25 = 0; num25 < list4.get_Count(); num25++)
            {
                int num26;
                if (!dictionary2.TryGetValue(list4.get_Item(num25), ref num26))
                {
                    dictionary2.Add(list4.get_Item(num25), num24);
                    array5[num25] = num24;
                    list4.set_Item(num24, list4.get_Item(num25));
                    num24++;
                }
                else
                {
                    array5[num25] = num26;
                }
            }
            outTCount = list5.get_Count();
            if (outTrisArr == null || outTrisArr.Length < outTCount)
            {
                outTrisArr = new int[outTCount];
            }
            for (int num27 = 0; num27 < outTCount; num27++)
            {
                outTrisArr[num27] = array5[list5.get_Item(num27)];
            }
            outVCount = num24;
            if (outVertsArr == null || outVertsArr.Length < outVCount)
            {
                outVertsArr = new VInt3[outVCount];
            }
            for (int num28 = 0; num28 < outVCount; num28++)
            {
                outVertsArr[num28] = list4.get_Item(num28);
            }
            for (int num29 = 0; num29 < listView.Count; num29++)
            {
                listView[num29].UsedForCut();
            }
            ListPool <VInt3> .Release(list4);

            ListPool <int> .Release(list5);

            ListPool <int> .Release(list7);

            ListPool <VInt2> .Release(list9);

            ListPool <bool> .Release(list11);

            ListPool <bool> .Release(list12);

            ListPool <IntRect> .Release(list8);
        }