public void Remove(int key)
        {
            MeshUtils.Assert(key < Size, "Key index out of range! " + key + " maxSize: " + Size);
            MeshUtils.Assert(dictionary[key].valid == true, "Key does not exists!");
            dictionary[key].valid = false;

            Count--;
        }
        /// <summary>
        /// c-tor
        /// </summary>
        /// <param name="pnts">points of the polygon</param>
        public Polygon(Vector2[] pnts)
        {
            MeshUtils.Assert(pnts.Length >= 3, "Invalid polygon!");

            Points = pnts;
            Area   = GetArea();

            holes = new List <Polygon>();
        }
        public void Add(int key, T data)
        {
            MeshUtils.Assert(key < Size, "Key index out of range! " + key + " maxSize: " + Size);
            MeshUtils.Assert(dictionary[key].valid == false, "Key already exists!");

            dictionary[key].valid = true;
            dictionary[key].data  = data;

            Count++;
        }
        public T this[int key]
        {
            get
            {
                MeshUtils.Assert(key < Size, "Key index out of range! " + key + " maxSize: " + Size);
                MeshUtils.Assert(dictionary[key].valid == true, "Key does not exists!");
                return(dictionary[key].data);
            }

            set
            {
                MeshUtils.Assert(dictionary[key].valid == true, "Key does not exists!");
                dictionary[key].data = value;
            }
        }
        public T GetFirstValue()
        {
            for (int i = 0; i < Size; i++)
            {
                var item = dictionary[i];

                if (item.valid)
                {
                    return(item.data);
                }
            }

            MeshUtils.Assert(false, "No valid key!");
            return(default(T));
        }
        public bool TryGetValue(int key, out T value)
        {
            MeshUtils.Assert(key < Size, "Key index out of range! " + key + " maxSize: " + Size);

            var item = dictionary[key];

            if (item.valid)
            {
                value = item.data;
                return(true);
            }

            value = default(T);
            return(false);
        }
        static Vector3 GetNormal(Vector3[] points)
        {
            var p0 = points[0];
            var p1 = points[1];

            const float epsylon = 0.01f;

            int i = 1;

            while ((p0 - p1).sqrMagnitude < epsylon)
            {
                p1 = points[i++];

                if (i == points.Length)
                {
                    MeshUtils.Assert(false, "All points are collinear!");
                    return(Vector3.zero);
                }
            }

            var p2 = points[i];

            while ((p0 - p2).sqrMagnitude < epsylon || (p1 - p2).sqrMagnitude < epsylon)
            {
                p2 = points[i++];

                if (i == points.Length)
                {
                    MeshUtils.Assert(false, "All points are collinear!");
                    return(Vector3.zero);
                }
            }

            var normal = MeshUtils.ComputePolygonNormal(p0, p1, p2);

            if (normal.sqrMagnitude < epsylon)
            {
                MeshUtils.Assert(false, "All points are collinear!");
                return(Vector3.zero);
            }

            return(normal);
        }
        public T[] ToArray()
        {
            var array = new T[Count];
            var idx   = 0;

            for (int i = 0; i < Size; i++)
            {
                if (dictionary[i].valid)
                {
                    array[idx++] = dictionary[i].data;

                    if (idx == Count)
                    {
                        return(array);
                    }
                }
            }

            MeshUtils.Assert(false, "ToArray failed, Count is wrong!");
            return(null);
        }
        private void Triangulate(List <Dictionary <int, int> > contours, Utils.Plane plane, List <Vector3>[] vertices, List <Vector3>[] normals, List <Vector2>[] uvs, List <int>[] triangles, bool uvCutMesh)
        {
            if (contours.Count == 0 || contours[0].Count < 3)
            {
                return;
            }

            // prepare plane matrix
            var m    = plane.GetPlaneMatrix();
            var mInv = m.inverse;

            var zShit = 0.0f;

            var polygons = new List <Polygon>(contours.Count);

            // construct polygons from contours
            Polygon highAreaPoly = null;

            foreach (var ctr in contours)
            {
                var polygonPoints = new Vector2[ctr.Count];
                var j             = 0;

                foreach (var i in ctr.Values)
                {
                    var p = mInv * vertices[0][i];
                    polygonPoints[j++] = p;

                    // save z-coordinate
                    zShit = p.z;
                }

                var polygon = new Polygon(polygonPoints);
                polygons.Add(polygon);

                if (highAreaPoly == null || highAreaPoly.Area < polygon.Area)
                {
                    highAreaPoly = polygon;
                }
            }

            MeshUtils.Assert(polygons.Count > 0, "Zero polygons!");

            // test for holes
            if (polygons.Count > 0)
            {
                var polyToRemove = new List <Polygon>();

                foreach (var polygon in polygons)
                {
                    if (polygon != highAreaPoly)
                    {
                        if (highAreaPoly.IsPointInside(polygon.Points[0]))
                        {
                            highAreaPoly.AddHole(polygon);
                            polyToRemove.Add(polygon);
                        }
                    }
                }

                foreach (var polygon in polyToRemove)
                {
                    polygons.Remove(polygon);
                }
            }

            var vertCounter0 = vertices[0].Count;
            var vertCounter1 = vertices[1].Count;

            foreach (var polygon in polygons)
            {
                var indices = polygon.Triangulate();

                // get polygon bounding square size
                var min         = Mathf.Min(polygon.Min.x, polygon.Min.y);
                var max         = Mathf.Max(polygon.Max.x, polygon.Max.y);
                var polygonSize = min - max;

//                MeshUtils.Log("PolygonSize: " + polygonSize + " " + polygon.Min + " " + polygon.Max);

                foreach (var polyPoint in polygon.Points)
                {
                    var p = m * new Vector3(polyPoint.x, polyPoint.y, zShit);

                    vertices[0].Add(p);
                    vertices[1].Add(p);
                    normals[0].Add(-plane.Normal);
                    normals[1].Add(plane.Normal);

                    if (uvCutMesh)
                    {
                        var uv0 = new Vector2((polyPoint.x - min) / polygonSize,
                                              (polyPoint.y - min) / polygonSize);
                        var uv1 = new Vector2((polyPoint.x - min) / polygonSize,
                                              (polyPoint.y - min) / polygonSize);

                        // normalize uv to fit cross-section uv area
                        var areaSizeX = crossSectionUV.z - crossSectionUV.x;
                        var areaSizeY = crossSectionUV.w - crossSectionUV.y;

                        uv0.x = crossSectionUV.x + uv0.x * areaSizeX;
                        uv0.y = crossSectionUV.y + uv0.y * areaSizeY;
                        uv1.x = crossSectionUV.x + uv1.x * areaSizeX;
                        uv1.y = crossSectionUV.y + uv1.y * areaSizeY;

                        uvs[0].Add(uv0);
                        uvs[1].Add(uv1);
                    }
                    else
                    {
                        uvs[0].Add(Vector2.zero);
                        uvs[1].Add(Vector2.zero);
                    }
                }

                var indicesCount = indices.Count;
                var j            = indicesCount - 1;
                for (var i = 0; i < indicesCount; i++)
                {
                    triangles[0].Add(vertCounter0 + indices[i]);
                    triangles[1].Add(vertCounter1 + indices[j]);
                    j--;
                }

                vertCounter0 += polygon.Points.Length;
                vertCounter1 += polygon.Points.Length;
            }
        }
        private float Cut(Mesh mesh, Transform meshTransform, Utils.Plane plane, bool triangulateHoles, bool fixPivot, bool getContourList, bool dontCut,
                          Vector4 crossSection, out Mesh mesh0, out Mesh mesh1, out Vector3 centroid0, out Vector3 centroid1, out ContourData intersectionData)
        {
            var stopWatch = new Stopwatch();

            stopWatch.Start();

#if PROFILING
            MeasureIt.Begin("CutAllocations");
#endif

            // cache mesh data
            var trianglesNum  = mesh.triangles.Length;
            var verticesNum   = mesh.vertices.Length;
            var meshTriangles = mesh.triangles;
            var meshVertices  = mesh.vertices;
            var meshNormals   = mesh.normals;
            var meshUV        = mesh.uv;

            this.crossSectionUV = crossSection;

            // preallocate buffers
            AllocateBuffers(trianglesNum, verticesNum);

#if PROFILING
            MeasureIt.End("CutAllocations");
            MeasureIt.Begin("CutCycleFirstPass");
#endif

            // inverse transform cutting plane
            plane.InverseTransform(meshTransform);

            // first pass - find complete triangles on both sides of the plane
            for (var i = 0; i < trianglesNum; i += 3)
            {
                // get triangle points
                var v0 = meshVertices[meshTriangles[i]];
                var v1 = meshVertices[meshTriangles[i + 1]];
                var v2 = meshVertices[meshTriangles[i + 2]];

                var side0 = plane.GetSideFix(ref v0);
                var side1 = plane.GetSideFix(ref v1);
                var side2 = plane.GetSideFix(ref v2);

                meshVertices[meshTriangles[i]]     = v0;
                meshVertices[meshTriangles[i + 1]] = v1;
                meshVertices[meshTriangles[i + 2]] = v2;

                // all points on one side
                if (side0 == side1 && side1 == side2)
                {
                    var idx = side0 ? 0 : 1;

                    if (triCache[meshTriangles[i]] == 0)
                    {
                        triangles[idx].Add(triCounter[idx]);
                        vertices[idx].Add(meshVertices[meshTriangles[i]]);
                        normals[idx].Add(meshNormals[meshTriangles[i]]);
                        uvs[idx].Add(meshUV[meshTriangles[i]]);

                        centroid[idx] += meshVertices[meshTriangles[i]];

                        triCache[meshTriangles[i]] = triCounter[idx] + 1;
                        triCounter[idx]++;
                    }
                    else
                    {
                        triangles[idx].Add(triCache[meshTriangles[i]] - 1);
                    }

                    if (triCache[meshTriangles[i + 1]] == 0)
                    {
                        triangles[idx].Add(triCounter[idx]);
                        vertices[idx].Add(meshVertices[meshTriangles[i + 1]]);
                        normals[idx].Add(meshNormals[meshTriangles[i + 1]]);
                        uvs[idx].Add(meshUV[meshTriangles[i + 1]]);

                        centroid[idx] += meshVertices[meshTriangles[i + 1]];

                        triCache[meshTriangles[i + 1]] = triCounter[idx] + 1;
                        triCounter[idx]++;
                    }
                    else
                    {
                        triangles[idx].Add(triCache[meshTriangles[i + 1]] - 1);
                    }

                    if (triCache[meshTriangles[i + 2]] == 0)
                    {
                        triangles[idx].Add(triCounter[idx]);
                        vertices[idx].Add(meshVertices[meshTriangles[i + 2]]);
                        normals[idx].Add(meshNormals[meshTriangles[i + 2]]);
                        uvs[idx].Add(meshUV[meshTriangles[i + 2]]);

                        centroid[idx] += meshVertices[meshTriangles[i + 2]];

                        triCache[meshTriangles[i + 2]] = triCounter[idx] + 1;
                        triCounter[idx]++;
                    }
                    else
                    {
                        triangles[idx].Add(triCache[meshTriangles[i + 2]] - 1);
                    }
                }
                else
                {
                    // intersection triangles add to list and process it in second pass
                    cutTris.Add(i);
                }
            }

            if (vertices[0].Count == 0)
            {
                centroid[0] = meshVertices[0];
            }
            else
            {
                centroid[0] /= vertices[0].Count;
            }

            if (vertices[1].Count == 0)
            {
                centroid[1] = meshVertices[1];
            }
            else
            {
                centroid[1] /= vertices[1].Count;
            }

#if PROFILING
            MeasureIt.End("CutCycleFirstPass");
            MeasureIt.Begin("CutCycleSecondPass");
#endif
            mesh0            = null;
            mesh1            = null;
            centroid0        = centroid[0];
            centroid1        = centroid[1];
            intersectionData = null;

            if (cutTris.Count < 1)
            {
                stopWatch.Stop();
                return(stopWatch.ElapsedMilliseconds);
            }

            AllocateContours(cutTris.Count);

            // second pass - cut intersecting triangles in half
            foreach (var cutTri in cutTris)
            {
                var triangle = new Triangle
                {
                    ids    = new[] { meshTriangles[cutTri + 0], meshTriangles[cutTri + 1], meshTriangles[cutTri + 2] },
                    pos    = new[] { meshVertices[meshTriangles[cutTri + 0]], meshVertices[meshTriangles[cutTri + 1]], meshVertices[meshTriangles[cutTri + 2]] },
                    normal = new[] { meshNormals[meshTriangles[cutTri + 0]], meshNormals[meshTriangles[cutTri + 1]], meshNormals[meshTriangles[cutTri + 2]] },
                    uvs    = new[] { meshUV[meshTriangles[cutTri + 0]], meshUV[meshTriangles[cutTri + 1]], meshUV[meshTriangles[cutTri + 2]] }
                };

                // check points with a plane
                var side0 = plane.GetSide(triangle.pos[0]);
                var side1 = plane.GetSide(triangle.pos[1]);
                var side2 = plane.GetSide(triangle.pos[2]);

                float   t0, t1;
                Vector3 s0, s1;

                var idxLeft  = side0 ? 0 : 1;
                var idxRight = 1 - idxLeft;

                if (side0 == side1)
                {
                    var a = plane.IntersectSegment(triangle.pos[2], triangle.pos[0], out t0, out s0);
                    var b = plane.IntersectSegment(triangle.pos[2], triangle.pos[1], out t1, out s1);

                    MeshUtils.Assert(a && b, "!!!!!!!!!!!!!!!");

                    // left side ... 2 triangles
                    var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[2], triangle.ids[0], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]);
                    var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[2], triangle.ids[1], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]);
                    var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]);
                    var v1Left = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.ids[1], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]);

                    // Triangle (s0, v0, s1)
                    triangles[idxLeft].Add(s0Left);
                    triangles[idxLeft].Add(v0Left);
                    triangles[idxLeft].Add(s1Left);

                    // Triangle (s1, v0, v1)
                    triangles[idxLeft].Add(s1Left);
                    triangles[idxLeft].Add(v0Left);
                    triangles[idxLeft].Add(v1Left);

                    // right side ... 1 triangle
                    var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[2], triangle.ids[0], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]);
                    var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[2], triangle.ids[1], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]);
                    var v2Right = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.ids[2], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]);

                    // Triangle (v2, s0, s1)
                    triangles[idxRight].Add(v2Right);
                    triangles[idxRight].Add(s0Right);
                    triangles[idxRight].Add(s1Right);

                    // buffer intersection vertices for triangulation
                    if (triangulateHoles)
                    {
                        if (idxLeft == 0)
                        {
                            contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1);
                        }
                        else
                        {
                            contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1);
                        }
                    }
                }
                else if (side0 == side2)
                {
                    var a = plane.IntersectSegment(triangle.pos[1], triangle.pos[0], out t0, out s1);
                    var b = plane.IntersectSegment(triangle.pos[1], triangle.pos[2], out t1, out s0);

                    MeshUtils.Assert(a && b, "!!!!!!!!!!!!!");

                    // left side ... 2 triangles
                    var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[1], triangle.ids[2], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]);
                    var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[1], triangle.ids[0], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]);
                    var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]);
                    var v2Left = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.ids[2], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]);

                    // Triangle (v2, s1, s0)
                    triangles[idxLeft].Add(v2Left);
                    triangles[idxLeft].Add(s1Left);
                    triangles[idxLeft].Add(s0Left);

                    // Triangle (v2, v0, s1)
                    triangles[idxLeft].Add(v2Left);
                    triangles[idxLeft].Add(v0Left);
                    triangles[idxLeft].Add(s1Left);

                    // right side ... 1 triangle
                    var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[1], triangle.ids[2], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]);
                    var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[1], triangle.ids[0], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]);
                    var v1Right = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.ids[1], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]);

                    // Triangle (s0, s1, v1)
                    triangles[idxRight].Add(s0Right);
                    triangles[idxRight].Add(s1Right);
                    triangles[idxRight].Add(v1Right);

                    // buffer intersection vertices for triangulation
                    if (triangulateHoles)
                    {
                        if (idxLeft == 0)
                        {
                            contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1);
                        }
                        else
                        {
                            contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1);
                        }
                    }
                }
                else
                {
                    var a = plane.IntersectSegment(triangle.pos[0], triangle.pos[1], out t0, out s0);
                    var b = plane.IntersectSegment(triangle.pos[0], triangle.pos[2], out t1, out s1);

                    MeshUtils.Assert(a && b, "!!!!!!!!!!!!!");

                    // right side ... 2 triangles
                    var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[0], triangle.ids[1], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]);
                    var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[0], triangle.ids[2], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]);
                    var v1Right = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.ids[1], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]);
                    var v2Right = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.ids[2], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]);

                    // Triangle (v2, s1, v1)
                    triangles[idxRight].Add(v2Right);
                    triangles[idxRight].Add(s1Right);
                    triangles[idxRight].Add(v1Right);

                    // Triangle (s1, s0, v1)
                    triangles[idxRight].Add(s1Right);
                    triangles[idxRight].Add(s0Right);
                    triangles[idxRight].Add(v1Right);

                    // left side ... 1 triangle
                    var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[0], triangle.ids[1], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]);
                    var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[0], triangle.ids[2], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]);
                    var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]);

                    // Triangle (s1, v0, s0)
                    triangles[idxLeft].Add(s1Left);
                    triangles[idxLeft].Add(v0Left);
                    triangles[idxLeft].Add(s0Left);

                    // buffer intersection vertices for triangulation
                    if (triangulateHoles)
                    {
                        if (idxLeft == 0)
                        {
                            contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1);
                        }
                        else
                        {
                            contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1);
                        }
                    }
                }
            }

