public static List <Vertices> ConvexPartition(Vertices vertices)
        {
            Polygon poly = new Polygon();

            foreach (Vector2 vertex in vertices)
            {
                poly.Points.Add(new TriangulationPoint(vertex.X, vertex.Y));
            }

            DTSweepContext tcx = new DTSweepContext();

            tcx.PrepareTriangulation(poly);
            DTSweep.Triangulate(tcx);

            List <Vertices> results = new List <Vertices>();

            foreach (DelaunayTriangle triangle in poly.Triangles)
            {
                Vertices v = new Vertices();
                foreach (TriangulationPoint p in triangle.Points)
                {
                    v.Add(new Vector2((float)p.X, (float)p.Y));
                }
                results.Add(v);
            }

            return(results);
        }
Exemple #2
0
        /// <summary>
        /// Decompose the polygon into several smaller non-concave polygon.
        /// </summary>
        public static List <List <Vector> > ConvexPartition(List <Vector> vertices)
        {
            Decomposition.CDT.Polygon.Polygon poly = new Decomposition.CDT.Polygon.Polygon();

            foreach (Vector vertex in vertices)
            {
                poly.Points.Add(new TriangulationPoint(vertex.X, vertex.Y));
            }

            DTSweepContext tcx = new DTSweepContext();

            tcx.PrepareTriangulation(poly);
            DTSweep.Triangulate(tcx);

            List <List <Vector> > results = new List <List <Vector> >();

            foreach (DelaunayTriangle triangle in poly.Triangles)
            {
                List <Vector> v = new List <Vector>();
                foreach (TriangulationPoint p in triangle.Points)
                {
                    v.Add(new Vector(p.X, p.Y));
                }

                results.Add(v);
            }

            return(results);
        }
Exemple #3
0
 public static void Triangulate(TriangulationContext tcx)
 {
     switch (tcx.Algorithm)
     {
     case TriangulationAlgorithm.DTSweep:
     default:
         DTSweep.Triangulate((DTSweepContext)tcx);
         break;
     }
 }
Exemple #4
0
        /// <summary>
        /// Given a set of points ordered counter-clockwise along a contour, return triangle indexes.
        /// </summary>
        /// <param name="points"></param>
        /// <param name="indexes"></param>
        /// <param name="convex">Triangulation may optionally be set to convex, which will result in some a convex shape.</param>
        /// <returns></returns>
        public static bool Triangulate(IList <Vector2> points, out List <int> indexes, bool convex = false)
        {
            indexes = new List <int>();

            int index = 0;

            Triangulatable soup = convex
                ? new PointSet(points.Select(x => new TriangulationPoint(x.x, x.y, index++)).ToList())
                : (Triangulatable) new Polygon(points.Select(x => new PolygonPoint(x.x, x.y, index++)));

            try
            {
                triangulationContext.Clear();
                triangulationContext.PrepareTriangulation(soup);
                DTSweep.Triangulate((DTSweepContext)triangulationContext);
            }
            catch (System.Exception e)
            {
                Log.Info("Triangulation failed: " + e.ToString());
                return(false);
            }

            foreach (DelaunayTriangle d in soup.Triangles)
            {
                if (d.Points[0].Index < 0 || d.Points[1].Index < 0 || d.Points[2].Index < 0)
                {
                    Log.Info("Triangulation failed: Additional vertices were inserted.");
                    return(false);
                }

                indexes.Add(d.Points[0].Index);
                indexes.Add(d.Points[1].Index);
                indexes.Add(d.Points[2].Index);
            }

            WindingOrder originalWinding = SurfaceTopology.GetWindingOrder(points);

            // if the re-triangulated first tri doesn't match the winding order of the original
            // vertices, flip 'em

            if (SurfaceTopology.GetWindingOrder(new Vector2[3]
            {
                points[indexes[0]],
                points[indexes[1]],
                points[indexes[2]],
            }) != originalWinding)
            {
                indexes.Reverse();
            }

            return(true);
        }
Exemple #5
0
    public static void Triangulate(Vector3[] polygon, Vector3 normal, out List <ThreeVector3> triangles)
    {
        if (polygon.Length < 3)
        {
            triangles = new List <ThreeVector3>();
            return;
        }

        //var planeNormal = Vector3.Cross(polygon[1] - polygon[0], polygon[2] - polygon[0]);
        //planeNormal.Normalize();
        //if (Vector3.Angle(planeNormal, normal) > Vector3.Angle(-planeNormal, normal))
        //{
        //    planeNormal = -planeNormal;
        //}

        //Quaternion rotation = Quaternion.identity;
        //if (planeNormal != Vector3.forward)
        //{
        //    rotation = Quaternion.FromToRotation(planeNormal, Vector3.forward);
        //}

        Quaternion rotation = Quaternion.FromToRotation(normal, Vector3.forward);

        // Rotate 1 point and note where it ends up in Z
        float z = (rotation * polygon[0]).z;

        var poly = new Polygon(ConvertPoints(polygon, rotation));

        DTSweepContext tcx = new DTSweepContext();

        tcx.PrepareTriangulation(poly);
        DTSweep.Triangulate(tcx);
        tcx = null;

        Quaternion invRot = Quaternion.Inverse(rotation);

        triangles = new List <ThreeVector3>();
        foreach (DelaunayTriangle t in poly.Triangles)
        {
            ThreeVector3 tri = new ThreeVector3();

            for (int i = 0; i < 3; ++i)
            {
                var     p   = t.Points[i];
                Vector3 pos = new Vector3(p.Xf, p.Yf, z);
                tri[i] = invRot * pos;
            }

            triangles.Add(tri);
        }
    }
