Beispiel #1
0
    private void CameraPreRender(Camera camera)
    {
        if (Material != null)
        {
            var cameraPosition      = camera.transform.position;
            var localCameraPosition = transform.InverseTransformPoint(cameraPosition);
            var localDistance       = localCameraPosition.magnitude;
            var scaleDistance       = SgtHelper.Divide(localDistance, MeshRadius);

            if (scaleDistance > 1.0f)
            {
                SgtHelper.EnableKeyword("SGT_A", Material);                 // Outside
            }
            else
            {
                SgtHelper.DisableKeyword("SGT_A", Material);                 // Outside

                if (DepthTex != null)
                {
#if UNITY_EDITOR
                    SgtHelper.MakeTextureReadable(DepthTex);
#endif
                    Material.SetFloat("_Sky", Sky * DepthTex.GetPixelBilinear(1.0f - scaleDistance, 0.0f).a);
                }
            }

            UpdateMaterialNonSerialized();
        }
    }
Beispiel #2
0
    public void UpdateModels()
    {
        updateModelsCalled = true;

        var angleStep = SgtHelper.Divide(360.0f, Segments);

        for (var i = 0; i < Segments; i++)
        {
            var model    = GetOrAddModel(i);
            var angle    = angleStep * i;
            var rotation = Quaternion.Euler(0.0f, angle, 0.0f);

            model.SetMesh(Mesh);
            model.SetMaterial(Material);
            model.SetRotation(rotation);
        }

        // Remove any excess
        if (Models != null)
        {
            var min = Mathf.Max(0, Segments);

            for (var i = Models.Count - 1; i >= min; i--)
            {
                SgtRingModel.Pool(Models[i]);

                Models.RemoveAt(i);
            }
        }
    }
    // TODO: Make this work correctly
    public override bool CalculateShadow()
    {
        if (base.CalculateShadow() == true)
        {
            var direction = default(Vector3);
            var position  = default(Vector3);
            var color     = default(Color);

            SgtHelper.CalculateLight(Light, transform.position, null, null, ref position, ref direction, ref color);

            var rotation = Quaternion.FromToRotation(direction, Vector3.back);

            SetVector(0, rotation * transform.right * transform.lossyScale.x * OuterRadius);
            SetVector(1, rotation * transform.up * transform.lossyScale.y * OuterRadius);
            SetVector(2, rotation * transform.forward * transform.lossyScale.z * OuterRadius);

            SortVectors();

            var spin  = Quaternion.LookRotation(Vector3.forward, new Vector2(-vectors[1].x, vectors[1].y));             // Orient the shadow ellipse
            var scale = SgtHelper.Reciprocal3(new Vector3(magnitudes[0], magnitudes[1], 1.0f));

            var shadowT = SgtHelper.Translation(-transform.position);
            var shadowR = SgtHelper.Rotation(spin * rotation);
            var shadowS = SgtHelper.Scaling(scale);

            Matrix = shadowS * shadowR * shadowT;
            Ratio  = SgtHelper.Divide(OuterRadius, OuterRadius - InnerRadius);

            return(true);
        }

        return(false);
    }
Beispiel #4
0
    public override bool CalculateShadow(ref Matrix4x4 matrix, ref float ratio)
    {
        if (base.CalculateShadow(ref matrix, ref ratio) == true)
        {
            var direction = default(Vector3);
            var position  = default(Vector3);
            var color     = default(Color);

            SgtHelper.CalculateLight(Light, transform.position, null, null, ref position, ref direction, ref color);

            var dot      = Vector3.Dot(direction, transform.up);
            var radiusXZ = (transform.lossyScale.x + transform.lossyScale.z) * 0.5f * RadiusMax;
            var radiusY  = transform.lossyScale.y * RadiusMax;
            var radius   = GetRadius(radiusY, radiusXZ, dot * Mathf.PI * 0.5f);
            var rotation = Quaternion.FromToRotation(direction, Vector3.back);
            var vector   = rotation * transform.up;
            var spin     = Quaternion.LookRotation(Vector3.forward, new Vector2(-vector.x, vector.y));             // Orient the shadow ellipse
            var scale    = SgtHelper.Reciprocal3(new Vector3(radiusXZ, radius, 1.0f));
            var shadowT  = SgtHelper.Translation(-transform.position);
            var shadowR  = SgtHelper.Rotation(spin * rotation);
            var shadowS  = SgtHelper.Scaling(scale);

            matrix = shadowS * shadowR * shadowT;
            ratio  = SgtHelper.Divide(RadiusMax, RadiusMax - RadiusMin);

            return(true);
        }

        return(false);
    }
Beispiel #5
0
    public void UpdateModels()
    {
        updateModelsCalled = true;

        var meshCount = Meshes != null ? Meshes.Count : 0;
        var scale     = SgtHelper.Divide(Radius, MeshRadius);

        for (var i = 0; i < meshCount; i++)
        {
            var mesh  = Meshes[i];
            var model = GetOrAddModel(i);

            model.SetMesh(mesh);
            model.SetMaterial(Material);
            model.SetScale(scale);
        }

        // Remove any excess
        if (Models != null)
        {
            for (var i = Models.Count - 1; i >= meshCount; i--)
            {
                SgtCloudsphereModel.Pool(Models[i]);

                Models.RemoveAt(i);
            }
        }
    }
