private void ConstructPolygon() { List <PolygonPoint> p2 = new List <PolygonPoint>(); int i = 0, l = _points.Count; for (; i < l; i += 1) { p2.Add(new PolygonPoint(_points[i].x, _points[i].y)); } _polygon = new Polygon(p2); P2T.Triangulate(_polygon); // _loom.QueueOnMainThread(ContinueCreatingShape); ContinueCreatingShape(); }
private void ConstructPolygon() { List <PolygonPoint> p2 = new List <PolygonPoint>(); int i = 0, l = _points.Count; for (; i < l; i += 1) { p2.Add(new PolygonPoint(_points [i].x, _points [i].y)); } _polygon = new Polygon(p2); _polygon.Simplify(); P2T.Triangulate(_polygon); ContinueCreatingShape(); }
protected void InitializeVertexData() { if (primitiveType == PrimitiveType.LineList) { List <PolygonPoint> points = GetPoints(); foreach (PolygonPoint point in points) { // It seems silly to not just say "VertexPositionColor v = new VertexPositionColor(new Vector3(vertex, 0), color);" // but its actually a JIT optimization to make sure this statement always gets inlined. // Reference: Downloaded powerpoint (Understanding XNA Framework Performance) at http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=16477 VertexPositionColor vpc = new VertexPositionColor(); vpc.Position.X = (float)point.X; vpc.Position.Y = (float)point.Y; if (vertexPositionColors.Count > 1) { vertexPositionColors.Add(lastVertexPositionColor); } lastVertexPositionColor = vpc; vertexPositionColors.Add(vpc); } } else if (primitiveType == PrimitiveType.TriangleList) { Polygon polygon = GetPolygon(); P2T.Triangulate(polygon); PolygonCount = polygon.Triangles.Count; foreach (DelaunayTriangle triangle in polygon.Triangles) { foreach (TriangulationPoint point in triangle.Points) { VertexPositionColor vpc = new VertexPositionColor(); vpc.Position.X = (float)point.X; vpc.Position.Y = (float)point.Y; vertexPositionColors.Add(vpc); } } } tranformedVPCs = vertexPositionColors.ToArray(); }
/// <summary> /// Creates a <see cref="PrimitiveType.TriangleList"/> of vertices which cover the interior of the /// specified <paramref name="points"/>. The path must be closed and describe a simple polygon. /// </summary> /// <param name="points">Points describing the border of a simple polygon.</param> /// <param name="zCoord">Z coordinate of the created vertices.</param> /// <param name="verts">Returns a <see cref="PrimitiveType.TriangleList"/> of vertices.</param> public static void Triangulate(PointF[] points, float zCoord, out PositionColoredTextured[] verts) { PointF[] pathPoints = AdjustPoints(points); if (pathPoints.Length < 3) { verts = null; return; } if (pathPoints.Length == 3) { verts = new PositionColoredTextured[3]; verts[0].Position = new Vector3(pathPoints[0].X, pathPoints[0].Y, zCoord); verts[1].Position = new Vector3(pathPoints[1].X, pathPoints[1].Y, zCoord); verts[2].Position = new Vector3(pathPoints[2].X, pathPoints[2].Y, zCoord); return; } IList <DelaunayTriangle> polygons; try { // Triangulation can fail (i.e. polygon is self-intersecting) var poly = new Poly2Tri.Polygon(pathPoints.Select(p => new PolygonPoint(p.X, p.Y))); P2T.Triangulate(poly); polygons = poly.Triangles; } catch (Exception) { verts = null; return; } verts = new PositionColoredTextured[polygons.Count * 3]; int offset = 0; foreach (DelaunayTriangle triangle in polygons) { verts[offset++].Position = new Vector3((float)triangle.Points[0].X, (float)triangle.Points[0].Y, zCoord); verts[offset++].Position = new Vector3((float)triangle.Points[1].X, (float)triangle.Points[1].Y, zCoord); verts[offset++].Position = new Vector3((float)triangle.Points[2].X, (float)triangle.Points[2].Y, zCoord); } }
GameObject GenerateCountryRegionSurface(int countryIndex, int regionIndex, Material material, Vector2 textureScale, Vector2 textureOffset, float textureRotation) { if (countryIndex < 0 || countryIndex >= _countries.Length) { return(null); } Country country = _countries [countryIndex]; Region region = country.regions [regionIndex]; if (region.points.Length < 3) { return(null); } Poly2Tri.Polygon poly = new Poly2Tri.Polygon(region.points); // Extracts enclaves from main region if (_enableEnclaves && regionIndex == country.mainRegionIndex) { // Remove negative provinces if (_showProvinces) { CountrySubstractProvinceEnclaves(countryIndex, region, poly); } else { CountrySubstractCountryEnclaves(countryIndex, region, poly); } } P2T.Triangulate(poly); // Prepare surface cache entry and deletes older surface if exists int cacheIndex = GetCacheIndexForCountryRegion(countryIndex, regionIndex); string id = cacheIndex.ToString(); // Creates surface mesh GameObject surf = Drawing.CreateSurface(id, poly, material, region.rect2D, textureScale, textureOffset, textureRotation, disposalManager); ParentObjectToRegion(id, COUNTRY_SURFACES_ROOT_NAME, surf); surfaces [cacheIndex] = surf; return(surf); }
private VertexPositionTexture[] createVerticesFromPoints(List <Vector2> points, out int primitiveCount) { List <PolygonPoint> p2tPoints = new List <PolygonPoint>(); Polygon polygon; Vector2 topLeft = points[0]; Vector2 bottomRight = points[0]; VertexPositionTexture[] vertices; int index = 0; foreach (Vector2 v in points) { p2tPoints.Add(new PolygonPoint(v.X, v.Y)); topLeft = Vector2.Min(v, topLeft); bottomRight = Vector2.Max(v, bottomRight); } polygon = new Polygon(p2tPoints); P2T.Triangulate(polygon); primitiveCount = polygon.Triangles.Count; vertices = new VertexPositionTexture[primitiveCount * 3]; foreach (DelaunayTriangle triangle in polygon.Triangles) { Vector2 p1 = new Vector2(triangle.Points[0].Xf, triangle.Points[0].Yf); Vector2 p2 = new Vector2(triangle.Points[1].Xf, triangle.Points[1].Yf); Vector2 p3 = new Vector2(triangle.Points[2].Xf, triangle.Points[2].Yf); vertices[index++] = new VertexPositionTexture( new Vector3(p1, 0), (p1 - topLeft) / (bottomRight - topLeft)); vertices[index++] = new VertexPositionTexture( new Vector3(p2, 0), (p2 - topLeft) / (bottomRight - topLeft)); vertices[index++] = new VertexPositionTexture( new Vector3(p3, 0), (p3 - topLeft) / (bottomRight - topLeft)); } return(vertices); }
public void movePillars() { P1B.GetComponent <Rigidbody2D>().velocity = new Vector2((p1 - pillarSpeed), 0); p1T.GetComponent <Rigidbody2D>().velocity = new Vector2((p2 - pillarSpeed), 0); P2B.GetComponent <Rigidbody2D>().velocity = new Vector2((p3 - pillarSpeed), 0); P2T.GetComponent <Rigidbody2D>().velocity = new Vector2((p4 - pillarSpeed), 0); if (P1B.transform.position.x <= -6.35 && p1T.transform.position.x <= -6.35) { P1 = P2 = false; P1B.transform.position = new Vector3(6.31f, (int)UnityEngine.Random.RandomRange(-2f, -5f), -2.1f); p1T.transform.position = new Vector3(P1B.transform.position.x + 4f, (int)UnityEngine.Random.RandomRange(3f, 6f), -2.1f); } if (P2B.transform.position.x <= -6.35 && P2T.transform.position.x <= -6.35) { P3 = P4 = false; P2B.transform.position = new Vector3(6.31f, (int)UnityEngine.Random.RandomRange(-2f, -5f), -2.1f); P2T.transform.position = new Vector3(P2B.transform.position.x + 4f, (int)UnityEngine.Random.RandomRange(3f, 6f), -2.1f); } }
// Token: 0x060042B5 RID: 17077 RVA: 0x001556A8 File Offset: 0x00153AA8 public List <int> Triangulate() { List <PolygonPoint> list = new List <PolygonPoint>(this.Points.Length); foreach (Vector2 vector in this.Points) { list.Add(new PolygonPoint((double)vector.x, (double)vector.y)); } ThirdParty.P2T.Polygon polygon = new ThirdParty.P2T.Polygon(list); foreach (Polygon polygon2 in this.holes) { List <PolygonPoint> list2 = new List <PolygonPoint>(polygon2.Points.Length); foreach (Vector2 vector2 in polygon2.Points) { list2.Add(new PolygonPoint((double)vector2.x, (double)vector2.y)); } polygon.AddHole(new ThirdParty.P2T.Polygon(list2)); } P2T.Triangulate(polygon); int count = polygon.Triangles.Count; List <int> list3 = new List <int>(count * 3); this.Points = new Vector2[count * 3]; int num = 0; for (int k = 0; k < count; k++) { list3.Add(num); list3.Add(num + 1); list3.Add(num + 2); this.Points[num + 2].x = (float)polygon.Triangles[k].Points._0.X; this.Points[num + 2].y = (float)polygon.Triangles[k].Points._0.Y; this.Points[num + 1].x = (float)polygon.Triangles[k].Points._1.X; this.Points[num + 1].y = (float)polygon.Triangles[k].Points._1.Y; this.Points[num].x = (float)polygon.Triangles[k].Points._2.X; this.Points[num].y = (float)polygon.Triangles[k].Points._2.Y; num += 3; } return(list3); }
public override IStyleData Calculate(MarkupFiller filler, MarkupLOD lod) { var contour = filler.IsMedian ? SetMedianOffset(filler) : filler.Contour.Trajectories.ToArray(); if (NeedReverse(contour)) { contour = contour.Select(t => t.Invert()).Reverse().ToArray(); } var parts = contour.Select(t => StyleHelper.CalculateSolid(t, lod, (tr) => tr, MinAngle, MinLength, MaxLength)).ToArray(); for (var i = 0; i < parts.Length; i += 1) { var partI = parts[i]; var partJ = parts[(i + 1) % parts.Length]; if (!FindIntersects(partI, partJ, false)) { FindIntersects(partJ, partI, true); } } var points = parts.SelectMany(p => p).Select(t => t.StartPosition).ToArray(); if (points.Length < 3) { return(null); } var polygon = new Polygon(points.Select(p => new PolygonPoint(p.x, p.z))); P2T.Triangulate(polygon); var triangles = polygon.Triangles.SelectMany(t => t.Points.Select(p => polygon.IndexOf(p))).ToArray(); return(new MarkupStylePolygonMesh(filler.Markup.Height, Elevation, parts.Select(g => g.Count).ToArray(), points, triangles, MaterialType)); }
/// <summary> /// 使用Poly2Tri进行三角剖分 /// </summary> /// <param name="polygons"></param> /// <returns></returns> private static List <DelaunayTriangle> GenerateTriangles(List <List <IntPoint> > polygons) { //根据时针方向判断可走区域和障碍 var walkables = new List <Polygon>(); var blockeds = new List <Polygon>(); for (int i = 0; i < polygons.Count; i++) { var list = Convert(polygons[i]); if (IsCCW(polygons[i])) { walkables.Add(new Polygon(list)); } else { blockeds.Add(new Polygon(list)); } } //可以考虑添加SteinerPoint来避免生成狭长的三角形 //三角剖分 List <DelaunayTriangle> triangles = new List <DelaunayTriangle>(); for (int index = 0; index < walkables.Count; index++) { for (int i = 0; i < blockeds.Count; i++) { walkables[index].AddHole(blockeds[i]); } P2T.Triangulate(walkables[index]); triangles.AddRange(walkables[index].Triangles); } return(triangles); }
public static Mesh triangulate(Spline s, AXTexCoords tex) { Debug.Log("E"); if (s == null) { return(null); } // poly has verts that are delimeted by 8888888 for holes // 1. transpose points to poly2tri structures // 2. create mesh Polygon _polygon = null; List <PolygonPoint> _points = new List <PolygonPoint>(); for (int i = 0; i < s.controlVertices.Count; i++) { _points.Add(new PolygonPoint((double)s.controlVertices[i].x, (double)s.controlVertices[i].y)); } // POLYGON if (_points.Count >= 3) { _polygon = new Polygon(_points); } // populate the polygon triangles if (_polygon != null) { P2T.Triangulate(_polygon); return(polygon2mesh(_polygon, tex)); } return(null); }
public static List <List <OxyPlot.DataPoint> > TriangulatePolygon(List <OxyPlot.DataPoint> xyPoints) { int nVertices = xyPoints.Count; if (nVertices <= 0) { return(new List <List <OxyPlot.DataPoint> >()); } var points = new List <PolygonPoint>(); foreach (var xy in xyPoints) { points.Add(new PolygonPoint(xy.X, xy.Y)); } Polygon poly = new Polygon(points); P2T.Triangulate(poly); List <List <OxyPlot.DataPoint> > simpleShapes = new List <List <OxyPlot.DataPoint> >(); foreach (var triangle in poly.Triangles) { List <OxyPlot.DataPoint> simple = new System.Collections.Generic.List <OxyPlot.DataPoint>(); foreach (var pt in triangle.Points) { simple.Add(new OxyPlot.DataPoint(pt.X, pt.Y)); } simpleShapes.Add(simple); } return(simpleShapes); }
public void triangulate() { List <PolygonPoint> points = new List <PolygonPoint>(); PointListNode current = _headPoint; _polygonPosition = current.position; while (current != null) { _polygonPosition = Vector2.Min(current.position, _polygonPosition); points.Add(new PolygonPoint(current.position.X, current.position.Y)); current = current.next; } Polygon polygon = new Polygon(points); P2T.Triangulate(polygon); _primitiveCount = polygon.Triangles.Count; int index = 0; foreach (DelaunayTriangle triangle in polygon.Triangles) { for (int i = 0; i < 3; i++) { _vertices[index++] = new VertexPositionColorTexture( new Vector3(triangle.Points[i].Xf, triangle.Points[i].Yf, 0), Color.White, Vector2.Zero); } } if (_polygonTexture != null) { _polygonTexture.Dispose(); } _polygonTexture = _level.controller.view.renderPolygon(_vertices, _primitiveCount); }
private void CutPoly(Int3[] verts, int[] tris, ref Int3[] outVertsArr, ref int[] outTrisArr, out int outVCount, out int outTCount, Int3[] extraShape, Int3 cuttingOffset, Bounds realBounds, TileHandler.CutMode mode = TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual, int perturbate = -1) { if (verts.Length == 0 || tris.Length == 0) { outVCount = 0; outTCount = 0; outTrisArr = new int[0]; outVertsArr = new Int3[0]; return; } if (perturbate > 10) { Debug.LogError("Too many perturbations aborting.\nThis may cause a tile in the navmesh to become empty. Try to see see if any of your NavmeshCut or NavmeshAdd components use invalid custom meshes."); outVCount = verts.Length; outTCount = tris.Length; outTrisArr = tris; outVertsArr = verts; return; } List <IntPoint> list = null; if (extraShape == null && (mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0) { throw new Exception("extraShape is null and the CutMode specifies that it should be used. Cannot use null shape."); } if ((mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0) { list = ListPool <IntPoint> .Claim(extraShape.Length); for (int i = 0; i < extraShape.Length; i++) { list.Add(new IntPoint((long)(extraShape[i].x + cuttingOffset.x), (long)(extraShape[i].z + cuttingOffset.z))); } } IntRect bounds = new IntRect(verts[0].x, verts[0].z, verts[0].x, verts[0].z); for (int j = 0; j < verts.Length; j++) { bounds = bounds.ExpandToContain(verts[j].x, verts[j].z); } List <NavmeshCut> list2; if (mode == TileHandler.CutMode.CutExtra) { list2 = ListPool <NavmeshCut> .Claim(); } else { list2 = NavmeshCut.GetAllInRange(realBounds); } List <NavmeshAdd> allInRange = NavmeshAdd.GetAllInRange(realBounds); List <int> list3 = ListPool <int> .Claim(); List <TileHandler.Cut> list4 = TileHandler.PrepareNavmeshCutsForCutting(list2, cuttingOffset, bounds, perturbate, allInRange.Count > 0); List <Int3> list5 = ListPool <Int3> .Claim(verts.Length * 2); List <int> list6 = ListPool <int> .Claim(tris.Length); Int3[] array = verts; int[] array2 = tris; if (list2.Count == 0 && allInRange.Count == 0 && (mode & ~(TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual)) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0) { this.CopyMesh(array, array2, list5, list6); } else { List <IntPoint> list7 = ListPool <IntPoint> .Claim(); Dictionary <TriangulationPoint, int> dictionary = new Dictionary <TriangulationPoint, int>(); List <PolygonPoint> list8 = ListPool <PolygonPoint> .Claim(); PolyTree polyTree = new PolyTree(); List <List <IntPoint> > intermediateResult = new List <List <IntPoint> >(); Stack <Polygon> stack = new Stack <Polygon>(); this.clipper.StrictlySimple = (perturbate > -1); this.clipper.ReverseSolution = true; Int3[] array3 = null; Int3[] clipOut = null; Int2 @int = default(Int2); if (allInRange.Count > 0) { array3 = new Int3[7]; clipOut = new Int3[7]; @int = new Int2(((Int3)realBounds.extents).x, ((Int3)realBounds.extents).z); } int num = -1; int k = -3; for (;;) { k += 3; while (k >= array2.Length) { num++; k = 0; if (num >= allInRange.Count) { array = null; break; } if (array == verts) { array = null; } allInRange[num].GetMesh(cuttingOffset, ref array, out array2); } if (array == null) { break; } Int3 int2 = array[array2[k]]; Int3 int3 = array[array2[k + 1]]; Int3 int4 = array[array2[k + 2]]; if (VectorMath.IsColinearXZ(int2, int3, int4)) { Debug.LogWarning("Skipping degenerate triangle."); } else { IntRect a = new IntRect(int2.x, int2.z, int2.x, int2.z); a = a.ExpandToContain(int3.x, int3.z); a = a.ExpandToContain(int4.x, int4.z); int num2 = Math.Min(int2.y, Math.Min(int3.y, int4.y)); int num3 = Math.Max(int2.y, Math.Max(int3.y, int4.y)); list3.Clear(); bool flag = false; for (int l = 0; l < list4.Count; l++) { int x = list4[l].boundsY.x; int y = list4[l].boundsY.y; if (IntRect.Intersects(a, list4[l].bounds) && y >= num2 && x <= num3 && (list4[l].cutsAddedGeom || num == -1)) { Int3 int5 = int2; int5.y = x; Int3 int6 = int2; int6.y = y; list3.Add(l); flag |= list4[l].isDual; } } if (list3.Count == 0 && (mode & TileHandler.CutMode.CutExtra) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0 && num == -1) { list6.Add(list5.Count); list6.Add(list5.Count + 1); list6.Add(list5.Count + 2); list5.Add(int2); list5.Add(int3); list5.Add(int4); } else { list7.Clear(); if (num == -1) { list7.Add(new IntPoint((long)int2.x, (long)int2.z)); list7.Add(new IntPoint((long)int3.x, (long)int3.z)); list7.Add(new IntPoint((long)int4.x, (long)int4.z)); } else { array3[0] = int2; array3[1] = int3; array3[2] = int4; int num4 = this.ClipAgainstRectangle(array3, clipOut, new Int2(@int.x * 2, @int.y * 2)); if (num4 == 0) { continue; } for (int m = 0; m < num4; m++) { list7.Add(new IntPoint((long)array3[m].x, (long)array3[m].z)); } } dictionary.Clear(); for (int n = 0; n < 16; n++) { if ((mode >> (n & 31) & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0) { if (1 << n == 1) { this.CutAll(list7, list3, list4, polyTree); } else if (1 << n == 2) { if (!flag) { goto IL_9A0; } this.CutDual(list7, list3, list4, flag, intermediateResult, polyTree); } else if (1 << n == 4) { this.CutExtra(list7, list, polyTree); } for (int num5 = 0; num5 < polyTree.ChildCount; num5++) { PolyNode polyNode = polyTree.Childs[num5]; List <IntPoint> contour = polyNode.Contour; List <PolyNode> childs = polyNode.Childs; if (childs.Count == 0 && contour.Count == 3 && num == -1) { for (int num6 = 0; num6 < 3; num6++) { Int3 int7 = new Int3((int)contour[num6].X, 0, (int)contour[num6].Y); int7.y = TileHandler.SampleYCoordinateInTriangle(int2, int3, int4, int7); list6.Add(list5.Count); list5.Add(int7); } } else { Polygon polygon = null; int num7 = -1; for (List <IntPoint> list9 = contour; list9 != null; list9 = ((num7 >= childs.Count) ? null : childs[num7].Contour)) { list8.Clear(); for (int num8 = 0; num8 < list9.Count; num8++) { PolygonPoint polygonPoint = new PolygonPoint((double)list9[num8].X, (double)list9[num8].Y); list8.Add(polygonPoint); Int3 int8 = new Int3((int)list9[num8].X, 0, (int)list9[num8].Y); int8.y = TileHandler.SampleYCoordinateInTriangle(int2, int3, int4, int8); dictionary[polygonPoint] = list5.Count; list5.Add(int8); } Polygon polygon2; if (stack.Count > 0) { polygon2 = stack.Pop(); polygon2.AddPoints(list8); } else { polygon2 = new Polygon(list8); } if (num7 == -1) { polygon = polygon2; } else { polygon.AddHole(polygon2); } num7++; } try { P2T.Triangulate(polygon); } catch (PointOnEdgeException) { Debug.LogWarning("PointOnEdgeException, perturbating vertices slightly.\nThis is usually fine. It happens sometimes because of rounding errors. Cutting will be retried a few more times."); this.CutPoly(verts, tris, ref outVertsArr, ref outTrisArr, out outVCount, out outTCount, extraShape, cuttingOffset, realBounds, mode, perturbate + 1); return; } try { for (int num9 = 0; num9 < polygon.Triangles.Count; num9++) { DelaunayTriangle delaunayTriangle = polygon.Triangles[num9]; list6.Add(dictionary[delaunayTriangle.Points._0]); list6.Add(dictionary[delaunayTriangle.Points._1]); list6.Add(dictionary[delaunayTriangle.Points._2]); } } catch (KeyNotFoundException) { Debug.LogWarning("KeyNotFoundException, perturbating vertices slightly.\nThis is usually fine. It happens sometimes because of rounding errors. Cutting will be retried a few more times."); this.CutPoly(verts, tris, ref outVertsArr, ref outTrisArr, out outVCount, out outTCount, extraShape, cuttingOffset, realBounds, mode, perturbate + 1); return; } TileHandler.PoolPolygon(polygon, stack); } } } IL_9A0 :; } } } } ListPool <IntPoint> .Release(list7); ListPool <PolygonPoint> .Release(list8); } this.CompressMesh(list5, list6, ref outVertsArr, ref outTrisArr, out outVCount, out outTCount); for (int num10 = 0; num10 < list2.Count; num10++) { list2[num10].UsedForCut(); } ListPool <Int3> .Release(list5); ListPool <int> .Release(list6); ListPool <int> .Release(list3); for (int num11 = 0; num11 < list4.Count; num11++) { ListPool <IntPoint> .Release(list4[num11].contour); } ListPool <TileHandler.Cut> .Release(list4); ListPool <NavmeshCut> .Release(list2); }
protected override void OnPaint(PaintEventArgs e) { var fx = e.Graphics; if (string.IsNullOrEmpty(_font)) { return; } var ffamilly = new FontFamily(_font); FontStyle?fstyle = null; foreach (var style in new[] { FontStyle.Regular, FontStyle.Bold, FontStyle.Italic, FontStyle.Underline, FontStyle.Strikeout }) { if (!ffamilly.IsStyleAvailable(style)) { continue; } fstyle = style; break; } if (!fstyle.HasValue) { return; } var strChar = new string(_glyph, 1); var txtEM = fx.MeasureString("M", _txtFont).Height; SizeF szGlyph; fx.DrawString("Reference from GDI+", _txtFont, Brushes.Black, 0f, 0f); using (var tmpFnt = new Font(ffamilly, GlyphFontSize, fstyle.Value)) { szGlyph = fx.MeasureString(strChar, tmpFnt); fx.DrawString(strChar, tmpFnt, Brushes.Black, 0f, txtEM); fx.DrawRectangle(Pens.Blue, 0f, txtEM, szGlyph.Width, szGlyph.Height); } fx.TranslateTransform(0f, szGlyph.Height + txtEM * 2f); fx.DrawRectangle(Pens.Blue, 0f, 0f, szGlyph.Width, szGlyph.Height); { List <List <PolygonPoint> > points_list = new List <List <PolygonPoint> >(); var polygonList_bottom = GeneratePolygonsFromGlyph(fx, ffamilly, fstyle.Value, "管孟ABC12334455", ref points_list); double[] min; double[] max; GetBoundingBox(ref points_list, out min, out max); var polygonList_base = PolygonsInBox(ref polygonList_bottom, min, max); var polygonSet_bottom = CreateSetFromList(polygonList_bottom); var polygonSet_base = CreateSetFromList(polygonList_base); P2T.Triangulate(polygonSet_bottom); P2T.Triangulate(polygonSet_base); List <double> triangels = new List <double>(); double z_bottom = -20; double z_base = 0; FromPolygonSetToTriangles(polygonSet_bottom, z_bottom, triangels); FromPolygonSetToTriangles(polygonSet_base, z_base, triangels); GetTrianglesBetweenTwoZPlane(points_list, z_base, z_bottom, triangels); //reverse y for (int i = 1; i < triangels.Count; i += 3) { triangels[i] = max[1] - triangels[i]; } WriteStl(triangels, "d:\\temp\\triangles_all2.stl"); } try { List <List <PolygonPoint> > points_list = new List <List <PolygonPoint> >(); //var polygonList = GeneratePolygonsFromGlyph(fx, ffamilly, fstyle.Value, strChar); var polygonList_bottom = GeneratePolygonsFromGlyph(fx, ffamilly, fstyle.Value, "管孟辉", ref points_list); double[] min; double[] max; GetBoundingBox(ref points_list, out min, out max); var polygonList_base = PolygonsInBox(ref polygonList_bottom, min, max); fx.ResetTransform(); fx.DrawString( string.Format("{0} Paths from GDI:", polygonList_bottom.Count), _txtFont, Brushes.Black, 0f, szGlyph.Height + txtEM); if (polygonList_bottom.Count == 0) { fx.DrawString( "Empty Path - Nothing to Tessellate ....", _txtFont, Brushes.DarkGreen, szGlyph.Width + 2 * txtEM, 0f); return; } var polygonSet_bottom = CreateSetFromList(polygonList_bottom); var polygonSet_base = CreateSetFromList(polygonList_base); P2T.Triangulate(polygonSet_bottom); P2T.Triangulate(polygonSet_base); fx.TranslateTransform(szGlyph.Width + 2 * txtEM, txtEM); var sb = new SolidBrush(Color.FromArgb(128, Color.Gray)); var ip = 0; var totalTriangles = 0; foreach (var pol in polygonSet_bottom.Polygons) { var cPen = PathPens[ip % PathPens.Length]; ++ip; foreach (var tri in pol.Triangles) { var ptfs = new PointF[] { new PointF(tri.Points[0].Xf * TgMulti, tri.Points[0].Yf * TgMulti) , new PointF(tri.Points[1].Xf * TgMulti, tri.Points[1].Yf * TgMulti) , new PointF(tri.Points[2].Xf * TgMulti, tri.Points[2].Yf * TgMulti) }; fx.FillPolygon(sb, ptfs); fx.DrawPolygon(cPen, ptfs); ++totalTriangles; } } fx.ResetTransform(); fx.DrawString( string.Format("Polygons: {0} / Total Triangles: {1}", ((System.Collections.ICollection)polygonSet_bottom.Polygons).Count, totalTriangles), _txtFont, Brushes.Black, szGlyph.Width + 2 * txtEM, 0f); } catch (Exception ex) { fx.ResetTransform(); fx.DrawString("EXCEPTION!!", _txtFont, Brushes.Red, szGlyph.Width + 2 * txtEM, 0f); fx.DrawString(ex.ToString(), _txtFont, Brushes.Red, szGlyph.Width + 2 * txtEM, txtEM); } }
void MakeSection(List <Vector3> verts, List <int> facs, PolyNode polyNode) { if (polyNode.IsHole) { Debug.LogError("Found a hole where there's not meant to be one."); return; } List <PolygonPoint> polygonPointList = new List <PolygonPoint>(); foreach (IntPoint Outvertex in polyNode.Contour) { polygonPointList.Add(new PolygonPoint(Outvertex.X / floatMultiplier, Outvertex.Y / floatMultiplier)); } MakeWalls(verts, facs, polyNode.Contour); Polygon poly = new Polygon(polygonPointList); foreach (PolyNode holeNode in polyNode.Childs) { MakeWalls(verts, facs, holeNode.Contour); List <PolygonPoint> holePointList = new List <PolygonPoint>(); foreach (IntPoint Holevertex in holeNode.Contour) { holePointList.Add(new PolygonPoint(Holevertex.X / floatMultiplier, Holevertex.Y / floatMultiplier)); } Polygon hole = new Polygon(holePointList); poly.AddHole(hole); } P2T.Triangulate(poly); IList <DelaunayTriangle> tris = poly.Triangles; IList <TriangulationPoint> points = poly.Points; if (poly.Holes != null) { foreach (Polygon hole in (poly.Holes)) { foreach (TriangulationPoint point in hole.Points) { points.Add(point); } } } int startingIndex = verts.Count; foreach (TriangulationPoint point in points) { verts.Add(new Vector3(point.Xf, height, point.Yf)); } foreach (DelaunayTriangle tri in tris) { facs.Add(points.IndexOf(tri.Points._2) + startingIndex); facs.Add(points.IndexOf(tri.Points._1) + startingIndex); facs.Add(points.IndexOf(tri.Points._0) + startingIndex); } foreach (PolyNode holeNode in polyNode.Childs) { foreach (PolyNode childNode in holeNode.Childs) { MakeSection(verts, facs, childNode); } } }
GameObject GenerateProvinceRegionSurface(int provinceIndex, int regionIndex, Material material, Vector2 textureScale, Vector2 textureOffset, float textureRotation, bool temporary) { if (provinceIndex < 0 || provinceIndex >= provinces.Length) { return(null); } if (provinces [provinceIndex].regions == null) { ReadProvincePackedString(provinces [provinceIndex]); } if (provinces [provinceIndex].regions == null || regionIndex < 0 || regionIndex >= provinces [provinceIndex].regions.Count) { return(null); } Province province = provinces [provinceIndex]; Region region = province.regions [regionIndex]; if (!temporary) { region.customMaterial = material; region.customTextureOffset = textureOffset; region.customTextureRotation = textureRotation; region.customTextureScale = textureScale; UpdateSurfaceCount(); } // Triangulate to get the polygon vertex indices Poly2Tri.Polygon poly = new Poly2Tri.Polygon(region.latlon); if (_enableProvinceEnclaves && regionIndex == province.mainRegionIndex) { ProvinceSubstractProvinceEnclaves(provinceIndex, region, poly); } // Antarctica, Saskatchewan (Canada), British Columbia (Canada), Krasnoyarsk (Russia) - special cases due to its geometry float step = _frontiersDetail == FRONTIERS_DETAIL.High ? 2f : 5f; if (steinerPoints == null) { steinerPoints = new List <TriangulationPoint> (1000); } else { steinerPoints.Clear(); } float x0 = region.latlonRect2D.min.x + step / 2f; float x1 = region.latlonRect2D.max.x - step / 2f; float y0 = region.latlonRect2D.min.y + step / 2f; float y1 = region.latlonRect2D.max.y - step / 2f; for (float x = x0; x < x1; x += step) { for (float y = y0; y < y1; y += step) { float xp = x + UnityEngine.Random.Range(-0.0001f, 0.0001f); float yp = y + UnityEngine.Random.Range(-0.0001f, 0.0001f); if (region.Contains(xp, yp)) { steinerPoints.Add(new TriangulationPoint(xp, yp)); // GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Sphere); // obj.transform.SetParent(WorldMapGlobe.instance.transform, false); // obj.transform.localScale = Vector3.one * 0.01f; // obj.transform.localPosition = Conversion.GetSpherePointFromLatLon(new Vector2(x,y)) * 1.01f; } } } if (steinerPoints.Count > 0) { poly.AddSteinerPoints(steinerPoints); } P2T.Triangulate(poly); int flip1, flip2; if (_earthInvertedMode) { flip1 = 2; flip2 = 1; } else { flip1 = 1; flip2 = 2; } int triCount = poly.Triangles.Count; Vector3[] revisedSurfPoints = new Vector3[triCount * 3]; for (int k = 0; k < triCount; k++) { DelaunayTriangle dt = poly.Triangles [k]; revisedSurfPoints [k * 3] = Conversion.GetSpherePointFromLatLon(dt.Points [0].X, dt.Points [0].Y); revisedSurfPoints [k * 3 + flip1] = Conversion.GetSpherePointFromLatLon(dt.Points [1].X, dt.Points [1].Y); revisedSurfPoints [k * 3 + flip2] = Conversion.GetSpherePointFromLatLon(dt.Points [2].X, dt.Points [2].Y); } int revIndex = revisedSurfPoints.Length - 1; // Generate surface mesh int cacheIndex = GetCacheIndexForProvinceRegion(provinceIndex, regionIndex); GameObject surf = Drawing.CreateSurface(SURFACE_GAMEOBJECT, revisedSurfPoints, revIndex, material, region.rect2Dbillboard, textureScale, textureOffset, textureRotation); surf.transform.SetParent(surfacesLayer.transform, false); surf.transform.localPosition = Misc.Vector3zero; if (_earthInvertedMode) { surf.transform.localScale = Misc.Vector3one * 0.998f; } surfaces [cacheIndex] = surf; return(surf); }
public static Mesh triangulatePolyNode(PolyNode node, AXTexCoords tex, int seglenBigInt = 1000000) { //Debug.Log ("D " + seglenBigInt); Polygon _polygon = null; if (seglenBigInt < 10) { seglenBigInt = 999999; } List <Mesh> meshes = new List <Mesh>(); // Contour is Solid PolygonPoints _points = null; if (seglenBigInt > 0 && seglenBigInt != 9999999) { _points = AXGeometryTools.Utilities.path2polygonPts(Pather.segmentPath(Clipper.CleanPolygon(node.Contour), seglenBigInt)); } else { _points = AXGeometryTools.Utilities.path2polygonPts(Clipper.CleanPolygon(node.Contour)); } // POLYGON if (_points.Count >= 3) { _polygon = new Polygon(_points); } //Debug.Log ("_polygon="+_points.Count); // ADD HOLES TO POLYGON foreach (PolyNode subnode in node.Childs) { PolygonPoints hpoints = null; if (seglenBigInt > 0 && seglenBigInt != 9999999) { hpoints = AXGeometryTools.Utilities.path2polygonPts(Pather.segmentPath(Clipper.CleanPolygon(subnode.Contour), seglenBigInt)); } else { hpoints = AXGeometryTools.Utilities.path2polygonPts(Clipper.CleanPolygon(subnode.Contour)); } if (hpoints.Count >= 3) { _polygon.AddHole(new Polygon(hpoints)); } } try { // STEINER POINTS ClipperOffset co = new ClipperOffset(); co.AddPath(node.Contour, AXClipperLib.JoinType.jtSquare, AXClipperLib.EndType.etClosedPolygon); //addSteinerPointsAtAllOffsets(ref _polygon, ref co, seglenBigInt/AXGeometryTools.Utilities.IntPointPrecision, seglenBigInt); addSteinerPointsAtAllOffsets(ref _polygon, ref co, (float)seglenBigInt / ((float)AXGeometryTools.Utilities.IntPointPrecision), seglenBigInt); P2T.Triangulate(_polygon); meshes.Add(polygon2mesh(_polygon, tex)); } catch { //Debug.Log ("Can't triangulate: probably point on edge."); } // Continue down the tree... /* * foreach(PolyNode cnode in node.Childs) * { * Mesh submesh = triangulatePolyNode(cnode, tex); * if (submesh != null) * meshes.Add(submesh); * } */ CombineInstance[] combine = new CombineInstance[meshes.Count]; for (int i = 0; i < meshes.Count; i++) { combine[i].mesh = meshes[i]; combine[i].transform = Matrix4x4.identity; } Mesh mesh = new Mesh(); mesh.CombineMeshes(combine); mesh.RecalculateNormals(); return(mesh); }
public void CreateMesh(Vector2[] vertsToCopy, Transform transform, int triangleIndex) { 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.GetComponent <Renderer>().bounds.max - transform.GetComponent <Renderer>().bounds.min; TextureImporter textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(spr)) as TextureImporter; List <PolygonPoint> p2 = new List <PolygonPoint>(); if (triangleIndex > 0) { vertsToCopy = CreateSubVertPoints(spr.bounds, vertsToCopy.ToList(), triangleIndex).ToArray(); } int i = 0; for (i = 0; i < vertsToCopy.Count(); i++) { p2.Add(new PolygonPoint(vertsToCopy[i].x, vertsToCopy[i].y)); } Polygon _polygon = new Polygon(p2); if (triangleIndex > 0) { List <TriangulationPoint> triPoints = GenerateGridPoints(spr.bounds, triangleIndex, _polygon); _polygon.AddSteinerPoints(triPoints); } P2T.Triangulate(_polygon); int idx = 0; foreach (DelaunayTriangle triangle in _polygon.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(idx); 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; newUv.x += (rec.x) / spr.texture.width; newUv.y += (rec.y) / spr.texture.height; SpriteMetaData[] smdArray = textureImporter.spritesheet; Vector2 pivot = new Vector2(.0f, .0f);; for (int k = 0; k < smdArray.Length; k++) { if (smdArray[k].name == spr.name) { switch (smdArray[k].alignment) { case (0): smdArray[k].pivot = Vector2.zero; break; case (1): smdArray[k].pivot = new Vector2(0f, 1f) - new Vector2(.5f, .5f); break; case (2): smdArray[k].pivot = new Vector2(0.5f, 1f) - new Vector2(.5f, .5f); break; case (3): smdArray[k].pivot = new Vector2(1f, 1f) - new Vector2(.5f, .5f); break; case (4): smdArray[k].pivot = new Vector2(0f, .5f) - new Vector2(.5f, .5f); break; case (5): smdArray[k].pivot = new Vector2(1f, .5f) - new Vector2(.5f, .5f); break; case (6): smdArray[k].pivot = new Vector2(0f, 0f) - new Vector2(.5f, .5f); break; case (7): smdArray[k].pivot = new Vector2(0.5f, 0f) - new Vector2(.5f, .5f); break; case (8): smdArray[k].pivot = new Vector2(1f, 0f) - new Vector2(.5f, .5f); break; case (9): smdArray[k].pivot -= new Vector2(.5f, .5f); break; } pivot = smdArray[k].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; uvsLocal.Add(newUv); normalsLocal.Add(new Vector3(0, 0, -1)); idx++; } else { resultsTriIndexesLocal.Add(resultsLocal.LastIndexOf(v)); } } } 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(); }
/// <summary> /// This decomposites the provided ground chunk, supporting holes too. /// This will convert the ground chunk into a Polygon object that is then /// passed to the Poly2Tri library which returns the triangle arrays of /// decomposition. /// </summary> /// <param name="chunk"></param> private void Decomp(GroundChunk chunk) { List <PolygonPoint> edge = new List <PolygonPoint>(); for (int i = 0; i < chunk.Edge.Count; i++) { edge.Add(new PolygonPoint(chunk.Edge[i].x, chunk.Edge[i].y)); } List <Polygon> holes = new List <Polygon>(); if (chunk.Holes != null) { for (int i = 0; i < chunk.Holes.Count; i++) { List <PolygonPoint> hole = new List <PolygonPoint>(); for (int j = 0; j < chunk.Holes[i].Count; j++) { hole.Add(new PolygonPoint(chunk.Holes[i][j].x, chunk.Holes[i][j].y)); } holes.Add(new Polygon(hole)); } } Polygon poly = new Polygon(edge); for (int i = 0; i < holes.Count; i++) { poly.AddHole(holes[i]); } //Triangulate! P2T.Triangulate(poly); IList <TriangulationPoint> points = poly.Points; IList <DelaunayTriangle> tris = poly.Triangles; List <Vector2> finalPoints = new List <Vector2>(); int[] finalTris = new int[tris.Count * 3]; Dictionary <TriangulationPoint, int> pointToIndex = new Dictionary <TriangulationPoint, int>(); for (int t = 0; t < tris.Count; t++) { DelaunayTriangle tri = tris[t]; for (int i = 0; i < 3; i++) { //check if the points are in the dictionary, if not add it with the next index int val = 0; if (pointToIndex.TryGetValue(tri.Points[i], out val)) { finalTris[t * 3 + i] = val; } else { finalPoints.Add(new Vector2() { x = tri.Points[i].Xf, y = tri.Points[i].Yf }); pointToIndex[tri.Points[i]] = finalPoints.Count - 1; finalTris[t * 3 + i] = finalPoints.Count - 1; } } } Decomp result = new Decomp(); result.Points = finalPoints; result.Tris = finalTris; chunk.Poly = result; }
private TileHandler.CuttingResult CutPoly(Int3[] verts, int[] tris, Int3[] extraShape, GraphTransform graphTransform, IntRect tiles, TileHandler.CutMode mode = TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual, int perturbate = -1) { if (verts.Length == 0 || tris.Length == 0) { return(new TileHandler.CuttingResult { verts = ArrayPool <Int3> .Claim(0), tris = ArrayPool <int> .Claim(0) }); } if (perturbate > 10) { Debug.LogError("Too many perturbations aborting.\nThis may cause a tile in the navmesh to become empty. Try to see see if any of your NavmeshCut or NavmeshAdd components use invalid custom meshes."); return(new TileHandler.CuttingResult { verts = verts, tris = tris }); } List <IntPoint> list = null; if (extraShape == null && (mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0) { throw new Exception("extraShape is null and the CutMode specifies that it should be used. Cannot use null shape."); } Bounds tileBoundsInGraphSpace = this.graph.GetTileBoundsInGraphSpace(tiles); Vector3 min = tileBoundsInGraphSpace.min; GraphTransform graphTransform2 = graphTransform * Matrix4x4.TRS(min, Quaternion.identity, Vector3.one); Vector2 v = new Vector2(tileBoundsInGraphSpace.size.x, tileBoundsInGraphSpace.size.z); if ((mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0) { list = ListPool <IntPoint> .Claim(extraShape.Length); for (int i = 0; i < extraShape.Length; i++) { Int3 @int = graphTransform2.InverseTransform(extraShape[i]); list.Add(new IntPoint((long)@int.x, (long)@int.z)); } } IntRect cutSpaceBounds = new IntRect(verts[0].x, verts[0].z, verts[0].x, verts[0].z); for (int j = 0; j < verts.Length; j++) { cutSpaceBounds = cutSpaceBounds.ExpandToContain(verts[j].x, verts[j].z); } List <NavmeshCut> list2; if (mode == TileHandler.CutMode.CutExtra) { list2 = ListPool <NavmeshCut> .Claim(); } else { list2 = this.cuts.QueryRect <NavmeshCut>(tiles); } List <NavmeshAdd> list3 = this.cuts.QueryRect <NavmeshAdd>(tiles); List <int> list4 = ListPool <int> .Claim(); List <TileHandler.Cut> list5 = TileHandler.PrepareNavmeshCutsForCutting(list2, graphTransform2, cutSpaceBounds, perturbate, list3.Count > 0); List <Int3> list6 = ListPool <Int3> .Claim(verts.Length * 2); List <int> list7 = ListPool <int> .Claim(tris.Length); if (list2.Count == 0 && list3.Count == 0 && (mode & ~(TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual)) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0) { TileHandler.CopyMesh(verts, tris, list6, list7); } else { List <IntPoint> list8 = ListPool <IntPoint> .Claim(); Dictionary <TriangulationPoint, int> dictionary = new Dictionary <TriangulationPoint, int>(); List <PolygonPoint> list9 = ListPool <PolygonPoint> .Claim(); PolyTree polyTree = new PolyTree(); List <List <IntPoint> > list10 = ListPool <List <IntPoint> > .Claim(); Stack <Polygon> stack = StackPool <Polygon> .Claim(); this.clipper.StrictlySimple = (perturbate > -1); this.clipper.ReverseSolution = true; Int3[] array = null; Int3[] clipOut = null; Int2 size = default(Int2); if (list3.Count > 0) { array = new Int3[7]; clipOut = new Int3[7]; size = new Int2(((Int3)v).x, ((Int3)v).y); } Int3[] array2 = null; for (int k = -1; k < list3.Count; k++) { Int3[] array3; int[] array4; if (k == -1) { array3 = verts; array4 = tris; } else { list3[k].GetMesh(ref array2, out array4, graphTransform2); array3 = array2; } for (int l = 0; l < array4.Length; l += 3) { Int3 int2 = array3[array4[l]]; Int3 int3 = array3[array4[l + 1]]; Int3 int4 = array3[array4[l + 2]]; if (VectorMath.IsColinearXZ(int2, int3, int4)) { Debug.LogWarning("Skipping degenerate triangle."); } else { IntRect a = new IntRect(int2.x, int2.z, int2.x, int2.z); a = a.ExpandToContain(int3.x, int3.z); a = a.ExpandToContain(int4.x, int4.z); int num = Math.Min(int2.y, Math.Min(int3.y, int4.y)); int num2 = Math.Max(int2.y, Math.Max(int3.y, int4.y)); list4.Clear(); bool flag = false; for (int m = 0; m < list5.Count; m++) { int x = list5[m].boundsY.x; int y = list5[m].boundsY.y; if (IntRect.Intersects(a, list5[m].bounds) && y >= num && x <= num2 && (list5[m].cutsAddedGeom || k == -1)) { Int3 int5 = int2; int5.y = x; Int3 int6 = int2; int6.y = y; list4.Add(m); flag |= list5[m].isDual; } } if (list4.Count == 0 && (mode & TileHandler.CutMode.CutExtra) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0 && k == -1) { list7.Add(list6.Count); list7.Add(list6.Count + 1); list7.Add(list6.Count + 2); list6.Add(int2); list6.Add(int3); list6.Add(int4); } else { list8.Clear(); if (k == -1) { list8.Add(new IntPoint((long)int2.x, (long)int2.z)); list8.Add(new IntPoint((long)int3.x, (long)int3.z)); list8.Add(new IntPoint((long)int4.x, (long)int4.z)); } else { array[0] = int2; array[1] = int3; array[2] = int4; int num3 = this.ClipAgainstRectangle(array, clipOut, size); if (num3 == 0) { goto IL_9D3; } for (int n = 0; n < num3; n++) { list8.Add(new IntPoint((long)array[n].x, (long)array[n].z)); } } dictionary.Clear(); for (int num4 = 0; num4 < 16; num4++) { if ((mode >> (num4 & 31) & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0) { if (1 << num4 == 1) { this.CutAll(list8, list4, list5, polyTree); } else if (1 << num4 == 2) { if (!flag) { goto IL_9C4; } this.CutDual(list8, list4, list5, flag, list10, polyTree); } else if (1 << num4 == 4) { this.CutExtra(list8, list, polyTree); } for (int num5 = 0; num5 < polyTree.ChildCount; num5++) { PolyNode polyNode = polyTree.Childs[num5]; List <IntPoint> contour = polyNode.Contour; List <PolyNode> childs = polyNode.Childs; if (childs.Count == 0 && contour.Count == 3 && k == -1) { for (int num6 = 0; num6 < 3; num6++) { Int3 int7 = new Int3((int)contour[num6].X, 0, (int)contour[num6].Y); int7.y = TileHandler.SampleYCoordinateInTriangle(int2, int3, int4, int7); list7.Add(list6.Count); list6.Add(int7); } } else { Polygon polygon = null; int num7 = -1; for (List <IntPoint> list11 = contour; list11 != null; list11 = ((num7 >= childs.Count) ? null : childs[num7].Contour)) { list9.Clear(); for (int num8 = 0; num8 < list11.Count; num8++) { PolygonPoint polygonPoint = new PolygonPoint((double)list11[num8].X, (double)list11[num8].Y); list9.Add(polygonPoint); Int3 int8 = new Int3((int)list11[num8].X, 0, (int)list11[num8].Y); int8.y = TileHandler.SampleYCoordinateInTriangle(int2, int3, int4, int8); dictionary[polygonPoint] = list6.Count; list6.Add(int8); } Polygon polygon2; if (stack.Count > 0) { polygon2 = stack.Pop(); polygon2.AddPoints(list9); } else { polygon2 = new Polygon(list9); } if (num7 == -1) { polygon = polygon2; } else { polygon.AddHole(polygon2); } num7++; } try { P2T.Triangulate(polygon); } catch (PointOnEdgeException) { Debug.LogWarning("PointOnEdgeException, perturbating vertices slightly.\nThis is usually fine. It happens sometimes because of rounding errors. Cutting will be retried a few more times."); return(this.CutPoly(verts, tris, extraShape, graphTransform, tiles, mode, perturbate + 1)); } try { for (int num9 = 0; num9 < polygon.Triangles.Count; num9++) { DelaunayTriangle delaunayTriangle = polygon.Triangles[num9]; list7.Add(dictionary[delaunayTriangle.Points._0]); list7.Add(dictionary[delaunayTriangle.Points._1]); list7.Add(dictionary[delaunayTriangle.Points._2]); } } catch (KeyNotFoundException) { Debug.LogWarning("KeyNotFoundException, perturbating vertices slightly.\nThis is usually fine. It happens sometimes because of rounding errors. Cutting will be retried a few more times."); return(this.CutPoly(verts, tris, extraShape, graphTransform, tiles, mode, perturbate + 1)); } TileHandler.PoolPolygon(polygon, stack); } } } IL_9C4 :; } } } IL_9D3 :; } } if (array2 != null) { ArrayPool <Int3> .Release(ref array2, false); } StackPool <Polygon> .Release(stack); ListPool <List <IntPoint> > .Release(list10); ListPool <IntPoint> .Release(list8); ListPool <PolygonPoint> .Release(list9); } TileHandler.CuttingResult result = default(TileHandler.CuttingResult); Polygon.CompressMesh(list6, list7, out result.verts, out result.tris); for (int num10 = 0; num10 < list2.Count; num10++) { list2[num10].UsedForCut(); } ListPool <Int3> .Release(list6); ListPool <int> .Release(list7); ListPool <int> .Release(list4); for (int num11 = 0; num11 < list5.Count; num11++) { ListPool <IntPoint> .Release(list5[num11].contour); } ListPool <TileHandler.Cut> .Release(list5); ListPool <NavmeshCut> .Release(list2); return(result); }
// Token: 0x060005E2 RID: 1506 RVA: 0x000360CC File Offset: 0x000344CC private void CutPoly(Int3[] verts, int[] tris, ref Int3[] outVertsArr, ref int[] outTrisArr, out int outVCount, out int outTCount, Int3[] extraShape, Int3 cuttingOffset, Bounds realBounds, TileHandler.CutMode mode = (TileHandler.CutMode) 3, int perturbate = 0) { if (verts.Length == 0 || tris.Length == 0) { outVCount = 0; outTCount = 0; outTrisArr = new int[0]; outVertsArr = new Int3[0]; return; } List <IntPoint> list = null; if (extraShape == null && (mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0) { throw new Exception("extraShape is null and the CutMode specifies that it should be used. Cannot use null shape."); } if ((mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0) { list = new List <IntPoint>(extraShape.Length); for (int i = 0; i < extraShape.Length; i++) { list.Add(new IntPoint((long)(extraShape[i].x + cuttingOffset.x), (long)(extraShape[i].z + cuttingOffset.z))); } } List <IntPoint> list2 = new List <IntPoint>(5); Dictionary <TriangulationPoint, int> dictionary = new Dictionary <TriangulationPoint, int>(); List <PolygonPoint> list3 = new List <PolygonPoint>(); IntRect b = new IntRect(verts[0].x, verts[0].z, verts[0].x, verts[0].z); for (int j = 0; j < verts.Length; j++) { b = b.ExpandToContain(verts[j].x, verts[j].z); } List <Int3> list4 = ListPool <Int3> .Claim(verts.Length * 2); List <int> list5 = ListPool <int> .Claim(tris.Length); PolyTree polyTree = new PolyTree(); List <List <IntPoint> > list6 = new List <List <IntPoint> >(); Stack <Polygon> stack = new Stack <Polygon>(); if (this.clipper == null) { this.clipper = new Clipper(0); } this.clipper.ReverseSolution = true; List <NavmeshCut> list7; if (mode == TileHandler.CutMode.CutExtra) { list7 = ListPool <NavmeshCut> .Claim(); } else { list7 = NavmeshCut.GetAllInRange(realBounds); } List <int> list8 = ListPool <int> .Claim(); List <IntRect> list9 = ListPool <IntRect> .Claim(); List <Int2> list10 = ListPool <Int2> .Claim(); List <List <IntPoint> > list11 = new List <List <IntPoint> >(); List <bool> list12 = ListPool <bool> .Claim(); List <bool> list13 = ListPool <bool> .Claim(); if (perturbate > 10) { Debug.LogError("Too many perturbations aborting : " + mode); Debug.Break(); outVCount = verts.Length; outTCount = tris.Length; outTrisArr = tris; outVertsArr = verts; return; } System.Random random = null; if (perturbate > 0) { random = new System.Random(); } for (int k = 0; k < list7.Count; k++) { Bounds bounds = list7[k].GetBounds(); Int3 @int = (Int3)bounds.min + cuttingOffset; Int3 int2 = (Int3)bounds.max + cuttingOffset; IntRect a = new IntRect(@int.x, @int.z, int2.x, int2.z); if (IntRect.Intersects(a, b)) { Int2 int3 = new Int2(0, 0); if (perturbate > 0) { int3.x = random.Next() % 6 * perturbate - 3 * perturbate; if (int3.x >= 0) { int3.x++; } int3.y = random.Next() % 6 * perturbate - 3 * perturbate; if (int3.y >= 0) { int3.y++; } } int count = list11.Count; list7[k].GetContour(list11); for (int l = count; l < list11.Count; l++) { List <IntPoint> list14 = list11[l]; if (list14.Count == 0) { Debug.LogError("Zero Length Contour"); list9.Add(default(IntRect)); list10.Add(new Int2(0, 0)); } else { IntRect item = new IntRect((int)list14[0].X + cuttingOffset.x, (int)list14[0].Y + cuttingOffset.y, (int)list14[0].X + cuttingOffset.x, (int)list14[0].Y + cuttingOffset.y); for (int m = 0; m < list14.Count; m++) { IntPoint value = list14[m]; value.X += (long)cuttingOffset.x; value.Y += (long)cuttingOffset.z; if (perturbate > 0) { value.X += (long)int3.x; value.Y += (long)int3.y; } list14[m] = value; item = item.ExpandToContain((int)value.X, (int)value.Y); } list10.Add(new Int2(@int.y, int2.y)); list9.Add(item); list12.Add(list7[k].isDual); list13.Add(list7[k].cutsAddedGeom); } } } } List <NavmeshAdd> allInRange = NavmeshAdd.GetAllInRange(realBounds); Int3[] array = verts; int[] array2 = tris; int num = -1; int n = -3; Int3[] array3 = null; Int3[] array4 = null; Int3 int4 = Int3.zero; if (allInRange.Count > 0) { array3 = new Int3[7]; array4 = new Int3[7]; int4 = (Int3)realBounds.extents; } for (;;) { n += 3; while (n >= array2.Length) { num++; n = 0; if (num >= allInRange.Count) { array = null; break; } if (array == verts) { array = null; } allInRange[num].GetMesh(cuttingOffset, ref array, out array2); } if (array == null) { break; } Int3 int5 = array[array2[n]]; Int3 int6 = array[array2[n + 1]]; Int3 int7 = array[array2[n + 2]]; IntRect a2 = new IntRect(int5.x, int5.z, int5.x, int5.z); a2 = a2.ExpandToContain(int6.x, int6.z); a2 = a2.ExpandToContain(int7.x, int7.z); int num2 = Math.Min(int5.y, Math.Min(int6.y, int7.y)); int num3 = Math.Max(int5.y, Math.Max(int6.y, int7.y)); list8.Clear(); bool flag = false; for (int num4 = 0; num4 < list11.Count; num4++) { int x = list10[num4].x; int y = list10[num4].y; if (IntRect.Intersects(a2, list9[num4]) && y >= num2 && x <= num3 && (list13[num4] || num == -1)) { Int3 int8 = int5; int8.y = x; Int3 int9 = int5; int9.y = y; list8.Add(num4); flag |= list12[num4]; } } if (list8.Count == 0 && (mode & TileHandler.CutMode.CutExtra) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0 && num == -1) { list5.Add(list4.Count); list5.Add(list4.Count + 1); list5.Add(list4.Count + 2); list4.Add(int5); list4.Add(int6); list4.Add(int7); } else { list2.Clear(); if (num == -1) { list2.Add(new IntPoint((long)int5.x, (long)int5.z)); list2.Add(new IntPoint((long)int6.x, (long)int6.z)); list2.Add(new IntPoint((long)int7.x, (long)int7.z)); } else { array3[0] = int5; array3[1] = int6; array3[2] = int7; int num5 = Utility.ClipPolygon(array3, 3, array4, 1, 0, 0); if (num5 == 0) { continue; } num5 = Utility.ClipPolygon(array4, num5, array3, -1, 2 * int4.x, 0); if (num5 == 0) { continue; } num5 = Utility.ClipPolygon(array3, num5, array4, 1, 0, 2); if (num5 == 0) { continue; } num5 = Utility.ClipPolygon(array4, num5, array3, -1, 2 * int4.z, 2); if (num5 == 0) { continue; } for (int num6 = 0; num6 < num5; num6++) { list2.Add(new IntPoint((long)array3[num6].x, (long)array3[num6].z)); } } dictionary.Clear(); Int3 int10 = int6 - int5; Int3 int11 = int7 - int5; Int3 int12 = int10; Int3 int13 = int11; int12.y = 0; int13.y = 0; for (int num7 = 0; num7 < 16; num7++) { if ((mode >> (num7 & 31) & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0) { if (1 << num7 == 1) { this.clipper.Clear(); this.clipper.AddPolygon(list2, PolyType.ptSubject); for (int num8 = 0; num8 < list8.Count; num8++) { this.clipper.AddPolygon(list11[list8[num8]], PolyType.ptClip); } polyTree.Clear(); this.clipper.Execute(ClipType.ctDifference, polyTree, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero); } else if (1 << num7 == 2) { if (!flag) { goto IL_1161; } this.clipper.Clear(); this.clipper.AddPolygon(list2, PolyType.ptSubject); for (int num9 = 0; num9 < list8.Count; num9++) { if (list12[list8[num9]]) { this.clipper.AddPolygon(list11[list8[num9]], PolyType.ptClip); } } list6.Clear(); this.clipper.Execute(ClipType.ctIntersection, list6, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero); this.clipper.Clear(); for (int num10 = 0; num10 < list6.Count; num10++) { this.clipper.AddPolygon(list6[num10], (!Clipper.Orientation(list6[num10])) ? PolyType.ptSubject : PolyType.ptClip); } for (int num11 = 0; num11 < list8.Count; num11++) { if (!list12[list8[num11]]) { this.clipper.AddPolygon(list11[list8[num11]], PolyType.ptClip); } } polyTree.Clear(); this.clipper.Execute(ClipType.ctDifference, polyTree, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero); } else if (1 << num7 == 4) { this.clipper.Clear(); this.clipper.AddPolygon(list2, PolyType.ptSubject); this.clipper.AddPolygon(list, PolyType.ptClip); polyTree.Clear(); this.clipper.Execute(ClipType.ctIntersection, polyTree, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero); } for (int num12 = 0; num12 < polyTree.ChildCount; num12++) { PolyNode polyNode = polyTree.Childs[num12]; List <IntPoint> contour = polyNode.Contour; List <PolyNode> childs = polyNode.Childs; if (childs.Count == 0 && contour.Count == 3 && num == -1) { for (int num13 = 0; num13 < contour.Count; num13++) { Int3 item2 = new Int3((int)contour[num13].X, 0, (int)contour[num13].Y); double num14 = (double)(int6.z - int7.z) * (double)(int5.x - int7.x) + (double)(int7.x - int6.x) * (double)(int5.z - int7.z); if (num14 == 0.0) { Debug.LogWarning("Degenerate triangle"); } else { double num15 = ((double)(int6.z - int7.z) * (double)(item2.x - int7.x) + (double)(int7.x - int6.x) * (double)(item2.z - int7.z)) / num14; double num16 = ((double)(int7.z - int5.z) * (double)(item2.x - int7.x) + (double)(int5.x - int7.x) * (double)(item2.z - int7.z)) / num14; item2.y = (int)Math.Round(num15 * (double)int5.y + num16 * (double)int6.y + (1.0 - num15 - num16) * (double)int7.y); list5.Add(list4.Count); list4.Add(item2); } } } else { Polygon polygon = null; int num17 = -1; for (List <IntPoint> list15 = contour; list15 != null; list15 = ((num17 >= childs.Count) ? null : childs[num17].Contour)) { list3.Clear(); for (int num18 = 0; num18 < list15.Count; num18++) { PolygonPoint polygonPoint = new PolygonPoint((double)list15[num18].X, (double)list15[num18].Y); list3.Add(polygonPoint); Int3 item3 = new Int3((int)list15[num18].X, 0, (int)list15[num18].Y); double num19 = (double)(int6.z - int7.z) * (double)(int5.x - int7.x) + (double)(int7.x - int6.x) * (double)(int5.z - int7.z); if (num19 == 0.0) { Debug.LogWarning("Degenerate triangle"); } else { double num20 = ((double)(int6.z - int7.z) * (double)(item3.x - int7.x) + (double)(int7.x - int6.x) * (double)(item3.z - int7.z)) / num19; double num21 = ((double)(int7.z - int5.z) * (double)(item3.x - int7.x) + (double)(int5.x - int7.x) * (double)(item3.z - int7.z)) / num19; item3.y = (int)Math.Round(num20 * (double)int5.y + num21 * (double)int6.y + (1.0 - num20 - num21) * (double)int7.y); dictionary[polygonPoint] = list4.Count; list4.Add(item3); } } Polygon polygon2; if (stack.Count > 0) { polygon2 = stack.Pop(); polygon2.AddPoints(list3); } else { polygon2 = new Polygon(list3); } if (polygon == null) { polygon = polygon2; } else { polygon.AddHole(polygon2); } num17++; } try { P2T.Triangulate(polygon); } catch (PointOnEdgeException) { Debug.LogWarning(string.Concat(new object[] { "PointOnEdgeException, perturbating vertices slightly ( at ", num7, " in ", mode, ")" })); this.CutPoly(verts, tris, ref outVertsArr, ref outTrisArr, out outVCount, out outTCount, extraShape, cuttingOffset, realBounds, mode, perturbate + 1); return; } for (int num22 = 0; num22 < polygon.Triangles.Count; num22++) { DelaunayTriangle delaunayTriangle = polygon.Triangles[num22]; list5.Add(dictionary[delaunayTriangle.Points._0]); list5.Add(dictionary[delaunayTriangle.Points._1]); list5.Add(dictionary[delaunayTriangle.Points._2]); } if (polygon.Holes != null) { for (int num23 = 0; num23 < polygon.Holes.Count; num23++) { polygon.Holes[num23].Points.Clear(); polygon.Holes[num23].ClearTriangles(); if (polygon.Holes[num23].Holes != null) { polygon.Holes[num23].Holes.Clear(); } stack.Push(polygon.Holes[num23]); } } polygon.ClearTriangles(); if (polygon.Holes != null) { polygon.Holes.Clear(); } polygon.Points.Clear(); stack.Push(polygon); } } } IL_1161 :; } } } Dictionary <Int3, int> dictionary2 = this.cached_Int3_int_dict; dictionary2.Clear(); if (this.cached_int_array.Length < list4.Count) { this.cached_int_array = new int[Math.Max(this.cached_int_array.Length * 2, list4.Count)]; } int[] array5 = this.cached_int_array; int num24 = 0; for (int num25 = 0; num25 < list4.Count; num25++) { int num26; if (!dictionary2.TryGetValue(list4[num25], out num26)) { dictionary2.Add(list4[num25], num24); array5[num25] = num24; list4[num24] = list4[num25]; num24++; } else { array5[num25] = num26; } } outTCount = list5.Count; if (outTrisArr == null || outTrisArr.Length < outTCount) { outTrisArr = new int[outTCount]; } for (int num27 = 0; num27 < outTCount; num27++) { outTrisArr[num27] = array5[list5[num27]]; } outVCount = num24; if (outVertsArr == null || outVertsArr.Length < outVCount) { outVertsArr = new Int3[outVCount]; } for (int num28 = 0; num28 < outVCount; num28++) { outVertsArr[num28] = list4[num28]; } for (int num29 = 0; num29 < list7.Count; num29++) { list7[num29].UsedForCut(); } ListPool <Int3> .Release(list4); ListPool <int> .Release(list5); ListPool <int> .Release(list8); ListPool <Int2> .Release(list10); ListPool <bool> .Release(list12); ListPool <bool> .Release(list13); ListPool <IntRect> .Release(list9); ListPool <NavmeshCut> .Release(list7); }
/// <summary> /// Update mesh according to internally stored polygons /// </summary> void UpdateMap() { polygonCollider.pathCount = this.polygons.Count; Mesh mesh = GetComponent <MeshFilter>().mesh; mesh.Clear(); #region Triangulation List <IntPolygon> polyList = new List <IntPolygon>(); int indexCount = 0; foreach (Path p in this.polygons) { indexCount += p.Count; polyList.Add(new IntPolygon(IntPolygon.toPolygonPoints(p))); P2T.Triangulate(polyList[polyList.Count - 1]); } #endregion #region vertices and triangles Vector3[] vertices = new Vector3[indexCount]; int[][] triangless = new int[polyList.Count][]; int indexOffset = 0; //UnityEngine.Debug.Log("polygon count = " + polyList.Count); // join vertices to form an array of vertices for (int i = 0; i < polyList.Count; i++) { polyList[i].getVerticesVector3(MAP_SCALE).CopyTo(vertices, indexOffset); // also set collider paths (Vector3 implicitly converts to Vector2) polygonCollider.SetPath(i, polyList[i].getVerticesVector2(MAP_SCALE)); // retrieve triangles for each polygons triangless[i] = polyList[i].getTriangles(indexOffset); indexOffset += this.polygons[i].Count; } mesh.vertices = vertices; // count the total number of triangles int triangleCount = 0; foreach (int[] tri in triangless) { triangleCount += tri.Length; } // join triangles to form an array of triangles int triangleOffset = 0; int[] triangles = new int[triangleCount]; for (int i = 0; i < polyList.Count; i++) { triangless[i].CopyTo(triangles, triangleOffset); triangleOffset += triangless[i].Length; } mesh.triangles = triangles; #endregion #region UVs Vector2[] uv = new Vector2[mesh.vertices.Length]; for (int i = 0; i < mesh.vertices.Length; i++) { uv[i].Set(mesh.vertices[i].x, mesh.vertices[i].y); } mesh.uv = uv; #endregion Vector3[] normals = new Vector3[indexCount]; for (int i = 0; i < normals.Length; i++) { normals[i] = Vector3.back; } mesh.normals = normals; mesh.Optimize(); }
public static Mesh triangulate(AXSpline poly, float height, AXTexCoords tex) { // poly has verts that are delimeted by 8888888 for holes //Debug.Log ("F"); // 1. transpose points to poly2tri structures // 2. create mesh Polygon _polygon = null; List <AXSpline> parts = poly.getSolidAndHoles(); if (parts == null || parts.Count == 0) { return(null); } // CONTOUR AXSpline contour = parts[0]; List <PolygonPoint> _points = new List <PolygonPoint>(); for (int ii = 0; ii < contour.vertCount; ii++) { _points.Add(new PolygonPoint((double)contour.verts[ii].x, (double)contour.verts[ii].y)); } // POLYGON if (_points.Count >= 3) { _polygon = new Polygon(_points); // HOLES? if (parts.Count > 1) { for (int i = 1; i < parts.Count; i++) { List <PolygonPoint> _holepoints = new List <PolygonPoint>(); for (int ii = 0; ii < parts[i].vertCount; ii++) { _holepoints.Add(new PolygonPoint((double)parts[i].verts[ii].x, (double)parts[i].verts[ii].y)); } if (_holepoints.Count >= 3) { Polygon _hole = new Polygon(_holepoints); _polygon.AddHole(_hole); } } } } // populate the polygon triangles if (_polygon != null) { P2T.Triangulate(_polygon); return(polygon2mesh(_polygon, tex)); } return(null); }
public IEnumerable <MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals) { var width = box.Width; var length = Math.Max(1, Math.Abs((int)box.Length)); var height = box.Height; var flatten = (float)_flattenFactor.Value; var text = _text.GetValue(); var family = _fontChooser.GetFontFamily(); var style = Enum.GetValues(typeof(FontStyle)).OfType <FontStyle>().FirstOrDefault(fs => family.IsStyleAvailable(fs)); if (!family.IsStyleAvailable(style)) { family = FontFamily.GenericSansSerif; } var set = new PolygonSet(); var sizes = new List <RectangleF>(); using (var bmp = new Bitmap(1, 1)) { using (var g = System.Drawing.Graphics.FromImage(bmp)) { using (var font = new Font(family, length, style, GraphicsUnit.Pixel)) { for (var i = 0; i < text.Length; i += 32) { using (var sf = new StringFormat(StringFormat.GenericTypographic)) { var rem = Math.Min(text.Length, i + 32) - i; var range = Enumerable.Range(0, rem).Select(x => new CharacterRange(x, 1)).ToArray(); sf.SetMeasurableCharacterRanges(range); var reg = g.MeasureCharacterRanges(text.Substring(i, rem), font, new RectangleF(0, 0, float.MaxValue, float.MaxValue), sf); sizes.AddRange(reg.Select(x => x.GetBounds(g))); } } } } } var xOffset = box.Start.DX; var yOffset = box.End.DY; for (var ci = 0; ci < text.Length; ci++) { var c = text[ci]; var size = sizes[ci]; var gp = new GraphicsPath(); gp.AddString(c.ToString(CultureInfo.InvariantCulture), family, (int)style, length, new PointF(0, 0), StringFormat.GenericTypographic); gp.Flatten(new System.Drawing.Drawing2D.Matrix(), flatten); var polygons = new List <Polygon>(); var poly = new List <PolygonPoint>(); for (var i = 0; i < gp.PointCount; i++) { var type = gp.PathTypes[i]; var point = gp.PathPoints[i]; poly.Add(new PolygonPoint(point.X + xOffset, -point.Y + yOffset)); if ((type & 0x80) == 0x80) { polygons.Add(new Polygon(poly)); poly.Clear(); } } var tri = new List <Polygon>(); Polygon polygon = null; foreach (var p in polygons) { if (polygon == null) { polygon = p; tri.Add(p); } else if (p.CalculateWindingOrder() != polygon.CalculateWindingOrder()) { polygon.AddHole(p); } else { polygon = null; tri.Add(p); } } foreach (var pp in tri) { try { P2T.Triangulate(pp); set.Add(pp); } catch { // Ignore } } xOffset += size.Width; } var zOffset = box.Start.Z; foreach (var polygon in set.Polygons) { foreach (var t in polygon.Triangles) { var points = t.Points.Select(x => new Coordinate((decimal)x.X, (decimal)x.Y, zOffset).Round(roundDecimals)).ToList(); var faces = new List <Coordinate[]>(); // Add the vertical faces var z = new Coordinate(0, 0, height).Round(roundDecimals); for (var j = 0; j < points.Count; j++) { var next = (j + 1) % points.Count; faces.Add(new[] { points[j], points[j] + z, points[next] + z, points[next] }); } // Add the top and bottom faces faces.Add(points.ToArray()); faces.Add(points.Select(x => x + z).Reverse().ToArray()); // Nothing new here, move along var solid = new Solid(generator.GetNextObjectID()) { Colour = Colour.GetRandomBrushColour() }; foreach (var arr in faces) { var face = new Face(generator.GetNextFaceID()) { Parent = solid, Plane = new Plane(arr[0], arr[1], arr[2]), Colour = solid.Colour, Texture = { Texture = texture } }; face.Vertices.AddRange(arr.Select(x => new Vertex(x, face))); face.UpdateBoundingBox(); face.AlignTextureToFace(); solid.Faces.Add(face); } solid.UpdateBoundingBox(); yield return(solid); } } }
public static void TriangulateWithHoles(ArrayList vectors, List <ArrayList> holes, ref Mesh mesh, bool ceiling, bool twoSided, float y) { if (vectors.Count >= 3) { PolygonPoint[] c = new PolygonPoint[vectors.Count]; List <Vector3> list = new List <Vector3>(); Vector2[] vectorArray = new Vector2[vectors.Count]; List <int> list2 = null; for (int i = 0; i < vectors.Count; i++) { Vector2 vector = (Vector2)vectors[i]; c[i] = new PolygonPoint((double)vector.x, (double)vector.y); list.Add(new Vector3(vector.x, y, vector.y)); vectorArray[i] = new Vector2(vector.x, vector.y); } ArrayList list3 = new ArrayList(c); Polygon p = new Polygon(c); foreach (ArrayList list4 in holes) { List <PolygonPoint> list5 = new List <PolygonPoint>(); for (int k = 0; k < list4.Count; k++) { Vector2 vector2 = (Vector2)list4[k]; list5.Add(new PolygonPoint((double)vector2.x, (double)vector2.y)); list.Add(new Vector3(vector2.x, y, vector2.y)); } list3.AddRange(list5); p.AddHole(new Polygon(list5)); } P2T.Triangulate(p); list2 = new List <int>(); for (int j = 0; j < p.Triangles.Count; j++) { if (twoSided) { list2.Add(list3.IndexOf(p.Triangles[j].Points._2)); list2.Add(list3.IndexOf(p.Triangles[j].Points._1)); list2.Add(list3.IndexOf(p.Triangles[j].Points._0)); list2.Add(list3.IndexOf(p.Triangles[j].Points._0)); list2.Add(list3.IndexOf(p.Triangles[j].Points._1)); list2.Add(list3.IndexOf(p.Triangles[j].Points._2)); } else if (!ceiling) { list2.Add(list3.IndexOf(p.Triangles[j].Points._2)); list2.Add(list3.IndexOf(p.Triangles[j].Points._1)); list2.Add(list3.IndexOf(p.Triangles[j].Points._0)); } else { list2.Add(list3.IndexOf(p.Triangles[j].Points._0)); list2.Add(list3.IndexOf(p.Triangles[j].Points._1)); list2.Add(list3.IndexOf(p.Triangles[j].Points._2)); } } list2.TrimExcess(); list.TrimExcess(); mesh.vertices = list.ToArray(); mesh.triangles = list2.ToArray(); mesh.RecalculateBounds(); } }
void Triangulate() { // fill up the poly2tri container that holds our main mesh vertices List <PolygonPoint> points = new List <PolygonPoint>(); // fill them with our data foreach (var point in script.mainMeshVertices.vertices) { points.Add(new PolygonPoint(point.x, point.z)); } Polygon pointSet = new Polygon(points); // add our holes to the pointSet variable foreach (var hole in script.meshHoles) { var holeVerts = hole.vertices; if (holeVerts.Count >= 3) { List <PolygonPoint> pointsHole = new List <PolygonPoint>(); foreach (var point in holeVerts) { pointsHole.Add(new PolygonPoint(point.x, point.z)); } pointSet.AddHole(new Polygon(pointsHole)); } } P2T.Triangulate(pointSet); // to generate correct vertex indices for our triangulation we add all of the triangulation points into a single list ... List <TriangulationPoint> triangulationVertices = new List <TriangulationPoint>(); triangulationVertices.AddRange(pointSet.Points); // ... including the holes if (pointSet.Holes != null) { foreach (var holePoints in pointSet.Holes) { foreach (var point in holePoints.Points) { triangulationVertices.Add(point); } } } // create mesh MeshCollider mc = script.GetComponent <MeshCollider>(); // remove old mesh if it exists DeleteMesh(mc.sharedMesh); Mesh mesh = new Mesh(); mesh.name = "TeleportationAreaMesh_" + GetHashCode(); List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); foreach (var point in triangulationVertices) { vertices.Add(new Vector3(point.Xf, 0.0f, point.Yf)); } foreach (var tri in pointSet.Triangles) { triangles.Add(triangulationVertices.IndexOf(tri.Points[2])); triangles.Add(triangulationVertices.IndexOf(tri.Points[1])); triangles.Add(triangulationVertices.IndexOf(tri.Points[0])); } mesh.vertices = vertices.ToArray(); mesh.triangles = triangles.ToArray(); SaveMesh(mesh); mc.sharedMesh = mesh; EditorUtility.SetDirty(mc); // the SetDirty above doesn't do anything // our link to the just created mesh will be lost // when we switch scenes so we use this ugly workaround // below for now... EditorSceneManager.MarkAllScenesDirty(); EditorSceneManager.SaveOpenScenes(); }
/// <summary> /// Creates a triangulation of the vertices given, and gives you the indices of it. /// </summary> /// <param name="aPoints">A list of points to triangulate.</param> /// <param name="aTreatAsPath">Should we discard any triangles at all? Use this if you want to get rid of triangles that are outside the path.</param> /// <param name="aInvert">if we're treating it as a path, should we instead sicard triangles inside the path?</param> /// <param name="aInvertBorderSize">When inverted, how large should the border be in each direction?</param> /// <returns>A magical list of indices describing the triangulation!</returns> public static List <int> GetIndices(ref List <Vector2> aPoints, bool aTreatAsPath, bool aInvert, Vector2 aInvertBorderSize, float aVertGridSpacing = 0) { Vector4 bounds = GetBounds(aPoints); if (aVertGridSpacing > 0) { SplitEdges(ref aPoints, aVertGridSpacing); } List <PolygonPoint> verts = new List <PolygonPoint>(aPoints.Count); for (int i = 0; i < aPoints.Count; i++) { verts.Add(new PolygonPoint(aPoints[i].x, aPoints[i].y)); } Polygon poly; if (aInvert) { float width = aInvertBorderSize.x == 0 ? (bounds.z - bounds.x) : aInvertBorderSize.x; float height = aInvertBorderSize.y == 0 ? (bounds.y - bounds.w) : aInvertBorderSize.y; aPoints.Add(new Vector2(bounds.x - width, bounds.w - height)); aPoints.Add(new Vector2(bounds.z + width, bounds.w - height)); aPoints.Add(new Vector2(bounds.z + width, bounds.y + height)); aPoints.Add(new Vector2(bounds.x - width, bounds.y + height)); List <PolygonPoint> outer = new List <PolygonPoint>(4); for (int i = 0; i < 4; i++) { outer.Add(new PolygonPoint(aPoints[(aPoints.Count - 4) + i].x, aPoints[(aPoints.Count - 4) + i].y)); } poly = new Polygon(outer); poly.AddHole(new Polygon(verts)); } else { poly = new Polygon(verts); } if (aVertGridSpacing > 0) { if (aInvert) { bounds = GetBounds(aPoints); } for (float y = bounds.w + aVertGridSpacing; y <= bounds.y; y += aVertGridSpacing) { for (float x = bounds.x + aVertGridSpacing; x <= bounds.z; x += aVertGridSpacing) { TriangulationPoint pt = new TriangulationPoint(x, y); bool inside = poly.IsPointInside(pt); if (inside) { poly.AddSteinerPoint(pt); } } } } P2T.Triangulate(poly); aPoints.Clear(); List <int> result = new List <int>(poly.Triangles.Count * 3); int ind = 0; foreach (DelaunayTriangle triangle in poly.Triangles) { TriangulationPoint p1 = triangle.Points[0]; TriangulationPoint p2 = triangle.PointCWFrom(p1); TriangulationPoint p3 = triangle.PointCWFrom(p2); aPoints.Add(new Vector2(p1.Xf, p1.Yf)); aPoints.Add(new Vector2(p2.Xf, p2.Yf)); aPoints.Add(new Vector2(p3.Xf, p3.Yf)); result.Add(ind++); result.Add(ind++); result.Add(ind++); } return(result); }
public Mesh CreateMeshFromVerts(Vector3[] vertsToCopy, Mesh mesh, List <int> pathSplitIds, Transform SpriteGO = null) { 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 = null; Rect rec = new Rect(); Vector3 bound = Vector3.zero; TextureImporter textureImporter = new TextureImporter(); if (SpriteGO != null && SpriteGO.GetComponent <SpriteRenderer>() && SpriteGO.GetComponent <SpriteRenderer>().sprite) { spr = SpriteGO.GetComponent <SpriteRenderer>().sprite; rec = spr.rect; bound = SpriteGO.GetComponent <Renderer>().bounds.max - SpriteGO.GetComponent <Renderer>().bounds.min; textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(spr)) as TextureImporter; } List <PolygonPoint> p2 = new List <PolygonPoint>(); List <TriangulationPoint> extraPoints = new List <TriangulationPoint>(); int i = 0; for (i = 0; i < vertsToCopy.Count(); i++) { if (i < pathSplitIds[0]) { p2.Add(new PolygonPoint(vertsToCopy[i].x, vertsToCopy[i].y)); } else { extraPoints.Add(new TriangulationPoint(vertsToCopy[i].x, vertsToCopy[i].y)); } } Polygon _polygon = new Polygon(p2); // this is how to add more points _polygon.AddSteinerPoints(extraPoints); P2T.Triangulate(_polygon); if (spr == null) { bound = new Vector3((float)(_polygon.Bounds.MaxX - _polygon.Bounds.MinX), (float)(_polygon.Bounds.MaxY - _polygon.Bounds.MinY), 0); } int idx = 0; foreach (DelaunayTriangle triangle in _polygon.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(idx); Vector2 newUv = new Vector2(((v.x - (float)_polygon.Bounds.MinX) / bound.x), ((v.y - (float)_polygon.Bounds.MinY) / bound.y)); if (spr != null) { 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; newUv.x += (rec.x) / spr.texture.width; newUv.y += (rec.y) / spr.texture.height; SpriteMetaData[] smdArray = textureImporter.spritesheet; Vector2 pivot = new Vector2(.0f, .0f);; for (int k = 0; k < smdArray.Length; k++) { if (smdArray[k].name == spr.name) { switch (smdArray[k].alignment) { case (0): smdArray[k].pivot = Vector2.zero; break; case (1): smdArray[k].pivot = new Vector2(0f, 1f) - new Vector2(.5f, .5f); break; case (2): smdArray[k].pivot = new Vector2(0.5f, 1f) - new Vector2(.5f, .5f); break; case (3): smdArray[k].pivot = new Vector2(1f, 1f) - new Vector2(.5f, .5f); break; case (4): smdArray[k].pivot = new Vector2(0f, .5f) - new Vector2(.5f, .5f); break; case (5): smdArray[k].pivot = new Vector2(1f, .5f) - new Vector2(.5f, .5f); break; case (6): smdArray[k].pivot = new Vector2(0f, 0f) - new Vector2(.5f, .5f); break; case (7): smdArray[k].pivot = new Vector2(0.5f, 0f) - new Vector2(.5f, .5f); break; case (8): smdArray[k].pivot = new Vector2(1f, 0f) - new Vector2(.5f, .5f); break; case (9): smdArray[k].pivot -= new Vector2(.5f, .5f); break; } pivot = smdArray[k].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; } uvsLocal.Add(newUv); normalsLocal.Add(new Vector3(0, 0, -1)); idx++; } else { resultsTriIndexesLocal.Add(resultsLocal.LastIndexOf(v)); } } } 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(); mesh.vertices = finalVertices; mesh.triangles = finalTriangles; mesh.uv = finalUvs; mesh.normals = finalNormals; mesh = calculateMeshTangents(mesh); return(mesh); }
/// <summary> /// Creates an extruded version of a given region /// </summary> /// <returns>The generate extrude game object.</returns> /// <param name="name">Name.</param> /// <param name="extrusionAmount">Size of the extrusion.</param> /// <param name="region">Region.</param> /// <param name="material">Material.</param> /// <param name="textureScale">Texture scale.</param> /// <param name="textureOffset">Texture offset.</param> /// <param name="textureRotation">Texture rotation.</param> public GameObject RegionGenerateExtrudeGameObject(string name, Region region, float extrusionAmount, Material topMaterial, Material sideMaterial, Vector2 textureScale, Vector2 textureOffset, float textureRotation, bool useRegionRect = true) { if (region == null || region.points.Length < 3) { return(null); } Rect rect = useRegionRect ? region.rect2D : new Rect(0.5f, 0.5f, 1f, 1f); GameObject go = new GameObject(name); go.transform.SetParent(transform, false); Poly2Tri.Polygon poly = new Poly2Tri.Polygon(region.points); P2T.Triangulate(poly); // Creates surface mesh GameObject surf = Drawing.CreateSurface("RegionTop", poly, topMaterial, rect, textureScale, textureOffset, textureRotation, null); surf.transform.SetParent(go.transform, false); surf.transform.localPosition = new Vector3(0, 0, -extrusionAmount); // Create side band int pointCount = region.points.Length; Vector3[] vertices = new Vector3[pointCount * 2]; int[] indices = new int[pointCount * 6]; int vi = 0, ii = -1; for (int k = 0; k < pointCount; k++, vi += 2) { vertices[vi] = region.points[k]; vertices[vi].z = -extrusionAmount; vertices[vi + 1] = vertices[vi]; vertices[vi + 1].z = 0; if (k == pointCount - 1) { indices[++ii] = vi + 1; indices[++ii] = vi; indices[++ii] = 1; indices[++ii] = vi + 1; indices[++ii] = 1; indices[++ii] = 0; } else { indices[++ii] = vi; indices[++ii] = vi + 1; indices[++ii] = vi + 2; indices[++ii] = vi + 1; indices[++ii] = vi + 3; indices[++ii] = vi + 2; } } GameObject band = new GameObject("RegionBand"); band.transform.SetParent(go.transform, false); Mesh mesh = new Mesh(); mesh.vertices = vertices; mesh.triangles = indices; mesh.RecalculateNormals(); MeshFilter mf = band.AddComponent <MeshFilter>(); mf.mesh = mesh; MeshRenderer mr = band.AddComponent <MeshRenderer>(); mr.sharedMaterial = sideMaterial; if (region.entity.allowHighlight && (region.entity is Country && _enableCountryHighlight || region.entity is Province && _enableProvinceHighlight)) { ExtrudedRegionInteraction interaction = go.AddComponent <ExtrudedRegionInteraction>(); interaction.map = this; interaction.region = region; interaction.topMaterial = topMaterial; interaction.sideMaterial = sideMaterial; interaction.highlightColor = region.entity is Country ? _fillColor : _provincesFillColor; } return(go); }