Exemple #6
0
        /// <summary>
        /// Decompose the polygon into several smaller non-concave polygon.
        /// </summary>
        public static List <Vertices> ConvexPartition(Vertices vertices)
        {
            Debug.Assert(vertices.Count > 3);

            Polygon poly = new Polygon();

            foreach (Vector2 vertex in vertices)
            {
                poly.Points.Add(new TriangulationPoint(vertex.X, vertex.Y));
            }

            if (vertices.Holes != null)
            {
                foreach (Vertices holeVertices in vertices.Holes)
                {
                    var hole = new Polygon();

                    foreach (Vector2 vertex in holeVertices)
                    {
                        hole.Points.Add(new TriangulationPoint(vertex.X, vertex.Y));
                    }

                    poly.AddHole(hole);
                }
            }

            DTSweepContext tcx = new DTSweepContext();

            tcx.PrepareTriangulation(poly);
            DTSweep.Triangulate(tcx);

            List <Vertices> results = new List <Vertices>();

            foreach (DelaunayTriangle triangle in poly.Triangles)
            {
                Vertices v = new Vertices();
                foreach (TriangulationPoint p in triangle.Points)
                {
                    v.Add(new Vector2((float)p.X, (float)p.Y));
                }

                results.Add(v);
            }

            return(results);
        }
        /// <summary>
        /// Decompose the polygon into several smaller non-concave polygon.
        /// </summary>
        public static List <Vertices> ConvexPartition(Vertices vertices)
        {
            Debug.Assert(vertices.Count > 3);

            var poly = new Polygon.Polygon();

            foreach (var vertex in vertices)
            {
                poly.Points.Add(new TriangulationPoint(vertex.x, vertex.y));
            }

            if (vertices.Holes != null)
            {
                foreach (var holeVertices in vertices.Holes)
                {
                    var hole = new Polygon.Polygon();

                    foreach (var vertex in holeVertices)
                    {
                        hole.Points.Add(new TriangulationPoint(vertex.x, vertex.y));
                    }

                    poly.AddHole(hole);
                }
            }

            var tcx = new DTSweepContext();

            tcx.PrepareTriangulation(poly);
            DTSweep.Triangulate(tcx);

            var results = new List <Vertices>();

            foreach (var triangle in poly.Triangles)
            {
                var v = new Vertices();
                foreach (var p in triangle.Points)
                {
                    v.Add(new Vector2(p.X, p.Y));
                }
                results.Add(v);
            }

            return(results);
        }
Exemple #8
0
        /// <summary>
        /// Decompose the polygon into several smaller non-concave polygon.
        /// </summary>
        public static List <List <Vector2> > ConvexPartition(List <Vector2> vertices, List <List <Vector2> > holes = null)
        {
            FarseerPhysics.Common.Decomposition.CDT.Polygon.Polygon poly = new FarseerPhysics.Common.Decomposition.CDT.Polygon.Polygon();

            foreach (Vector2 vertex in vertices)
            {
                poly.Points.Add(new TriangulationPoint(vertex.x, vertex.y));
            }

            if (holes != null)
            {
                foreach (List <Vector2> holeVertices in holes)
                {
                    FarseerPhysics.Common.Decomposition.CDT.Polygon.Polygon hole = new FarseerPhysics.Common.Decomposition.CDT.Polygon.Polygon();

                    foreach (Vector2 vertex in holeVertices)
                    {
                        hole.Points.Add(new TriangulationPoint(vertex.x, vertex.y));
                    }

                    poly.AddHole(hole);
                }
            }

            DTSweepContext tcx = new DTSweepContext();

            tcx.PrepareTriangulation(poly);
            DTSweep.Triangulate(tcx);

            List <List <Vector2> > results = new List <List <Vector2> >();

            foreach (DelaunayTriangle triangle in poly.Triangles)
            {
                List <Vector2> v = new List <Vector2>();
                foreach (TriangulationPoint p in triangle.Points)
                {
                    v.Add(new Vector2((float)p.X, (float)p.Y));
                }
                results.Add(v);
            }

            return(results);
        }
        private void Delaunay()
        {
            var      pts = Points.Select(p => new TriangulationPoint(p.Key.x, p.Key.y)).ToList();
            PointSet set = new PointSet(pts);

            DTSweepContext tcx = new DTSweepContext();

            tcx.PrepareTriangulation(set);
            DTSweep.Triangulate(tcx);

            Triangles.Clear();
            foreach (DelaunayTriangle triangle in set.Triangles)
            {
                List <Point3D> tri = new List <Point3D>();
                foreach (TriangulationPoint p in triangle.Points)
                {
                    Point2D p2d = new Point2D(p.X, p.Y);
                    tri.Add(new Point3D(p.X, p.Y, Points[p2d]));
                }
                Triangles.Add(new Triangle3(tri[0], tri[1], tri[2]));
            }
        }
    public int[] Triangulate(UnityEngine.Vector2[] verts)
    {
        PolygonPoint[] points = new PolygonPoint[verts.Length];
        for (int i = 0; i < verts.Length; i++)
        {
            points[i] = new PolygonPoint(verts[i].x, verts[i].y);
        }
        Polygon        polygon = new Polygon(points);
        DTSweepContext tcx     = new DTSweepContext();

        tcx.PrepareTriangulation(polygon);
        DTSweep.Triangulate(tcx);
        int[] resultPoints = new int[polygon.Triangles.Count * 3];
        int   idx          = 0;

        foreach (DelaunayTriangle triangle in polygon.Triangles)
        {
            resultPoints[idx++] = FindIndex(points, triangle.Points._0);
            resultPoints[idx++] = FindIndex(points, triangle.Points._1);
            resultPoints[idx++] = FindIndex(points, triangle.Points._2);
        }
        return(resultPoints);
    }
        private static List <Triangle2> DelaunayOfPointSet(List <Point2D> points)
        {
            var      pts = points.Select(p => new TriangulationPoint(p.x, p.y)).ToList();
            PointSet set = new PointSet(pts);

            DTSweepContext tcx = new DTSweepContext();

            tcx.PrepareTriangulation(set);
            DTSweep.Triangulate(tcx);

            var triangles = new List <Triangle2>();

            foreach (DelaunayTriangle triangle in set.Triangles)
            {
                List <Point2D> tri = new List <Point2D>();
                foreach (TriangulationPoint p in triangle.Points)
                {
                    tri.Add(new Point2D(p.X, p.Y));
                }
                triangles.Add(new Triangle2(tri[0], tri[1], tri[2]));
            }
            return(triangles);
        }