Beispiel #6
0
    private void CameraPreRender(Camera camera)
    {
        // Write CameraOffset
        if (Outers != null)
        {
            var dir = camera.transform.position - transform.position;
            var pos = transform.InverseTransformPoint(transform.position + dir.normalized * CameraOffset);

            for (var i = Outers.Count - 1; i >= 0; i--)
            {
                var outer = Outers[i];

                if (outer != null)
                {
                    outer.transform.localPosition = pos;
                }
            }
        }

        // Write camera-dependant shader values
        if (InnerMaterial != null && OuterMaterial != null)
        {
            var cameraPosition       = camera.transform.position;
            var localCameraPosition  = transform.InverseTransformPoint(cameraPosition);
            var localDistance        = localCameraPosition.magnitude;
            var clampedSky           = Mathf.InverseLerp(OuterRadius, InnerMeshRadius, localDistance);
            var innerAtmosphereDepth = default(float);
            var outerAtmosphereDepth = default(float);
            var radiusRatio          = SgtHelper.Divide(InnerMeshRadius, OuterRadius);
            var scaleDistance        = SgtHelper.Divide(localDistance, OuterRadius);
            var innerDensity         = 1.0f - InnerFog;
            var outerDensity         = 1.0f - OuterFog;

            SgtHelper.CalculateAtmosphereThicknessAtHorizon(radiusRatio, 1.0f, scaleDistance, out innerAtmosphereDepth, out outerAtmosphereDepth);

            SgtHelper.SetTempMaterial(InnerMaterial, OuterMaterial);

            if (scaleDistance > 1.0f)
            {
                SgtHelper.EnableKeyword("SGT_A");                 // Outside
            }
            else
            {
                SgtHelper.DisableKeyword("SGT_A");                 // Outside
            }

            InnerMaterial.SetFloat("_HorizonLengthRecip", SgtHelper.Reciprocal(innerAtmosphereDepth * innerDensity));
            OuterMaterial.SetFloat("_HorizonLengthRecip", SgtHelper.Reciprocal(outerAtmosphereDepth * outerDensity));

            if (OuterDepthTex != null)
            {
#if UNITY_EDITOR
                SgtHelper.MakeTextureReadable(OuterDepthTex);
#endif
                OuterMaterial.SetFloat("_Sky", Sky * OuterDepthTex.GetPixelBilinear(clampedSky / outerDensity, 0.0f).a);
            }

            UpdateMaterialNonSerialized();
        }
    }
    protected virtual void UpdateMaterial()
    {
        if (innerMaterial == null)
        {
            innerMaterial = SgtHelper.CreateTempMaterial(SgtHelper.ShaderNamePrefix + "CoronaInner");
        }
        if (outerMaterial == null)
        {
            outerMaterial = SgtHelper.CreateTempMaterial(SgtHelper.ShaderNamePrefix + "CoronaOuter");
        }

        var scale        = SgtHelper.Divide(OuterMeshRadius, OuterRadius);
        var worldToLocal = SgtHelper.Scaling(scale) * transform.worldToLocalMatrix;
        var color        = SgtHelper.Brighten(Color, Brightness);
        var renderQueue  = (int)RenderQueue + RenderQueueOffset;

        innerMaterial.renderQueue = renderQueue;
        innerMaterial.SetColor("_Color", color);
        innerMaterial.SetTexture("_AtmosphereLut", atmosphereLut);
        innerMaterial.SetFloat("_AtmosphereScale", DensityScale);
        innerMaterial.SetFloat("_Power", InnerPower);
        innerMaterial.SetFloat("_SkyRadius", OuterRadius);
        innerMaterial.SetFloat("_SkyRadiusRecip", SgtHelper.Reciprocal(OuterRadius));
        innerMaterial.SetMatrix("_WorldToLocal", worldToLocal);

        outerMaterial.renderQueue = renderQueue;
        outerMaterial.SetColor("_Color", color);
        outerMaterial.SetTexture("_AtmosphereLut", atmosphereLut);
        outerMaterial.SetFloat("_AtmosphereScale", DensityScale);
        outerMaterial.SetMatrix("_WorldToLocal", worldToLocal);
    }
Beispiel #8
0
    public void UpdateOuters()
    {
        updateOutersCalled = true;

        var meshCount  = OuterMeshes != null ? OuterMeshes.Count : 0;
        var outerScale = SgtHelper.Divide(OuterRadius, OuterMeshRadius);

        for (var i = 0; i < meshCount; i++)
        {
            var outerMesh = OuterMeshes[i];
            var outer     = GetOrAddOuter(i);

            outer.SetMesh(outerMesh);
            outer.SetMaterial(OuterMaterial);
            outer.SetScale(outerScale);
        }

        // Remove any excess
        if (Outers != null)
        {
            for (var i = Outers.Count - 1; i >= meshCount; i--)
            {
                var outer = Outers[i];

                if (outer != null)
                {
                    SgtAtmosphereOuter.Pool(outer);
                }

                Outers.RemoveAt(i);
            }
        }
    }
Beispiel #9
0
    private void UpdateMaterialNonSerialized()
    {
        var scale        = SgtHelper.Divide(OuterMeshRadius, OuterRadius);
        var worldToLocal = SgtHelper.Scaling(scale) * transform.worldToLocalMatrix;

        InnerMaterial.SetMatrix("_WorldToLocal", worldToLocal);
        OuterMaterial.SetMatrix("_WorldToLocal", worldToLocal);
    }
Beispiel #10
0
    public static void CalculateAtmosphereThicknessAtHorizon(float groundRadius, float skyRadius, float distance, out float groundThickness, out float skyThickness)
    {
        var horizonDistance    = DistanceToHorizon(groundRadius, distance);
        var maxSkyThickness    = Mathf.Sin(Mathf.Acos(SgtHelper.Divide(groundRadius, skyRadius))) * skyRadius;
        var maxGroundThickness = Mathf.Min(horizonDistance, maxSkyThickness);

        groundThickness = Mathf.Max(maxGroundThickness, skyRadius - groundRadius);
        skyThickness    = maxSkyThickness + maxGroundThickness;
    }
