├── LICENSE
├── PolygonMesh2D.cs
├── README.md
└── example.gif
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Tiger Oakes
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/PolygonMesh2D.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Linq;
3 | using System.Collections.Generic;
4 |
5 | [ExecuteInEditMode]
6 | [RequireComponent (typeof (PolygonCollider2D))]
7 | [RequireComponent (typeof (MeshRenderer))]
8 | [RequireComponent (typeof (MeshFilter))]
9 | ///
10 | /// Builds a Mesh for a gameObject using the PolygonCollider2D's path
11 | public class PolygonMesh2D : MonoBehaviour {
12 | protected PolygonCollider2D polygon;
13 | protected MeshFilter meshFilter;
14 |
15 | ///The index of the polygon path to use for the mesh
16 | int pathIndex = 0;
17 | ///The Z position for the generated mesh
18 | public float zPosition = 0f;
19 |
20 | void Start() {
21 | polygon = gameObject.GetComponent();
22 | meshFilter = gameObject.GetComponent();
23 | }
24 |
25 | #if UNITY_EDITOR
26 | ///
27 | ///(Re)builds the Mesh using the path of the PolygonCollider2D
28 | public void OnColliderUpdate() {
29 | Vector2[] path = polygon.GetPath(pathIndex);
30 | Mesh msh = new Mesh();
31 |
32 | msh.vertices = path.Select(v => new Vector3(v.x, v.y, zPosition)).ToArray();
33 | msh.triangles = new Triangulator(path).Triangulate();
34 |
35 | msh.RecalculateNormals();
36 | msh.RecalculateBounds();
37 | meshFilter.mesh = msh;
38 |
39 | //recalculate UV
40 | Bounds bounds = msh.bounds;
41 |
42 | msh.uv = path.Select(v => new Vector2(v.x / bounds.size.x, v.y / bounds.size.y)).ToArray();
43 | }
44 |
45 | void Update() {
46 | if (!Application.isPlaying) OnColliderUpdate();
47 | }
48 | #endif
49 | }
50 |
51 | class Triangulator {
52 | private List mPoints = new List();
53 |
54 | public Triangulator (Vector2[] points) {
55 | mPoints = new List(points);
56 | }
57 |
58 | public int[] Triangulate() {
59 | List indices = new List();
60 |
61 | int n = mPoints.Count;
62 | if (n < 3) return indices.ToArray();
63 |
64 | int[] V = new int[n];
65 | if (Area() > 0) {
66 | for (int v = 0; v < n; v++)
67 | V[v] = v;
68 | }
69 | else {
70 | for (int v = 0; v < n; v++)
71 | V[v] = (n - 1) - v;
72 | }
73 |
74 | int nv = n;
75 | int count = 2 * nv;
76 | for (int m = 0, v = nv - 1; nv > 2; ) {
77 | if ((count--) <= 0)
78 | return indices.ToArray();
79 |
80 | int u = v;
81 | if (nv <= u)
82 | u = 0;
83 | v = u + 1;
84 | if (nv <= v)
85 | v = 0;
86 | int w = v + 1;
87 | if (nv <= w)
88 | w = 0;
89 |
90 | if (Snip(u, v, w, nv, V)) {
91 | int a, b, c, s, t;
92 | a = V[u];
93 | b = V[v];
94 | c = V[w];
95 | indices.Add(a);
96 | indices.Add(b);
97 | indices.Add(c);
98 | m++;
99 | for (s = v, t = v + 1; t < nv; s++, t++)
100 | V[s] = V[t];
101 | nv--;
102 | count = 2 * nv;
103 | }
104 | }
105 |
106 | indices.Reverse();
107 | return indices.ToArray();
108 | }
109 |
110 | private float Area () {
111 | int n = mPoints.Count;
112 | float A = 0.0f;
113 | for (int p = n - 1, q = 0; q < n; p = q++) {
114 | Vector2 pval = mPoints[p];
115 | Vector2 qval = mPoints[q];
116 | A += pval.x * qval.y - qval.x * pval.y;
117 | }
118 | return (A * 0.5f);
119 | }
120 |
121 | private bool Snip (int u, int v, int w, int n, int[] V) {
122 | int p;
123 | Vector2 A = mPoints[V[u]];
124 | Vector2 B = mPoints[V[v]];
125 | Vector2 C = mPoints[V[w]];
126 | if (Mathf.Epsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x))))
127 | return false;
128 | for (p = 0; p < n; p++) {
129 | if ((p == u) || (p == v) || (p == w))
130 | continue;
131 | Vector2 P = mPoints[V[p]];
132 | if (InsideTriangle(A, B, C, P))
133 | return false;
134 | }
135 | return true;
136 | }
137 |
138 | private bool InsideTriangle (Vector2 A, Vector2 B, Vector2 C, Vector2 P) {
139 | float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
140 | float cCROSSap, bCROSScp, aCROSSbp;
141 |
142 | ax = C.x - B.x; ay = C.y - B.y;
143 | bx = A.x - C.x; by = A.y - C.y;
144 | cx = B.x - A.x; cy = B.y - A.y;
145 | apx = P.x - A.x; apy = P.y - A.y;
146 | bpx = P.x - B.x; bpy = P.y - B.y;
147 | cpx = P.x - C.x; cpy = P.y - C.y;
148 |
149 | aCROSSbp = ax * bpy - ay * bpx;
150 | cCROSSap = cx * apy - cy * apx;
151 | bCROSScp = bx * cpy - by * cpx;
152 |
153 | return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Polygon2D Editor for Unity
4 |
5 | 
6 |
7 | Uses the PolygonCollider2D collider to generate a mesh for a gameobject,
8 | letting you draw polygonal platforms in the Unity edtior via the Edit Collider button.
9 | Just drag the script onto your platform GameObject and you're good to go.
10 |
11 | This script uses the [Triangulator](http://wiki.unity3d.com/index.php?title=Triangulator) class.
12 |
13 | ## Installing / Getting started
14 |
15 | Just **[download the script](PolygonMesh2D.cs)** and place it somewhere inside your Unity project's assets.
16 | Everything needed in contained within one file.
17 |
18 | Use the component by dragging it onto a GameObject or by using the Add Component dialog. This will automatically add a Polygon Collider 2D component if it isn't already present.
19 |
20 | In the Polygon Collider 2D Component, click the "Edit Collider" button to adjust the shape of the collider. The mesh will autoatically adjust itself to fill the collider.
21 |
22 | ## Licensing
23 |
24 | Licsenced under the [MIT License](./LICENSE).
25 |
--------------------------------------------------------------------------------
/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NotWoods/unity-polygon-2d-editor/aa8ebd85e6a8eb22ddbb03b54b552688460ae9fc/example.gif
--------------------------------------------------------------------------------