Exemple #12
0
    /// <summary>
    /// Create a Mesh from a given Polygon.
    /// </summary>
    /// <returns>The freshly minted mesh.</returns>
    /// <param name="polygon">Polygon you want to triangulate.</param>
    public static Mesh CreateMesh(Polygon polygon)
    {
        // Check for the easy case (a triangle)
        if (polygon.holes.Count == 0 && (polygon.outside.Count == 3 ||
                                         (polygon.outside.Count == 4 && polygon.outside[3] == polygon.outside[0])))
        {
            return(CreateTriangle(polygon));
        }

        // Ensure we have the rotation properly calculated, and have a valid normal
        if (polygon.rotation == Quaternion.identity)
        {
            polygon.CalcRotation();
        }
        if (polygon.planeNormal == Vector3.zero)
        {
            return(null);                                                       // bad data
        }
        // Rotate 1 point and note where it ends up in Z
        float z = (polygon.rotation * polygon.outside[0]).z;

        // Prepare a map from vertex codes to 3D positions.
        Dictionary <uint, Vector3> codeToPosition = new Dictionary <uint, Vector3>();

        // Convert the outside points (throwing out Z at this point)
        Poly2Tri.Polygon poly = new Poly2Tri.Polygon(ConvertPoints(polygon.outside, polygon.rotation, codeToPosition));

        // Convert each of the holes
        foreach (List <Vector3> hole in polygon.holes)
        {
            poly.AddHole(new Poly2Tri.Polygon(ConvertPoints(hole, polygon.rotation, codeToPosition)));
        }

        // Triangulate it!  Note that this may throw an exception if the data is bogus.
        try {
            DTSweepContext tcx = new DTSweepContext();
            tcx.PrepareTriangulation(poly);
            DTSweep.Triangulate(tcx);
            tcx = null;
        } catch (System.Exception e) {
            throw e;
        }

        // Now, to get back to our original positions, use our code-to-position map.  We do
        // this instead of un-rotating to be a little more robust about noncoplanar polygons.

        // Create the Vector3 vertices (undoing the rotation),
        // and also build a map of vertex codes to indices
        Quaternion?            invRot      = null;
        Dictionary <uint, int> codeToIndex = new Dictionary <uint, int>();
        List <Vector3>         vertexList  = new List <Vector3>();

        foreach (DelaunayTriangle t in poly.Triangles)
        {
            foreach (var p in t.Points)
            {
                if (codeToIndex.ContainsKey(p.VertexCode))
                {
                    continue;
                }
                codeToIndex[p.VertexCode] = vertexList.Count;
                Vector3 pos;
                if (!codeToPosition.TryGetValue(p.VertexCode, out pos))
                {
                    // This can happen in rare cases when we're hitting limits of floating-point precision.
                    // Rather than fail, let's just do the inverse rotation.
                    if (!invRot.HasValue)
                    {
                        invRot = Quaternion.Inverse(polygon.rotation);
                    }
                    pos = invRot.Value * new Vector3(p.Xf, p.Yf, z);
                }
                vertexList.Add(pos);
            }
        }

        // Create the indices array
        int[] indices = new int[poly.Triangles.Count * 3];
        {
            int i = 0;
            foreach (DelaunayTriangle t in poly.Triangles)
            {
                indices[i++] = codeToIndex[t.Points[0].VertexCode];
                indices[i++] = codeToIndex[t.Points[1].VertexCode];
                indices[i++] = codeToIndex[t.Points[2].VertexCode];
            }
        }

        // Create the UV list, by looking up the closest point for each in our poly
        Vector2[] uv = null;
        if (polygon.outsideUVs != null)
        {
            uv = new Vector2[vertexList.Count];
            for (int i = 0; i < vertexList.Count; i++)
            {
                uv[i] = polygon.ClosestUV(vertexList[i]);
            }
        }

        // Create the mesh
        Mesh msh = new Mesh();

        msh.vertices  = vertexList.ToArray();
        msh.triangles = indices;
        msh.uv        = uv;
        msh.RecalculateNormals();
        msh.RecalculateBounds();
        return(msh);
    }