Beispiel #11
0
    protected override void CalculateStars(out List <SgtStarfieldStar> stars, out bool pool)
    {
        var texture = SourceTex as Texture2D;

        stars = tempStars; tempStars.Clear();
        pool  = true;

        if (texture != null && Resolution > 0.0f && Resolution <= 1.0f)
        {
#if UNITY_EDITOR
            SgtHelper.MakeTextureReadable(texture);
            SgtHelper.MakeTextureTruecolor(texture);
#endif
            var samplesX = Mathf.FloorToInt(SourceTex.width * Resolution);
            var samplesY = Mathf.FloorToInt(SourceTex.height * Resolution);
            var stepX    = SgtHelper.Reciprocal(samplesX);
            var stepY    = SgtHelper.Reciprocal(samplesY);
            var halfSize = Size * 0.5f;
            var scale    = SgtHelper.Divide(SourceTex.width, samplesX);

            SgtHelper.BeginRandomSeed(Seed);
            {
                for (var y = 0; y < samplesY; y++)
                {
                    for (var x = 0; x < samplesX; x++)
                    {
                        var fracX = x * stepX;
                        var fracY = y * stepY;
                        var pixel = texture.GetPixelBilinear(fracX, fracY);
                        var gray  = pixel.grayscale;

                        if (gray > Threshold)
                        {
                            var star     = SgtClassPool <SgtStarfieldStar> .Pop() ?? new SgtStarfieldStar(); stars.Add(star);
                            var position = -halfSize + Random.insideUnitSphere * Jitter * StarRadiusMax * scale;

                            position.x += Size.x * fracX;
                            position.y += Size.y * GetHeight(pixel);
                            position.z += Size.z * fracY;

                            star.Sprite      = GetRandomStarSprite();
                            star.Color       = pixel;
                            star.Radius      = Random.Range(StarRadiusMin, StarRadiusMax) * scale;
                            star.Angle       = Random.Range(0.0f, Mathf.PI * 2.0f);
                            star.Position    = position;
                            star.PulseRange  = Random.value * StarPulseMax;
                            star.PulseSpeed  = Random.value;
                            star.PulseOffset = Random.value;
                        }
                    }
                }
            }
            SgtHelper.EndRandomSeed();
        }
    }
    private void UpdateOuters()
    {
        outers.RemoveAll(o => o == null);

        if (OuterMeshes.Count != outers.Count)
        {
            SgtHelper.ResizeArrayTo(ref outers, OuterMeshes.Count, i => SgtCoronaOuter.Create(this), o => SgtCoronaOuter.Pool(o));
        }

        var outerScale = SgtHelper.Divide(OuterRadius, OuterMeshRadius);

        for (var i = OuterMeshes.Count - 1; i >= 0; i--)
        {
            outers[i].ManualUpdate(OuterMeshes[i], outerMaterial, outerScale);
        }
    }
    private void UpdateModels()
    {
        models.RemoveAll(m => m == null);

        if (Meshes.Count != models.Count)
        {
            SgtHelper.ResizeArrayTo(ref models, Meshes.Count, i => SgtCloudsphereModel.Create(this), m => SgtCloudsphereModel.Pool(m));
        }

        var scale = SgtHelper.Divide(Radius, MeshRadius);

        for (var i = Meshes.Count - 1; i >= 0; i--)
        {
            models[i].ManualUpdate(Meshes[i], material, scale);
        }
    }
Beispiel #14
0
    public static Vector4 CalculateSpriteUV(Sprite s)
    {
        var uv = default(Vector4);

        if (s != null)
        {
            var r = s.textureRect;
            var t = s.texture;

            uv.x = SgtHelper.Divide(r.xMin, t.width);
            uv.y = SgtHelper.Divide(r.yMin, t.height);
            uv.z = SgtHelper.Divide(r.xMax, t.width);
            uv.w = SgtHelper.Divide(r.yMax, t.height);
        }

        return(uv);
    }
Beispiel #15
0
    protected void UpdateSegments()
    {
        segments.RemoveAll(m => m == null);

        if (SegmentCount != segments.Count)
        {
            SgtHelper.ResizeArrayTo(ref segments, SegmentCount, i => SgtRingSegment.Create(this), s => SgtRingSegment.Pool(s));
        }

        var angleStep = SgtHelper.Divide(360.0f, SegmentCount);

        for (var i = SegmentCount - 1; i >= 0; i--)
        {
            var angle    = angleStep * i;
            var rotation = Quaternion.Euler(0.0f, angle, 0.0f);

            segments[i].ManualUpdate(mesh, material, rotation);
        }
    }
Beispiel #16
0
    protected virtual void OnDrawGizmosSelected()
    {
        if (SgtHelper.Enabled(this) == true)
        {
            var matrix = default(Matrix4x4);
            var ratio  = default(float);

            if (CalculateShadow(ref matrix, ref ratio) == true)
            {
                Gizmos.matrix = matrix.inverse;

                var distA = 0.0f;
                var distB = 1.0f;
                var scale = 1.0f * Mathf.Deg2Rad;
                var inner = SgtHelper.Divide(RadiusMin, RadiusMax);

                for (var i = 1; i < 10; i++)
                {
                    var posA = new Vector3(0.0f, 0.0f, distA);
                    var posB = new Vector3(0.0f, 0.0f, distB);

                    Gizmos.color = new Color(1.0f, 1.0f, 1.0f, Mathf.Pow(0.75f, i) * 0.125f);

                    for (var a = 1; a <= 360; a++)
                    {
                        posA.x = posB.x = Mathf.Sin(a * scale);
                        posA.y = posB.y = Mathf.Cos(a * scale);

                        Gizmos.DrawLine(posA, posB);

                        posA.x = posB.x = posA.x * inner;
                        posA.y = posB.y = posA.y * inner;

                        Gizmos.DrawLine(posA, posB);
                    }

                    distA = distB;
                    distB = distB * 2.0f;
                }
            }
        }
    }
    public virtual void SetCurrentCamera(Camera c)
    {
        if (c != null)
        {
            UpdateMaterial();

            var cameraPosition       = c.transform.position;
            var localCameraPosition  = transform.InverseTransformPoint(cameraPosition);
            var localDistance        = localCameraPosition.magnitude;
            var clampedAltitude      = Mathf.InverseLerp(MiddleRadius, OuterRadius, localDistance);
            var innerAtmosphereDepth = default(float);
            var outerAtmosphereDepth = default(float);
            var radiusRatio          = SgtHelper.Divide(InnerMeshRadius, OuterRadius);
            var innerHeightRatio     = SgtHelper.Divide(MiddleHeight, OuterRadius);
            var scaleDistance        = SgtHelper.Divide(localDistance, OuterRadius);
            var fog = 1.0f - Fog;

            SgtHelper.CalculateAtmosphereThicknessAtHorizon(radiusRatio, 1.0f, scaleDistance, out innerAtmosphereDepth, out outerAtmosphereDepth);

            // Make the fog level reduce when you get closer than the ground height
            innerAtmosphereDepth = Mathf.Max(innerAtmosphereDepth, innerHeightRatio);

            if (scaleDistance > 1.0f)
            {
                innerKeywords.Add("SGT_A"); outerKeywords.Add("SGT_A");
            }

            if (Smooth == true)
            {
                innerKeywords.Add("SGT_B"); outerKeywords.Add("SGT_B");
            }

            SgtHelper.SetKeywords(innerMaterial, innerKeywords); innerKeywords.Clear();
            SgtHelper.SetKeywords(outerMaterial, outerKeywords); outerKeywords.Clear();

            innerMaterial.SetFloat("_HorizonLengthRecip", SgtHelper.Reciprocal(innerAtmosphereDepth * fog));
            outerMaterial.SetFloat("_HorizonLengthRecip", SgtHelper.Reciprocal(outerAtmosphereDepth * fog));

            outerMaterial.SetFloat("_Power", CalculateOuterPower(cameraPosition, clampedAltitude));
        }
    }
