123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine.Experimental.Rendering.Universal.LibTessDotNet;
- namespace UnityEngine.Experimental.Rendering.Universal
- {
- internal static class LightUtility
- {
- public static bool CheckForChange(int a, ref int b)
- {
- bool changed = a != b;
- b = a;
- return changed;
- }
- public static bool CheckForChange(float a, ref float b)
- {
- bool changed = a != b;
- b = a;
- return changed;
- }
- public static bool CheckForChange(bool a, ref bool b)
- {
- bool changed = a != b;
- b = a;
- return changed;
- }
- public static bool CheckForChange(Vector2 a, ref Vector2 b)
- {
- bool changed = a != b;
- b = a;
- return changed;
- }
- public static bool CheckForChange(Sprite a, ref Sprite b)
- {
- bool changed = !Equals(a, b);
- b = a;
- return changed;
- }
- public static Bounds CalculateBoundingSphere(ref Vector3[] vertices, ref Color[] colors, float falloffDistance)
- {
- Bounds localBounds = new Bounds();
- Vector3 minimum = new Vector3(float.MaxValue, float.MaxValue);
- Vector3 maximum = new Vector3(float.MinValue, float.MinValue);
- for (int i = 0; i < vertices.Length; i++)
- {
- Vector3 vertex = vertices[i];
- vertex.x += falloffDistance * colors[i].r;
- vertex.y += falloffDistance * colors[i].g;
- minimum.x = vertex.x < minimum.x ? vertex.x : minimum.x;
- minimum.y = vertex.y < minimum.y ? vertex.y : minimum.y;
- maximum.x = vertex.x > maximum.x ? vertex.x : maximum.x;
- maximum.y = vertex.y > maximum.y ? vertex.y : maximum.y;
- }
- localBounds.max = maximum;
- localBounds.min = minimum;
- return localBounds;
- }
- // Takes in a mesh that
- public static Bounds GenerateParametricMesh(ref Mesh mesh, float radius, float falloffDistance, float angle, int sides)
- {
- if (mesh == null)
- mesh = new Mesh();
- float angleOffset = Mathf.PI / 2.0f + Mathf.Deg2Rad * angle;
- if (sides < 3)
- {
- radius = 0.70710678118654752440084436210485f * radius;
- sides = 4;
- }
- if(sides == 4)
- {
- angleOffset = Mathf.PI / 4.0f + Mathf.Deg2Rad * angle;
- }
- // Return a shape with radius = 1
- Vector3[] vertices;
- int[] triangles;
- Color[] colors;
- int centerIndex;
- vertices = new Vector3[1 + 2 * sides];
- colors = new Color[1 + 2 * sides];
- triangles = new int[3 * 3 * sides];
- centerIndex = 2 * sides;
- // Color will contain r,g = x,y extrusion direction, a = alpha. b is unused at the moment. The inner shape should not be extruded
- Color color = new Color(0, 0, 0, 1);
- vertices[centerIndex] = Vector3.zero;
- colors[centerIndex] = color;
- float radiansPerSide = 2 * Mathf.PI / sides;
-
- for (int i = 0; i < sides; i++)
- {
- float endAngle = (i + 1) * radiansPerSide;
- Vector3 extrudeDir = new Vector3(Mathf.Cos(endAngle + angleOffset), Mathf.Sin(endAngle + angleOffset), 0);
- Vector3 endPoint = radius * extrudeDir;
- int vertexIndex;
- vertexIndex = (2 * i + 2) % (2 * sides);
- vertices[vertexIndex] = endPoint; // This is the extruded endpoint
- vertices[vertexIndex + 1] = endPoint;
- colors[vertexIndex] = new Color(extrudeDir.x, extrudeDir.y, 0, 0);
- colors[vertexIndex + 1] = color;
- // Triangle 1 (Tip)
- int triangleIndex = 9 * i;
- triangles[triangleIndex] = vertexIndex + 1;
- triangles[triangleIndex + 1] = 2 * i + 1;
- triangles[triangleIndex + 2] = centerIndex;
- // Triangle 2 (Upper Top Left)
- triangles[triangleIndex + 3] = vertexIndex;
- triangles[triangleIndex + 4] = 2 * i;
- triangles[triangleIndex + 5] = 2 * i + 1;
- // Triangle 2 (Bottom Top Left)
- triangles[triangleIndex + 6] = vertexIndex + 1;
- triangles[triangleIndex + 7] = vertexIndex;
- triangles[triangleIndex + 8] = 2 * i + 1;
- }
- mesh.Clear();
- mesh.vertices = vertices;
- mesh.colors = colors;
- mesh.triangles = triangles;
- return CalculateBoundingSphere(ref vertices, ref colors, falloffDistance);
- }
- public static Bounds GenerateSpriteMesh(ref Mesh mesh, Sprite sprite, float scale)
- {
- if (mesh == null)
- mesh = new Mesh();
- if (sprite != null)
- {
- Vector2[] vertices2d = sprite.vertices;
- Vector3[] vertices3d = new Vector3[vertices2d.Length];
- Color[] colors = new Color[vertices2d.Length];
- Vector4[] volumeColor = new Vector4[vertices2d.Length];
- ushort[] triangles2d = sprite.triangles;
- int[] triangles3d = new int[triangles2d.Length];
- Vector3 center = 0.5f * scale * (sprite.bounds.min + sprite.bounds.max);
- for (int vertexIdx = 0; vertexIdx < vertices2d.Length; vertexIdx++)
- {
- Vector3 pos = new Vector3(vertices2d[vertexIdx].x, vertices2d[vertexIdx].y) - center;
- vertices3d[vertexIdx] = scale * pos;
- colors[vertexIdx] = new Color(0,0,0,1); // This will not have any extrusion available. Alpha will be 1 * the pixel alpha
- }
- for (int triangleIdx = 0; triangleIdx < triangles2d.Length; triangleIdx++)
- {
- triangles3d[triangleIdx] = (int)triangles2d[triangleIdx];
- }
- mesh.Clear();
- mesh.vertices = vertices3d;
- mesh.uv = sprite.uv;
- mesh.triangles = triangles3d;
- mesh.colors = colors;
- return CalculateBoundingSphere(ref vertices3d, ref colors, 0);
- }
- return new Bounds(Vector3.zero, Vector3.zero);
- }
- static void GetFalloffExtrusion(ContourVertex[] contourPoints, int contourPointCount, ref List<Vector2> extrusionDir)
- {
- for (int i = 0; i < contourPointCount; ++i)
- {
- int h = (i == 0) ? (contourPointCount - 1) : (i - 1);
- int j = (i + 1) % contourPointCount;
- Vector2 pp = new Vector2(contourPoints[h].Position.X, contourPoints[h].Position.Y);
- Vector2 cp = new Vector2(contourPoints[i].Position.X, contourPoints[i].Position.Y);
- Vector2 np = new Vector2(contourPoints[j].Position.X, contourPoints[j].Position.Y);
- Vector2 cpd = cp - pp;
- Vector2 npd = np - cp;
- if (cpd.magnitude < 0.001f || npd.magnitude < 0.001f)
- continue;
- Vector2 vl = cpd.normalized;
- Vector2 vr = npd.normalized;
- vl = new Vector2(-vl.y, vl.x);
- vr = new Vector2(-vr.y, vr.x);
- Vector2 va = vl.normalized + vr.normalized;
- Vector2 vn = -va.normalized;
- if (va.magnitude > 0 && vn.magnitude > 0)
- {
- Vector2 dir = new Vector2(vn.x, vn.y);
- extrusionDir.Add(dir);
- }
- }
- }
- static object InterpCustomVertexData(Vec3 position, object[] data, float[] weights)
- {
- return data[0];
- }
- public static void GetFalloffShape(Vector3[] shapePath, ref List<Vector2> extrusionDir)
- {
- int pointCount = shapePath.Length;
- var inputs = new ContourVertex[pointCount];
- for (int i = 0; i < pointCount; ++i)
- inputs[i] = new ContourVertex() { Position = new Vec3() { X = shapePath[i].x, Y = shapePath[i].y }, Data = null };
- GetFalloffExtrusion(inputs, pointCount, ref extrusionDir);
- }
- public static Bounds GenerateShapeMesh(ref Mesh mesh, Vector3[] shapePath, float falloffDistance)
- {
- Bounds localBounds;
- Color meshInteriorColor = new Color(0,0,0,1);
- List<Vector3> finalVertices = new List<Vector3>();
- List<int> finalIndices = new List<int>();
- List<Color> finalColors = new List<Color>();
- // Create interior geometry
- int pointCount = shapePath.Length;
- var inputs = new ContourVertex[pointCount];
- for (int i = 0; i < pointCount; ++i)
- inputs[i] = new ContourVertex() { Position = new Vec3() { X = shapePath[i].x, Y = shapePath[i].y }, Data = meshInteriorColor };
- Tess tessI = new Tess();
- tessI.AddContour(inputs, ContourOrientation.Original);
- tessI.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3, InterpCustomVertexData);
- var indicesI = tessI.Elements.Select(i => i).ToArray();
- var verticesI = tessI.Vertices.Select(v => new Vector3(v.Position.X, v.Position.Y, 0)).ToArray();
- var colorsI = tessI.Vertices.Select(v => new Color(((Color)v.Data).r, ((Color)v.Data).g, ((Color)v.Data).b, ((Color)v.Data).a)).ToArray();
- finalVertices.AddRange(verticesI);
- finalIndices.AddRange(indicesI);
- finalColors.AddRange(colorsI);
- // Create falloff geometry
- List<Vector2> extrusionDirs = new List<Vector2>();
- GetFalloffShape(shapePath, ref extrusionDirs);
- pointCount = finalVertices.Count;
- int falloffPointCount = 2 * shapePath.Length;
- for (int i = 0; i < shapePath.Length; i++)
- {
- // Making triangles ABD and DCA
- int triangleIndex = 2 * i;
- int aIndex = pointCount + triangleIndex;
- int bIndex = pointCount + triangleIndex + 1;
- int cIndex = pointCount + (triangleIndex + 2) % falloffPointCount;
- int dIndex = pointCount + (triangleIndex + 3) % falloffPointCount;
- Vector3 point = shapePath[i];
- // We are making degenerate triangles which will be extruded by the shader
- finalVertices.Add(point);
- finalVertices.Add(point);
- finalIndices.Add(aIndex);
- finalIndices.Add(bIndex);
- finalIndices.Add(dIndex);
- finalIndices.Add(dIndex);
- finalIndices.Add(cIndex);
- finalIndices.Add(aIndex);
-
- Color aColor = new Color(0, 0, 0, 1);
- Color bColor = new Color(extrusionDirs[i].x, extrusionDirs[i].y, 0, 0);
- finalColors.Add(aColor);
- finalColors.Add(bColor);
- }
- Color[] colors = finalColors.ToArray();
- Vector3[] vertices = finalVertices.ToArray();
- mesh.Clear();
- mesh.vertices = vertices;
- mesh.colors = colors;
- mesh.SetIndices(finalIndices.ToArray(), MeshTopology.Triangles, 0);
- localBounds = CalculateBoundingSphere(ref vertices, ref colors, falloffDistance);
- return localBounds;
- }
- public static void AddShadowCasterGroupToList(ShadowCasterGroup2D shadowCaster, List<ShadowCasterGroup2D> list)
- {
- int positionToInsert = 0;
- for (positionToInsert = 0; positionToInsert < list.Count; positionToInsert++)
- {
- if (shadowCaster.GetShadowGroup() == list[positionToInsert].GetShadowGroup())
- break;
- }
- list.Insert(positionToInsert, shadowCaster);
- }
- public static void RemoveShadowCasterGroupFromList(ShadowCasterGroup2D shadowCaster, List<ShadowCasterGroup2D> list)
- {
- list.Remove(shadowCaster);
- }
- static CompositeShadowCaster2D FindTopMostCompositeShadowCaster(ShadowCaster2D shadowCaster)
- {
- CompositeShadowCaster2D retGroup = null;
- Transform transformToCheck = shadowCaster.transform.parent;
- while(transformToCheck != null)
- {
- CompositeShadowCaster2D currentGroup = transformToCheck.GetComponent<CompositeShadowCaster2D>();
- if (currentGroup != null)
- retGroup = currentGroup;
- transformToCheck = transformToCheck.parent;
- }
- return retGroup;
- }
- public static bool AddToShadowCasterGroup(ShadowCaster2D shadowCaster, ref ShadowCasterGroup2D shadowCasterGroup)
- {
- ShadowCasterGroup2D newShadowCasterGroup = FindTopMostCompositeShadowCaster(shadowCaster) as ShadowCasterGroup2D;
- if (newShadowCasterGroup == null)
- newShadowCasterGroup = shadowCaster.GetComponent<ShadowCaster2D>();
- if (newShadowCasterGroup != null && shadowCasterGroup != newShadowCasterGroup)
- {
- newShadowCasterGroup.RegisterShadowCaster2D(shadowCaster);
- shadowCasterGroup = newShadowCasterGroup;
- return true;
- }
- return false;
- }
- public static void RemoveFromShadowCasterGroup(ShadowCaster2D shadowCaster, ShadowCasterGroup2D shadowCasterGroup)
- {
- if(shadowCasterGroup != null)
- shadowCasterGroup.UnregisterShadowCaster2D(shadowCaster);
- }
- #if UNITY_EDITOR
- public static int GetShapePathHash(Vector3[] path)
- {
- unchecked
- {
- int hashCode = (int)2166136261;
- if (path != null)
- {
- foreach (var point in path)
- hashCode = hashCode * 16777619 ^ point.GetHashCode();
- }
- else
- {
- hashCode = 0;
- }
- return hashCode;
- }
- }
- #endif
- }
- }
|