Exemple #13
0
    public static MeshProperties[] CreateMesh(List <BoundaryPoint> genPoly, Transform objTrans, float spriteSquareSize)
    {
        const int   _FRONTOFFSET     = 3;
        const float _BACKFACE_OFFSET = 0.5f;
        const float _SCALE_FACTOR    = 1.1f;

        MeshProperties _generatedMesh;
        MeshProperties _frontFaceMesh;

        Vector2[] _genPolyArrFront = new Vector2[genPoly.Count];

        List <VertexProperties> _verts = new List <VertexProperties>();
        List <VertexProperties> _frontFaceVerticies = new List <VertexProperties>();

        List <int> _indicies          = new List <int>();
        List <int> _frontFaceIndicies = new List <int>();

        //ConvertingToArray
        for (int i = 0; i < genPoly.Count; i++)
        {
            _genPolyArrFront[i] = objTrans.TransformPoint(genPoly[i].Pos);
        }

        Vector3 vecSum = Vector3.zero;

        //VerticiesFront
        for (int i = 0; i < genPoly.Count; i++)
        {
            Vector3 _position = new Vector3(_genPolyArrFront[i].x, _genPolyArrFront[i].y, 0.0f);

            vecSum += _position;

            _verts.Add(new VertexProperties {
                position = _position
            });
            _verts.Add(new VertexProperties {
                position = _position
            });
            _verts.Add(new VertexProperties {
                position = _position
            });

            _frontFaceVerticies.Add(new VertexProperties {
                position = _position
            });
        }

        //Calculating the center of the unscaled polygon
        Vector3 polygonCenter = vecSum / genPoly.Count;

        polygonCenter.z = objTrans.position.z;

        Matrix4x4 scaleMatrix = BlastProof.Mathematics.ScaleMatrix(_SCALE_FACTOR);

        Vector3 vecSum2 = Vector3.zero;

        //VerticiesBack
        for (int i = 0; i < genPoly.Count; i++)
        {
            Vector3 _position = scaleMatrix.MultiplyPoint(new Vector3(_genPolyArrFront[i].x, _genPolyArrFront[i].y, _BACKFACE_OFFSET));
            vecSum2 += _position;

            _verts.Add(new VertexProperties {
                position = _position
            });
            _verts.Add(new VertexProperties {
                position = _position
            });
            _verts.Add(new VertexProperties {
                position = _position
            });
        }

        Vector3 scaledPolyCenter = vecSum2 / genPoly.Count;

        scaledPolyCenter.z = objTrans.position.z;

        //Caching how much should the polygon move on axis so it matches the original scale polygon
        Vector3 translVec = polygonCenter - scaledPolyCenter;

        Matrix4x4 transMatrix = BlastProof.Mathematics.TranslateMatrix(translVec);

        //Multiplying each backface polygon position with the translation matrix so the center of backface polygon and frontface polygon matches
        for (int i = _verts.Count / 2; i < _verts.Count; i++)
        {
            _verts[i].position = transMatrix.MultiplyPoint(_verts[i].position);
        }

        var newGenPolyArrFront = new List <Poly2Tri.PolygonPoint>();

        for (int i = 0; i < _genPolyArrFront.Length; i++)
        {
            var point = new Poly2Tri.PolygonPoint(_genPolyArrFront[i].x, _genPolyArrFront[i].y);
            point.index = i;
            newGenPolyArrFront.Add(point);
        }

        Poly2Tri.Polygon poly = new Poly2Tri.Polygon(newGenPolyArrFront);

        DTSweepContext tcx = new DTSweepContext();

        tcx.PrepareTriangulation(poly);
        DTSweep.Triangulate(tcx);

        List <int> indiciesFromTriangulator = new List <int>();

        foreach (var triangle in poly.Triangles)
        {
            foreach (var point in triangle.Points)
            {
                indiciesFromTriangulator.Add(point.index);
            }
        }

        indiciesFromTriangulator.Reverse();

        Triangulator tri = new Triangulator(_genPolyArrFront);

        int[] triangledPoly = indiciesFromTriangulator.ToArray();

        //FrontFaceIndicies
        for (int i = 0; i < triangledPoly.Length; i++)
        {
            _indicies.Add(triangledPoly[i] * _FRONTOFFSET);
            _frontFaceIndicies.Add(triangledPoly[i]);
        }

        //BackFaceIndicies
        for (int i = triangledPoly.Length - 1; i >= 0; i--)
        {
            _indicies.Add(triangledPoly[i] * _FRONTOFFSET + (_verts.Count / 2));
        }

        //Front-Back Faces normals
        for (int i = 0; i < _indicies.Count / 2; i += 3)
        {
            int[] v1 = { _indicies[i], _indicies[(i + 1) % (_indicies.Count / 2)], _indicies[(i + 2) % (_indicies.Count / 2)] };
            int[] v2 = { _indicies[i + (_indicies.Count / 2)], _indicies[(i + 1) % (_indicies.Count / 2) + (_indicies.Count / 2)], _indicies[(i + 2) % (_indicies.Count / 2) + (_indicies.Count / 2)] };

            GetNormalsForVerts(_verts, v1);
            GetNormalsForVerts(_verts, v2);
            GetUVsWithSize(_verts, v1, Faces.forward, spriteSquareSize);
            GetUVsWithSize(_verts, v2, Faces.forward, spriteSquareSize);
        }

        //Generating Side Triangles
        for (int i = 1; i < _verts.Count / 2; i += 6)
        {
            int[] frontFaceVerts = { i, (i + 3) % (_verts.Count / 2) };
            int[] backFaceVerts  = { (i + (_verts.Count / 2)), (i + 3) % (_verts.Count / 2) + (_verts.Count / 2) };

            //verts pos are used as uvs
            int[] uvCoord = { i, (i + 3) % (_verts.Count / 2), (i + (_verts.Count / 2)), (i + 3) % (_verts.Count / 2) + (_verts.Count / 2) };

            GetQuadIndicies(frontFaceVerts, backFaceVerts, _indicies, _verts);

            GetUVsWithSize(_verts, uvCoord, Faces.left, spriteSquareSize);
        }

        //Generate Up-Down Verts
        for (int i = 5; i < _verts.Count / 2; i += 6)
        {
            int[] frontFaceVerts = { i % (_verts.Count / 2), (i + 3) % (_verts.Count / 2) };
            int[] backFaceVerts  = { (i % (_verts.Count / 2) + (_verts.Count / 2)),
                                     (i + 3) % (_verts.Count / 2) + (_verts.Count / 2) };

            //verts pos are used as uvs
            int[] uvCoord = { i % (_verts.Count / 2), (i + 3) % (_verts.Count / 2), (i % (_verts.Count / 2) + (_verts.Count / 2)), (i + 3) % (_verts.Count / 2) + (_verts.Count / 2) };

            GetQuadIndicies(frontFaceVerts, backFaceVerts, _indicies, _verts);
            GetUVsWithSize(_verts, uvCoord, Faces.up, spriteSquareSize);
        }

        _generatedMesh             = new MeshProperties(_verts);
        _generatedMesh.mesh_center = polygonCenter;
        _generatedMesh.SetIndicies(_indicies.ToArray());

        _frontFaceMesh             = new MeshProperties(_frontFaceVerticies);
        _frontFaceMesh.mesh_center = polygonCenter;
        _frontFaceMesh.SetIndicies(_frontFaceIndicies.ToArray());

        return(new MeshProperties[] { _generatedMesh, _frontFaceMesh });
    }