Beispiel #18
0
    public override bool CalculateShadow(ref Matrix4x4 matrix, ref float ratio)
    {
        if (base.CalculateShadow(ref matrix, ref ratio) == true)
        {
            if (Texture != null)
            {
                if (SgtHelper.Enabled(RingMesh) == true)
                {
                    RadiusMin = RingMesh.RadiusMin;
                    RadiusMax = RingMesh.RadiusMax;
                }

                var direction = default(Vector3);
                var position  = default(Vector3);
                var color     = default(Color);

                SgtHelper.CalculateLight(Light, transform.position, null, null, ref position, ref direction, ref color);

                var rotation = Quaternion.FromToRotation(direction, Vector3.back);
                var squash   = Vector3.Dot(direction, transform.up);                 // Find how squashed the ellipse is based on light direction
                var width    = transform.lossyScale.x * RadiusMax;
                var length   = transform.lossyScale.z * RadiusMax;
                var axis     = rotation * transform.up;                                                // Find the transformed up axis
                var spin     = Quaternion.LookRotation(Vector3.forward, new Vector2(-axis.x, axis.y)); // Orient the shadow ellipse
                var scale    = SgtHelper.Reciprocal3(new Vector3(width, length * Mathf.Abs(squash), 1.0f));
                var skew     = Mathf.Tan(SgtHelper.Acos(-squash));

                var shadowT = SgtHelper.Translation(-transform.position);
                var shadowR = SgtHelper.Rotation(spin * rotation);          // Spin the shadow so lines up with its tilt
                var shadowS = SgtHelper.Scaling(scale);                     // Scale the ring into an oval
                var shadowK = SgtHelper.ShearingZ(new Vector2(0.0f, skew)); // Skew the shadow so it aligns with the ring plane

                matrix = shadowS * shadowK * shadowR * shadowT;
                ratio  = SgtHelper.Divide(RadiusMax, RadiusMax - RadiusMin);

                return(true);
            }
        }

        return(false);
    }
Beispiel #19
0
    protected virtual void RegenerateMesh()
    {
        mesh = SgtObjectPool <Mesh> .Add(mesh, m => m.Clear());

        SgtProceduralMesh.Clear();
        {
            if (SegmentDetail >= 3)
            {
                var angleTotal = SgtHelper.Divide(Mathf.PI * 2.0f, SegmentCount);
                var angleStep  = SgtHelper.Divide(angleTotal, SegmentDetail);
                var coordStep  = SgtHelper.Reciprocal(SegmentDetail);

                for (var i = 0; i <= SegmentDetail; i++)
                {
                    var coord = coordStep * i;
                    var angle = angleStep * i;
                    var sin   = Mathf.Sin(angle);
                    var cos   = Mathf.Cos(angle);

                    SgtProceduralMesh.PushPosition(sin * InnerRadius, 0.0f, cos * InnerRadius);
                    SgtProceduralMesh.PushPosition(sin * OuterRadius, 0.0f, cos * OuterRadius);

                    SgtProceduralMesh.PushNormal(Vector3.up);
                    SgtProceduralMesh.PushNormal(Vector3.up);

                    SgtProceduralMesh.PushCoord1(0.0f, coord);
                    SgtProceduralMesh.PushCoord1(1.0f, coord);
                }
            }
        }
        SgtProceduralMesh.SplitStrip(HideFlags.DontSave);

        mesh = SgtProceduralMesh.Pop(); SgtProceduralMesh.Discard();

        if (mesh != null)
        {
            var bounds = mesh.bounds;

            mesh.bounds = SgtHelper.NewBoundsCenter(bounds, bounds.center + bounds.center.normalized * BoundsShift);
        }
    }
Beispiel #20
0
    protected override void RegenerateMesh()
    {
        mesh = SgtObjectPool <Mesh> .Add(mesh, m => m.Clear());

        SgtProceduralMesh.Clear();
        {
            if (SegmentDetail >= 3)
            {
                var angleTotal = SgtHelper.Divide(Mathf.PI * 2.0f, SegmentCount);
                var angleStep  = SgtHelper.Divide(angleTotal, SegmentDetail);
                var coordStep  = SgtHelper.Reciprocal(SegmentDetail);

                for (var i = 0; i <= SegmentDetail; i++)
                {
                    var coord = coordStep * i;
                    var angle = angleStep * i;
                    var sin   = Mathf.Sin(angle);
                    var cos   = Mathf.Cos(angle);
                    var iPos  = new Vector3(sin * InnerRadius, 0.0f, cos * InnerRadius);
                    var oPos  = new Vector3(sin * OuterRadius, 0.0f, cos * OuterRadius);

                    SgtProceduralMesh.PushPosition(iPos);
                    SgtProceduralMesh.PushPosition(oPos);

                    SgtProceduralMesh.PushNormal(Vector3.up);
                    SgtProceduralMesh.PushNormal(Vector3.up);

                    SgtProceduralMesh.PushCoord1(0.0f, coord * InnerRadius);
                    SgtProceduralMesh.PushCoord1(1.0f, coord * OuterRadius);

                    SgtProceduralMesh.PushCoord2(InnerRadius, 0.0f);
                    SgtProceduralMesh.PushCoord2(OuterRadius, 0.0f);
                }
            }
        }
        SgtProceduralMesh.SplitStrip(HideFlags.DontSave);

        mesh = SgtProceduralMesh.Pop(); SgtProceduralMesh.Discard();
    }
