private void DrawCap(Rect rect, SegmentSide side, Vector top, Vector bottom, double zOffset) { var capUv = m_mesh.UvMapping.ToUv(rect); var capOffset = (bottom - top).Normal() * capUv.Size.Width * CalculateUnitsPerEdgeUv().X; var otherTop = side == SegmentSide.Left ? top - capOffset : top + capOffset; var otherBottom = side == SegmentSide.Left ? bottom - capOffset : bottom + capOffset; if (side == SegmentSide.Left) { Utils.Swap(ref top, ref otherTop); Utils.Swap(ref bottom, ref otherBottom); } MeshEdgeData.AddQuad( new Point3D(bottom.X, bottom.Y, zOffset), new Point3D(top.X, top.Y, zOffset), new Point3D(otherTop.X, otherTop.Y, zOffset), new Point3D(otherBottom.X, otherBottom.Y, zOffset), capUv.BottomLeft, capUv.TopLeft, capUv.TopRight, capUv.BottomRight); }
private List <Vector> DrawSegment(Segment segment) { var segmentUvMapping = GetUvMappingOf(segment.Direction); if (segmentUvMapping == null || segmentUvMapping.Bodies.Count == 0) { return(new List <Vector> { segment.Begin, segment.End }); } var bodyUvSize = m_mesh.UvMapping.ToUv(segmentUvMapping.Bodies[0]).Size; var unitsPerEdgeUv = CalculateUnitsPerEdgeUv(); var bodyWidthInUnits = bodyUvSize.Width * unitsPerEdgeUv.X; var halfBodyHeightInUnits = bodyUvSize.Height * unitsPerEdgeUv.Y / 2; var bodyUv = Rect.Empty; var start = segment.Begin; var smoothFactor = Math.Max(1, m_mesh.SmoothFactor); var doLeftCap = ShouldCloseSegment(segment, SegmentSide.Left); var doRightCap = ShouldCloseSegment(segment, SegmentSide.Right); if (doLeftCap) { segment.PrevPrev = segment.Prev = null; } if (doRightCap) { segment.NextNext = segment.Next = null; } if (segment.PrevPrev.HasValue && segment.Prev.HasValue && ShouldCloseSegment(new Segment { Prev = segment.PrevPrev, Begin = segment.Prev.Value, End = segment.Begin, }, SegmentSide.Left)) { segment.PrevPrev = null; } var prevNumOfCuts = (double)Math.Max((int)Math.Floor((segment.Begin - (segment.Prev ?? segment.Begin)).Length / (bodyWidthInUnits + m_mesh.StrechThreshold)), 1) * smoothFactor; var endPrevious = Utils.HermiteLerp(segment.PrevPrev ?? segment.Prev ?? segment.Begin, segment.Prev ?? segment.Begin, segment.Begin, segment.End, prevNumOfCuts == 1 ? 0.001 : ((prevNumOfCuts - 1) / prevNumOfCuts)); var startOffset = (start - endPrevious).Normal() * halfBodyHeightInUnits; if (doLeftCap) { DrawCap(segmentUvMapping.LeftCap, SegmentSide.Left, segment.Begin + startOffset, segment.Begin - startOffset, segmentUvMapping.ZOffset); } if (doLeftCap && doRightCap) { smoothFactor = 1; } var numberOfCuts = Math.Max((int)Math.Floor((segment.End - segment.Begin).Length / (bodyWidthInUnits + m_mesh.StrechThreshold)), 1) * smoothFactor; var fillPoints = new List <Vector>(numberOfCuts); for (int i = 0; i < numberOfCuts; i++) { var percentEnd = (i + 1) / (double)numberOfCuts; var end = Utils.HermiteLerp(segment.Prev ?? segment.Begin, segment.Begin, segment.End, segment.Next ?? segment.End, percentEnd); var endOffset = (end - start).Normal() * halfBodyHeightInUnits; var localTopLeft = start + startOffset; var localTopRight = end + endOffset; var localBottomLeft = start - startOffset; var localBottomRight = end - endOffset; fillPoints.Add(start); start = end; startOffset = endOffset; if (i % smoothFactor == 0) { bodyUv = m_mesh.UvMapping.ToUv(segmentUvMapping.Bodies[Math.Abs(percentEnd.GetHashCode() % segmentUvMapping.Bodies.Count)]); bodyUv.Width /= smoothFactor; } else { bodyUv.X += bodyUv.Width; } MeshEdgeData.AddQuad( new Point3D(localBottomLeft.X, localBottomLeft.Y, segmentUvMapping.ZOffset), new Point3D(localTopLeft.X, localTopLeft.Y, segmentUvMapping.ZOffset), new Point3D(localTopRight.X, localTopRight.Y, segmentUvMapping.ZOffset), new Point3D(localBottomRight.X, localBottomRight.Y, segmentUvMapping.ZOffset), bodyUv.BottomLeft, bodyUv.TopLeft, bodyUv.TopRight, bodyUv.BottomRight); } if (doRightCap) { DrawCap(segmentUvMapping.RightCap, SegmentSide.Right, segment.End + startOffset, segment.End - startOffset, segmentUvMapping.ZOffset); } return(fillPoints); }