Exemple #14
0
        /// <summary>
        /// Given a set of points ordered counter-clockwise along a contour and a set of holes, return triangle indexes.
        /// </summary>
        /// <param name="points"></param>
        /// <param name="holes"></param>
        /// <param name="indexes">Indices outside of the points list index into holes when layed out linearly.
        /// {vertices 0,1,2...vertices.length-1, holes 0 values, hole 1 values etc.} </param>
        /// <returns></returns>
        public static bool Triangulate(IList <Vector2> points, IList <IList <Vector2> > holes, out List <int> indexes)
        {
            indexes = new List <int>();

            int index = 0;

            var allPoints = new List <Vector2>(points);

            Polygon polygon = new Polygon(points.Select(x => new PolygonPoint(x.x, x.y, index++)));

            if (holes != null)
            {
                for (int i = 0; i < holes.Count; i++)
                {
                    allPoints.AddRange(holes[i]);
                    var holePolgyon = new Polygon(holes[i].Select(x => new PolygonPoint(x.x, x.y, index++)));
                    polygon.AddHole(holePolgyon);
                }
            }

            try
            {
                triangulationContext.Clear();
                triangulationContext.PrepareTriangulation(polygon);
                DTSweep.Triangulate((DTSweepContext)triangulationContext);
            }
            catch (System.Exception e)
            {
                Log.Info("Triangulation failed: " + e.ToString());
                return(false);
            }

            foreach (DelaunayTriangle d in polygon.Triangles)
            {
                if (d.Points[0].Index < 0 || d.Points[1].Index < 0 || d.Points[2].Index < 0)
                {
                    Log.Info("Triangulation failed: Additional vertices were inserted.");
                    return(false);
                }

                indexes.Add(d.Points[0].Index);
                indexes.Add(d.Points[1].Index);
                indexes.Add(d.Points[2].Index);
            }

            WindingOrder originalWinding = SurfaceTopology.GetWindingOrder(points);

            // if the re-triangulated first tri doesn't match the winding order of the original
            // vertices, flip 'em

            if (SurfaceTopology.GetWindingOrder(new Vector2[3]
            {
                allPoints[indexes[0]],
                allPoints[indexes[1]],
                allPoints[indexes[2]],
            }) != originalWinding)
            {
                indexes.Reverse();
            }

            return(true);
        }
    public void CreateMesh(Vector2[] vertsToCopy, Transform transform)
    {
        List <Vector3> resultsLocal                   = new List <Vector3>();
        List <int>     resultsTriIndexesLocal         = new List <int>();
        List <int>     resultsTriIndexesReversedLocal = new List <int>();
        List <Vector2> uvsLocal     = new List <Vector2>();
        List <Vector3> normalsLocal = new List <Vector3>();

        Sprite  spr   = transform.GetComponent <SpriteRenderer>().sprite;
        Rect    rec   = spr.rect;
        Vector3 bound = transform.renderer.bounds.max - transform.renderer.bounds.min;


        TextureImporter textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(spr)) as TextureImporter;


        int i = 0;

        Polygon poly = new Polygon();

        for (i = 0; i < vertsToCopy.Length; i++)
        {
            poly.Points.Add(new TriangulationPoint(vertsToCopy[i].x, vertsToCopy[i].y));
        }

        DTSweepContext tcx = new DTSweepContext();

        tcx.PrepareTriangulation(poly);
        DTSweep.Triangulate(tcx);


        int  indexNumber  = 0;
        bool multiSprites = false;

        foreach (DelaunayTriangle triangle in poly.Triangles)
        {
            Vector3 v = new Vector3();
            foreach (TriangulationPoint p in triangle.Points)
            {
                v = new Vector3((float)p.X, (float)p.Y, 0);
                if (!resultsLocal.Contains(v))
                {
                    resultsLocal.Add(v);
                    resultsTriIndexesLocal.Add(indexNumber);
                    Vector2 newUv = new Vector2((v.x / bound.x) + 0.5f, (v.y / bound.y) + 0.5f);

                    newUv.x *= rec.width / spr.texture.width;
                    newUv.y *= rec.height / spr.texture.height;
                    //Debug.Log(spr.textureRectOffset);
                    newUv.x += (rec.x) / spr.texture.width;
                    newUv.y += (rec.y) / spr.texture.height;

                    //Debug.Log(Application.unityVersion);

                    SpriteMetaData[] smdArray = textureImporter.spritesheet;
                    Vector2          pivot    = new Vector2(.0f, .0f);;

                    for (int j = 0; j < smdArray.Length; j++)
                    {
                        if (smdArray[j].name == spr.name)
                        {
                            switch (smdArray[j].alignment)
                            {
                            case (0):
                                smdArray[j].pivot = Vector2.zero;
                                break;

                            case (1):
                                smdArray[j].pivot = new Vector2(0f, 1f) - new Vector2(.5f, .5f);
                                break;

                            case (2):
                                smdArray[j].pivot = new Vector2(0.5f, 1f) - new Vector2(.5f, .5f);
                                break;

                            case (3):
                                smdArray[j].pivot = new Vector2(1f, 1f) - new Vector2(.5f, .5f);
                                break;

                            case (4):
                                smdArray[j].pivot = new Vector2(0f, .5f) - new Vector2(.5f, .5f);
                                break;

                            case (5):
                                smdArray[j].pivot = new Vector2(1f, .5f) - new Vector2(.5f, .5f);
                                break;

                            case (6):
                                smdArray[j].pivot = new Vector2(0f, 0f) - new Vector2(.5f, .5f);
                                break;

                            case (7):
                                smdArray[j].pivot = new Vector2(0.5f, 0f) - new Vector2(.5f, .5f);
                                break;

                            case (8):
                                smdArray[j].pivot = new Vector2(1f, 0f) - new Vector2(.5f, .5f);
                                break;

                            case (9):
                                smdArray[j].pivot -= new Vector2(.5f, .5f);
                                break;
                            }
                            pivot = smdArray[j].pivot;
                        }
                    }
                    if (textureImporter.spriteImportMode == SpriteImportMode.Single)
                    {
                        pivot = textureImporter.spritePivot - new Vector2(.5f, .5f);
                    }
                    newUv.x += ((pivot.x) * rec.width) / spr.texture.width;
                    newUv.y += ((pivot.y) * rec.height) / spr.texture.height;

                    /*
                     * if(Application.unityVersion != "4.3.0f4")
                     * {
                     *
                     *      Debug.Log(spr.textureRectOffset.x);
                     *      newUv.x += (spr.textureRectOffset.x)/ spr.texture.width;
                     *      newUv.y += (spr.textureRectOffset.y)/ spr.texture.height;
                     * }
                     */
                    uvsLocal.Add(newUv);
                    normalsLocal.Add(new Vector3(0, 0, -1));


                    indexNumber++;
                }
                else
                {
                    resultsTriIndexesLocal.Add(resultsLocal.LastIndexOf(v));
                }
            }
        }
        if (!multiSprites)
        {
            Debug.Log("Tip: Sprite Pivot should be set to Center, with no custom pivot before conversion");
        }

        for (int j = resultsTriIndexesLocal.Count - 1; j >= 0; j--)
        {
            resultsTriIndexesReversedLocal.Add(resultsTriIndexesLocal[j]);
        }

        results.AddRange(resultsLocal);
        resultsTriIndexes.AddRange(resultsTriIndexesLocal);
        resultsTriIndexesReversed.AddRange(resultsTriIndexesReversedLocal);
        uvs.AddRange(uvsLocal);
        normals.AddRange(normalsLocal);

        resultsLocal.Clear();
        resultsTriIndexesLocal.Clear();
        resultsTriIndexesReversedLocal.Clear();
        uvsLocal.Clear();
        normalsLocal.Clear();

        finalVertices = results.ToArray();

        finalNormals = normals.ToArray();
        finalUvs     = uvs.ToArray();

        finalTriangles = resultsTriIndexesReversed.ToArray();

        //results.Clear();
        //resultsTriIndexesReversed.Clear();
    }