Beispiel #21
0
    protected virtual void Update()
    {
        if (LightningSpawner == null)
        {
            Pool(this);
        }
        else
        {
            if (Application.isPlaying == true)
            {
                Age += Time.deltaTime;
            }

            if (Age >= Life)
            {
                SgtComponentPool <SgtLightning> .Add(this);
            }
            else if (material != null)
            {
                material.SetFloat("_Age", SgtHelper.Divide(Age, Life));
            }
        }
    }
    public void RebuildPatch(SgtPatch patch)
    {
        if (Resolution > 0)
        {
            var resAdd1      = Resolution + 1;
            var resAdd2      = Resolution + 2;
            var resAdd3      = Resolution + 3;
            var resRecip     = SgtHelper.Reciprocal(Resolution);
            var mainVerts    = resAdd1 * resAdd1;
            var skirtVerts   = resAdd1 * 4;
            var mainIndices  = Resolution * Resolution * 6;
            var skirtIndices = Resolution * 24;
            var mesh         = patch.Mesh;
            var vertex       = default(int);
            var vertex2      = default(int);
            var index        = default(int);

            if (positions == null || positions.Length != mainVerts + skirtVerts)
            {
                positions = new Vector3[mainVerts + skirtVerts];
            }
            if (coords1 == null || coords1.Length != mainVerts + skirtVerts)
            {
                coords1 = new Vector2[mainVerts + skirtVerts];
            }
            if (coords2 == null || coords2.Length != mainVerts + skirtVerts)
            {
                coords2 = new Vector2[mainVerts + skirtVerts];
            }
            if (normals == null || normals.Length != mainVerts + skirtVerts)
            {
                normals = new Vector3[mainVerts + skirtVerts];
            }
            if (tangents == null || tangents.Length != mainVerts + skirtVerts)
            {
                tangents = new Vector4[mainVerts + skirtVerts];
            }
            if (quadPoints == null || quadPoints.Length != resAdd3 * resAdd3)
            {
                quadPoints = new Vector3[resAdd3 * resAdd3];
            }
            if (quadNormals == null || quadNormals.Length != resAdd2 * resAdd2)
            {
                quadNormals = new Vector3[resAdd2 * resAdd2];
            }
            if (quadTangents == null || quadTangents.Length != resAdd2 * resAdd2)
            {
                quadTangents = new Vector3[resAdd2 * resAdd2];
            }

            // Go through all vertices, but extend the borders by one
            for (var y = -1; y < resAdd2; y++)
            {
                for (var x = -1; x < resAdd2; x++)
                {
                    var u      = x * resRecip;
                    var v      = y * resRecip;
                    var pointB = Lerp3(patch.PointBL, patch.PointBR, u);
                    var pointT = Lerp3(patch.PointTL, patch.PointTR, u);
                    var point  = GetSurfacePositionLocal(Lerp3(pointB, pointT, v));

                    index = x + 1 + (y + 1) * resAdd3;

                    quadPoints[index] = point;

                    // Is this a main vertex?
                    if (x >= 0 && x < resAdd1 && y >= 0 && y < resAdd1)
                    {
                        var coordB = Lerp2(patch.CoordBL, patch.CoordBR, u);
                        var coordT = Lerp2(patch.CoordTL, patch.CoordTR, u);
                        var coord1 = Lerp2(coordB, coordT, v);
                        var coord2 = new Vector2(u, v);
                        var center = (patch.PointBL + patch.PointBR + patch.PointTL + patch.PointTR) * 0.25f;

                        if (OnCalculateCoord1 != null)
                        {
                            OnCalculateCoord1(point, center, ref coord1);
                        }
                        if (OnCalculateCoord2 != null)
                        {
                            OnCalculateCoord2(point, center, ref coord2);
                        }

                        vertex = x + y * resAdd1;

                        positions[vertex] = point;

                        coords1[vertex] = coord1;

                        coords2[vertex] = coord2;
                    }
                }
            }

            // Quad normals & tangents
            for (var y = 0; y < resAdd2; y++)
            {
                for (var x = 0; x < resAdd2; x++)
                {
                    var bl = x + y * resAdd3;
                    var br = x + 1 + y * resAdd3;
                    var tl = x + (y + 1) * resAdd3;
                    var tr = x + 1 + (y + 1) * resAdd3;

                    var b = quadPoints[bl] - quadPoints[br];
                    var t = quadPoints[tl] - quadPoints[tr];
                    var l = quadPoints[bl] - quadPoints[tl];
                    var r = quadPoints[br] - quadPoints[tr];

                    var h = (b + t).normalized;
                    var v = (l + r).normalized;
                    var i = x + y * resAdd2;

                    quadNormals[i] = Vector3.Cross(h, v);

                    quadTangents[i] = v;
                }
            }

            // Normals & Tangents
            for (var y = 0; y < resAdd1; y++)
            {
                for (var x = 0; x < resAdd1; x++)
                {
                    var bl = x + y * resAdd2;
                    var br = x + 1 + y * resAdd2;
                    var tl = x + (y + 1) * resAdd2;
                    var tr = x + 1 + (y + 1) * resAdd2;

                    var n = quadNormals[bl] + quadNormals[br] + quadNormals[tl] + quadNormals[tr];
                    var t = quadTangents[bl] + quadTangents[br] + quadTangents[tl] + quadTangents[tr];
                    var i = x + y * resAdd1;

                    normals[i] = n.normalized;
                    //normals[i] = positions[i].normalized;

                    tangents[i] = SgtHelper.NewVector4(t.normalized, 1.0f);
                }
            }

            // Skirt vertices
            var scale = 1.0f - SgtHelper.Divide(SkirtThickness * Mathf.Pow(0.5f, patch.Depth), 1.0f);

            for (var i = 0; i < resAdd1; i++)
            {
                // Bottom
                vertex  = mainVerts + i;
                vertex2 = i;

                positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2];

                // Top
                vertex  = mainVerts + i + resAdd1;
                vertex2 = resAdd1 * Resolution + i;

                positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2];

                // Left
                vertex  = mainVerts + i + resAdd1 + resAdd1;
                vertex2 = resAdd1 * i;

                positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2];

                // Right
                vertex  = mainVerts + i + resAdd1 + resAdd1 + resAdd1;
                vertex2 = resAdd1 * i + Resolution;

                positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2];
            }

            // Indices
            if (indices == null || indices.Length != mainIndices + skirtIndices)
            {
                indices = new int[mainIndices + skirtIndices];

                // Main
                for (var y = 0; y < Resolution; y++)
                {
                    for (var x = 0; x < Resolution; x++)
                    {
                        index  = (x + y * Resolution) * 6;
                        vertex = x + y * resAdd1;

                        indices[index + 0] = vertex;
                        indices[index + 1] = vertex + 1;
                        indices[index + 2] = vertex + resAdd1;
                        indices[index + 3] = vertex + resAdd1 + 1;
                        indices[index + 4] = vertex + resAdd1;
                        indices[index + 5] = vertex + 1;
                    }
                }

                // Skirt
                for (var i = 0; i < Resolution; i++)
                {
                    // Bottom
                    index   = mainIndices + (Resolution * 0 + i) * 6;
                    vertex  = mainVerts + i;
                    vertex2 = i;

                    indices[index + 0] = vertex;
                    indices[index + 1] = vertex + 1;
                    indices[index + 2] = vertex2;
                    indices[index + 3] = vertex2 + 1;
                    indices[index + 4] = vertex2;
                    indices[index + 5] = vertex + 1;

                    // Top
                    index   = mainIndices + (Resolution * 1 + i) * 6;
                    vertex  = mainVerts + i + resAdd1;
                    vertex2 = Resolution * resAdd1 + i;

                    indices[index + 0] = vertex2;
                    indices[index + 1] = vertex2 + 1;
                    indices[index + 2] = vertex;
                    indices[index + 3] = vertex + 1;
                    indices[index + 4] = vertex;
                    indices[index + 5] = vertex2 + 1;

                    // Left
                    index   = mainIndices + (Resolution * 2 + i) * 6;
                    vertex  = mainVerts + i + resAdd1 + resAdd1;
                    vertex2 = i * resAdd1;

                    indices[index + 0] = vertex;
                    indices[index + 1] = vertex2;
                    indices[index + 2] = vertex + 1;
                    indices[index + 3] = vertex2 + resAdd1;
                    indices[index + 4] = vertex + 1;
                    indices[index + 5] = vertex2;

                    // Right
                    index   = mainIndices + (Resolution * 3 + i) * 6;
                    vertex  = mainVerts + i + resAdd1 + resAdd1 + resAdd1;
                    vertex2 = i * resAdd1 + Resolution;

                    indices[index + 0] = vertex2;
                    indices[index + 1] = vertex;
                    indices[index + 2] = vertex2 + resAdd1;
                    indices[index + 3] = vertex + 1;
                    indices[index + 4] = vertex2 + resAdd1;
                    indices[index + 5] = vertex;
                }
            }

            if (mesh != null)
            {
                mesh.Clear();
            }
            else
            {
                mesh = patch.Mesh = SgtObjectPool <Mesh> .Pop() ?? new Mesh();

                mesh.name      = "Patch";
                mesh.hideFlags = HideFlags.DontSave;
            }

            mesh.vertices  = positions;
            mesh.uv        = coords1;
            mesh.uv2       = coords2;
            mesh.normals   = normals;
            mesh.tangents  = tangents;
            mesh.triangles = indices;
            mesh.RecalculateBounds();

            patch.MeshCenter = mesh.bounds.center;
        }
    }
