Exemple #1
0
        public void WindUpdate(uint frame)
        {
            float h2o = (float)_scene.RegionInfo.RegionSettings.WaterHeight;
            float gnd;
            float sunpos;

            // Simulate time passing on fixed sun regions.
            // Otherwise use the region's local sun position.
            if (_scene.RegionInfo.RegionSettings.FixedSun)
                sunpos = (float)((DateTime.Now.TimeOfDay.TotalSeconds / 600.0) % 24.0);
            else
                sunpos = (float)(_scene.RegionInfo.RegionSettings.SunPosition % 24.0);

            // Sun position is quantized by the simulator to about once every three seconds.
            // Add a fudge factor to fill in the steps.
            if (LastSunPos != sunpos)
            {
                LastSunPos = sunpos;
                SunFudge = 0.0f;
            }
            else
            {
                SunFudge += 0.002f;
            }

            sunpos += SunFudge;

            RunningStat rsCell = new RunningStat();

            // Based on the Prevailing wind algorithm
            // Inspired by Kanker Greenacre
            // Modified by Balpien Hammerer to account for terrain turbulence, winds aloft and wind setters

            // Wind Direction
            double ThetaWD = (sunpos / 24.0 * (2.0 * Math.PI) * m_rateChangeFlutter) % (Math.PI * 2.0);
            double offset = Math.Sin(ThetaWD) * Math.Sin(ThetaWD*2) * Math.Sin(ThetaWD*9) * Math.Cos(ThetaWD*4);
            double windDir = m_avgWindDirection * (Math.PI/180.0f) + (m_varWindDirection * (Math.PI/180.0f) * offset);

            // Wind Speed
            double ThetaWS = (sunpos / 24.0 * (2.0 * Math.PI) * m_rateChangeAloft) % (Math.PI * 2.0);
            offset = Math.Sin(ThetaWS) * Math.Sin(ThetaWS*4) + (Math.Sin(ThetaWS*13) / 3.0);
            double windSpeed = (m_avgWindStrength + (m_varWindStrength * offset));

            if (windSpeed < 0)
            {
                windSpeed = -windSpeed;
                windDir += Math.PI;
            }

            // Water Direction
            double ThetaHD = (sunpos / 24.0 * (2.0 * Math.PI) * m_rateChangeFlutter) % (Math.PI * 2.0);
            double woffset = Math.Sin(ThetaHD) * Math.Sin(ThetaHD*2) * Math.Sin(ThetaHD*9) * Math.Cos(ThetaHD*4);
            double waterDir = m_avgWaterDirection * (Math.PI/180.0f) + (m_varWaterDirection * (Math.PI/180.0f) * woffset);

            // Water Speed
            double ThetaHS = (sunpos / 24.0 * (2.0 * Math.PI) * m_rateChangeSurge) % (Math.PI * 2.0);
            woffset = Math.Sin(ThetaHS) * Math.Sin(ThetaHS*3) * Math.Sin(ThetaHS*9) * Math.Cos(ThetaHS*4) * Math.Cos(ThetaHS*13);
            double waterSpeed = (m_avgWaterStrength + (m_varWaterStrength * woffset));

            if (waterSpeed < 0)
            {
                waterSpeed = -waterSpeed;
                waterDir += Math.PI;
            }
            //m_log.DebugFormat("[{0}] sunpos={1} water={2} dir={3} ThetaHD={4} ThetaHS={5} wo={6}", Name, sunpos, waterSpeed, waterDir, ThetaHD, ThetaHS, woffset);

            //m_log.DebugFormat("[{0}] sunpos={1} wind={2} dir={3} theta1={4} theta2={5}", Name, sunpos, windSpeed, windDir, theta1, theta2);

            // Set the predominate wind in each cell, but examine the terrain heights
            // to adjust the winds. Elevation and the pattern of heights in each 16m
            // cell infuence the ground winds.
            for (int y = 0; y < 16; y++)
            {
                for (int x = 0; x < 16; x++)
                {
                    rsCell.Clear();

                    // Compute terrain statistics. They are needed later.
                    for (int iy = 0; iy < 16; iy++)
                    {
                        for (int ix = 0; ix < 16; ix++)
                        {
                            // For the purpose of these computations, it is the above water height that matters.
                            // Any ground below water is treated as zero.
                            gnd = Math.Max(_scene.PhysicsScene.TerrainChannel.GetRawHeightAt(x * 16 + ix, y * 16 + iy) - h2o, 0);
                            rsCell.Push(gnd);
                        }
                    }

                    // Look for the range of heights in the cell and the overall skewness. Use this
                    // to determine ground induced deflection. It is a rough approximation of
                    // ground wind turbulance. The max height is used later to determine the boundary layer.
                    float cellrange = (float)Math.Max((rsCell.Max() - rsCell.Min()) / 5.0f, 1.0);
                    float cellskew = (float)rsCell.Skewness();
                    m_ranges[y * 16 + x] = (float)(rsCell.Max() - rsCell.Min());
                    m_skews[y * 16 + x] = cellskew;
                    m_maxheights[y * 16 + x] = (float)rsCell.Max();

                    // Begin with winds aloft,starting with the fixed wind value set by wind setters.
                    Vector2 wind = m_windsAloft[y * 16 + x];

                    // Update the cell with default zephyr winds aloft (no turbulence) if the wind speed is not fixed.
                    if ((m_options[y * 16 + x] & WindConstants.WindSpeedFixed) == 0)
                    {
                        // Compute the winds aloft (no turbulence)
                        wind.X = (float)Math.Cos(windDir);
                        wind.Y = (float)Math.Sin(windDir);
                        //wind.Normalize();
                        wind.X *= (float)windSpeed;
                        wind.Y *= (float)windSpeed;
                        m_windsAloft[y * 16 + x] = wind;
                    }

                    // Compute ground winds (apply terrain turbulence) from the winds aloft cell.
                    if ((m_options[y * 16 + x] & WindConstants.WindSpeedTurbulence) != 0)
                    {
                        double speed = Math.Sqrt(wind.X * wind.X + wind.Y * wind.Y);
                        wind = wind / (float)speed;
                        double dir = Math.Atan2(wind.Y, wind.X);

                        wind.X = (float)Math.Cos((Math.PI * cellskew * 0.333 * cellrange) + dir);
                        wind.Y = (float)Math.Sin((Math.PI * cellskew * 0.333 * cellrange) + dir);
                        //wind.Normalize();
                        wind.X *= (float)speed;
                        wind.Y *= (float)speed;
                    }

                    m_windsGround[y * 16 + x] = wind;

                    // Update the cell with default zephyr water currents if the speed is not fixed.
                    if ((m_options[y * 16 + x] & WindConstants.WindSpeedFixed) == 0)
                    {
                        // Compute the winds aloft (no turbulence)
                        wind.X = (float)Math.Cos(waterDir);
                        wind.Y = (float)Math.Sin(waterDir);
                        //wind.Normalize();
                        wind.X *= (float)waterSpeed;
                        wind.Y *= (float)waterSpeed;
                        m_waterCurrent[y * 16 + x] = wind;
                    }

                    //m_log.DebugFormat("[ZephyrWind] speed={0} dir={1} skew={2} range={3} wind={4}", windSpeed, windDir, cellskew, cellrange, wind);
                    
                }
            }
           
            // Send the updated wind data to the physics engine.
            _scene.PhysicsScene.SendPhysicsWindData(m_waterCurrent, m_windsGround, m_windsAloft, m_ranges, m_maxheights);
        }
        public void WindUpdate(uint frame)
        {
            float h2o = (float)_scene.RegionInfo.RegionSettings.WaterHeight;
            float gnd;
            float sunpos;

            // Simulate time passing on fixed sun regions.
            // Otherwise use the region's local sun position.
            if (_scene.RegionInfo.RegionSettings.FixedSun)
            {
                sunpos = (float)((DateTime.Now.TimeOfDay.TotalSeconds / 600.0) % 24.0);
            }
            else
            {
                sunpos = (float)(_scene.RegionInfo.RegionSettings.SunPosition % 24.0);
            }

            // Sun position is quantized by the simulator to about once every three seconds.
            // Add a fudge factor to fill in the steps.
            if (LastSunPos != sunpos)
            {
                LastSunPos = sunpos;
                SunFudge   = 0.0f;
            }
            else
            {
                SunFudge += 0.002f;
            }

            sunpos += SunFudge;

            RunningStat rsCell = new RunningStat();

            // Based on the Prevailing wind algorithm
            // Inspired by Kanker Greenacre
            // Modified by Balpien Hammerer to account for terrain turbulence, winds aloft and wind setters

            // Wind Direction
            double ThetaWD = (sunpos / 24.0 * (2.0 * Math.PI) * m_rateChangeFlutter) % (Math.PI * 2.0);
            double offset  = Math.Sin(ThetaWD) * Math.Sin(ThetaWD * 2) * Math.Sin(ThetaWD * 9) * Math.Cos(ThetaWD * 4);
            double windDir = m_avgWindDirection * (Math.PI / 180.0f) + (m_varWindDirection * (Math.PI / 180.0f) * offset);

            // Wind Speed
            double ThetaWS = (sunpos / 24.0 * (2.0 * Math.PI) * m_rateChangeAloft) % (Math.PI * 2.0);

            offset = Math.Sin(ThetaWS) * Math.Sin(ThetaWS * 4) + (Math.Sin(ThetaWS * 13) / 3.0);
            double windSpeed = (m_avgWindStrength + (m_varWindStrength * offset));

            if (windSpeed < 0)
            {
                windSpeed = -windSpeed;
                windDir  += Math.PI;
            }

            // Water Direction
            double ThetaHD  = (sunpos / 24.0 * (2.0 * Math.PI) * m_rateChangeFlutter) % (Math.PI * 2.0);
            double woffset  = Math.Sin(ThetaHD) * Math.Sin(ThetaHD * 2) * Math.Sin(ThetaHD * 9) * Math.Cos(ThetaHD * 4);
            double waterDir = m_avgWaterDirection * (Math.PI / 180.0f) + (m_varWaterDirection * (Math.PI / 180.0f) * woffset);

            // Water Speed
            double ThetaHS = (sunpos / 24.0 * (2.0 * Math.PI) * m_rateChangeSurge) % (Math.PI * 2.0);

            woffset = Math.Sin(ThetaHS) * Math.Sin(ThetaHS * 3) * Math.Sin(ThetaHS * 9) * Math.Cos(ThetaHS * 4) * Math.Cos(ThetaHS * 13);
            double waterSpeed = (m_avgWaterStrength + (m_varWaterStrength * woffset));

            if (waterSpeed < 0)
            {
                waterSpeed = -waterSpeed;
                waterDir  += Math.PI;
            }
            //m_log.DebugFormat("[{0}] sunpos={1} water={2} dir={3} ThetaHD={4} ThetaHS={5} wo={6}", Name, sunpos, waterSpeed, waterDir, ThetaHD, ThetaHS, woffset);

            //m_log.DebugFormat("[{0}] sunpos={1} wind={2} dir={3} theta1={4} theta2={5}", Name, sunpos, windSpeed, windDir, theta1, theta2);

            // Set the predominate wind in each cell, but examine the terrain heights
            // to adjust the winds. Elevation and the pattern of heights in each 16m
            // cell infuence the ground winds.
            for (int y = 0; y < 16; y++)
            {
                for (int x = 0; x < 16; x++)
                {
                    rsCell.Clear();

                    // Compute terrain statistics. They are needed later.
                    for (int iy = 0; iy < 16; iy++)
                    {
                        for (int ix = 0; ix < 16; ix++)
                        {
                            // For the purpose of these computations, it is the above water height that matters.
                            // Any ground below water is treated as zero.
                            gnd = Math.Max(_scene.PhysicsScene.TerrainChannel.GetRawHeightAt(x * 16 + ix, y * 16 + iy) - h2o, 0);
                            rsCell.Push(gnd);
                        }
                    }

                    // Look for the range of heights in the cell and the overall skewness. Use this
                    // to determine ground induced deflection. It is a rough approximation of
                    // ground wind turbulance. The max height is used later to determine the boundary layer.
                    float cellrange = (float)Math.Max((rsCell.Max() - rsCell.Min()) / 5.0f, 1.0);
                    float cellskew  = (float)rsCell.Skewness();
                    m_ranges[y * 16 + x]     = (float)(rsCell.Max() - rsCell.Min());
                    m_skews[y * 16 + x]      = cellskew;
                    m_maxheights[y * 16 + x] = (float)rsCell.Max();

                    // Begin with winds aloft,starting with the fixed wind value set by wind setters.
                    Vector2 wind = m_windsAloft[y * 16 + x];

                    // Update the cell with default zephyr winds aloft (no turbulence) if the wind speed is not fixed.
                    if ((m_options[y * 16 + x] & WindConstants.WindSpeedFixed) == 0)
                    {
                        // Compute the winds aloft (no turbulence)
                        wind.X = (float)Math.Cos(windDir);
                        wind.Y = (float)Math.Sin(windDir);
                        //wind.Normalize();
                        wind.X *= (float)windSpeed;
                        wind.Y *= (float)windSpeed;
                        m_windsAloft[y * 16 + x] = wind;
                    }

                    // Compute ground winds (apply terrain turbulence) from the winds aloft cell.
                    if ((m_options[y * 16 + x] & WindConstants.WindSpeedTurbulence) != 0)
                    {
                        double speed = Math.Sqrt(wind.X * wind.X + wind.Y * wind.Y);
                        wind = wind / (float)speed;
                        double dir = Math.Atan2(wind.Y, wind.X);

                        wind.X = (float)Math.Cos((Math.PI * cellskew * 0.333 * cellrange) + dir);
                        wind.Y = (float)Math.Sin((Math.PI * cellskew * 0.333 * cellrange) + dir);
                        //wind.Normalize();
                        wind.X *= (float)speed;
                        wind.Y *= (float)speed;
                    }

                    m_windsGround[y * 16 + x] = wind;

                    // Update the cell with default zephyr water currents if the speed is not fixed.
                    if ((m_options[y * 16 + x] & WindConstants.WindSpeedFixed) == 0)
                    {
                        // Compute the winds aloft (no turbulence)
                        wind.X = (float)Math.Cos(waterDir);
                        wind.Y = (float)Math.Sin(waterDir);
                        //wind.Normalize();
                        wind.X *= (float)waterSpeed;
                        wind.Y *= (float)waterSpeed;
                        m_waterCurrent[y * 16 + x] = wind;
                    }

                    //m_log.DebugFormat("[ZephyrWind] speed={0} dir={1} skew={2} range={3} wind={4}", windSpeed, windDir, cellskew, cellrange, wind);
                }
            }

            // Send the updated wind data to the physics engine.
            _scene.PhysicsScene.SendPhysicsWindData(m_waterCurrent, m_windsGround, m_windsAloft, m_ranges, m_maxheights);
        }