Exemple #16
0
    /// <summary>
    /// Create a Mesh from a given Polygon.
    /// </summary>
    /// <returns>The freshly minted mesh.</returns>
    /// <param name="polygon">Polygon you want to triangulate.</param>
    public static Mesh CreateMesh(Polygon polygon)
    {
        // Ensure we have the rotation properly calculated
        if (polygon.rotation == Quaternion.identity)
        {
            polygon.CalcRotation();
        }

        // Rotate 1 point and note where it ends up in Z
        float z = (polygon.rotation * polygon.outside[0]).z;

        // Convert the outside points (throwing out Z at this point)
        Poly2Tri.Polygon poly = new Poly2Tri.Polygon(ConvertPoints(polygon.outside, polygon.rotation));

        // Convert each of the holes
        foreach (List <Vector3> hole in polygon.holes)
        {
            poly.AddHole(new Poly2Tri.Polygon(ConvertPoints(hole, polygon.rotation)));
        }

        // Triangulate it!  Note that this may throw an exception if the data is bogus.
        DTSweepContext tcx = new DTSweepContext();

        tcx.PrepareTriangulation(poly);
        DTSweep.Triangulate(tcx);
        tcx = null;

        // Create the Vector3 vertices (undoing the rotation),
        // and also build a map of vertex codes to indices
        Quaternion             invRot      = Quaternion.Inverse(polygon.rotation);
        Dictionary <uint, int> codeToIndex = new Dictionary <uint, int>();
        List <Vector3>         vertexList  = new List <Vector3>();

        foreach (DelaunayTriangle t in poly.Triangles)
        {
            foreach (var p in t.Points)
            {
                if (codeToIndex.ContainsKey(p.VertexCode))
                {
                    continue;
                }
                codeToIndex[p.VertexCode] = vertexList.Count;
                Vector3 pos = new Vector3(p.Xf, p.Yf, z);                       // (restore the Z we saved earlier)
                vertexList.Add(invRot * pos);
            }
        }

        // Create the indices array
        int[] indices = new int[poly.Triangles.Count * 3];
        {
            int i = 0;
            foreach (DelaunayTriangle t in poly.Triangles)
            {
                indices[i++] = codeToIndex[t.Points[0].VertexCode];
                indices[i++] = codeToIndex[t.Points[1].VertexCode];
                indices[i++] = codeToIndex[t.Points[2].VertexCode];
            }
        }

        // Create the UV list, by looking up the closest point for each in our poly
        Vector2[] uv = null;
//		if (polygon.outsideUVs != null) {
//			uv = new Vector2[vertexList.Count];
//			for (int i=0; i<vertexList.Count; i++) {
//				uv[i] = polygon.ClosestUV(vertexList[i]);
//			}
//		}

        // Create the mesh
        Mesh msh = new Mesh();

        msh.vertices  = vertexList.ToArray();
        msh.triangles = indices;
        msh.uv        = uv;
        msh.RecalculateNormals();
        msh.RecalculateBounds();
        return(msh);
    }
Exemple #17
0
    private static Mesh CreateMesh(Sprite sprite, Vector2[] polygon)
    {
        if (sprite != null && polygon != null)
        {
            Rect bounds = GetBounds(polygon);

            DTSweepContext ctx  = new DTSweepContext();
            Polygon        poly = new Polygon(polygon.Select(p => new PolygonPoint(p.x, p.y)));

            ctx.PrepareTriangulation(poly);
            DTSweep.Triangulate(ctx);

            List <Vector2> verts = new List <Vector2>();
            List <int>     tris  = new List <int>();

            foreach (DelaunayTriangle tri in poly.Triangles)
            {
                verts.AddRange(tri.Points.Reverse().Select(p => new Vector2(p.Xf, p.Yf)));
                for (int i = 0; i < 3; i++)
                {
                    tris.Add(tris.Count);
                }
            }

            Mesh mesh = new Mesh();
            mesh.vertices  = verts.Select(x => (Vector3)x).ToArray();
            mesh.triangles = tris.ToArray();

            List <Vector2> uv = new List <Vector2>();

            Vector3 lower = new Vector3(bounds.x, bounds.y);
            Vector3 size  = new Vector3(bounds.xMax, bounds.yMax) - lower;

            Rect uvBounds = new Rect(sprite.rect.x / sprite.texture.width, sprite.rect.y / sprite.texture.height,
                                     sprite.rect.width / sprite.texture.width, sprite.rect.height / sprite.texture.height);

            float scalex = sprite.bounds.size.x / bounds.width;
            float scaley = sprite.bounds.size.y / bounds.height;

            Vector3[] scaled = mesh.vertices;

            for (int i = 0; i < mesh.vertices.Length; i++)
            {
                Vector3 v   = scaled[i];
                Vector3 rel = v - lower;
                uv.Add(new Vector2(rel.x / size.x * uvBounds.width, rel.y / size.y * uvBounds.height) +
                       new Vector2(uvBounds.x, uvBounds.y));

                scaled[i] = new Vector3(v.x * scalex, v.y * scaley, v.z) - ((Vector3)bounds.center * scalex) +
                            sprite.bounds.center;
            }

            mesh.vertices = scaled;
            mesh.uv       = uv.ToArray();
            mesh.RecalculateNormals();
            mesh.RecalculateBounds();
            mesh.Optimize();

            return(mesh);
        }

        return(null);
    }
