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 });
        }
示例#7
0
        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);
        }
示例#8
0
        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);
        }
示例#11
0
 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());
            }
        }
示例#20
0
        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;
        }
示例#26
0
        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);
        }
示例#28
0
        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);
        }
示例#29
0
        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));
            }
        }