Example #1
0
        public override void ComputeSpectrum(Vector3[,] spectrum, float tileSizeMultiplier, int maxResolution, System.Random random)
        {
            float tileSize       = TileSize * tileSizeMultiplier;
            float totalAmplitude = amplitude * ComputeWaveAmplitude(windSpeed);
            float realSizeInv    = 1.0f / tileSize;

            int   resolution      = spectrum.GetLength(0);
            int   halfResolution  = resolution / 2;
            float linearWindSpeed = windSpeed;
            float L     = linearWindSpeed * linearWindSpeed / gravity;
            float LPow2 = L * L;
            float l     = FastMath.Pow2(L / cutoffFactor);

            float scale = Mathf.Sqrt(totalAmplitude * Mathf.Pow(100.0f / tileSize, 2.35f) / 2000000.0f);

            for (int x = 0; x < resolution; ++x)
            {
                float kx = 2.0f * Mathf.PI * (x /* + 0.5f*/ - halfResolution) * realSizeInv;

                for (int y = 0; y < resolution; ++y)
                {
                    float ky = 2.0f * Mathf.PI * (y /* + 0.5f*/ - halfResolution) * realSizeInv;

                    float k    = Mathf.Sqrt(kx * kx + ky * ky);
                    float kk   = k * k;
                    float kkkk = kk * kk;

                    float p = Mathf.Exp(-1.0f / (kk * LPow2) - kk * l) / kkkk;
                    p = scale * Mathf.Sqrt(p);

                    float h  = FastMath.Gauss01() * p;
                    float hi = FastMath.Gauss01() * p;

                    int xCoord = (x + halfResolution) % resolution;
                    int yCoord = (y + halfResolution) % resolution;

                    if (x == halfResolution && y == halfResolution)
                    {
                        h  = 0;
                        hi = 0;
                    }

                    spectrum[xCoord, yCoord] = new Vector3(h, hi, 1.0f);
                }
            }
        }
