private void EndRegeneration()
    {
        for (var i = groups.Count - 1; i >= 0; i--)
        {
            var group = groups[i];

            if (group.Stars.Count > 0)
            {
                group.Stars.Clear();                 // No longer needed, and they've already been pooled in RegenerateMeshes()

                for (var j = group.Models.Count - 1; j >= 0; j--)
                {
                    var model = group.Models[j];

                    if (model.Mesh == null)
                    {
                        SgtStarfieldModel.Pool(model);

                        group.Models.RemoveAt(j);
                    }
                }
            }
            else
            {
                SgtStarfieldGroup.Pool(group);

                groups.RemoveAt(i);
            }
        }
    }
    public static void MarkForDestruction(SgtStarfieldModel model)
    {
        if (model != null)
        {
            model.Group = null;

            model.gameObject.SetActive(true);
        }
    }
    protected virtual void OnDestroy()
    {
        for (var i = Models.Count - 1; i >= 0; i--)
        {
            SgtStarfieldModel.MarkForDestruction(Models[i]);
        }

        Models.Clear();
    }
    public static void MarkForDestruction(SgtStarfieldModel model)
    {
        if (model != null)
        {
            model.Group = null;

            model.gameObject.SetActive(true);
        }
    }
    public static void Pool(SgtStarfieldModel model)
    {
        if (model != null)
        {
            model.Group = null;

            model.PoolMeshNow();

            SgtComponentPool <SgtStarfieldModel> .Add(model);
        }
    }
    public static void Pool(SgtStarfieldModel model)
    {
        if (model != null)
        {
            model.Group = null;

            model.PoolMeshNow();

            SgtComponentPool<SgtStarfieldModel>.Add(model);
        }
    }
    public static void Pool(SgtStarfieldGroup group)
    {
        if (group != null)
        {
            group.Starfield = null;
            group.Texture   = null;
            group.Material  = null;

            for (var i = group.Models.Count - 1; i >= 0; i--)
            {
                SgtStarfieldModel.Pool(group.Models[i]);
            }

            group.Models.Clear();

            SgtComponentPool <SgtStarfieldGroup> .Add(group);
        }
    }
    protected override void RegenerateMeshes()
    {
        var stars = default(List <SgtStarfieldStar>);
        var pool  = default(bool);

        CalculateStars(out stars, out pool);

        if (stars != null)
        {
            // Sort stars into groups
            for (var i = stars.Count - 1; i >= 0; i--)
            {
                var star = stars[i];

                if (star != null)
                {
                    var group = GetGroup(star.Sprite);

                    group.Stars.Add(star);
                }
            }

            // Pool stars?
            if (pool == true)
            {
                SgtClassPool <SgtStarfieldStar> .Add(stars);
            }

            // Build groups
            for (var i = groups.Count - 1; i >= 0; i--)
            {
                var group = groups[i];

                if (group.Stars.Count > 0)
                {
                    var groupStars = group.Stars;
                    var minMaxSet  = false;
                    var min        = default(Vector3);
                    var max        = default(Vector3);

                    SgtProceduralMesh.Clear();

                    for (var j = groupStars.Count - 1; j >= 0; j--)
                    {
                        var star     = groupStars[j];
                        var position = star.Position;
                        var radius   = star.Radius;
                        var uv       = SgtHelper.CalculateSpriteUV(star.Sprite);
                        var rotation = Quaternion.FromToRotation(Vector3.back, position.normalized) * Quaternion.Euler(0.0f, 0.0f, star.Angle);
                        var up       = rotation * Vector3.up * radius;
                        var right    = rotation * Vector3.right * radius;

                        ExpandBounds(ref minMaxSet, ref min, ref max, position, radius);

                        SgtProceduralMesh.PushPosition(position - up - right);
                        SgtProceduralMesh.PushPosition(position - up + right);
                        SgtProceduralMesh.PushPosition(position + up - right);
                        SgtProceduralMesh.PushPosition(position + up + right);

                        SgtProceduralMesh.PushColor(star.Color, 4);

                        SgtProceduralMesh.PushCoord1(uv.x, uv.y);
                        SgtProceduralMesh.PushCoord1(uv.z, uv.y);
                        SgtProceduralMesh.PushCoord1(uv.x, uv.w);
                        SgtProceduralMesh.PushCoord1(uv.z, uv.w);
                    }

                    var bounds = SgtHelper.NewBoundsFromMinMax(min, max);

                    SgtProceduralMesh.SplitQuads(HideFlags.DontSave);

                    var meshCount = SgtProceduralMesh.Count;

                    // Copy meshes
                    for (var j = 0; j < meshCount; j++)
                    {
                        var mesh  = SgtProceduralMesh.Pop();
                        var model = group.Models.Count > j ? group.Models[j] : SgtStarfieldModel.Create(group);

                        mesh.bounds = bounds;

                        model.Mesh = mesh;
                    }
                }
            }
        }
    }
    protected virtual void RegenerateMeshes()
    {
        var stars = default(List <SgtStarfieldStar>);
        var pool  = default(bool);

        CalculateStars(out stars, out pool);

        if (stars != null)
        {
            // Sort stars into groups
            for (var i = stars.Count - 1; i >= 0; i--)
            {
                var star = stars[i];

                if (star != null)
                {
                    var group = GetGroup(star.Sprite);

                    group.Stars.Add(star);
                }
            }

            // Pool stars?
            if (pool == true)
            {
                SgtClassPool <SgtStarfieldStar> .Add(stars);
            }

            // Build groups
            for (var i = groups.Count - 1; i >= 0; i--)
            {
                var group = groups[i];

                if (group.Stars.Count > 0)
                {
                    var groupStars = group.Stars;
                    var minMaxSet  = false;
                    var min        = default(Vector3);
                    var max        = default(Vector3);

                    SgtProceduralMesh.Clear();

                    for (var j = groupStars.Count - 1; j >= 0; j--)
                    {
                        var star     = groupStars[j];
                        var position = star.Position;
                        var radius   = star.Radius;
                        var uv       = SgtHelper.CalculateSpriteUV(star.Sprite);
                        var angle    = star.Angle / Mathf.PI;

                        ExpandBounds(ref minMaxSet, ref min, ref max, position, radius);

                        SgtProceduralMesh.PushPosition(position, 4);

                        SgtProceduralMesh.PushColor(star.Color, 4);

                        SgtProceduralMesh.PushNormal(-1.0f, 1.0f, angle);
                        SgtProceduralMesh.PushNormal(1.0f, 1.0f, angle);
                        SgtProceduralMesh.PushNormal(-1.0f, -1.0f, angle);
                        SgtProceduralMesh.PushNormal(1.0f, -1.0f, angle);

                        SgtProceduralMesh.PushTangent(star.PulseOffset, star.PulseSpeed, star.PulseRange, 0.0f, 4);

                        SgtProceduralMesh.PushCoord1(uv.x, uv.y);
                        SgtProceduralMesh.PushCoord1(uv.z, uv.y);
                        SgtProceduralMesh.PushCoord1(uv.x, uv.w);
                        SgtProceduralMesh.PushCoord1(uv.z, uv.w);

                        SgtProceduralMesh.PushCoord2(radius, 0.5f);
                        SgtProceduralMesh.PushCoord2(radius, -0.5f);
                        SgtProceduralMesh.PushCoord2(radius, 0.5f);
                        SgtProceduralMesh.PushCoord2(radius, -0.5f);
                    }

                    var bounds = SgtHelper.NewBoundsFromMinMax(min, max);

                    SgtProceduralMesh.SplitQuads(HideFlags.DontSave);

                    var meshCount = SgtProceduralMesh.Count;

                    // Copy meshes
                    for (var j = 0; j < meshCount; j++)
                    {
                        var mesh  = SgtProceduralMesh.Pop();
                        var model = group.Models.Count > j ? group.Models[j] : SgtStarfieldModel.Create(group);

                        mesh.bounds = bounds;

                        model.Mesh = mesh;
                    }
                }
            }
        }
    }