Beispiel #23
0
    protected virtual void Update()
    {
        if (Follower == null)
        {
            ClearDebris(); return;
        }

        var followerPosition = Follower.position;
        var followerDensity  = GetDensity(followerPosition);

        if (followerDensity > 0.0f)
        {
            var debrisCount = Debris != null ? Debris.Count : 0;

            if (debrisCount < SpawnLimit)
            {
                spawnCooldown -= Time.deltaTime;

                while (spawnCooldown <= 0.0f)
                {
                    spawnCooldown += Random.Range(SpawnRateMin, SpawnRateMax);

                    SpawnDebris(false);

                    debrisCount += 1;

                    if (debrisCount >= SpawnLimit)
                    {
                        break;
                    }
                }
            }
        }

        if (Debris != null)
        {
            var distanceRange = HideDistance - ShowDistance;

            for (var i = Debris.Count - 1; i >= 0; i--)
            {
                var debris = Debris[i];

                if (debris != null)
                {
                    var targetScale = default(float);
                    var distance    = Vector3.Distance(followerPosition, debris.transform.position);

                    // Fade its size in
                    debris.Show = SgtHelper.Dampen(debris.Show, 1.0f, ShowSpeed, Time.deltaTime, 0.1f);

                    if (distance < ShowDistance)
                    {
                        targetScale = 1.0f;
                    }
                    else if (distance > HideDistance)
                    {
                        targetScale = 0.0f;
                    }
                    else
                    {
                        targetScale = 1.0f - SgtHelper.Divide(distance - ShowDistance, distanceRange);
                    }

                    debris.transform.localScale = debris.Scale * debris.Show * Mathf.Max(minScale, targetScale);

                    if (targetScale <= 0.0f)
                    {
                        Despawn(debris, i);
                    }
                }
                else
                {
                    Debris.RemoveAt(i);
                }
            }
        }
    }
    public static void GenerateMesh(SgtPatch patch)
    {
        var terrain = patch.Terrain;

        if (terrain.Resolution > 0)
        {
            var positions    = terrain.Positions;
            var coords1      = terrain.Coords1;
            var coords2      = terrain.Coords2;
            var normals      = terrain.Normals;
            var tangents     = terrain.Tangents;
            var quadPoints   = terrain.QuadPoints;
            var quadNormals  = terrain.QuadNormals;
            var quadTangents = terrain.QuadTangents;
            var indices      = terrain.Indices;
            var res          = terrain.Resolution;
            var resAdd1      = res + 1;
            var resAdd2      = res + 2;
            var resAdd3      = res + 3;
            var resRecip     = SgtHelper.Reciprocal(res);
            var mainVerts    = resAdd1 * resAdd1;
            var skirtVerts   = resAdd1 * 4;
            var mainIndices  = res * res * 6;
            var skirtIndices = res * 24;
            var vertex       = default(int);
            var vertex2      = default(int);
            var index        = default(int);

            if (positions.Length != mainVerts + skirtVerts)
            {
                terrain.Positions = positions = new Vector3[mainVerts + skirtVerts];
            }
            if (coords1.Length != mainVerts + skirtVerts)
            {
                terrain.Coords1 = coords1 = new Vector2[mainVerts + skirtVerts];
            }
            if (coords2.Length != mainVerts + skirtVerts)
            {
                terrain.Coords2 = coords2 = new Vector2[mainVerts + skirtVerts];
            }
            if (normals.Length != mainVerts + skirtVerts)
            {
                terrain.Normals = normals = new Vector3[mainVerts + skirtVerts];
            }
            if (tangents.Length != mainVerts + skirtVerts)
            {
                terrain.Tangents = tangents = new Vector4[mainVerts + skirtVerts];
            }
            if (quadPoints.Length != resAdd3 * resAdd3)
            {
                terrain.QuadPoints = quadPoints = new Vector3[resAdd3 * resAdd3];
            }
            if (quadNormals.Length != resAdd2 * resAdd2)
            {
                terrain.QuadNormals = quadNormals = new Vector3[resAdd2 * resAdd2];
            }
            if (quadTangents.Length != resAdd2 * resAdd2)
            {
                terrain.QuadTangents = quadTangents = new Vector3[resAdd2 * resAdd2];
            }

            // Go through all vertices, but extend the borders by one
            for (var y = -1; y < resAdd2; y++)
            {
                for (var x = -1; x < resAdd2; x++)
                {
                    var u      = x * resRecip;
                    var v      = y * resRecip;
                    var pointB = Lerp3(patch.PointBL, patch.PointBR, u);
                    var pointT = Lerp3(patch.PointTL, patch.PointTR, u);
                    var point  = Lerp3(pointB, pointT, v).normalized; point *= terrain.GetHeight(point);

                    index = x + 1 + (y + 1) * resAdd3;

                    quadPoints[index] = point;

                    // Is this a main vertex?
                    if (x >= 0 && x < resAdd1 && y >= 0 && y < resAdd1)
                    {
                        var coordB = Lerp2(patch.CoordBL, patch.CoordBR, u);
                        var coordT = Lerp2(patch.CoordTL, patch.CoordTR, u);
                        var coord1 = Lerp2(coordB, coordT, v);

                        vertex = x + y * resAdd1;

                        positions[vertex] = point;

                        coords1[vertex] = coord1;

                        coords2[vertex] = new Vector2(u, v);
                    }
                }
            }

            // Quad normals & tangents
            for (var y = 0; y < resAdd2; y++)
            {
                for (var x = 0; x < resAdd2; x++)
                {
                    var bl = x + y * resAdd3;
                    var br = x + 1 + y * resAdd3;
                    var tl = x + (y + 1) * resAdd3;
                    var tr = x + 1 + (y + 1) * resAdd3;

                    var b = quadPoints[bl] - quadPoints[br];
                    var t = quadPoints[tl] - quadPoints[tr];
                    var l = quadPoints[bl] - quadPoints[tl];
                    var r = quadPoints[br] - quadPoints[tr];

                    var h = (b + t).normalized;
                    var v = (l + r).normalized;
                    var i = x + y * resAdd2;

                    quadNormals[i] = Vector3.Cross(h, v);

                    quadTangents[i] = v;
                }
            }

            // Normals & Tangents
            for (var y = 0; y < resAdd1; y++)
            {
                for (var x = 0; x < resAdd1; x++)
                {
                    var bl = x + y * resAdd2;
                    var br = x + 1 + y * resAdd2;
                    var tl = x + (y + 1) * resAdd2;
                    var tr = x + 1 + (y + 1) * resAdd2;

                    var n = quadNormals[bl] + quadNormals[br] + quadNormals[tl] + quadNormals[tr];
                    var t = quadTangents[bl] + quadTangents[br] + quadTangents[tl] + quadTangents[tr];
                    var i = x + y * resAdd1;

                    normals[i] = n.normalized;
                    //normals[i] = positions[i].normalized;

                    tangents[i] = SgtHelper.NewVector4(t.normalized, 1.0f);
                }
            }

            // Skirt vertices
            var scale = 1.0f - SgtHelper.Divide(terrain.SkirtThickness * Mathf.Pow(0.5f, patch.Depth), 1.0f);

            for (var i = 0; i < resAdd1; i++)
            {
                // Bottom
                vertex  = mainVerts + i;
                vertex2 = i;

                positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2];

                // Top
                vertex  = mainVerts + i + resAdd1;
                vertex2 = resAdd1 * res + i;

                positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2];

                // Left
                vertex  = mainVerts + i + resAdd1 + resAdd1;
                vertex2 = resAdd1 * i;

                positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2];

                // Right
                vertex  = mainVerts + i + resAdd1 + resAdd1 + resAdd1;
                vertex2 = resAdd1 * i + res;

                positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2];
            }

            // Indices
            if (indices.Length != mainIndices + skirtIndices)
            {
                terrain.Indices = indices = new int[mainIndices + skirtIndices];

                // Main
                for (var y = 0; y < res; y++)
                {
                    for (var x = 0; x < res; x++)
                    {
                        index  = (x + y * res) * 6;
                        vertex = x + y * resAdd1;

                        indices[index + 0] = vertex;
                        indices[index + 1] = vertex + 1;
                        indices[index + 2] = vertex + resAdd1;
                        indices[index + 3] = vertex + resAdd1 + 1;
                        indices[index + 4] = vertex + resAdd1;
                        indices[index + 5] = vertex + 1;
                    }
                }

                // Skirt
                for (var i = 0; i < res; i++)
                {
                    // Bottom
                    index   = mainIndices + (res * 0 + i) * 6;
                    vertex  = mainVerts + i;
                    vertex2 = i;

                    indices[index + 0] = vertex;
                    indices[index + 1] = vertex + 1;
                    indices[index + 2] = vertex2;
                    indices[index + 3] = vertex2 + 1;
                    indices[index + 4] = vertex2;
                    indices[index + 5] = vertex + 1;

                    // Top
                    index   = mainIndices + (res * 1 + i) * 6;
                    vertex  = mainVerts + i + resAdd1;
                    vertex2 = res * resAdd1 + i;

                    indices[index + 0] = vertex2;
                    indices[index + 1] = vertex2 + 1;
                    indices[index + 2] = vertex;
                    indices[index + 3] = vertex + 1;
                    indices[index + 4] = vertex;
                    indices[index + 5] = vertex2 + 1;

                    // Left
                    index   = mainIndices + (res * 2 + i) * 6;
                    vertex  = mainVerts + i + resAdd1 + resAdd1;
                    vertex2 = i * resAdd1;

                    indices[index + 0] = vertex;
                    indices[index + 1] = vertex2;
                    indices[index + 2] = vertex + 1;
                    indices[index + 3] = vertex2 + resAdd1;
                    indices[index + 4] = vertex + 1;
                    indices[index + 5] = vertex2;

                    // Right
                    index   = mainIndices + (res * 3 + i) * 6;
                    vertex  = mainVerts + i + resAdd1 + resAdd1 + resAdd1;
                    vertex2 = i * resAdd1 + res;

                    indices[index + 0] = vertex2;
                    indices[index + 1] = vertex;
                    indices[index + 2] = vertex2 + resAdd1;
                    indices[index + 3] = vertex + 1;
                    indices[index + 4] = vertex2 + resAdd1;
                    indices[index + 5] = vertex;
                }
            }

            if (patch.Mesh != null)
            {
                patch.Mesh.Clear();
            }
            else
            {
                patch.Mesh = SgtObjectPool <Mesh> .Pop() ?? new Mesh();

                patch.Mesh.hideFlags = HideFlags.DontSave;
            }

            patch.Mesh.vertices  = positions;
            patch.Mesh.uv        = coords1;
            patch.Mesh.uv2       = coords2;
            patch.Mesh.normals   = normals;
            patch.Mesh.tangents  = tangents;
            patch.Mesh.triangles = indices;
            patch.Mesh.RecalculateBounds();

            patch.MeshCenter = patch.Mesh.bounds.center;
        }
    }
