private static void MirrorVertices(Rect rect, NativeSlice <Vertex>?vertices, int vertexStart, int vertexCount, bool flipHorizontal) { if (!vertices.HasValue) { return; } var verts = vertices.GetValueOrDefault(); if (flipHorizontal) { for (int i = 0; i < vertexCount; ++i) { var vertex = verts[vertexStart + i]; vertex.position.x = rect.xMax - (vertex.position.x - rect.xMax); vertex.uv.x = -vertex.uv.x; verts[vertexStart + i] = vertex; } } else { for (int i = 0; i < vertexCount; ++i) { var vertex = verts[vertexStart + i]; vertex.position.y = rect.yMax - (vertex.position.y - rect.yMax); vertex.uv.y = -vertex.uv.y; verts[vertexStart + i] = vertex; } } }
private static void TessellateFilledFan(TessellationType tessellationType, Vector2 center, float radius, Color color, float posZ, VertexFlags vertexFlags, NativeSlice <Vertex>?vertices, NativeSlice <UInt16>?indices, ref UInt16 indexOffset, ref UInt16 vertexCount, ref UInt16 indexCount, bool countOnly) { VertexFlags innerVertexFlags, outerVertexFlags; if (tessellationType == TessellationType.EdgeCorner) { innerVertexFlags = VertexFlags.IsEdge; outerVertexFlags = VertexFlags.IsSolid; } else { innerVertexFlags = vertexFlags; outerVertexFlags = vertexFlags; } if (countOnly) { vertexCount += (UInt16)(kSubdivisions + 1); indexCount += (UInt16)((kSubdivisions - 1) * 3); return; } var p = new Vector2(center.x - radius, center.y); var verts = vertices.GetValueOrDefault(); var inds = indices.GetValueOrDefault(); verts[vertexCount++] = new Vertex() { position = new Vector3(center.x, center.y, posZ), uv = p, tint = color, flags = (float)innerVertexFlags }; verts[vertexCount++] = new Vertex() { position = new Vector3(p.x, p.y, posZ), uv = center, tint = color, flags = (float)outerVertexFlags }; for (int k = 1; k < kSubdivisions; ++k) { float angle = (Mathf.PI / 2.0f) * ((float)k) / (kSubdivisions - 1); p = center + new Vector2(-Mathf.Cos(angle), -Mathf.Sin(angle)) * radius; verts[vertexCount++] = new Vertex() { position = new Vector3(p.x, p.y, posZ), uv = center, tint = color, flags = (float)outerVertexFlags }; inds[indexCount++] = (UInt16)(indexOffset + 0); inds[indexCount++] = (UInt16)(indexOffset + k + 1); inds[indexCount++] = (UInt16)(indexOffset + k); } indexOffset += (UInt16)(kSubdivisions + 1); }
private static void FlipWinding(NativeSlice <UInt16>?indices, int indexStart, int indexCount) { if (!indices.HasValue) { return; } var inds = indices.GetValueOrDefault(); for (int i = 0; i < indexCount; i += 3) { UInt16 tmp = inds[indexStart + i]; inds[indexStart + i] = inds[indexStart + i + 1]; inds[indexStart + i + 1] = tmp; } }
private static void TessellateBorderedFan(TessellationType tessellationType, Vector2 center, float radius, float leftWidth, float topWidth, Color color, float posZ, VertexFlags vertexFlags, NativeSlice <Vertex>?vertices, NativeSlice <UInt16>?indices, ref UInt16 indexOffset, ref UInt16 vertexCount, ref UInt16 indexCount, bool countOnly) { VertexFlags innerVertexFlags, outerVertexFlags; if (tessellationType == TessellationType.EdgeCorner) { innerVertexFlags = VertexFlags.IsEdge; outerVertexFlags = VertexFlags.IsSolid; } else { innerVertexFlags = vertexFlags; outerVertexFlags = vertexFlags; } if (countOnly) { vertexCount += (UInt16)(kSubdivisions * 2); indexCount += (UInt16)((kSubdivisions - 1) * 6); return; } var a = radius - leftWidth; var b = radius - topWidth; var p = new Vector2(center.x - radius, center.y); var q = new Vector2(center.x - a, center.y); var verts = vertices.GetValueOrDefault(); var inds = indices.GetValueOrDefault(); verts[vertexCount++] = new Vertex { position = new Vector3(q.x, q.y, posZ), uv = q - p, tint = color, flags = (float)innerVertexFlags }; verts[vertexCount++] = new Vertex { position = new Vector3(p.x, p.y, posZ), uv = p - q, tint = color, flags = (float)outerVertexFlags }; for (int k = 1; k < kSubdivisions; ++k) { float percent = ((float)k) / (kSubdivisions - 1); float angle = (Mathf.PI / 2.0f) * percent; p = center + new Vector2(-Mathf.Cos(angle), -Mathf.Sin(angle)) * radius; q = center + new Vector2(-a * Mathf.Cos(angle), -b * Mathf.Sin(angle)); verts[vertexCount++] = new Vertex { position = new Vector3(q.x, q.y, posZ), uv = q - p, tint = color, flags = (float)innerVertexFlags }; verts[vertexCount++] = new Vertex { position = new Vector3(p.x, p.y, posZ), uv = p - q, tint = color, flags = (float)outerVertexFlags }; int i = k * 2; inds[indexCount++] = (UInt16)(indexOffset + (i - 2)); inds[indexCount++] = (UInt16)(indexOffset + (i)); inds[indexCount++] = (UInt16)(indexOffset + (i - 1)); inds[indexCount++] = (UInt16)(indexOffset + (i - 1)); inds[indexCount++] = (UInt16)(indexOffset + (i)); inds[indexCount++] = (UInt16)(indexOffset + (i + 1)); } indexOffset += (UInt16)(kSubdivisions * 2); }
private static void TessellateQuad(Rect rect, TessellationType tessellationType, Color color, float posZ, VertexFlags vertexFlags, NativeSlice <Vertex>?vertices, NativeSlice <UInt16>?indices, 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)vertexFlags; break; default: throw new NotImplementedException(); } var verts = vertices.GetValueOrDefault(); verts[vertexCount++] = new Vertex { position = new Vector3(x0, y0, posZ), uv = uv0, tint = color, flags = flags0 }; verts[vertexCount++] = new Vertex { position = new Vector3(x3, y0, posZ), uv = uv1, tint = color, flags = flags1 }; verts[vertexCount++] = new Vertex { position = new Vector3(x0, y3, posZ), uv = uv2, tint = color, flags = flags2 }; verts[vertexCount++] = new Vertex { position = new Vector3(x3, y3, posZ), uv = uv3, tint = color, flags = flags3 }; var inds = indices.GetValueOrDefault(); inds[indexCount++] = (UInt16)(indexOffset + 0); inds[indexCount++] = (UInt16)(indexOffset + 2); inds[indexCount++] = (UInt16)(indexOffset + 1); inds[indexCount++] = (UInt16)(indexOffset + 3); inds[indexCount++] = (UInt16)(indexOffset + 1); inds[indexCount++] = (UInt16)(indexOffset + 2); indexOffset += 4; }