internal static Vector2[] TraceRectangle(Rectangle rect, Stroke stroke, TessellationOptions tessellationOptions) { var width = rect.Size.x; var height = rect.Size.y; if (width <= ShapeUtils.Epsilon || height <= ShapeUtils.Epsilon) { return(null); } if (IsSimpleRectangle(rect)) { // Fast path, square corners, no patterns var r = new Rect(rect.Position, rect.Size); return(new Vector2[] { new Vector2(r.xMin, r.yMin), new Vector2(r.xMax, r.yMin), new Vector2(r.xMax, r.yMax), new Vector2(r.xMin, r.yMax) }); } else { var contour = BuildRectangleContour(rect); return(ShapeUtils.TraceShape(contour, stroke, tessellationOptions)); } }
private static void TessellateShapeLibTess(Shape vectorShape, Color color, List <Geometry> geoms, TessellationOptions tessellationOptions) { UnityEngine.Profiling.Profiler.BeginSample("LibTess"); var tess = new Tess(); var angle = 45.0f * Mathf.Deg2Rad; var mat = Matrix2D.RotateLH(angle); var invMat = Matrix2D.RotateLH(-angle); var pats = new List <Vector2[]>(); foreach (var c in vectorShape.Contours) { var contour = new List <Vector2>(100); var tracedshape = ShapeUtils.TraceShape(c, vectorShape.PathProps.Stroke, tessellationOptions); foreach (var v in tracedshape) { contour.Add(mat.MultiplyPoint(v)); } pats.Add(tracedshape); tess.AddContour(contour.Select(v => new ContourVertex() { Position = new Vec3() { X = v.x, Y = v.y } }).ToArray(), ContourOrientation.Original); } var windingRule = (vectorShape.Fill.Mode == FillMode.OddEven) ? WindingRule.EvenOdd : WindingRule.NonZero; try { tess.Tessellate(windingRule, ElementType.Polygons, 3); } catch (System.Exception) { Debug.LogWarning("Shape tessellation failed, skipping..."); UnityEngine.Profiling.Profiler.EndSample(); return; } var indices = tess.Elements.Select(i => (UInt16)i); var vertices = tess.Vertices.Select(v => invMat.MultiplyPoint(new Vector2(v.Position.X, v.Position.Y))); var paths = pats.ToArray(); if (indices.Count() > 0) { geoms.Add(new Geometry() { Vertices = vertices.ToArray(), Indices = indices.ToArray(), Paths = paths, Color = color, Fill = vectorShape.Fill, FillTransform = vectorShape.FillTransform }); } UnityEngine.Profiling.Profiler.EndSample(); }
private static void TessellateConvexContour(Shape shape, Stroke stroke, Color color, List <Geometry> geoms, TessellationOptions tessellationOptions) { if (shape.Contours.Length != 1 || shape.Contours[0].Segments.Length == 0) { return; } UnityEngine.Profiling.Profiler.BeginSample("TessellateConvexContour"); // Compute geometric mean var contour = shape.Contours[0]; var mean = Vector2.zero; foreach (var seg in contour.Segments) { mean += seg.P0; } mean /= contour.Segments.Length; var tracedShape = ShapeUtils.TraceShape(contour, stroke, tessellationOptions); var vertices = new Vector2[tracedShape.Length + 1]; var indices = new UInt16[tracedShape.Length * 3]; var paths = new Vector2[tracedShape.Length]; vertices[0] = mean; for (int i = 0; i < tracedShape.Length; ++i) { vertices[i + 1] = paths[i] = tracedShape[i]; indices[i * 3] = 0; indices[i * 3 + 1] = (UInt16)(i + 1); indices[i * 3 + 2] = ((i + 2) >= vertices.Length) ? (UInt16)1 : (UInt16)(i + 2); } geoms.Add(new Geometry() { Vertices = vertices, Indices = indices, Paths = new Vector2[][] { paths }, Color = color, Fill = shape.Fill, FillTransform = shape.FillTransform }); UnityEngine.Profiling.Profiler.EndSample(); }
internal static List <Vector2[]> TraceNodeHierarchyShapes(SceneNode root, TessellationOptions tessellationOptions) { var shapes = new List <Vector2[]>(); foreach (var nodeInfo in WorldTransformedSceneNodes(root, null)) { var node = nodeInfo.Node; // We process the drawables even though they are obsolete, until we remove the IDrawable interface entirely if (node.Drawables != null) { foreach (var drawable in node.Drawables) { var vectorShape = drawable as Shape; if (vectorShape != null) { foreach (var c in vectorShape.Contours) { var shape = ShapeUtils.TraceShape(c, vectorShape.PathProps.Stroke, tessellationOptions); if (shape.Length > 0) { shapes.Add(shape.Select(v => nodeInfo.WorldTransform * v).ToArray()); } } continue; } var vectorPath = drawable as Path; if (vectorPath != null) { var shape = ShapeUtils.TraceShape(vectorPath.Contour, vectorPath.PathProps.Stroke, tessellationOptions); if (shape.Length > 0) { shapes.Add(shape.Select(v => nodeInfo.WorldTransform * v).ToArray()); } continue; } var vectorRect = drawable as Rectangle; if (vectorRect != null) { var shape = ShapeUtils.TraceRectangle(vectorRect, vectorRect.PathProps.Stroke, tessellationOptions); if (shape.Length > 0) { shapes.Add(shape.Select(v => nodeInfo.WorldTransform * v).ToArray()); } continue; } } } if (node.Shapes != null) { foreach (var shape in node.Shapes) { foreach (var c in shape.Contours) { var tracedShape = ShapeUtils.TraceShape(c, shape.PathProps.Stroke, tessellationOptions); if (tracedShape.Length > 0) { shapes.Add(tracedShape.Select(v => nodeInfo.WorldTransform * v).ToArray()); } } } } } return(shapes); }