Beispiel #25
0
    public void UpdateMesh()
    {
        updateMeshCalled = true;

        if (Mesh == null)
        {
            Mesh = SgtHelper.CreateTempMesh("Plane");

            if (Planes != null)
            {
                for (var i = Planes.Count - 1; i >= 0; i--)
                {
                    var plane = Planes[i];

                    if (plane != null)
                    {
                        plane.SetMesh(Mesh);
                    }
                }
            }
        }
        else
        {
            Mesh.Clear(false);
        }

        if (PlaneDetail >= 2)
        {
            var detail    = Mathf.Min(PlaneDetail, SgtHelper.QuadsPerMesh / 2);             // Limit the amount of vertices that get made
            var positions = new Vector3[detail * 2 + 2];
            var normals   = new Vector3[detail * 2 + 2];
            var coords1   = new Vector2[detail * 2 + 2];
            var coords2   = new Vector2[detail * 2 + 2];
            var indices   = new int[detail * 6];
            var angleStep = SgtHelper.Divide(Mathf.PI * 2.0f, detail);
            var coordStep = SgtHelper.Reciprocal(detail);

            for (var i = 0; i <= detail; i++)
            {
                var coord = coordStep * i;
                var angle = angleStep * i;
                var sin   = Mathf.Sin(angle);
                var cos   = Mathf.Cos(angle);
                var offV  = i * 2;

                positions[offV + 0] = new Vector3(sin * InnerRadius, 0.0f, cos * InnerRadius);
                positions[offV + 1] = new Vector3(sin * OuterRadius, 0.0f, cos * OuterRadius);

                normals[offV + 0] = Vector3.up;
                normals[offV + 1] = Vector3.up;

                coords1[offV + 0] = new Vector2(0.0f, coord * InnerRadius);
                coords1[offV + 1] = new Vector2(1.0f, coord * OuterRadius);

                coords2[offV + 0] = new Vector2(InnerRadius, 0.0f);
                coords2[offV + 1] = new Vector2(OuterRadius, 0.0f);
            }

            for (var i = 0; i < detail; i++)
            {
                var offV = i * 2;
                var offI = i * 6;

                indices[offI + 0] = offV + 0;
                indices[offI + 1] = offV + 1;
                indices[offI + 2] = offV + 2;
                indices[offI + 3] = offV + 3;
                indices[offI + 4] = offV + 2;
                indices[offI + 5] = offV + 1;
            }

            Mesh.vertices  = positions;
            Mesh.normals   = normals;
            Mesh.uv        = coords1;
            Mesh.uv2       = coords2;
            Mesh.triangles = indices;
        }
    }
