void OnGenerateVisualContent(MeshGenerationContext mgc) { Rect r = contentRect; if (r.width < 0.01f || r.height < 0.01f) { return; // Skip rendering when too small. } float left = 0; float right = r.width; float top = 0; float bottom = r.height; k_Vertices[0].position = new Vector3(left, bottom, Vertex.nearZ); k_Vertices[1].position = new Vector3(left, top, Vertex.nearZ); k_Vertices[2].position = new Vector3(right, top, Vertex.nearZ); k_Vertices[3].position = new Vector3(right, bottom, Vertex.nearZ); MeshWriteData mwd = mgc.Allocate(k_Vertices.Length, k_Indices.Length, m_Texture); // Remap 0..1 to the uv region. Rect uvs = mwd.uvRegion; k_Vertices[0].uv = new Vector2(uvs.xMin, uvs.yMin); k_Vertices[1].uv = new Vector2(uvs.xMin, uvs.yMax); k_Vertices[2].uv = new Vector2(uvs.xMax, uvs.yMax); k_Vertices[3].uv = new Vector2(uvs.xMax, uvs.yMin); mwd.SetAllVertices(k_Vertices); mwd.SetAllIndices(k_Indices); }
void OnGenerateVisualContent(MeshGenerationContext mgc) { Rect r = contentRect; if (r.width < 0.01f || r.height < 0.01f) { return; // Skip rendering when too small. } Color color = resolvedStyle.color; k_Vertices[0].tint = Color.black; k_Vertices[1].tint = Color.black; k_Vertices[2].tint = color; k_Vertices[3].tint = color; float left = 0; float right = r.width; float top = 0; float bottom = r.height; k_Vertices[0].position = new Vector3(left, bottom, Vertex.nearZ); k_Vertices[1].position = new Vector3(left, top, Vertex.nearZ); k_Vertices[2].position = new Vector3(right, top, Vertex.nearZ); k_Vertices[3].position = new Vector3(right, bottom, Vertex.nearZ); MeshWriteData mwd = mgc.Allocate(k_Vertices.Length, k_Indices.Length); mwd.SetAllVertices(k_Vertices); mwd.SetAllIndices(k_Indices); }
private static void MakeVectorGraphics9SliceBackground(Vertex[] svgVertices, ushort[] svgIndices, float svgWidth, float svgHeight, Rect targetRect, Vector4 sliceLTRB, bool stretch, Color tint, int settingIndexOffset, MeshBuilder.AllocMeshData meshAlloc) { MeshWriteData meshWriteData = meshAlloc.alloc((uint)svgVertices.Length, (uint)svgIndices.Length, ref meshAlloc); meshWriteData.SetAllIndices(svgIndices); bool flag = !stretch; if (flag) { throw new NotImplementedException("Support for repeating 9-slices is not done yet"); } MeshBuilder.s_VectorGraphics9Slice.Begin(); Rect uvRegion = meshWriteData.uvRegion; int num = svgVertices.Length; Vector2 vector = new Vector2(1f / (svgWidth - sliceLTRB.z - sliceLTRB.x), 1f / (svgHeight - sliceLTRB.w - sliceLTRB.y)); Vector2 vector2 = new Vector2(targetRect.width - svgWidth, targetRect.height - svgHeight); for (int i = 0; i < num; i++) { Vertex vertex = svgVertices[i]; Vector2 vector3; vector3.x = Mathf.Clamp01((vertex.position.x - sliceLTRB.x) * vector.x); vector3.y = Mathf.Clamp01((vertex.position.y - sliceLTRB.y) * vector.y); vertex.position.x = vertex.position.x + vector3.x * vector2.x; vertex.position.y = vertex.position.y + vector3.y * vector2.y; vertex.uv.x = vertex.uv.x * uvRegion.width + uvRegion.xMin; vertex.uv.y = vertex.uv.y * uvRegion.height + uvRegion.yMin; vertex.tint *= tint; uint num2 = (uint)(((int)vertex.opacityPageSVGSettingIndex.b << 8 | (int)vertex.opacityPageSVGSettingIndex.a) + settingIndexOffset); vertex.opacityPageSVGSettingIndex.b = (byte)(num2 >> 8); vertex.opacityPageSVGSettingIndex.a = (byte)num2; meshWriteData.SetNextVertex(vertex); } MeshBuilder.s_VectorGraphics9Slice.End(); }
internal static void MakeText(MeshInfo meshInfo, Vector2 offset, MeshBuilder.AllocMeshData meshAlloc) { int num = MeshBuilder.LimitTextVertices(meshInfo.vertexCount, true); int num2 = num / 4; MeshWriteData meshWriteData = meshAlloc.Allocate((uint)(num2 * 4), (uint)(num2 * 6)); int i = 0; int num3 = 0; int num4 = 0; while (i < num2) { meshWriteData.SetNextVertex(MeshBuilder.ConvertTextVertexToUIRVertex(meshInfo, num3, offset)); meshWriteData.SetNextVertex(MeshBuilder.ConvertTextVertexToUIRVertex(meshInfo, num3 + 1, offset)); meshWriteData.SetNextVertex(MeshBuilder.ConvertTextVertexToUIRVertex(meshInfo, num3 + 2, offset)); meshWriteData.SetNextVertex(MeshBuilder.ConvertTextVertexToUIRVertex(meshInfo, num3 + 3, offset)); meshWriteData.SetNextIndex((ushort)num3); meshWriteData.SetNextIndex((ushort)(num3 + 1)); meshWriteData.SetNextIndex((ushort)(num3 + 2)); meshWriteData.SetNextIndex((ushort)(num3 + 2)); meshWriteData.SetNextIndex((ushort)(num3 + 3)); meshWriteData.SetNextIndex((ushort)num3); i++; num3 += 4; num4 += 6; } }
void OnGenerateVisualContent(MeshGenerationContext mgc) { Rect r = contentRect; if (r.width < 0.01f || r.height < 0.01f) { return; // Skip rendering when too small. } float radiusX = r.width / 2; float radiusY = r.height / 2; k_Vertices[0].position = new Vector3(radiusX, radiusY, Vertex.nearZ); float angle = 0; for (int i = 1; i < 7; ++i) { k_Vertices[i].position = new Vector3( radiusX + radiusX * Mathf.Cos(angle), radiusY - radiusY * Mathf.Sin(angle), Vertex.nearZ); angle += 2f * Mathf.PI / 6; } MeshWriteData mwd = mgc.Allocate(k_Vertices.Length, k_Indices.Length); mwd.SetAllVertices(k_Vertices); mwd.SetAllIndices(k_Indices); }
public void GenerateTickHeadContent(MeshGenerationContext context) { const float tipY = 20f; const float height = 6f; const float width = 11f; const float middle = 6f; Color color; if (EditorGUIUtility.isProSkin) { color = m_DebugPlayhead ? ColorUtility.FromHtmlString("#234A6C") : Color.white; } else { color = m_DebugPlayhead ? ColorUtility.FromHtmlString("#2E5B8D") : Color.white; } MeshWriteData mesh = context.Allocate(3, 3); Vertex[] vertices = new Vertex[3]; vertices[0].position = new Vector3(middle, tipY, Vertex.nearZ); vertices[1].position = new Vector3(width, tipY - height, Vertex.nearZ); vertices[2].position = new Vector3(0, tipY - height, Vertex.nearZ); vertices[0].tint = color; vertices[1].tint = color; vertices[2].tint = color; mesh.SetAllVertices(vertices); mesh.SetAllIndices(new ushort[] { 0, 2, 1 }); }
private MeshWriteData AllocRawVertsIndices(uint vertexCount, uint indexCount, ref MeshBuilder.AllocMeshData allocatorData) { this.m_CurrentEntry.vertices = this.m_VertsPool.Alloc(vertexCount); this.m_CurrentEntry.indices = this.m_IndicesPool.Alloc(indexCount); MeshWriteData pooledMeshWriteData = this.GetPooledMeshWriteData(); pooledMeshWriteData.Reset(this.m_CurrentEntry.vertices, this.m_CurrentEntry.indices); return(pooledMeshWriteData); }
public static void SetNextVertex(this MeshWriteData md, Vector3 pos, Vector2 uv, Color32 tint) { Color32 flags = new Color32(0, 0, 0, (byte)VertexFlags.LastType); md.SetNextVertex(new Vertex() { position = pos, uv = uv, tint = tint, idsFlags = flags }); }
public static void SetNextVertex(this MeshWriteData md, Vector3 pos, Vector2 uv, Color32 tint) { #if UNITY_2021_1_OR_NEWER Color32 ids = new Color32(0, 0, 0, 0); Color32 flags = new Color32((byte)VertexFlags.IsGraphViewEdge, 0, 0, 0); md.SetNextVertex(new Vertex() { position = pos, uv = uv, tint = tint, ids = ids, flags = flags }); #else Color32 flags = new Color32(0, 0, 0, (byte)VertexFlags.LastType); md.SetNextVertex(new Vertex() { position = pos, uv = uv, tint = tint, idsFlags = flags }); #endif }
private static void MakeQuad(Rect rcPosition, Rect rcTexCoord, Color color, float posZ, MeshBuilder.AllocMeshData meshAlloc) { MeshWriteData meshWriteData = meshAlloc.Allocate(4u, 6u); float x = rcPosition.x; float xMax = rcPosition.xMax; float yMax = rcPosition.yMax; float y = rcPosition.y; Rect uvRegion = meshWriteData.uvRegion; float x2 = rcTexCoord.x * uvRegion.width + uvRegion.xMin; float x3 = rcTexCoord.xMax * uvRegion.width + uvRegion.xMin; float y2 = rcTexCoord.y * uvRegion.height + uvRegion.yMin; float y3 = rcTexCoord.yMax * uvRegion.height + uvRegion.yMin; meshWriteData.SetNextVertex(new Vertex { position = new Vector3(x, yMax, posZ), tint = color, uv = new Vector2(x2, y2) }); meshWriteData.SetNextVertex(new Vertex { position = new Vector3(xMax, yMax, posZ), tint = color, uv = new Vector2(x3, y2) }); meshWriteData.SetNextVertex(new Vertex { position = new Vector3(x, y, posZ), tint = color, uv = new Vector2(x2, y3) }); meshWriteData.SetNextVertex(new Vertex { position = new Vector3(xMax, y, posZ), tint = color, uv = new Vector2(x3, y3) }); meshWriteData.SetNextIndex(0); meshWriteData.SetNextIndex(2); meshWriteData.SetNextIndex(1); meshWriteData.SetNextIndex(1); meshWriteData.SetNextIndex(2); meshWriteData.SetNextIndex(3); }
private void ValidateMeshWriteData() { for (int i = 0; i < this.m_NextMeshWriteDataPoolItem; i++) { MeshWriteData meshWriteData = this.m_MeshWriteDataPool[i]; bool flag = meshWriteData.vertexCount > 0 && meshWriteData.currentVertex < meshWriteData.vertexCount; if (flag) { Debug.LogError(string.Concat(new string[] { "Not enough vertices written in generateVisualContent callback (asked for ", meshWriteData.vertexCount.ToString(), " but only wrote ", meshWriteData.currentVertex.ToString(), ")" })); Vertex nextVertex = meshWriteData.m_Vertices[0]; while (meshWriteData.currentVertex < meshWriteData.vertexCount) { meshWriteData.SetNextVertex(nextVertex); } } bool flag2 = meshWriteData.indexCount > 0 && meshWriteData.currentIndex < meshWriteData.indexCount; if (flag2) { Debug.LogError(string.Concat(new string[] { "Not enough indices written in generateVisualContent callback (asked for ", meshWriteData.indexCount.ToString(), " but only wrote ", meshWriteData.currentIndex.ToString(), ")" })); while (meshWriteData.currentIndex < meshWriteData.indexCount) { meshWriteData.SetNextIndex(0); } } } }
internal static void MakeText(NativeArray <UnityEngine.UIElements.TextVertex> uiVertices, Vector2 offset, MeshBuilder.AllocMeshData meshAlloc) { int num = MeshBuilder.LimitTextVertices(uiVertices.Length, true); int num2 = num / 4; MeshWriteData meshWriteData = meshAlloc.Allocate((uint)(num2 * 4), (uint)(num2 * 6)); int i = 0; int num3 = 0; while (i < num2) { meshWriteData.SetNextVertex(MeshBuilder.ConvertTextVertexToUIRVertex(uiVertices[num3], offset)); meshWriteData.SetNextVertex(MeshBuilder.ConvertTextVertexToUIRVertex(uiVertices[num3 + 1], offset)); meshWriteData.SetNextVertex(MeshBuilder.ConvertTextVertexToUIRVertex(uiVertices[num3 + 2], offset)); meshWriteData.SetNextVertex(MeshBuilder.ConvertTextVertexToUIRVertex(uiVertices[num3 + 3], offset)); meshWriteData.SetNextIndex((ushort)num3); meshWriteData.SetNextIndex((ushort)(num3 + 1)); meshWriteData.SetNextIndex((ushort)(num3 + 2)); meshWriteData.SetNextIndex((ushort)(num3 + 2)); meshWriteData.SetNextIndex((ushort)(num3 + 3)); meshWriteData.SetNextIndex((ushort)num3); i++; num3 += 4; } }
private static void TessellateRoundedCorner(Rect rect, Color color, float posZ, Vector2 radius, MeshWriteData mesh, ref UInt16 indexOffset, ref UInt16 vertexCount, ref UInt16 indexCount, bool countOnly) { var cornerCenter = rect.position + radius; var subRect = Rect.zero; if (radius == Vector2.zero) { // Without radius, we use a single quad to fill the section // ------- // | | // | | // ------- TessellateQuad(rect, TessellationType.Content, color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); return; } // Just fill the corner with radius, plus up to 2 quads to fill the remainder of the section // _------- // *\ | | // *__\| A | // | | | // | B | | // | | | // ---------- TessellateFilledFan(TessellationType.Content, cornerCenter, radius, color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); if (radius.x < rect.width) { // A subRect = new Rect(rect.x + radius.x, rect.y, rect.width - radius.x, rect.height); TessellateQuad(subRect, TessellationType.Content, color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); } if (radius.y < rect.height) { // B subRect = new Rect(rect.x, rect.y + radius.y, radius.x < rect.width ? radius.x : rect.width, rect.height - radius.y); TessellateQuad(subRect, TessellationType.Content, color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); } }
private static void TessellateRoundedBorders(ref MeshGenerationContextUtils.BorderParams border, float posZ, MeshWriteData mesh, ref UInt16 vertexCount, ref UInt16 indexCount, bool countOnly) { // To tessellate the 4 corners, the rect is divided in 4 quadrants and every quadrant is computed as if they were the top-left corner. // The quadrants are then mirrored and the triangles winding flipped as necessary. UInt16 indexOffset = 0; UInt16 startVc = 0, startIc = 0; var halfSize = new Vector2(border.rect.width * 0.5f, border.rect.height * 0.5f); var quarterRect = new Rect(border.rect.x, border.rect.y, halfSize.x, halfSize.y); // Top-left TessellateRoundedBorder(quarterRect, border.color, posZ, border.topLeftRadius, border.leftWidth, border.topWidth, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); // Top-right startVc = vertexCount; startIc = indexCount; TessellateRoundedBorder(quarterRect, border.color, posZ, border.topRightRadius, border.rightWidth, border.topWidth, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); if (!countOnly) { MirrorVertices(quarterRect, mesh.m_Vertices, startVc, vertexCount - startVc, true); FlipWinding(mesh.m_Indices, startIc, indexCount - startIc); } // Bottom-right startVc = vertexCount; startIc = indexCount; TessellateRoundedBorder(quarterRect, border.color, posZ, border.bottomRightRadius, border.rightWidth, border.bottomWidth, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); if (!countOnly) { MirrorVertices(quarterRect, mesh.m_Vertices, startVc, vertexCount - startVc, true); MirrorVertices(quarterRect, mesh.m_Vertices, startVc, vertexCount - startVc, false); } // Bottom-left startVc = vertexCount; startIc = indexCount; TessellateRoundedBorder(quarterRect, border.color, posZ, border.bottomLeftRadius, border.leftWidth, border.bottomWidth, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); if (!countOnly) { MirrorVertices(quarterRect, mesh.m_Vertices, startVc, vertexCount - startVc, false); FlipWinding(mesh.m_Indices, startIc, indexCount - startIc); } }
private static void TessellateBorderInternal(ref MeshGenerationContextUtils.BorderParams border, float posZ, MeshWriteData mesh, ref UInt16 vertexCount, ref UInt16 indexCount, bool countOnly = false) { TessellateRoundedBorders(ref border, posZ, mesh, ref vertexCount, ref indexCount, countOnly); }
private static void TessellateRectInternal(ref MeshGenerationContextUtils.RectangleParams rectParams, float posZ, MeshWriteData mesh, ref UInt16 vertexCount, ref UInt16 indexCount, bool countOnly = false) { if (!rectParams.HasRadius(kEpsilon)) { UInt16 indexOffset = 0; TessellateQuad(rectParams.rect, TessellationType.Content, rectParams.color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); } else { TessellateRoundedCorners(ref rectParams, posZ, mesh, ref vertexCount, ref indexCount, countOnly); } }
private unsafe static void RectClipTriangle(Vertex *vt, ushort *it, Vector4 clipRectMinMax, MeshWriteData mwd, ref ushort nextNewVertex) { Vertex *ptr = stackalloc Vertex[13]; int num = 0; for (int i = 0; i < 3; i++) { bool flag = vt[i].position.x >= clipRectMinMax.x && vt[i].position.y >= clipRectMinMax.y && vt[i].position.x <= clipRectMinMax.z && vt[i].position.y <= clipRectMinMax.w; if (flag) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = vt[i]; } } bool flag2 = num == 3; if (flag2) { mwd.SetNextIndex(*it); mwd.SetNextIndex(it[1]); mwd.SetNextIndex(it[2]); } else { Vector3 vertexBaryCentricCoordinates = MeshBuilder.GetVertexBaryCentricCoordinates(vt, clipRectMinMax.x, clipRectMinMax.y); Vector3 vertexBaryCentricCoordinates2 = MeshBuilder.GetVertexBaryCentricCoordinates(vt, clipRectMinMax.z, clipRectMinMax.y); Vector3 vertexBaryCentricCoordinates3 = MeshBuilder.GetVertexBaryCentricCoordinates(vt, clipRectMinMax.x, clipRectMinMax.w); Vector3 vertexBaryCentricCoordinates4 = MeshBuilder.GetVertexBaryCentricCoordinates(vt, clipRectMinMax.z, clipRectMinMax.w); bool flag3 = vertexBaryCentricCoordinates.x >= -1E-07f && vertexBaryCentricCoordinates.x <= 1.00000012f && vertexBaryCentricCoordinates.y >= -1E-07f && vertexBaryCentricCoordinates.y <= 1.00000012f && vertexBaryCentricCoordinates.z >= -1E-07f && vertexBaryCentricCoordinates.z <= 1.00000012f; if (flag3) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangle(vt, clipRectMinMax.x, clipRectMinMax.y, vertexBaryCentricCoordinates); } bool flag4 = vertexBaryCentricCoordinates2.x >= -1E-07f && vertexBaryCentricCoordinates2.x <= 1.00000012f && vertexBaryCentricCoordinates2.y >= -1E-07f && vertexBaryCentricCoordinates2.y <= 1.00000012f && vertexBaryCentricCoordinates2.z >= -1E-07f && vertexBaryCentricCoordinates2.z <= 1.00000012f; if (flag4) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangle(vt, clipRectMinMax.z, clipRectMinMax.y, vertexBaryCentricCoordinates2); } bool flag5 = vertexBaryCentricCoordinates3.x >= -1E-07f && vertexBaryCentricCoordinates3.x <= 1.00000012f && vertexBaryCentricCoordinates3.y >= -1E-07f && vertexBaryCentricCoordinates3.y <= 1.00000012f && vertexBaryCentricCoordinates3.z >= -1E-07f && vertexBaryCentricCoordinates3.z <= 1.00000012f; if (flag5) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangle(vt, clipRectMinMax.x, clipRectMinMax.w, vertexBaryCentricCoordinates3); } bool flag6 = vertexBaryCentricCoordinates4.x >= -1E-07f && vertexBaryCentricCoordinates4.x <= 1.00000012f && vertexBaryCentricCoordinates4.y >= -1E-07f && vertexBaryCentricCoordinates4.y <= 1.00000012f && vertexBaryCentricCoordinates4.z >= -1E-07f && vertexBaryCentricCoordinates4.z <= 1.00000012f; if (flag6) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangle(vt, clipRectMinMax.z, clipRectMinMax.w, vertexBaryCentricCoordinates4); } float num2 = MeshBuilder.IntersectSegments(vt->position.x, vt->position.y, vt[1].position.x, vt[1].position.y, clipRectMinMax.x, clipRectMinMax.y, clipRectMinMax.z, clipRectMinMax.y); bool flag7 = num2 != 3.40282347E+38f; if (flag7) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangleEdge(vt, 0, 1, num2); } num2 = MeshBuilder.IntersectSegments(vt[1].position.x, vt[1].position.y, vt[2].position.x, vt[2].position.y, clipRectMinMax.x, clipRectMinMax.y, clipRectMinMax.z, clipRectMinMax.y); bool flag8 = num2 != 3.40282347E+38f; if (flag8) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangleEdge(vt, 1, 2, num2); } num2 = MeshBuilder.IntersectSegments(vt[2].position.x, vt[2].position.y, vt->position.x, vt->position.y, clipRectMinMax.x, clipRectMinMax.y, clipRectMinMax.z, clipRectMinMax.y); bool flag9 = num2 != 3.40282347E+38f; if (flag9) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangleEdge(vt, 2, 0, num2); } num2 = MeshBuilder.IntersectSegments(vt->position.x, vt->position.y, vt[1].position.x, vt[1].position.y, clipRectMinMax.z, clipRectMinMax.y, clipRectMinMax.z, clipRectMinMax.w); bool flag10 = num2 != 3.40282347E+38f; if (flag10) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangleEdge(vt, 0, 1, num2); } num2 = MeshBuilder.IntersectSegments(vt[1].position.x, vt[1].position.y, vt[2].position.x, vt[2].position.y, clipRectMinMax.z, clipRectMinMax.y, clipRectMinMax.z, clipRectMinMax.w); bool flag11 = num2 != 3.40282347E+38f; if (flag11) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangleEdge(vt, 1, 2, num2); } num2 = MeshBuilder.IntersectSegments(vt[2].position.x, vt[2].position.y, vt->position.x, vt->position.y, clipRectMinMax.z, clipRectMinMax.y, clipRectMinMax.z, clipRectMinMax.w); bool flag12 = num2 != 3.40282347E+38f; if (flag12) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangleEdge(vt, 2, 0, num2); } num2 = MeshBuilder.IntersectSegments(vt->position.x, vt->position.y, vt[1].position.x, vt[1].position.y, clipRectMinMax.x, clipRectMinMax.w, clipRectMinMax.z, clipRectMinMax.w); bool flag13 = num2 != 3.40282347E+38f; if (flag13) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangleEdge(vt, 0, 1, num2); } num2 = MeshBuilder.IntersectSegments(vt[1].position.x, vt[1].position.y, vt[2].position.x, vt[2].position.y, clipRectMinMax.x, clipRectMinMax.w, clipRectMinMax.z, clipRectMinMax.w); bool flag14 = num2 != 3.40282347E+38f; if (flag14) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangleEdge(vt, 1, 2, num2); } num2 = MeshBuilder.IntersectSegments(vt[2].position.x, vt[2].position.y, vt->position.x, vt->position.y, clipRectMinMax.x, clipRectMinMax.w, clipRectMinMax.z, clipRectMinMax.w); bool flag15 = num2 != 3.40282347E+38f; if (flag15) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangleEdge(vt, 2, 0, num2); } num2 = MeshBuilder.IntersectSegments(vt->position.x, vt->position.y, vt[1].position.x, vt[1].position.y, clipRectMinMax.x, clipRectMinMax.y, clipRectMinMax.x, clipRectMinMax.w); bool flag16 = num2 != 3.40282347E+38f; if (flag16) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangleEdge(vt, 0, 1, num2); } num2 = MeshBuilder.IntersectSegments(vt[1].position.x, vt[1].position.y, vt[2].position.x, vt[2].position.y, clipRectMinMax.x, clipRectMinMax.y, clipRectMinMax.x, clipRectMinMax.w); bool flag17 = num2 != 3.40282347E+38f; if (flag17) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangleEdge(vt, 1, 2, num2); } num2 = MeshBuilder.IntersectSegments(vt[2].position.x, vt[2].position.y, vt->position.x, vt->position.y, clipRectMinMax.x, clipRectMinMax.y, clipRectMinMax.x, clipRectMinMax.w); bool flag18 = num2 != 3.40282347E+38f; if (flag18) { ptr[(IntPtr)(num++) * (IntPtr)sizeof(Vertex)] = MeshBuilder.InterpolateVertexInTriangleEdge(vt, 2, 0, num2); } bool flag19 = num == 0; if (!flag19) { float *ptr2 = stackalloc float[num]; * ptr2 = 0f; for (int j = 1; j < num; j++) { ptr2[j] = Mathf.Atan2(ptr[j].position.y - ptr->position.y, ptr[j].position.x - ptr->position.x); bool flag20 = ptr2[j] < 0f; if (flag20) { ptr2[j] += 6.28318548f; } } int *ptr3 = stackalloc int[num]; * ptr3 = 0; uint num3 = 0u; for (int k = 1; k < num; k++) { int num4 = -1; float num5 = 3.40282347E+38f; for (int l = 1; l < num; l++) { bool flag21 = ((ulong)num3 & (ulong)(1L << (l & 31))) == 0uL && ptr2[l] < num5; if (flag21) { num5 = ptr2[l]; num4 = l; } } ptr3[k] = num4; num3 |= 1u << num4; } ushort num6 = nextNewVertex; for (int m = 0; m < num; m++) { mwd.m_Vertices[(int)num6 + m] = ptr[ptr3[m]]; } nextNewVertex += (ushort)num; int num7 = num - 2; bool flag22 = false; Vector3 position = mwd.m_Vertices[(int)num6].position; for (int n = 0; n < num7; n++) { int num8 = (int)num6 + n + 1; int num9 = (int)num6 + n + 2; bool flag23 = !flag22; if (flag23) { float num10 = ptr2[ptr3[n + 1]]; float num11 = ptr2[ptr3[n + 2]]; bool flag24 = num11 - num10 >= 3.14159274f; if (flag24) { num8 = (int)(num6 + 1); num9 = (int)num6 + num - 1; flag22 = true; } } Vector3 position2 = mwd.m_Vertices[num8].position; Vector3 position3 = mwd.m_Vertices[num9].position; Vector3 vector = Vector3.Cross(position2 - position, position3 - position); mwd.SetNextIndex(num6); bool flag25 = vector.z < 0f; if (flag25) { mwd.SetNextIndex((ushort)num9); mwd.SetNextIndex((ushort)num8); } else { mwd.SetNextIndex((ushort)num8); mwd.SetNextIndex((ushort)num9); } } } } }
private static void TessellateFilledFan(TessellationType tessellationType, Vector2 center, Vector2 radius, Color color, float posZ, MeshWriteData mesh, ref UInt16 indexOffset, ref UInt16 vertexCount, ref UInt16 indexCount, bool countOnly) { if (countOnly) { vertexCount += (UInt16)(kSubdivisions + 1); indexCount += (UInt16)((kSubdivisions - 1) * 3); return; } float innerVertexFlags, outerVertexFlags; if (tessellationType == TessellationType.EdgeCorner) { innerVertexFlags = (float)VertexFlags.IsEdge; outerVertexFlags = (float)VertexFlags.IsSolid; } else { outerVertexFlags = innerVertexFlags = (float)mesh.m_Flags; } var p = new Vector2(center.x - radius.x, center.y); mesh.SetNextVertex(new Vertex() { position = new Vector3(center.x, center.y, posZ), uv = p, tint = color, flags = innerVertexFlags }); mesh.SetNextVertex(new Vertex() { position = new Vector3(p.x, p.y, posZ), uv = center, tint = color, flags = outerVertexFlags }); vertexCount += 2; for (int k = 1; k < kSubdivisions; ++k) { float angle = (Mathf.PI * 0.5f) * ((float)k) / (kSubdivisions - 1); p = center + new Vector2(-Mathf.Cos(angle), -Mathf.Sin(angle)) * radius; mesh.SetNextVertex(new Vertex() { position = new Vector3(p.x, p.y, posZ), uv = center, tint = color, flags = outerVertexFlags }); vertexCount++; mesh.SetNextIndex((UInt16)(indexOffset + 0)); mesh.SetNextIndex((UInt16)(indexOffset + k + 1)); mesh.SetNextIndex((UInt16)(indexOffset + k)); indexCount += 3; } indexOffset += (UInt16)(kSubdivisions + 1); }
private void OnGenerateVisualContent(MeshGenerationContext cxt) { MeshParts mp = new MeshParts(); MultiLayerPerception mlp = _TestMLP; AddRect(mp, 0, 1, Color.gray); if (mlp != null) { using (IWorker oneshotSyncWorker = WorkerFactory.CreateWorker(_testMLP.model, _extraLayers, WorkerFactory.Device.GPU)) { using (Tensor obsTensor = new Tensor(new TensorShape(1, mlp._shape.inputSize))) { if (_observe.Length < mlp._shape.inputSize) { _observe = new float[mlp._shape.inputSize]; } for (int iINode = 0; iINode < mlp._shape.inputSize; iINode++) { obsTensor[iINode] = _observe[iINode]; } oneshotSyncWorker.Execute(obsTensor).FlushSchedule(); } for (int iINode = 0; iINode < mlp._shape.inputSize; iINode++) { AddRect(mp, GetNodePos(0, iINode), NodeSize, ActNodeColor(_observe[iINode])); } using (Tensor hvr = oneshotSyncWorker.PeekOutput(MultiLayerPerception.LayerNames.Hidden)) { using (Tensor hva = oneshotSyncWorker.PeekOutput(MultiLayerPerception.LayerNames.HiddenActive)) { for (int iHNode = 0; iHNode < mlp._shape.hiddenSize; iHNode++) { AddRect(mp, GetNodePos(1, iHNode), NodeSize, RawNodeColor(hvr[iHNode])); AddRect(mp, GetNodePos(1, iHNode) + new float2(0.5f, 0) * NodeSize, new float2(0.5f, 1) * NodeSize, ActNodeColor(hva[iHNode])); } } } using (Tensor ovr = oneshotSyncWorker.PeekOutput(MultiLayerPerception.LayerNames.Output)) { using (Tensor ova = oneshotSyncWorker.PeekOutput()) { for (int iONode = 0; iONode < mlp._shape.outputSize; iONode++) { AddRect(mp, GetNodePos(2, iONode), NodeSize, RawNodeColor(ovr[iONode])); AddRect(mp, GetNodePos(2, iONode) + new float2(0.5f, 0) * NodeSize, new float2(0.5f, 1) * NodeSize, ActNodeColor(ova[iONode])); } } } } string[] layerNames = new string[] { MultiLayerPerception.LayerNames.Hidden, MultiLayerPerception.LayerNames.Output }; float2 xBuf = NodeSize / 2; xBuf.y = 0; int prvLayer = 0; int curLayer = 1; foreach (string layerName in layerNames) { TensorShape tShape = _testMLP.GetLayerShape(layerName); for (int iPNode = 0; iPNode < tShape.flatHeight; iPNode++) { for (int iCNode = 0; iCNode < tShape.flatWidth; iCNode++) { float2 posI = GetNodePos(prvLayer, iPNode) + NodeSize / 2; float2 posW = GetNodePos(curLayer, iCNode) + NodeSize / 2; float t = 0.5f + mlp.GetWeight(layerName, iPNode, iCNode); DrawLine(mp, posI + xBuf, posW - xBuf, 0.025f, TurboColorMap.Map(t)); } } prvLayer = curLayer; curLayer++; } } MeshWriteData meshData = cxt.Allocate(mp.vertices.Count, mp.IndicesCount); if (meshData.vertexCount > 0) { meshData.SetAllVertices(mp.vertices.ToArray()); meshData.SetAllIndices(mp.GetIndices()); } }
public MeshWriteData DrawMesh(int vertexCount, int indexCount, Texture texture, Material material, MeshGenerationContext.MeshFlags flags) { MeshWriteData pooledMeshWriteData = this.GetPooledMeshWriteData(); bool flag = vertexCount == 0 || indexCount == 0; MeshWriteData result; if (flag) { pooledMeshWriteData.Reset(default(NativeSlice <Vertex>), default(NativeSlice <ushort>)); result = pooledMeshWriteData; } else { this.m_CurrentEntry = new UIRStylePainter.Entry { vertices = this.m_VertsPool.Alloc((uint)vertexCount), indices = this.m_IndicesPool.Alloc((uint)indexCount), material = material, uvIsDisplacement = (flags == MeshGenerationContext.MeshFlags.UVisDisplacement), clipRectID = this.m_ClipRectID, isStencilClipped = this.m_StencilClip, addFlags = VertexFlags.IsSolid }; Debug.Assert(this.m_CurrentEntry.vertices.Length == vertexCount); Debug.Assert(this.m_CurrentEntry.indices.Length == indexCount); Rect uvRegion = new Rect(0f, 0f, 1f, 1f); bool flag2 = flags == MeshGenerationContext.MeshFlags.IsSVGGradients; bool flag3 = flags == MeshGenerationContext.MeshFlags.IsCustomSVGGradients; bool flag4 = flag2 | flag3; if (flag4) { this.m_CurrentEntry.addFlags = (flag2 ? VertexFlags.IsSVGGradients : VertexFlags.IsCustomSVGGradients); bool flag5 = flag3; if (flag5) { this.m_CurrentEntry.custom = texture; } this.currentElement.renderChainData.usesAtlas = true; } else { bool flag6 = texture != null; if (flag6) { RectInt rectInt; bool flag7 = this.m_AtlasManager != null && this.m_AtlasManager.TryGetLocation(texture as Texture2D, out rectInt); if (flag7) { this.m_CurrentEntry.addFlags = ((texture.filterMode == FilterMode.Point) ? VertexFlags.IsAtlasTexturedPoint : VertexFlags.IsAtlasTexturedBilinear); this.currentElement.renderChainData.usesAtlas = true; uvRegion = new Rect((float)rectInt.x, (float)rectInt.y, (float)rectInt.width, (float)rectInt.height); } else { this.m_CurrentEntry.addFlags = VertexFlags.IsCustomTextured; this.m_CurrentEntry.custom = texture; } } } pooledMeshWriteData.Reset(this.m_CurrentEntry.vertices, this.m_CurrentEntry.indices, uvRegion); this.m_Entries.Add(this.m_CurrentEntry); this.totalVertices += this.m_CurrentEntry.vertices.Length; this.totalIndices += this.m_CurrentEntry.indices.Length; this.m_CurrentEntry = default(UIRStylePainter.Entry); result = pooledMeshWriteData; } return(result); }
internal static void MakeSlicedQuad(ref MeshGenerationContextUtils.RectangleParams rectParams, float posZ, MeshBuilder.AllocMeshData meshAlloc) { MeshWriteData meshWriteData = meshAlloc.Allocate(16u, 54u); float num = 1f; Texture2D texture2D = rectParams.texture as Texture2D; bool flag = texture2D != null; if (flag) { num = texture2D.pixelsPerPoint; } float num2 = (float)rectParams.texture.width; float num3 = (float)rectParams.texture.height; float num4 = num / num2; float num5 = num / num3; float num6 = Mathf.Max(0f, (float)rectParams.leftSlice); float num7 = Mathf.Max(0f, (float)rectParams.rightSlice); float num8 = Mathf.Max(0f, (float)rectParams.bottomSlice); float num9 = Mathf.Max(0f, (float)rectParams.topSlice); float num10 = Mathf.Clamp(num6 * num4, 0f, 1f); float num11 = Mathf.Clamp(num7 * num4, 0f, 1f); float num12 = Mathf.Clamp(num8 * num5, 0f, 1f); float num13 = Mathf.Clamp(num9 * num5, 0f, 1f); MeshBuilder.k_TexCoordSlicesX[0] = rectParams.uv.min.x; MeshBuilder.k_TexCoordSlicesX[1] = rectParams.uv.min.x + num10; MeshBuilder.k_TexCoordSlicesX[2] = rectParams.uv.max.x - num11; MeshBuilder.k_TexCoordSlicesX[3] = rectParams.uv.max.x; MeshBuilder.k_TexCoordSlicesY[0] = rectParams.uv.max.y; MeshBuilder.k_TexCoordSlicesY[1] = rectParams.uv.max.y - num12; MeshBuilder.k_TexCoordSlicesY[2] = rectParams.uv.min.y + num13; MeshBuilder.k_TexCoordSlicesY[3] = rectParams.uv.min.y; Rect uvRegion = meshWriteData.uvRegion; for (int i = 0; i < 4; i++) { MeshBuilder.k_TexCoordSlicesX[i] = MeshBuilder.k_TexCoordSlicesX[i] * uvRegion.width + uvRegion.xMin; MeshBuilder.k_TexCoordSlicesY[i] = (rectParams.uv.min.y + rectParams.uv.max.y - MeshBuilder.k_TexCoordSlicesY[i]) * uvRegion.height + uvRegion.yMin; } float num14 = num6 + num7; bool flag2 = num14 > rectParams.rect.width; if (flag2) { float num15 = rectParams.rect.width / num14; num6 *= num15; num7 *= num15; } float num16 = num8 + num9; bool flag3 = num16 > rectParams.rect.height; if (flag3) { float num17 = rectParams.rect.height / num16; num8 *= num17; num9 *= num17; } MeshBuilder.k_PositionSlicesX[0] = rectParams.rect.x; MeshBuilder.k_PositionSlicesX[1] = rectParams.rect.x + num6; MeshBuilder.k_PositionSlicesX[2] = rectParams.rect.xMax - num7; MeshBuilder.k_PositionSlicesX[3] = rectParams.rect.xMax; MeshBuilder.k_PositionSlicesY[0] = rectParams.rect.yMax; MeshBuilder.k_PositionSlicesY[1] = rectParams.rect.yMax - num8; MeshBuilder.k_PositionSlicesY[2] = rectParams.rect.y + num9; MeshBuilder.k_PositionSlicesY[3] = rectParams.rect.y; for (int j = 0; j < 16; j++) { int num18 = j % 4; int num19 = j / 4; meshWriteData.SetNextVertex(new Vertex { position = new Vector3(MeshBuilder.k_PositionSlicesX[num18], MeshBuilder.k_PositionSlicesY[num19], posZ), uv = new Vector2(MeshBuilder.k_TexCoordSlicesX[num18], MeshBuilder.k_TexCoordSlicesY[num19]), tint = rectParams.color }); } meshWriteData.SetAllIndices(MeshBuilder.slicedQuadIndices); }
internal static void MakeVectorGraphicsStretchBackground(Vertex[] svgVertices, ushort[] svgIndices, float svgWidth, float svgHeight, Rect targetRect, Rect sourceUV, ScaleMode scaleMode, Color tint, int settingIndexOffset, MeshBuilder.AllocMeshData meshAlloc, out int finalVertexCount, out int finalIndexCount) { Vector2 vector = new Vector2(svgWidth * sourceUV.width, svgHeight * sourceUV.height); Vector2 vector2 = new Vector2(sourceUV.xMin * svgWidth, sourceUV.yMin * svgHeight); Rect rect = new Rect(vector2, vector); bool flag = sourceUV.xMin != 0f || sourceUV.yMin != 0f || sourceUV.width != 1f || sourceUV.height != 1f; float num = vector.x / vector.y; float num2 = targetRect.width / targetRect.height; Vector2 vector3; Vector2 vector4; switch (scaleMode) { case ScaleMode.StretchToFill: vector3 = new Vector2(0f, 0f); vector4.x = targetRect.width / vector.x; vector4.y = targetRect.height / vector.y; break; case ScaleMode.ScaleAndCrop: { vector3 = new Vector2(0f, 0f); bool flag2 = num2 > num; if (flag2) { vector4.x = (vector4.y = targetRect.width / vector.x); float num3 = targetRect.height / vector4.y; float num4 = rect.height / 2f - num3 / 2f; vector3.y -= num4 * vector4.y; rect.y += num4; rect.height = num3; flag = true; } else { bool flag3 = num2 < num; if (flag3) { vector4.x = (vector4.y = targetRect.height / vector.y); float num5 = targetRect.width / vector4.x; float num6 = rect.width / 2f - num5 / 2f; vector3.x -= num6 * vector4.x; rect.x += num6; rect.width = num5; flag = true; } else { vector4.x = (vector4.y = targetRect.width / vector.x); } } break; } case ScaleMode.ScaleToFit: { bool flag4 = num2 > num; if (flag4) { vector4.x = (vector4.y = targetRect.height / vector.y); vector3.x = (targetRect.width - vector.x * vector4.x) * 0.5f; vector3.y = 0f; } else { vector4.x = (vector4.y = targetRect.width / vector.x); vector3.x = 0f; vector3.y = (targetRect.height - vector.y * vector4.y) * 0.5f; } break; } default: throw new NotImplementedException(); } MeshBuilder.s_VectorGraphicsStretch.Begin(); vector3 -= vector2 * vector4; int num7 = svgVertices.Length; int num8 = svgIndices.Length; MeshBuilder.ClipCounts clipCounts = default(MeshBuilder.ClipCounts); Vector4 zero = Vector4.zero; bool flag5 = flag; if (flag5) { bool flag6 = rect.width <= 0f || rect.height <= 0f; if (flag6) { finalVertexCount = (finalIndexCount = 0); MeshBuilder.s_VectorGraphicsStretch.End(); return; } zero = new Vector4(rect.xMin, rect.yMin, rect.xMax, rect.yMax); clipCounts = MeshBuilder.UpperBoundApproximateRectClippingResults(svgVertices, svgIndices, zero); num7 += clipCounts.clippedTriangles * 6; num8 += clipCounts.addedTriangles * 3; num8 -= clipCounts.degenerateTriangles * 3; } MeshWriteData meshWriteData = meshAlloc.alloc((uint)num7, (uint)num8, ref meshAlloc); bool flag7 = flag; if (flag7) { MeshBuilder.RectClip(svgVertices, svgIndices, zero, meshWriteData, clipCounts, ref num7); } else { meshWriteData.SetAllIndices(svgIndices); } Debug.Assert(meshWriteData.currentVertex == 0); Rect uvRegion = meshWriteData.uvRegion; int num9 = svgVertices.Length; for (int i = 0; i < num9; i++) { Vertex vertex = svgVertices[i]; vertex.position.x = vertex.position.x * vector4.x + vector3.x; vertex.position.y = vertex.position.y * vector4.y + vector3.y; vertex.uv.x = vertex.uv.x * uvRegion.width + uvRegion.xMin; vertex.uv.y = vertex.uv.y * uvRegion.height + uvRegion.yMin; vertex.tint *= tint; uint num10 = (uint)(((int)vertex.opacityPageSVGSettingIndex.b << 8 | (int)vertex.opacityPageSVGSettingIndex.a) + settingIndexOffset); vertex.opacityPageSVGSettingIndex.b = (byte)(num10 >> 8); vertex.opacityPageSVGSettingIndex.a = (byte)num10; meshWriteData.SetNextVertex(vertex); } for (int j = num9; j < num7; j++) { Vertex vertex2 = meshWriteData.m_Vertices[j]; vertex2.position.x = vertex2.position.x * vector4.x + vector3.x; vertex2.position.y = vertex2.position.y * vector4.y + vector3.y; vertex2.uv.x = vertex2.uv.x * uvRegion.width + uvRegion.xMin; vertex2.uv.y = vertex2.uv.y * uvRegion.height + uvRegion.yMin; vertex2.tint *= tint; uint num11 = (uint)(((int)vertex2.opacityPageSVGSettingIndex.b << 8 | (int)vertex2.opacityPageSVGSettingIndex.a) + settingIndexOffset); vertex2.opacityPageSVGSettingIndex.b = (byte)(num11 >> 8); vertex2.opacityPageSVGSettingIndex.a = (byte)num11; meshWriteData.SetNextVertex(vertex2); } finalVertexCount = meshWriteData.vertexCount; finalIndexCount = meshWriteData.indexCount; MeshBuilder.s_VectorGraphicsStretch.End(); }
private unsafe static void RectClip(Vertex[] vertices, ushort[] indices, Vector4 clipRectMinMax, MeshWriteData mwd, MeshBuilder.ClipCounts cc, ref int newVertexCount) { int num = cc.lastClippedIndex; bool flag = cc.firstDegenerateIndex != -1 && cc.firstDegenerateIndex < num; if (flag) { num = cc.firstDegenerateIndex; } ushort num2 = (ushort)vertices.Length; for (int i = 0; i < cc.firstClippedIndex; i++) { mwd.SetNextIndex(indices[i]); } ushort *ptr = stackalloc ushort[3]; Vertex *ptr2 = stackalloc Vertex[3]; for (int j = cc.firstClippedIndex; j < num; j += 3) { *ptr = indices[j]; ptr[1] = indices[j + 1]; ptr[2] = indices[j + 2]; *ptr2 = vertices[(int)(*ptr)]; ptr2[1] = vertices[(int)ptr[1]]; ptr2[2] = vertices[(int)ptr[2]]; Vector4 vector; vector.x = ((ptr2->position.x < ptr2[1].position.x) ? ptr2->position.x : ptr2[1].position.x); vector.x = ((vector.x < ptr2[2].position.x) ? vector.x : ptr2[2].position.x); vector.y = ((ptr2->position.y < ptr2[1].position.y) ? ptr2->position.y : ptr2[1].position.y); vector.y = ((vector.y < ptr2[2].position.y) ? vector.y : ptr2[2].position.y); vector.z = ((ptr2->position.x > ptr2[1].position.x) ? ptr2->position.x : ptr2[1].position.x); vector.z = ((vector.z > ptr2[2].position.x) ? vector.z : ptr2[2].position.x); vector.w = ((ptr2->position.y > ptr2[1].position.y) ? ptr2->position.y : ptr2[1].position.y); vector.w = ((vector.w > ptr2[2].position.y) ? vector.w : ptr2[2].position.y); bool flag2 = vector.x >= clipRectMinMax.x && vector.z <= clipRectMinMax.z && vector.y >= clipRectMinMax.y && vector.w <= clipRectMinMax.w; if (flag2) { mwd.SetNextIndex(*ptr); mwd.SetNextIndex(ptr[1]); mwd.SetNextIndex(ptr[2]); } else { bool flag3 = vector.x >= clipRectMinMax.z || vector.z <= clipRectMinMax.x || vector.y >= clipRectMinMax.w || vector.w <= clipRectMinMax.y; if (!flag3) { MeshBuilder.RectClipTriangle(ptr2, ptr, clipRectMinMax, mwd, ref num2); } } } int num3 = indices.Length; for (int k = cc.lastClippedIndex + 1; k < num3; k++) { mwd.SetNextIndex(indices[k]); } newVertexCount = (int)num2; mwd.m_Vertices = mwd.m_Vertices.Slice(0, newVertexCount); mwd.m_Indices = mwd.m_Indices.Slice(0, mwd.currentIndex); }
private static void TessellateRoundedBorder(Rect rect, Color color, float posZ, Vector2 radius, float leftWidth, float topWidth, MeshWriteData mesh, ref UInt16 indexOffset, ref UInt16 vertexCount, ref UInt16 indexCount, bool countOnly) { var cornerCenter = rect.position + radius; var subRect = Rect.zero; if (radius == Vector2.zero) { // Without radius, we use two quads for the outlines // ------------ // | | B | // | A |------- // | | // | | // ----- if (leftWidth > kEpsilon) { // A subRect = new Rect(rect.x, rect.y, leftWidth, rect.height); TessellateQuad(subRect, TessellationType.EdgeVertical, color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); } if (topWidth > kEpsilon) { // B subRect = new Rect(rect.x + leftWidth, rect.y, rect.width - leftWidth, topWidth); TessellateQuad(subRect, TessellationType.EdgeHorizontal, color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); } return; } // With radius, we have to create a fan-shaped outline, plus up to 2 quads for the straight outlines // If the radius is smaller than the border width, we create a filled fan plus the required quads instead. if (radius.x < leftWidth || radius.y < topWidth) { // A TessellateFilledFan(TessellationType.EdgeCorner, cornerCenter, radius, color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); if (radius.x < leftWidth && radius.y < topWidth) { // _______________ // -* | | | // * A\ | C| | // *____\|__| F | // | B | | // |________|__________| // | | // | E | // | | // |________| // B subRect = new Rect(rect.x, rect.y + radius.y, leftWidth, topWidth - radius.x); TessellateQuad(subRect, TessellationType.EdgeCorner, color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); // C subRect = new Rect(rect.x + radius.x, rect.y, leftWidth - radius.x, radius.y); TessellateQuad(subRect, TessellationType.EdgeCorner, color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); } else if (radius.x < leftWidth) { // ____________ // -* | | F | // * A\ | B|_______| // *____\|__| // | | // | | // | E | // | | // | | // |________| // B subRect = new Rect(rect.x + radius.x, rect.y, leftWidth - radius.x, Mathf.Max(radius.y, topWidth)); TessellateQuad(subRect, TessellationType.EdgeCorner, color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); } else { // ____________ // -* | | // * A\ | | // *____\| F | // | B | | // |_____|__________| // | | // |E | // | | // |__| // B subRect = new Rect(rect.x, rect.y + radius.y, Mathf.Max(radius.x, leftWidth), topWidth - radius.y); TessellateQuad(subRect, TessellationType.EdgeCorner, color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); } } else { // _________ // -* | F | // * A\_|_______| // *__/ // | | // | | // |E | // | | // |__| // A TessellateBorderedFan(TessellationType.EdgeCorner, cornerCenter, radius, leftWidth, topWidth, color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); } // Tessellate the straight outlines // E float cornerSize = Mathf.Max(radius.y, topWidth); subRect = new Rect(rect.x, rect.y + cornerSize, leftWidth, rect.height - cornerSize); TessellateQuad(subRect, TessellationType.EdgeVertical, color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); // F cornerSize = Mathf.Max(radius.x, leftWidth); subRect = new Rect(rect.x + cornerSize, rect.y, rect.width - cornerSize, topWidth); TessellateQuad(subRect, TessellationType.EdgeHorizontal, color, posZ, mesh, ref indexOffset, ref vertexCount, ref indexCount, countOnly); }
private static void TessellateQuad(Rect rect, TessellationType tessellationType, Color color, float posZ, MeshWriteData mesh, ref UInt16 indexOffset, ref UInt16 vertexCount, ref UInt16 indexCount, bool countOnly) { if (rect.width < kEpsilon || rect.height < kEpsilon) { return; } if (countOnly) { vertexCount += 4; indexCount += 6; return; } float x0 = rect.x; float x3 = rect.xMax; float y0 = rect.y; float y3 = rect.yMax; Vector2 uv0, uv1, uv2, uv3; float flags0, flags1, flags2, flags3; switch (tessellationType) { case TessellationType.EdgeHorizontal: // The uvs contain the displacement from the vertically opposed corner. uv0 = new Vector2(0, y0 - y3); uv1 = new Vector2(0, y0 - y3); uv2 = new Vector2(0, y3 - y0); uv3 = new Vector2(0, y3 - y0); flags0 = flags1 = (float)VertexFlags.IsSolid; flags2 = flags3 = (float)VertexFlags.IsEdge; break; case TessellationType.EdgeVertical: // The uvs contain the displacement from the horizontally opposed corner. uv0 = new Vector2(x0 - x3, 0); uv1 = new Vector2(x3 - x0, 0); uv2 = new Vector2(x0 - x3, 0); uv3 = new Vector2(x3 - x0, 0); flags0 = flags2 = (float)VertexFlags.IsSolid; flags1 = flags3 = (float)VertexFlags.IsEdge; break; case TessellationType.EdgeCorner: uv0 = uv1 = uv2 = uv3 = Vector2.zero; flags0 = flags1 = flags2 = flags3 = (float)VertexFlags.IsSolid; break; case TessellationType.Content: uv0 = uv1 = uv2 = uv3 = Vector2.zero; // UVs are computed later for content flags0 = flags1 = flags2 = flags3 = (float)mesh.m_Flags; break; default: throw new NotImplementedException(); } mesh.SetNextVertex(new Vertex { position = new Vector3(x0, y0, posZ), uv = uv0, tint = color, flags = flags0 }); mesh.SetNextVertex(new Vertex { position = new Vector3(x3, y0, posZ), uv = uv1, tint = color, flags = flags1 }); mesh.SetNextVertex(new Vertex { position = new Vector3(x0, y3, posZ), uv = uv2, tint = color, flags = flags2 }); mesh.SetNextVertex(new Vertex { position = new Vector3(x3, y3, posZ), uv = uv3, tint = color, flags = flags3 }); mesh.SetNextIndex((UInt16)(indexOffset + 0)); mesh.SetNextIndex((UInt16)(indexOffset + 2)); mesh.SetNextIndex((UInt16)(indexOffset + 1)); mesh.SetNextIndex((UInt16)(indexOffset + 3)); mesh.SetNextIndex((UInt16)(indexOffset + 1)); mesh.SetNextIndex((UInt16)(indexOffset + 2)); vertexCount += 4; indexCount += 6; indexOffset += 4; }
protected override void OnGenerateVisualContent(MeshGenerationContext cxt) { var mp = new MeshParts(); List <int3> curTri = new List <int3>(); Color[] clrByDepth = new Color[_subDiv + 1]; for (int iClr = 0; iClr < clrByDepth.Length; iClr++) { float t = iClr / (float)(clrByDepth.Length); clrByDepth[iClr] = Color.HSVToRGB(t, 1, 1); } for (int iTriVtx = 0; iTriVtx < 3; iTriVtx++) { Vertex vtx = new Vertex(); vtx.position = (Vector2)T_LsFromNs(TriangleMat[iTriVtx]); vtx.tint = clrByDepth[_subDiv]; // it circular mp.vertices.Add(vtx); } curTri.Add(new int3(2, 1, 0)); for (int iDiv = 0; iDiv < _subDiv; iDiv++) { List <int3> nxtTri = new List <int3>(); foreach (var outerTri in curTri) { int vtxOffset = mp.vertices.Count; for (int iTriVtx = 0; iTriVtx < 3; iTriVtx++) { var pntLS = Vector3.zero; for (int iEdge = 0; iEdge < 3; iEdge++) { pntLS += (iEdge == iTriVtx) ? Vector3.zero: mp.vertices[outerTri[iEdge]].position; } pntLS /= 2; Vertex vtx = new Vertex(); vtx.position = pntLS; vtx.tint = clrByDepth[iDiv]; mp.vertices.Add(vtx); } for (int iTriVtx = 0; iTriVtx < 3; iTriVtx++) { // Broad cast it to xyz; int3 newTri = outerTri[iTriVtx]; if (iTriVtx == 0) { newTri.yz = vtxOffset + new int2(2, 1); } else if (iTriVtx == 1) { newTri.xz = vtxOffset + new int2(2, 0); } else if (iTriVtx == 2) { newTri.xy = vtxOffset + new int2(1, 0); } nxtTri.Add(newTri); } nxtTri.Add(vtxOffset + new int3(0, 1, 2)); } curTri = nxtTri; } foreach (var tri in curTri) { mp.triangles.Add(tri); //indices.AddRange(new ushort[] { (ushort)tri.z, (ushort)tri.y, (ushort)tri.x }); } if (GeneBankManager.Inst && GeneBankManager.Inst.GenomeCount > 0) { ApplyGenomeColors(mp.vertices); } AddPoint(mp, T_NsFromBs(_value_bs), math.cmin(layout.size / 30), Color.white); MeshWriteData meshData = cxt.Allocate(mp.vertices.Count, mp.triangles.Count * 3); meshData.SetAllVertices(mp.vertices.ToArray()); meshData.SetAllIndices(mp.GetIndices()); }
private static void TessellateBorderedFan(TessellationType tessellationType, Vector2 center, Vector2 radius, float leftWidth, float topWidth, Color color, float posZ, MeshWriteData mesh, ref UInt16 indexOffset, ref UInt16 vertexCount, ref UInt16 indexCount, bool countOnly) { if (countOnly) { vertexCount += (UInt16)(kSubdivisions * 2); indexCount += (UInt16)((kSubdivisions - 1) * 6); return; } float innerVertexFlags, outerVertexFlags; if (tessellationType == TessellationType.EdgeCorner) { innerVertexFlags = (float)VertexFlags.IsEdge; outerVertexFlags = (float)VertexFlags.IsSolid; } else { innerVertexFlags = outerVertexFlags = (float)mesh.m_Flags; } var a = radius.x - leftWidth; var b = radius.y - topWidth; var p = new Vector2(center.x - radius.x, center.y); var q = new Vector2(center.x - a, center.y); mesh.SetNextVertex(new Vertex { position = new Vector3(q.x, q.y, posZ), uv = q - p, tint = color, flags = innerVertexFlags }); mesh.SetNextVertex(new Vertex { position = new Vector3(p.x, p.y, posZ), uv = p - q, tint = color, flags = outerVertexFlags }); vertexCount += 2; for (int k = 1; k < kSubdivisions; ++k) { float percent = ((float)k) / (kSubdivisions - 1); float angle = (Mathf.PI * 0.5f) * percent; p = center + new Vector2(-Mathf.Cos(angle), -Mathf.Sin(angle)) * radius; q = center + new Vector2(-a * Mathf.Cos(angle), -b * Mathf.Sin(angle)); mesh.SetNextVertex(new Vertex { position = new Vector3(q.x, q.y, posZ), uv = q - p, tint = color, flags = innerVertexFlags }); mesh.SetNextVertex(new Vertex { position = new Vector3(p.x, p.y, posZ), uv = p - q, tint = color, flags = outerVertexFlags }); vertexCount += 2; int i = k * 2; mesh.SetNextIndex((UInt16)(indexOffset + (i - 2))); mesh.SetNextIndex((UInt16)(indexOffset + (i))); mesh.SetNextIndex((UInt16)(indexOffset + (i - 1))); mesh.SetNextIndex((UInt16)(indexOffset + (i - 1))); mesh.SetNextIndex((UInt16)(indexOffset + (i))); mesh.SetNextIndex((UInt16)(indexOffset + (i + 1))); indexCount += 6; } indexOffset += (UInt16)(kSubdivisions * 2); }
unsafe static void RectClip(Vertex[] vertices, UInt16[] indices, Vector4 clipRectMinMax, MeshWriteData mwd, ClipCounts cc, ref int newVertexCount) { int lastEffectiveClippedIndex = cc.lastClippedIndex; if (cc.firstDegenerateIndex != -1 && cc.firstDegenerateIndex < lastEffectiveClippedIndex) { lastEffectiveClippedIndex = cc.firstDegenerateIndex; } UInt16 nextNewVertex = (UInt16)vertices.Length; // Copy all non-clipped indices for (int i = 0; i < cc.firstClippedIndex; i++) { mwd.SetNextIndex(indices[i]); } // Clipped triangles UInt16 *it = stackalloc UInt16[3]; // Indices of the triangle Vertex *vt = stackalloc Vertex[3]; // Vertices of the triangle for (int i = cc.firstClippedIndex; i < lastEffectiveClippedIndex; i += 3) { it[0] = indices[i]; it[1] = indices[i + 1]; it[2] = indices[i + 2]; vt[0] = vertices[it[0]]; vt[1] = vertices[it[1]]; vt[2] = vertices[it[2]]; Vector4 triRectMinMax; triRectMinMax.x = vt[0].position.x < vt[1].position.x ? vt[0].position.x : vt[1].position.x; triRectMinMax.x = triRectMinMax.x < vt[2].position.x ? triRectMinMax.x : vt[2].position.x; triRectMinMax.y = vt[0].position.y < vt[1].position.y ? vt[0].position.y : vt[1].position.y; triRectMinMax.y = triRectMinMax.y < vt[2].position.y ? triRectMinMax.y : vt[2].position.y; triRectMinMax.z = vt[0].position.x > vt[1].position.x ? vt[0].position.x : vt[1].position.x; triRectMinMax.z = triRectMinMax.z > vt[2].position.x ? triRectMinMax.z : vt[2].position.x; triRectMinMax.w = vt[0].position.y > vt[1].position.y ? vt[0].position.y : vt[1].position.y; triRectMinMax.w = triRectMinMax.w > vt[2].position.y ? triRectMinMax.w : vt[2].position.y; // Test if the rect is outside (degenerate triangle), or totally inside (not clipped), // else it is _probably_ clipped, but can still be either degenerate or unclipped if ((triRectMinMax.x >= clipRectMinMax.x) && (triRectMinMax.z <= clipRectMinMax.z) && (triRectMinMax.y >= clipRectMinMax.y) && (triRectMinMax.w <= clipRectMinMax.w)) { // Clean triangle mwd.SetNextIndex(it[0]); mwd.SetNextIndex(it[1]); mwd.SetNextIndex(it[2]); continue; } if ((triRectMinMax.x >= clipRectMinMax.z) || (triRectMinMax.z <= clipRectMinMax.x) || (triRectMinMax.y >= clipRectMinMax.w) || (triRectMinMax.w <= clipRectMinMax.y)) { continue; // Skip this triangle. It is fully clipped. } // The full shabang RectClipTriangle(vt, it, clipRectMinMax, mwd, ref nextNewVertex); } // Copy remaining non-clipped indices int indexCount = indices.Length; for (int i = cc.lastClippedIndex + 1; i < indexCount; i++) { mwd.SetNextIndex(indices[i]); } newVertexCount = nextNewVertex; mwd.m_Vertices = mwd.m_Vertices.Slice(0, newVertexCount); mwd.m_Indices = mwd.m_Indices.Slice(0, mwd.currentIndex); }
unsafe static void RectClipTriangle(Vertex *vt, UInt16 *it, Vector4 clipRectMinMax, MeshWriteData mwd, ref UInt16 nextNewVertex) { Vertex *newVerts = stackalloc Vertex[4 + 3 + 6]; int newVertsCount = 0; // First check, add original triangle vertices if they all fall within the clip rect, and early out if they are 3. // This hopefully will trap the majority of triangles. for (int i = 0; i < 3; i++) { if ((vt[i].position.x >= clipRectMinMax.x) && (vt[i].position.y >= clipRectMinMax.y) && (vt[i].position.x <= clipRectMinMax.z) && (vt[i].position.y <= clipRectMinMax.w)) { newVerts[newVertsCount++] = vt[i]; } } if (newVertsCount == 3) { // Entire triangle is contained within the clip rect, just reference the original triangle verts and sayonara mwd.SetNextIndex(it[0]); mwd.SetNextIndex(it[1]); mwd.SetNextIndex(it[2]); return; } // Next, check if any clip rect vertices are within the triangle, and register those Vector3 uvwTL = GetVertexBaryCentricCoordinates(vt, clipRectMinMax.x, clipRectMinMax.y); Vector3 uvwTR = GetVertexBaryCentricCoordinates(vt, clipRectMinMax.z, clipRectMinMax.y); Vector3 uvwBL = GetVertexBaryCentricCoordinates(vt, clipRectMinMax.x, clipRectMinMax.w); Vector3 uvwBR = GetVertexBaryCentricCoordinates(vt, clipRectMinMax.z, clipRectMinMax.w); const float kEpsilon = 0.0000001f; // Better be safe and have more verts than miss some const float kMin = -kEpsilon; const float kMax = 1 + kEpsilon; if ((uvwTL.x >= kMin && uvwTL.x <= kMax) && (uvwTL.y >= kMin && uvwTL.y <= kMax) && (uvwTL.z >= kMin && uvwTL.z <= kMax)) { newVerts[newVertsCount++] = InterpolateVertexInTriangle(vt, clipRectMinMax.x, clipRectMinMax.y, uvwTL); } if ((uvwTR.x >= kMin && uvwTR.x <= kMax) && (uvwTR.y >= kMin && uvwTR.y <= kMax) && (uvwTR.z >= kMin && uvwTR.z <= kMax)) { newVerts[newVertsCount++] = InterpolateVertexInTriangle(vt, clipRectMinMax.z, clipRectMinMax.y, uvwTR); } if ((uvwBL.x >= kMin && uvwBL.x <= kMax) && (uvwBL.y >= kMin && uvwBL.y <= kMax) && (uvwBL.z >= kMin && uvwBL.z <= kMax)) { newVerts[newVertsCount++] = InterpolateVertexInTriangle(vt, clipRectMinMax.x, clipRectMinMax.w, uvwBL); } if ((uvwBR.x >= kMin && uvwBR.x <= kMax) && (uvwBR.y >= kMin && uvwBR.y <= kMax) && (uvwBR.z >= kMin && uvwBR.z <= kMax)) { newVerts[newVertsCount++] = InterpolateVertexInTriangle(vt, clipRectMinMax.z, clipRectMinMax.w, uvwBR); } // Next, test triangle edges against rect sides (12 tests) float t; t = IntersectSegments(vt[0].position.x, vt[0].position.y, vt[1].position.x, vt[1].position.y, clipRectMinMax.x, clipRectMinMax.y, clipRectMinMax.z, clipRectMinMax.y); // Edge 1 against top side if (t != float.MaxValue) { newVerts[newVertsCount++] = InterpolateVertexInTriangleEdge(vt, 0, 1, t); } t = IntersectSegments(vt[1].position.x, vt[1].position.y, vt[2].position.x, vt[2].position.y, clipRectMinMax.x, clipRectMinMax.y, clipRectMinMax.z, clipRectMinMax.y); // Edge 2 against top side if (t != float.MaxValue) { newVerts[newVertsCount++] = InterpolateVertexInTriangleEdge(vt, 1, 2, t); } t = IntersectSegments(vt[2].position.x, vt[2].position.y, vt[0].position.x, vt[0].position.y, clipRectMinMax.x, clipRectMinMax.y, clipRectMinMax.z, clipRectMinMax.y); // Edge 3 against top side if (t != float.MaxValue) { newVerts[newVertsCount++] = InterpolateVertexInTriangleEdge(vt, 2, 0, t); } t = IntersectSegments(vt[0].position.x, vt[0].position.y, vt[1].position.x, vt[1].position.y, clipRectMinMax.z, clipRectMinMax.y, clipRectMinMax.z, clipRectMinMax.w); // Edge 1 against right side if (t != float.MaxValue) { newVerts[newVertsCount++] = InterpolateVertexInTriangleEdge(vt, 0, 1, t); } t = IntersectSegments(vt[1].position.x, vt[1].position.y, vt[2].position.x, vt[2].position.y, clipRectMinMax.z, clipRectMinMax.y, clipRectMinMax.z, clipRectMinMax.w); // Edge 2 against right side if (t != float.MaxValue) { newVerts[newVertsCount++] = InterpolateVertexInTriangleEdge(vt, 1, 2, t); } t = IntersectSegments(vt[2].position.x, vt[2].position.y, vt[0].position.x, vt[0].position.y, clipRectMinMax.z, clipRectMinMax.y, clipRectMinMax.z, clipRectMinMax.w); // Edge 3 against right side if (t != float.MaxValue) { newVerts[newVertsCount++] = InterpolateVertexInTriangleEdge(vt, 2, 0, t); } t = IntersectSegments(vt[0].position.x, vt[0].position.y, vt[1].position.x, vt[1].position.y, clipRectMinMax.x, clipRectMinMax.w, clipRectMinMax.z, clipRectMinMax.w); // Edge 1 against bottom side if (t != float.MaxValue) { newVerts[newVertsCount++] = InterpolateVertexInTriangleEdge(vt, 0, 1, t); } t = IntersectSegments(vt[1].position.x, vt[1].position.y, vt[2].position.x, vt[2].position.y, clipRectMinMax.x, clipRectMinMax.w, clipRectMinMax.z, clipRectMinMax.w); // Edge 2 against bottom side if (t != float.MaxValue) { newVerts[newVertsCount++] = InterpolateVertexInTriangleEdge(vt, 1, 2, t); } t = IntersectSegments(vt[2].position.x, vt[2].position.y, vt[0].position.x, vt[0].position.y, clipRectMinMax.x, clipRectMinMax.w, clipRectMinMax.z, clipRectMinMax.w); // Edge 3 against bottom side if (t != float.MaxValue) { newVerts[newVertsCount++] = InterpolateVertexInTriangleEdge(vt, 2, 0, t); } t = IntersectSegments(vt[0].position.x, vt[0].position.y, vt[1].position.x, vt[1].position.y, clipRectMinMax.x, clipRectMinMax.y, clipRectMinMax.x, clipRectMinMax.w); // Edge 1 against left side if (t != float.MaxValue) { newVerts[newVertsCount++] = InterpolateVertexInTriangleEdge(vt, 0, 1, t); } t = IntersectSegments(vt[1].position.x, vt[1].position.y, vt[2].position.x, vt[2].position.y, clipRectMinMax.x, clipRectMinMax.y, clipRectMinMax.x, clipRectMinMax.w); // Edge 2 against left side if (t != float.MaxValue) { newVerts[newVertsCount++] = InterpolateVertexInTriangleEdge(vt, 1, 2, t); } t = IntersectSegments(vt[2].position.x, vt[2].position.y, vt[0].position.x, vt[0].position.y, clipRectMinMax.x, clipRectMinMax.y, clipRectMinMax.x, clipRectMinMax.w); // Edge 3 against left side if (t != float.MaxValue) { newVerts[newVertsCount++] = InterpolateVertexInTriangleEdge(vt, 2, 0, t); } if (newVertsCount == 0) { return; // This should be rare. It means the bounding box test intersected but the accurate test found no intersection. It's ok. } // The first added vertex will be our anchor for the fan // All vertices involved in the result are accumulated in newVerts. Calculate angles of vertices with regards to the first vertex to sort against. float *vertAngles = stackalloc float[newVertsCount]; vertAngles[0] = 0; // Doesn't matter, unused const float k2PI = Mathf.PI * 2.0f; for (int i = 1; i < newVertsCount; i++) { vertAngles[i] = Mathf.Atan2(newVerts[i].position.y - newVerts[0].position.y, newVerts[i].position.x - newVerts[0].position.x); if (vertAngles[i] < 0.0f) { vertAngles[i] += k2PI; } } // Sort vertices in angle order int *sortedVerts = stackalloc int[newVertsCount]; sortedVerts[0] = 0; uint addedFlag = 0; // Bit field for each vertex, max 32.. definitely enough for (int i = 1; i < newVertsCount; i++) { int minIndex = -1; float minAngle = float.MaxValue; for (int j = 1; j < newVertsCount; j++) { if (((addedFlag & (1 << j)) == 0) && (vertAngles[j] < minAngle)) { minAngle = vertAngles[j]; minIndex = j; } } sortedVerts[i] = minIndex; addedFlag = addedFlag | (1U << minIndex); } // Register new vertices UInt16 newVerticesIndex = nextNewVertex; for (int i = 0; i < newVertsCount; i++) { mwd.m_Vertices[newVerticesIndex + i] = newVerts[sortedVerts[i]]; } nextNewVertex += (UInt16)newVertsCount; // Build a fan, our selection of first edge might be crossing the middle of the tessellated polygon // so the fan is not starting from side to side, but from middle to middle. This is why wrapAroundHandled is there. int newTriCount = newVertsCount - 2; bool wrapAroundHandled = false; Vector3 p0 = mwd.m_Vertices[newVerticesIndex].position; for (int i = 0; i < newTriCount; i++) { int index1 = newVerticesIndex + i + 1; int index2 = newVerticesIndex + i + 2; if (!wrapAroundHandled) { float angle1 = vertAngles[sortedVerts[i + 1]]; float angle2 = vertAngles[sortedVerts[i + 2]]; if (angle2 - angle1 >= Mathf.PI) { index1 = newVerticesIndex + 1; index2 = newVerticesIndex + newVertsCount - 1; wrapAroundHandled = true; } } Vector3 p1 = mwd.m_Vertices[index1].position; Vector3 p2 = mwd.m_Vertices[index2].position; Vector3 c = Vector3.Cross(p1 - p0, p2 - p0); // Add the indices in the right winding order mwd.SetNextIndex((UInt16)(newVerticesIndex)); if (c.z < 0) { mwd.SetNextIndex((UInt16)index1); mwd.SetNextIndex((UInt16)index2); } else { mwd.SetNextIndex((UInt16)index2); mwd.SetNextIndex((UInt16)index1); } } // For each new triangle }
void QuadA(Vector2 pos, Vector2 size, Vector2 uvSize, Vector2 uvOffset, Color color, MeshWriteData mesh, ushort vertextOffset) { var x0 = pos.x; var y0 = pos.y; var x1 = pos.x + size.x; var y1 = pos.y + size.y; mesh.SetNextVertex(new Vertex() { position = new Vector3(x0, y0, Vertex.nearZ), tint = color, uv = new Vector2(0, 1) * uvSize * mesh.uvRegion.size + mesh.uvRegion.position }); mesh.SetNextVertex(new Vertex() { position = new Vector3(x1, y0, Vertex.nearZ), tint = color, uv = new Vector2(1, 1) * uvSize * mesh.uvRegion.size + mesh.uvRegion.position }); mesh.SetNextVertex(new Vertex() { position = new Vector3(x0, y1, Vertex.nearZ), tint = color, uv = new Vector2(0, uvOffset.y) * uvSize * mesh.uvRegion.size + mesh.uvRegion.position }); mesh.SetNextVertex(new Vertex() { position = new Vector3(x1, y1, Vertex.nearZ), tint = color, uv = new Vector2(1, uvOffset.y) * uvSize * mesh.uvRegion.size + mesh.uvRegion.position }); for (int i = 0; i < k_Indices.Length; i++) { mesh.SetNextIndex((ushort)(k_Indices[i] + vertextOffset)); } }