#if PROFILING
            MeasureIt.End("CutCycleSecondPass");
#endif


            if (triangulateHoles || getContourList)
            {
#if PROFILING
                MeasureIt.Begin("FindContours");
#endif

                contour.FindContours();

#if PROFILING
                MeasureIt.End("FindContours");
#endif
            }

            List <int>[] trianglesCut = null;

            if (triangulateHoles)
            {
#if PROFILING
                MeasureIt.Begin("Triangulate");
#endif

                trianglesCut = new List <int>[2] {
                    new List <int>(contour.MidPointsCount), new List <int>(contour.MidPointsCount)
                };
                Triangulate(contour.contour, plane, vertices, normals, uvs, trianglesCut, true);

#if PROFILING
                MeasureIt.End("Triangulate");
#endif
            }

            intersectionData = null;

            if (getContourList)
            {
#if PROFILING
                MeasureIt.Begin("GetContourList");
#endif
                List <Vector3[]> contoursList = null;

                GetContourList(contour.contour, vertices[0], out contoursList);

                intersectionData = new ContourData(contoursList, meshTransform);

#if PROFILING
                MeasureIt.End("GetContourList");
#endif
            }

            centroid0 = centroid[0];
            centroid1 = centroid[1];

            if (dontCut)
            {
                MeshUtils.Assert(intersectionData != null, "F**k");
                MeshUtils.Assert(getContourList != false, "Fuck2");
                mesh0 = null;
                mesh1 = null;
                return(stopWatch.ElapsedMilliseconds);
            }

            if (vertices[0].Count > 0 && vertices[1].Count > 0)
            {
#if PROFILING
                MeasureIt.Begin("CutEndCopyBack");
#endif

                mesh0 = new Mesh();
                mesh1 = new Mesh();

                var verticesArray0 = vertices[0].ToArray();
                var verticesArray1 = vertices[1].ToArray();

#if PROFILING
                MeasureIt.Begin("FixPivot");
#endif

                if (fixPivot)
                {
                    MeshUtils.CenterPivot(verticesArray0, centroid[0]);
                    MeshUtils.CenterPivot(verticesArray1, centroid[1]);
                }

#if PROFILING
                MeasureIt.End("FixPivot");
#endif

                mesh0.vertices = verticesArray0;
                mesh0.normals  = normals[0].ToArray();
                mesh0.uv       = uvs[0].ToArray();

                mesh1.vertices = verticesArray1;
                mesh1.normals  = normals[1].ToArray();
                mesh1.uv       = uvs[1].ToArray();

                if (triangulateHoles && trianglesCut[0].Count > 0)
                {
                    mesh0.subMeshCount = 2;
                    mesh0.SetTriangles(triangles[0].ToArray(), 0);
                    mesh0.SetTriangles(trianglesCut[0].ToArray(), 1);

                    mesh1.subMeshCount = 2;
                    mesh1.SetTriangles(triangles[1].ToArray(), 0);
                    mesh1.SetTriangles(trianglesCut[1].ToArray(), 1);
                }
                else
                {
                    mesh0.triangles = triangles[0].ToArray();
                    mesh1.triangles = triangles[1].ToArray();
                }

#if PROFILING
                MeasureIt.End("CutEndCopyBack");
#endif

                stopWatch.Stop();
                return(stopWatch.ElapsedMilliseconds);
            }

            mesh0 = null;
            mesh1 = null;
            stopWatch.Stop();

