Ejemplo n.º 1
0
        static public void Tick(World world, World.State state, World.State nextState)
        {
            _ProfileWindTick.Begin();

            float inverseFullIceCoverage = 1.0f / world.Data.FullIceCoverage;

            for (int y = 0; y < world.Size; y++)
            {
                float latitude = world.Data.windInfo[y].latitude;
                var   windInfo = world.Data.windInfo[y];

                for (int x = 0; x < world.Size; x++)
                {
                    int index = world.GetIndex(x, y);

                    float upperPressure       = state.UpperAirPressure[index];
                    float lowerPressure       = state.LowerAirPressure[index];
                    float upperTemperature    = state.UpperAirTemperature[index];
                    float lowerTemperature    = state.LowerAirTemperature[index];
                    float elevation           = state.Elevation[index];
                    float waterDepth          = state.WaterDepth[index];
                    float waterAndIceDepth    = state.WaterAndIceDepth[index];
                    float elevationOrSeaLevel = elevation + waterAndIceDepth;
                    var   normal      = state.Normal[index];
                    float iceCoverage = state.IceMass[index] * inverseFullIceCoverage;
                    float friction;
                    if (waterDepth > 0)
                    {
                        friction = world.Data.WindOceanFriction;
                    }
                    else
                    {
                        friction = world.Data.WindLandFriction;
                    }
                    friction = Mathf.Clamp01(Mathf.Lerp(friction, world.Data.WindIceFriction, iceCoverage));
                    float lowerTemperatureAtSeaLevel = lowerTemperature - world.Data.TemperatureLapseRate * elevationOrSeaLevel;
                    float molarMassLowerAir          = Atmosphere.GetMolarMassAir(world, state.LowerAirMass[index], state.Humidity[index]);
                    float molarMassUpperAir          = Atmosphere.GetMolarMassAir(world, state.UpperAirMass[index] + state.StratosphereMass, state.CloudMass[index]);
                    float surfaceAirDensity          = Atmosphere.GetAirDensity(world, lowerPressure, lowerTemperatureAtSeaLevel, molarMassLowerAir);
                    float boundaryElevation          = elevationOrSeaLevel + world.Data.BoundaryZoneElevation;
                    float upperTemperatureAtSeaLevel = upperTemperature - world.Data.TemperatureLapseRate * boundaryElevation;
                    float tropopausePressure         = upperPressure * Mathf.Pow(1 + world.Data.TemperatureLapseRate / upperTemperatureAtSeaLevel * world.Data.TropopauseElevation, -world.Data.PressureExponent * molarMassUpperAir);
                    float tropopauseDensity          = Atmosphere.GetAirDensity(world, tropopausePressure, upperTemperature + world.Data.TemperatureLapseRate * (world.Data.TropopauseElevation - boundaryElevation), molarMassUpperAir);

                    var upperWindH = GetHorizontalWind(world, state, x, y, state.UpperWind[index], latitude, state.PlanetRotationSpeed, windInfo.coriolisParam, windInfo.inverseCoriolisParam, world.Data.GlobalCoriolisInfluenceWindUpper, state.UpperAirPressure, state.UpperAirTemperature, true, tropopausePressure, elevationOrSeaLevel, world.Data.TropopauseElevation, 0, tropopauseDensity, molarMassUpperAir);
                    var lowerWindH = GetHorizontalWind(world, state, x, y, state.LowerWind[index], latitude, state.PlanetRotationSpeed, windInfo.coriolisParam, windInfo.inverseCoriolisParam, world.Data.GlobalCoriolisInfluenceWindLower, state.LowerAirPressure, state.LowerAirTemperature, false, lowerPressure, elevationOrSeaLevel, elevationOrSeaLevel, friction, surfaceAirDensity, molarMassLowerAir);

                    // within 1 km of the ground, frictional forces slow wind down
                    float neighborPressureDifferential  = 0;
                    float neighborElevationDifferential = 0;
                    if (lowerWindH.x < 0)
                    {
                        int neighborIndex = world.GetNeighborIndex(x, y, 0);
                        neighborPressureDifferential  += -lowerWindH.x * (lowerPressure - state.LowerAirPressure[neighborIndex]);
                        neighborElevationDifferential += -lowerWindH.x * (state.Elevation[neighborIndex] + state.WaterAndIceDepth[neighborIndex] - elevationOrSeaLevel);
                    }
                    else
                    {
                        var neighborIndex = world.GetNeighborIndex(x, y, 1);
                        neighborPressureDifferential  += lowerWindH.x * (lowerPressure - state.LowerAirPressure[neighborIndex]);
                        neighborElevationDifferential += lowerWindH.x * (state.Elevation[neighborIndex] + state.WaterAndIceDepth[neighborIndex] - elevationOrSeaLevel);
                    }
                    if (lowerWindH.y < 0)
                    {
                        var neighborIndex = world.GetNeighborIndex(x, y, 3);
                        neighborPressureDifferential  += -lowerWindH.y * (lowerPressure - state.LowerAirPressure[neighborIndex]);
                        neighborElevationDifferential += -lowerWindH.y * (state.Elevation[neighborIndex] + state.WaterAndIceDepth[neighborIndex] - elevationOrSeaLevel);
                    }
                    else
                    {
                        var neighborIndex = world.GetNeighborIndex(x, y, 2);
                        neighborPressureDifferential  += lowerWindH.y * (lowerPressure - state.LowerAirPressure[neighborIndex]);
                        neighborElevationDifferential += lowerWindH.y * (state.Elevation[neighborIndex] + state.WaterAndIceDepth[neighborIndex] - elevationOrSeaLevel);
                    }
                    var verticalTemperatureDifferential = lowerTemperatureAtSeaLevel - upperTemperatureAtSeaLevel;

                    float lowerWindSpeedH = lowerWindH.magnitude;
                    float lowerWindV      = neighborElevationDifferential * world.Data.MountainUpdraftWindSpeed;
                    lowerWindV += neighborPressureDifferential * world.Data.DestinationPressureDifferentialToVerticalWindSpeed; // thermal
                    lowerWindV += (lowerPressure - upperPressure) * world.Data.PressureToVerticalWindSpeed;                     // thermal


                    nextState.LowerWind[index] = new Vector3(lowerWindH.x, lowerWindH.y, lowerWindV);
                    nextState.UpperWind[index] = new Vector3(upperWindH.x, upperWindH.y, 0);

                    if (float.IsNaN(nextState.UpperWind[index].x) || float.IsNaN(nextState.LowerWind[index].x) || float.IsNaN(nextState.LowerWind[index].z))
                    {
                        Debug.DebugBreak();
                    }

                    if (world.IsOcean(state.WaterDepth[index]))
                    {
                        Vector2 densityDifferential = Vector2.zero;
                        Vector2 shallowCurrentH;
                        float   shallowCurrentV = 0;

                        if (iceCoverage < 1)
                        {
                            shallowCurrentH = GetCurrentHorizontal(world, x, y, latitude, state.PlanetRotationSpeed, windInfo.coriolisParam, windInfo.inverseCoriolisParam, lowerWindH);
                            if (iceCoverage > 0)
                            {
                                shallowCurrentH *= 1.0f - iceCoverage;
                            }
                        }
                        else
                        {
                            shallowCurrentH = Vector2.zero;
                        }

                        if (state.DeepWaterMass[index] > 0)
                        {
                            float density = state.DeepWaterDensity[index];
                            for (int i = 0; i < 4; i++)
                            {
                                var neighbor = world.GetNeighbor(x, y, i);
                                int nIndex   = world.GetIndex(neighbor.x, neighbor.y);
                                if (state.DeepWaterMass[nIndex] > 0)
                                {
                                    //var neighborWind = state.Wind[nIndex];
                                    //nWind += neighborWind;

                                    switch (i)
                                    {
                                    case 0:
                                        densityDifferential.x += state.DeepWaterDensity[nIndex] - density;
                                        break;

                                    case 1:
                                        densityDifferential.x -= state.DeepWaterDensity[nIndex] - density;
                                        break;

                                    case 2:
                                        densityDifferential.y -= state.DeepWaterDensity[nIndex] - density;
                                        break;

                                    case 3:
                                        densityDifferential.y += state.DeepWaterDensity[nIndex] - density;
                                        break;
                                    }
                                }
                                else
                                {
                                    //switch (i)
                                    //{
                                    //	case 0:
                                    //		shallowCurrentV += shallowCurrentH.x;
                                    //		if (shallowCurrentH.x < 0)
                                    //		{
                                    //			shallowCurrentH.x = 0;
                                    //		}
                                    //		break;
                                    //	case 1:
                                    //		shallowCurrentV -= shallowCurrentH.x;
                                    //		if (shallowCurrentH.x > 0)
                                    //		{
                                    //			shallowCurrentH.x = 0;
                                    //		}
                                    //		break;
                                    //	case 2:
                                    //		shallowCurrentV -= shallowCurrentH.y;
                                    //		if (shallowCurrentH.y > 0)
                                    //		{
                                    //			shallowCurrentH.y = 0;
                                    //		}
                                    //		break;
                                    //	case 3:
                                    //		shallowCurrentV += shallowCurrentH.y;
                                    //		if (shallowCurrentH.y < 0)
                                    //		{
                                    //			shallowCurrentH.y = 0;
                                    //		}
                                    //		break;
                                    //}
                                }
                            }
                        }
                        densityDifferential *= world.Data.OceanDensityCurrentSpeed;
                        nextState.DeepWaterCurrent[index]    = new Vector3(densityDifferential.x, densityDifferential.y, 0);
                        nextState.ShallowWaterCurrent[index] = new Vector3(shallowCurrentH.x, shallowCurrentH.y, shallowCurrentV);
                    }
                    else
                    {
                        nextState.DeepWaterCurrent[index]    = Vector3.zero;
                        nextState.ShallowWaterCurrent[index] = Vector3.zero;
                    }
                }
            }


            _ProfileWindTick.End();
        }