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); }
/// <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); }
public static void Triangulate(TriangulationContext tcx) { switch (tcx.Algorithm) { case TriangulationAlgorithm.DTSweep: default: DTSweep.Triangulate((DTSweepContext)tcx); break; } }
/// <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); }
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); } }
/// <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); }
/// <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); }
/// <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); }
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 }); }
/// <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(); }
/// <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); }
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); }
/// <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); }
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); }
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)); }