using System.Collections.Generic; using UnityEngine; public class DrawShape : MonoBehaviour { // List of Vector3 points that define the shape public List points; public Material material; public void Draw(List list, Vector3 offset) { Vector3 startPoint = list[0]; Vector3 endPoint = list[list.Count - 1]; List newPoints = new List(); newPoints.Add(startPoint+ offset); newPoints.AddRange(list); newPoints.Add(endPoint+ offset); points = newPoints; if (points == null || points.Count < 3) { Debug.LogError("You need at least 3 points to define a shape."); return; } // Create a new GameObject to hold the mesh GameObject shapeObject = new GameObject("Shape"); shapeObject.transform.parent = transform; shapeObject.transform.localPosition = Vector3.zero; // Add MeshFilter and MeshRenderer components MeshFilter meshFilter = shapeObject.AddComponent(); MeshRenderer meshRenderer = shapeObject.AddComponent(); // Create the mesh and assign it to the MeshFilter Mesh mesh = new Mesh(); meshFilter.mesh = mesh; // Set the vertices from the points list mesh.vertices = points.ToArray(); // Triangulate the points int[] triangles = Triangulate(points); // Set the triangles mesh.triangles = triangles; // Recalculate normals and bounds mesh.RecalculateNormals(); mesh.RecalculateBounds(); // Set a basic material meshRenderer.material = material; } int[] Triangulate(List vertices) { // Simple ear clipping triangulation algorithm for concave/convex polygons // Note: This is a very basic implementation and may not handle all cases. List indices = new List(); int n = vertices.Count; if (n < 3) return indices.ToArray(); int[] V = new int[n]; if (Area(vertices) > 0) { for (int v = 0; v < n; v++) V[v] = v; } else { for (int v = 0; v < n; v++) V[v] = (n - 1) - v; } int nv = n; int count = 2 * nv; for (int m = 0, v = nv - 1; nv > 2;) { if ((count--) <= 0) return indices.ToArray(); int u = v; if (nv <= u) u = 0; v = u + 1; if (nv <= v) v = 0; int w = v + 1; if (nv <= w) w = 0; if (Snip(vertices, u, v, w, nv, V)) { int a, b, c, s, t; a = V[u]; b = V[v]; c = V[w]; indices.Add(a); indices.Add(b); indices.Add(c); m++; for (s = v, t = v + 1; t < nv; s++, t++) V[s] = V[t]; nv--; count = 2 * nv; } } return indices.ToArray(); } float Area(List vertices) { int n = vertices.Count; float A = 0.0f; for (int p = n - 1, q = 0; q < n; p = q++) { Vector3 v0 = vertices[p]; Vector3 v1 = vertices[q]; A += v0.x * v1.y - v1.x * v0.y; } return A * 0.5f; } bool Snip(List vertices, int u, int v, int w, int n, int[] V) { int p; Vector3 A = vertices[V[u]]; Vector3 B = vertices[V[v]]; Vector3 C = vertices[V[w]]; if (Mathf.Epsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x)))) return false; for (p = 0; p < n; p++) { if ((p == u) || (p == v) || (p == w)) continue; Vector3 P = vertices[V[p]]; if (InsideTriangle(A, B, C, P)) return false; } return true; } bool InsideTriangle(Vector3 A, Vector3 B, Vector3 C, Vector3 P) { float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy; float cCROSSap, bCROSScp, aCROSSbp; ax = C.x - B.x; ay = C.y - B.y; bx = A.x - C.x; by = A.y - C.y; cx = B.x - A.x; cy = B.y - A.y; apx = P.x - A.x; apy = P.y - A.y; bpx = P.x - B.x; bpy = P.y - B.y; cpx = P.x - C.x; cpy = P.y - C.y; aCROSSbp = ax * bpy - ay * bpx; cCROSSap = cx * apy - cy * apx; bCROSScp = bx * cpy - by * cpx; return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); } }