//            UnityEngine.Debug.Log("Empty cut! " + vertices[0].Count + " " + vertices[1].Count);

            return(stopWatch.ElapsedMilliseconds);
        }
Exemple #11
0
        public bool FindContours()
        {
            if (midPoints.Count == 0)
            {
                return(false);
            }

#if DEBUG_CONTOUR
            MeshUtils.Log("MidPoint: " + midPoints.Count);

            foreach (var midPoint in midPoints)
            {
                if (midPoint.Value.idNext == HashType.MaxValue || midPoint.Value.idPrev == HashType.MaxValue)
                {
                    MeshUtils.Log(midPoint.Value.id + " " + midPoint.Value.idNext + " " + midPoint.Value.idPrev);

                    var sphere = PrimitivesPro.GameObjects.Sphere.Create(0.1f, 10, 0, 0, NormalsType.Vertex,
                                                                         PivotPosition.Center);
                    sphere.transform.position            = midPoint.Value.position;
                    sphere.renderer.sharedMaterial.color = Color.red;
                }
            }
#endif

            var midContour = new Dictionary <HashType, int>(midPoints.Count);

            var loopsMax = 10000;

            // find contour
            var pStart = midPoints.GetFirstValue();
            midContour.Add(pStart.id, pStart.vertexId);
            midPoints.Remove(pStart.id);
            var nextP = pStart.idNext;

            while (midPoints.Count > 0)
            {
                if (nextP == HashType.MaxValue)
                {
                    return(false);
                }

                MidPoint p;
                if (!midPoints.TryGetValue(nextP, out p))
                {
//                    throw new Exception("Contour failed");
                    return(false);
                }

                // add new point on contour
                midContour.Add(p.id, p.vertexId);
                midPoints.Remove(p.id);

                if (midContour.ContainsKey(p.idNext))
                {
                    if (midContour.ContainsKey(p.idPrev))
                    {
                        // closing the loop!
                        contour.Add(new Dictionary <int, int>(midContour));
                        midContour.Clear();

                        if (midPoints.Count == 0)
                        {
                            break;
                        }

                        pStart = midPoints.GetFirstValue();
                        midContour.Add(pStart.id, pStart.vertexId);
                        midPoints.Remove(pStart.id);
                        nextP = pStart.idNext;
                        continue;
                    }

                    nextP = p.idPrev;
                }
                else
                {
                    nextP = p.idNext;
                }

                loopsMax--;
                if (loopsMax == 0)
                {
                    MeshUtils.Assert(false, "ForeverLoop!");
//                    throw new Exception("Contour failed");
                    return(false);
                }
            }

            return(true);
        }