void Triangulate(List<Dictionary<int, int>> contours, Math.Plane plane, List<Vector3>[] vertices, List<Vector3>[] normals, List<Vector2>[] uvs, List<Vector4>[] tangents, List<Color32>[] colors, List<int>[] triangles, bool uvCutMesh, bool useTangents, bool useColors, bool useNormals) { if (contours.Count == 0 || contours[0].Count < 3) { // Utils.Log("Contour empty!: "); return; } // prepare plane matrix var m = plane.GetPlaneMatrix(); var mInv = m.inverse; var zShit = 0.0f; var polygons = new List<Polygon>(contours.Count); // construct polygons from contours Polygon highAreaPoly = null; foreach (var ctr in contours) { var polygonPoints = new Vector2[ctr.Count]; var j = 0; foreach (var i in ctr.Values) { var p = mInv*vertices[0][i]; polygonPoints[j++] = p; // save z-coordinate zShit = p.z; } var polygon = new Polygon(polygonPoints); polygons.Add(polygon); if (highAreaPoly == null || Mathf.Abs(highAreaPoly.Area) < Mathf.Abs(polygon.Area)) { highAreaPoly = polygon; } } ExploderUtils.Assert(polygons.Count > 0, "Zero polygons!"); // test for holes if (polygons.Count > 0) { var polyToRemove = new List<Polygon>(); foreach (var polygon in polygons) { if (polygon != highAreaPoly) { if (highAreaPoly.IsPointInside(polygon.Points[0])) { highAreaPoly.AddHole(polygon); polyToRemove.Add(polygon); } } } foreach (var polygon in polyToRemove) { polygons.Remove(polygon); } } var vertCounter0 = vertices[0].Count; var vertCounter1 = vertices[1].Count; foreach (var polygon in polygons) { var indices = polygon.Triangulate(); if (indices == null) { continue; } // get polygon bounding square size var min = Mathf.Min(polygon.Min.x, polygon.Min.y); var max = Mathf.Max(polygon.Max.x, polygon.Max.y); var polygonSize = max - min; // Utils.Log("PolygonSize: " + polygonSize + " " + polygon.Min + " " + polygon.Max); // Utils.Log("Triangulate polygons: " + polygon.Points.Length); foreach (var polyPoint in polygon.Points) { var p = m * new Vector3(polyPoint.x, polyPoint.y, zShit); vertices[0].Add(p); vertices[1].Add(p); if (useNormals) { normals[0].Add(-plane.Normal); normals[1].Add(plane.Normal); } if (uvCutMesh) { var uv0 = new Vector2((polyPoint.x - min)/polygonSize, (polyPoint.y - min)/polygonSize); var uv1 = new Vector2((polyPoint.x - min)/polygonSize, (polyPoint.y - min)/polygonSize); // normalize uv to fit cross-section uv area var areaSizeX = crossSectionUV.z - crossSectionUV.x; var areaSizeY = crossSectionUV.w - crossSectionUV.y; uv0.x = crossSectionUV.x + uv0.x * areaSizeX; uv0.y = crossSectionUV.y + uv0.y * areaSizeY; uv1.x = crossSectionUV.x + uv1.x * areaSizeX; uv1.y = crossSectionUV.y + uv1.y * areaSizeY; uvs[0].Add(uv0); uvs[1].Add(uv1); } else { uvs[0].Add(Vector2.zero); uvs[1].Add(Vector2.zero); } if (useTangents) { // fast and dirty way to create tangents var v0 = plane.Normal; MeshUtils.Swap(ref v0.x, ref v0.y); MeshUtils.Swap(ref v0.y, ref v0.z); Vector4 tangent = Vector3.Cross(plane.Normal, v0); tangent.w = 1.0f; tangents[0].Add(tangent); tangent.w = -1.0f; tangents[1].Add(tangent); } if (useColors) { colors[0].Add(crossSectionVertexColour); colors[1].Add(crossSectionVertexColour); } } var indicesCount = indices.Count; var j = indicesCount - 1; for (int i = 0; i < indicesCount; i++) { triangles[0].Add(vertCounter0 + indices[i]); triangles[1].Add(vertCounter1 + indices[j]); j--; } vertCounter0 += polygon.Points.Length; vertCounter1 += polygon.Points.Length; } }
/// <summary> /// add hole (polygon inside this polygon) /// </summary> /// <param name="polygon">polygon representing the hole</param> public void AddHole(Polygon polygon) { holes.Add(polygon); }
/// <summary> /// quick test if another polygon is inside this polygon /// </summary> /// <param name="polygon">testing polygon</param> /// <returns></returns> public bool IsPolygonInside(Polygon polygon) { if (Area > polygon.Area) { return IsPointInside(polygon.Points[0]); } return false; }
void Triangulate(List <Dictionary <int, int> > contours, Math.Plane plane, List <Vector3>[] vertices, List <Vector3>[] normals, List <Vector2>[] uvs, List <Vector4>[] tangents, List <Color32>[] colors, List <int>[] triangles, bool uvCutMesh, bool useTangents, bool useColors, bool useNormals) { if (contours.Count == 0 || contours[0].Count < 3) { // Utils.Log("Contour empty!: "); return; } // prepare plane matrix var m = plane.GetPlaneMatrix(); var mInv = m.inverse; var zShit = 0.0f; var polygons = new List <Polygon>(contours.Count); // construct polygons from contours Polygon highAreaPoly = null; foreach (var ctr in contours) { var polygonPoints = new Vector2[ctr.Count]; var j = 0; foreach (var i in ctr.Values) { var p = mInv * vertices[0][i]; polygonPoints[j++] = p; // save z-coordinate zShit = p.z; } var polygon = new Polygon(polygonPoints); polygons.Add(polygon); if (highAreaPoly == null || Mathf.Abs(highAreaPoly.Area) < Mathf.Abs(polygon.Area)) { highAreaPoly = polygon; } } ExploderUtils.Assert(polygons.Count > 0, "Zero polygons!"); // test for holes if (polygons.Count > 0) { var polyToRemove = new List <Polygon>(); foreach (var polygon in polygons) { if (polygon != highAreaPoly) { if (highAreaPoly.IsPointInside(polygon.Points[0])) { highAreaPoly.AddHole(polygon); polyToRemove.Add(polygon); } } } foreach (var polygon in polyToRemove) { polygons.Remove(polygon); } } var vertCounter0 = vertices[0].Count; var vertCounter1 = vertices[1].Count; foreach (var polygon in polygons) { var indices = polygon.Triangulate(); if (indices == null) { continue; } // get polygon bounding square size var min = Mathf.Min(polygon.Min.x, polygon.Min.y); var max = Mathf.Max(polygon.Max.x, polygon.Max.y); var polygonSize = max - min; // Utils.Log("PolygonSize: " + polygonSize + " " + polygon.Min + " " + polygon.Max); // Utils.Log("Triangulate polygons: " + polygon.Points.Length); foreach (var polyPoint in polygon.Points) { var p = m * new Vector3(polyPoint.x, polyPoint.y, zShit); vertices[0].Add(p); vertices[1].Add(p); if (useNormals) { normals[0].Add(-plane.Normal); normals[1].Add(plane.Normal); } if (uvCutMesh) { var uv0 = new Vector2((polyPoint.x - min) / polygonSize, (polyPoint.y - min) / polygonSize); var uv1 = new Vector2((polyPoint.x - min) / polygonSize, (polyPoint.y - min) / polygonSize); // normalize uv to fit cross-section uv area var areaSizeX = crossSectionUV.z - crossSectionUV.x; var areaSizeY = crossSectionUV.w - crossSectionUV.y; uv0.x = crossSectionUV.x + uv0.x * areaSizeX; uv0.y = crossSectionUV.y + uv0.y * areaSizeY; uv1.x = crossSectionUV.x + uv1.x * areaSizeX; uv1.y = crossSectionUV.y + uv1.y * areaSizeY; uvs[0].Add(uv0); uvs[1].Add(uv1); } else { uvs[0].Add(Vector2.zero); uvs[1].Add(Vector2.zero); } if (useTangents) { // fast and dirty way to create tangents var v0 = plane.Normal; MeshUtils.Swap(ref v0.x, ref v0.y); MeshUtils.Swap(ref v0.y, ref v0.z); Vector4 tangent = Vector3.Cross(plane.Normal, v0); tangent.w = 1.0f; tangents[0].Add(tangent); tangent.w = -1.0f; tangents[1].Add(tangent); } if (useColors) { colors[0].Add(crossSectionVertexColour); colors[1].Add(crossSectionVertexColour); } } var indicesCount = indices.Count; var j = indicesCount - 1; for (int i = 0; i < indicesCount; i++) { triangles[0].Add(vertCounter0 + indices[i]); triangles[1].Add(vertCounter1 + indices[j]); j--; } vertCounter0 += polygon.Points.Length; vertCounter1 += polygon.Points.Length; } }