Exemple #18
0
    /// <summary>
    /// Create a Mesh from a given Polygon.
    /// </summary>
    /// <returns>The freshly minted mesh.</returns>
    /// <param name="polygon">Polygon you want to triangulate.</param>
    public static bool CreateMesh(List <Poly2Mesh.Polygon> polygons, ref Mesh dstMesh)
    {
        // TODO: use vertex indices instead of actual vertices to find original vertices

        var poly2TriPolygons = new List <Poly2Tri.Polygon>();
        var codeToPositions  = new List <Dictionary <uint, Vector3> >();
        var zs = new List <float>();

        // Ensure we have the rotation properly calculated, and have a valid normal
        for (int p = 0; p < polygons.Count; p++)
        {
            if (polygons[p].rotation == Quaternion.identity)
            {
                polygons[p].CalcRotation();
            }
            if (polygons[p].planeNormal == Vector3.zero)
            {
                Debug.Log("polygons[p].planeNormal == Vector3.zero");
                return(false);       // bad data
            }

            // Rotate 1 point and note where it ends up in Z
            float z = (polygons[p].rotation * polygons[p].outside[0]).z;

            // Prepare a map from vertex codes to 3D positions.
            Dictionary <uint, Vector3> codeToPosition = new Dictionary <uint, Vector3>();

            // Convert the outside points (throwing out Z at this point)
            Poly2Tri.Polygon poly = new Poly2Tri.Polygon(ConvertPoints(polygons[p].outside, polygons[p].rotation, codeToPosition));


            // Convert each of the holes
            if (polygons[p].holes != null)
            {
                foreach (List <Vector3> hole in polygons[p].holes)
                {
                    poly.AddHole(new Poly2Tri.Polygon(ConvertPoints(hole, polygons[p].rotation, codeToPosition)));
                }
            }

            codeToPositions.Add(codeToPosition);
            poly2TriPolygons.Add(poly);
            zs.Add(z);
        }

        // Triangulate it!  Note that this may throw an exception if the data is bogus.
        for (int p = 0; p < poly2TriPolygons.Count; p++)
        {
            try
            {
                DTSweepContext tcx = new DTSweepContext();
                tcx.PrepareTriangulation(poly2TriPolygons[p]);
                DTSweep.Triangulate(tcx);
                tcx = null;
            } catch (System.Exception e) {
                //Profiler.Exit(profileID);
                Debug.LogException(e);
                //throw e;
            }
        }

        // Now, to get back to our original positions, use our code-to-position map.  We do
        // this instead of un-rotating to be a little more robust about noncoplanar polygons.

        // Create the Vector3 vertices (undoing the rotation),
        // and also build a map of vertex codes to indices
        Quaternion?            invRot      = null;
        Dictionary <uint, int> codeToIndex = new Dictionary <uint, int>();
        List <Vector3>         vertexList  = new List <Vector3>();
        List <int>             indexList   = new List <int>();
        int triangleCount = 0;

        for (int p = 0; p < polygons.Count; p++)
        {
            var poly           = poly2TriPolygons[p];
            var polygon        = polygons[p];
            var z              = zs[p];
            var codeToPosition = codeToPositions[p];
            triangleCount += poly.Triangles.Count;
            codeToIndex.Clear();
            foreach (DelaunayTriangle t in poly.Triangles)
            {
                foreach (var point in t.Points)
                {
                    if (codeToIndex.ContainsKey(point.VertexCode))
                    {
                        continue;
                    }
                    codeToIndex[point.VertexCode] = vertexList.Count;
                    Vector3 pos;
                    if (!codeToPosition.TryGetValue(point.VertexCode, out pos))
                    {
                        // This can happen in rare cases when we're hitting limits of floating-point precision.
                        // Rather than fail, let's just do the inverse rotation.
                        Debug.LogWarning("Vertex code lookup failed; using inverse rotation.");
                        if (!invRot.HasValue)
                        {
                            invRot = Quaternion.Inverse(polygon.rotation);
                        }
                        pos = invRot.Value * new Vector3(point.Xf, point.Yf, z);
                    }
                    vertexList.Add(pos);
                }
            }
            if (polygon.inverse)
            {
                foreach (DelaunayTriangle t in poly.Triangles)
                {
                    indexList.Add(codeToIndex[t.Points[2].VertexCode]);
                    indexList.Add(codeToIndex[t.Points[1].VertexCode]);
                    indexList.Add(codeToIndex[t.Points[0].VertexCode]);
                }
            }
            else
            {
                foreach (DelaunayTriangle t in poly.Triangles)
                {
                    indexList.Add(codeToIndex[t.Points[0].VertexCode]);
                    indexList.Add(codeToIndex[t.Points[1].VertexCode]);
                    indexList.Add(codeToIndex[t.Points[2].VertexCode]);
                }
            }
        }

        // Create the indices array
        var indices = indexList.ToArray();

        // Create the mesh
        dstMesh.vertices  = vertexList.ToArray();
        dstMesh.triangles = indices;
        dstMesh.RecalculateNormals();
        return(true);
    }
Exemple #19
0
    private void CreateMesh()
    {
        Sprite sprite = spriteRenderer.sprite;

        Rect bounds = GetBounds(polygon);

        DTSweepContext ctx  = new DTSweepContext();
        Polygon        poly = new Polygon(polygon.Select(p => new PolygonPoint(p.x, p.y)));

        ctx.PrepareTriangulation(poly);
        DTSweep.Triangulate(ctx);

        List <Vector2> verts = new List <Vector2>();
        List <int>     tris  = new List <int>();

        foreach (DelaunayTriangle tri in poly.Triangles)
        {
            verts.AddRange(tri.Points.Reverse().Select(p => new Vector2(p.Xf, p.Yf)));
            for (int i = 0; i < 3; i++)
            {
                tris.Add(tris.Count);
            }
        }

        Mesh mesh = new Mesh();

        mesh.vertices  = verts.Select(x => (Vector3)x).ToArray();
        mesh.triangles = tris.ToArray();

        List <Vector2> uv = new List <Vector2>();

        Vector3 lower = new Vector3(bounds.x, bounds.y);
        Vector3 size  = new Vector3(bounds.xMax, bounds.yMax) - lower;

        Rect uv_bounds = new Rect(sprite.rect.x / sprite.texture.width, sprite.rect.y / sprite.texture.height, sprite.rect.width / sprite.texture.width, sprite.rect.height / sprite.texture.height);

        float scalex = sprite.bounds.size.x / bounds.width;
        float scaley = sprite.bounds.size.y / bounds.height;

        Vector3[] scaled = mesh.vertices;

        for (int i = 0; i < mesh.vertices.Length; i++)
        {
            Vector3 v   = scaled[i];
            Vector3 rel = v - lower;
            uv.Add(new Vector2(rel.x / size.x * uv_bounds.width, rel.y / size.y * uv_bounds.height) + new Vector2(uv_bounds.x, uv_bounds.y));

            scaled[i] = new Vector3(v.x * scalex, v.y * scaley, v.z) - ((Vector3)bounds.center * scalex) + sprite.bounds.center;
        }

        mesh.vertices = scaled;
        mesh.uv       = uv.ToArray();
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
        mesh.Optimize();

        //GameObject go = new GameObject();
        //MeshFilter mf = go.AddComponent<MeshFilter>();
        //mf.sharedMesh = mesh;
        //MeshRenderer mr = go.AddComponent<MeshRenderer>();
        //mr.sharedMaterial = spriteRenderer.sharedMaterial;

        ScriptableObjectUtility.CreateAsset(mesh);
    }