Beispiel #26
0
    public void UpdateDebris()
    {
        var size = (long)System.Math.Ceiling(SgtHelper.Divide(HideDistance, (float)CellSize));

        if (Target != null && CellSize > 0.0f && Prefabs != null && DebrisCountTarget > 0 && size > 0)
        {
            var worldPoint = Target.position;
            var centerX    = (long)System.Math.Round(worldPoint.x / CellSize);
            var centerY    = (long)System.Math.Round(worldPoint.y / CellSize);
            var centerZ    = (long)System.Math.Round(worldPoint.z / CellSize);

            var newBounds = new SgtBoundsL(centerX, centerY, centerZ, size);

            if (newBounds != bounds)
            {
                var probability = DebrisCountTarget / (size * size * size);
                var cellMin     = (float)CellSize * (0.5f - CellNoise);
                var cellMax     = (float)CellSize * (0.5f + CellNoise);

                for (var z = newBounds.minZ; z <= newBounds.maxZ; z++)
                {
                    for (var y = newBounds.minY; y <= newBounds.maxY; y++)
                    {
                        for (var x = newBounds.minX; x <= newBounds.maxX; x++)
                        {
                            if (bounds.Contains(x, y, z) == false)
                            {
                                // Calculate seed for this grid cell and try to minimize visible symmetry
                                var seed = Seed ^ (x * (1 << 8)) ^ (y * (1 << 16)) ^ (z * (1 << 24));

                                SgtHelper.BeginRandomSeed((int)(seed % int.MaxValue));
                                {
                                    // Can debris potentially spawn in this cell?
                                    if (Random.value < probability)
                                    {
                                        var debrisX     = x * CellSize + Random.Range(cellMin, cellMax);
                                        var debrisY     = y * CellSize + Random.Range(cellMin, cellMax);
                                        var debrisZ     = z * CellSize + Random.Range(cellMin, cellMax);
                                        var debrisPoint = new Vector3((float)debrisX, (float)debrisY, (float)debrisZ);

                                        // Spawn everywhere, or only inside specified shapes?
                                        if (SpawnInside == null || Random.value < SpawnInside.GetDensity(debrisPoint))
                                        {
                                            Spawn(x, y, z, debrisPoint);
                                        }
                                    }
                                }
                                SgtHelper.EndRandomSeed();
                            }
                        }
                    }
                }

                bounds = newBounds;

                if (Debris != null)
                {
                    for (var i = Debris.Count - 1; i >= 0; i--)
                    {
                        var debris = Debris[i];

                        if (debris == null)
                        {
                            Debris.RemoveAt(i);
                        }
                        else if (bounds.Contains(debris.Cell) == false)
                        {
                            Despawn(debris, i);
                        }
                    }
                }
            }

            UpdateDebrisScale(worldPoint);
        }
        else
        {
            ClearDebris();
        }
    }