Example #2
0
        override public void ComputeSpectrum(Vector3[,] spectrum, float tileSizeMultiplier, int maxResolution, System.Random random)
        {
            int resolution     = spectrum.GetLength(0);
            int halfResolution = resolution / 2;
            int numRandomSkips = (maxResolution - resolution) / 2;

            if (numRandomSkips < 0)
            {
                numRandomSkips = 0;
            }

            float frequencyScale = 2.0f * Mathf.PI / (TileSize * tileSizeMultiplier);

            float U10 = windSpeed;

            //float omegac = 0.84f;
            float omegac = 0.84f * Mathf.Pow((float)System.Math.Tanh(Mathf.Pow(fetch / 22000.0f, 0.4f)), -0.75f);

            float sqrt10 = Mathf.Sqrt(10.0f);

            // short-wave parameters
            const float cm = 0.23f;
            float       km = 2.0f * gravity / (cm * cm);

            // long-wave parameters
            float kp = gravity * FastMath.Pow2(omegac / U10);
            float cp = PhaseSpeed(kp, km);

            float omega  = U10 / cp;
            float alphap = 0.006f * Mathf.Sqrt(omega);

            float sigma = 0.08f * (1.0f + 4.0f * Mathf.Pow(omegac, -3.0f));

            float z0       = 3.7e-5f * U10 * U10 / gravity * Mathf.Pow(U10 / cp, 0.9f);
            float friction = U10 * 0.41f / Mathf.Log(10.0f / z0);                       // 0.41 is the estimated 'k' from "the law of the wall"

            float a0 = Mathf.Log(2.0f) / 4.0f;
            float ap = 4.0f;
            float am = 0.13f * friction / cm;

            float alpham = 0.01f * (friction < cm ? 1.0f + Mathf.Log(friction / cm) : 1.0f + 3.0f * Mathf.Log(friction / cm));

            // skip random values that normally would be generated at max resolution
                        #pragma warning disable 0219
            for (int i = 0; i < numRandomSkips; ++i)
            {
                for (int ii = 0; ii < maxResolution; ++ii)
                {
                    Random.Range(0.000001f, 1.0f);
                    float t = Random.value;
                    Random.Range(0.000001f, 1.0f);
                    t = Random.value;
                }
            }

            for (int x = 0; x < resolution; ++x)
            {
                float kx = frequencyScale * (x /* + 0.5f*/ - halfResolution);

                // skip random values that normally would be generated at max resolution
                for (int i = 0; i < numRandomSkips; ++i)
                {
                    Random.Range(0.000001f, 1.0f);
                    float t = Random.value;
                    Random.Range(0.000001f, 1.0f);
                    t = Random.value;
                }

                for (int y = 0; y < resolution; ++y)
                {
                    float ky = frequencyScale * (y /* + 0.5f*/ - halfResolution);

                    float k = Mathf.Sqrt(kx * kx + ky * ky);
                    float c = PhaseSpeed(k, km);

                    /*
                     * Long-wave spectrum (bl)
                     */
                    float moskowitz = Mathf.Exp((-5.0f / 4.0f) * FastMath.Pow2(kp / k));

                    float gamma   = omegac <= 1.0f ? 1.7f : 1.7f + 6 * Mathf.Log(omegac);
                    float r       = Mathf.Exp(-FastMath.Pow2(Mathf.Sqrt(k / kp) - 1.0f) / (2.0f * sigma * sigma));
                    float jonswap = Mathf.Pow(gamma, r);

                    float fp = moskowitz * jonswap * Mathf.Exp(-(omega / sqrt10) * (Mathf.Sqrt(k / kp) - 1.0f));

                    float bl = 0.5f * alphap * (cp / c) * fp;

                    /*
                     * Short-wave spectrum (bh)
                     */
                    float fm = Mathf.Exp(-0.25f * FastMath.Pow2(k / km - 1.0f));
                    float bh = 0.5f * alpham * (cm / c) * fm * moskowitz;                                   // equation in paper seems to be wrong (missing moskowitz term) / it's fixed now

                    /*
                     * Directionality
                     */
                    float deltak = (float)System.Math.Tanh(a0 + ap * Mathf.Pow(c / cp, 2.5f) + am * Mathf.Pow(cm / c, 2.5f));

                    //float dp = windSpeed.x * kx / k + windSpeed.y * ky / k;
                    //float phi = Mathf.Acos(dp);

                    /*
                     * Total omni-directional spectrum
                     */
                    float sk = amplitude * (bl + bh) /* (1.0f + deltak * Mathf.Cos(2.0f * phi))*/ / (k * k * k * k * 2.0f * Mathf.PI);

                    // precision problems may sometimes produce negative values here
                    if (sk > 0.0f)
                    {
                        sk = Mathf.Sqrt(sk) * frequencyScale * 0.5f;                                            // 1.1 added * 0.5 to match empirical wikipedia wave height data
                    }
                    else
                    {
                        sk = 0.0f;
                    }

                    float h  = FastMath.Gauss01() * sk;
                    float hi = FastMath.Gauss01() * sk;

                    int xCoord = (x + halfResolution) % resolution;
                    int yCoord = (y + halfResolution) % resolution;

                    if (x == halfResolution && y == halfResolution)
                    {
                        h      = 0.0f;
                        hi     = 0.0f;
                        deltak = 0.0f;
                    }

                    spectrum[xCoord, yCoord] = new Vector3(h, hi, deltak);
                }

                // skip random values that normally would be generated at max resolution
                for (int i = 0; i < numRandomSkips; ++i)
                {
                    Random.Range(0.000001f, 1.0f);
                    float t = Random.value;
                    Random.Range(0.000001f, 1.0f);
                    t = Random.value;
                }
            }

            // skip random values that normally would be generated at max resolution
            for (int i = 0; i < numRandomSkips; ++i)
            {
                for (int ii = 0; ii < maxResolution; ++ii)
                {
                    Random.Range(0.000001f, 1.0f);
                    float t = Random.value;
                    Random.Range(0.000001f, 1.0f);
                    t = Random.value;
                }
            }
#pragma warning restore 0219
        }