Exemple #20
0
    public static Mesh CreateXYMesh(Polygon polygon)
    {
        //AML Maybe pass this as arg and reduce coords to XY
        float z = polygon.outside[0].z;

        // Check for the easy case (a triangle)
        if (polygon.holes.Count == 0 && (polygon.outside.Count == 3 ||
                                         (polygon.outside.Count == 4 && polygon.outside[3] == polygon.outside[0])))
        {
            return(CreateTriangle(polygon));
        }
        // Convert the outside points (throwing out Z at this point)
        Poly2Tri.Polygon poly = new Poly2Tri.Polygon(ConvertPoints(polygon.outside));
        // Convert each of the holes
        foreach (List <Vector3> hole in polygon.holes)
        {
            poly.AddHole(new Poly2Tri.Polygon(ConvertPoints(hole)));
        }
        // Triangulate it!  Note that this may throw an exception if the data is bogus.
        try {
            DTSweepContext tcx = new DTSweepContext();
            tcx.PrepareTriangulation(poly);
            DTSweep.Triangulate(tcx);
            tcx = null;
        } catch (System.Exception e) {
            //Profiler.Exit(profileID);
            throw e;
        }
        // Create the indices array
        Dictionary <uint, int> codeToIndex = new Dictionary <uint, int>();
        List <Vector3>         vertexList  = new List <Vector3>();

        foreach (DelaunayTriangle t in poly.Triangles)
        {
            foreach (var p in t.Points)
            {
                if (codeToIndex.ContainsKey(p.VertexCode))
                {
                    continue;
                }
                codeToIndex[p.VertexCode] = vertexList.Count;
                vertexList.Add(new Vector3(p.Xf, p.Yf, z));
            }
        }
        int[] indices = new int[poly.Triangles.Count * 3];
        {
            int i = 0;
            foreach (DelaunayTriangle t in poly.Triangles)
            {
                indices[i++] = codeToIndex[t.Points[0].VertexCode];
                indices[i++] = codeToIndex[t.Points[1].VertexCode];
                indices[i++] = codeToIndex[t.Points[2].VertexCode];
            }
        }

        // Create the UV list, by looking up the closest point for each in our poly
        Vector2[] uv = null;
        if (polygon.outsideUVs != null)
        {
            uv = new Vector2[vertexList.Count];
            for (int i = 0; i < vertexList.Count; i++)
            {
                uv[i] = polygon.ClosestUV(vertexList[i]);
            }
        }

        // Create the mesh
        Mesh msh = new Mesh();

        msh.vertices  = vertexList.ToArray();
        msh.triangles = indices;
        msh.uv        = uv;
        msh.RecalculateNormals();
        msh.RecalculateBounds();
        return(msh);
    }
    public static Mesh CreateMesh(Polygon polygon)
    {
        if (polygon.holes.Count == 0 && (polygon.outside.Count == 3 || (polygon.outside.Count == 4 && polygon.outside[3] == polygon.outside[0])))
        {
            return(CreateTriangle(polygon));
        }

        Dictionary <uint, Vector2> codeToPosition = new Dictionary <uint, Vector2>();

        Polygon2DTriangulation.Polygon poly = new Polygon2DTriangulation.Polygon(ConvertPoints(polygon.outside, codeToPosition));

        foreach (List <Vector2> hole in polygon.holes)
        {
            poly.AddHole(new Polygon2DTriangulation.Polygon(ConvertPoints(hole, codeToPosition)));
        }

        try {
            DTSweepContext tcx = new DTSweepContext();
            tcx.PrepareTriangulation(poly);
            DTSweep.Triangulate(tcx);
            tcx = null;
        } catch (System.Exception e) {
            throw(e);
        }

        Dictionary <uint, int> codeToIndex = new Dictionary <uint, int>();
        List <Vector2>         vertexList  = new List <Vector2>();

        foreach (DelaunayTriangle t in poly.Triangles)
        {
            foreach (var p in t.Points)
            {
                if (codeToIndex.ContainsKey(p.VertexCode))
                {
                    continue;
                }

                codeToIndex[p.VertexCode] = vertexList.Count;

                Vector2 pos;
                if (!codeToPosition.TryGetValue(p.VertexCode, out pos))
                {
                    pos = new Vector2(p.Xf, -p.Yf);
                }

                vertexList.Add(pos);
            }
        }

        int[] indices = new int[poly.Triangles.Count * 3];
        {
            int i = 0;
            foreach (DelaunayTriangle t in poly.Triangles)
            {
                indices[i++] = codeToIndex[t.Points[0].VertexCode];
                indices[i++] = codeToIndex[t.Points[1].VertexCode];
                indices[i++] = codeToIndex[t.Points[2].VertexCode];
            }
        }

        Vector2[] uv = null;
        if (polygon.outsideUVs != null)
        {
            uv = new Vector2[vertexList.Count];
            for (int i = 0; i < vertexList.Count; i++)
            {
                uv[i] = polygon.ClosestUV(vertexList[i]);
            }
        }

        return(CreateMesh(vertexList.ToArray(), indices, uv));
    }