Ejemplo n.º 1
0
        private float GetFlux(MySimpleArray <Vector4> fluxMap, List <MaiNeighbour> neighbours,
                              MaiNeighbourDirection neighbourPosition, MaiNeighbourDirection fluxDirection)
        {
            var requestedElement = neighbours.Where(c => c.DirectionIndex == neighbourPosition).ToList();

            if (!requestedElement.Any())
            {
                return(0);
            }
            else
            {
                return(fluxMap.GetValue(requestedElement.First().Position)[(int)fluxDirection]);
            }
        }
Ejemplo n.º 2
0
 private DebMapValues DebugGetMapValues(int x, int y, SimpleHeightArray waterMap, SimpleHeightArray waterMap1,
                                        SimpleHeightArray waterMap2, MySimpleArray <Vector4> fluxMap, MySimpleArray <Vector2> velocityMap,
                                        SimpleHeightArray sedimentMap, SimpleHeightArray sedimentMap1)
 {
     return(new DebMapValues()
     {
         waterMapVal = waterMap.GetValue(x, y),
         waterMap1Val = waterMap1.GetValue(x, y),
         waterMap2Val = waterMap2.GetValue(x, y),
         fluxMapVal = fluxMap.GetValue(x, y),
         velocityMapVal = velocityMap.GetValue(x, y),
         sedimentMapVal = sedimentMap.GetValue(x, y),
         sedimentMap1Val = sedimentMap1.GetValue(x, y)
     });
 }
Ejemplo n.º 3
0
        public void Erode(SimpleHeightArray heightMap, MeiHydraulicEroderConfiguration configuration)
        {
            //int stepCount = configuration.StepCount;
            //float deltaT = configuration.DeltaT;
            //float constantWaterAdding = configuration.ConstantWaterAdding;
            //float A_pipeCrossSection = configuration.A_PipeCrossSection;
            //float l_pipeLength = configuration.L_PipeLength;
            //float g_GravityAcceleration = configuration.GravityAcceleration;
            //float ks_DissolvingConstant = configuration.DissolvingConstant;
            //float kd_DepositionConstant = configuration.DepositionConstant;
            //float ke_EvaporationConstant = configuration.EvaporationConstant;
            //float kc_SedimentCapacityConstant = configuration.SedimentCapacityConstant;
            //Vector2 gridSize = configuration.GridSize;

            int     stepCount                   = configuration.StepCount;
            float   deltaT                      = configuration.DeltaT;
            float   constantWaterAdding         = configuration.ConstantWaterAdding;
            float   A_pipeCrossSection          = configuration.A_PipeCrossSection;
            float   l_pipeLength                = configuration.L_PipeLength;
            float   g_GravityAcceleration       = configuration.GravityAcceleration;
            float   ks_DissolvingConstant       = configuration.DissolvingConstant;
            float   kd_DepositionConstant       = configuration.DepositionConstant;
            float   ke_EvaporationConstant      = configuration.EvaporationConstant;
            float   kc_SedimentCapacityConstant = configuration.SedimentCapacityConstant;
            Vector2 gridSize                    = configuration.GridSize;

            float lX = gridSize.x;
            float lY = gridSize.y;

            var waterMap   = new SimpleHeightArray(heightMap.Width, heightMap.Height);
            var waterMap_1 = new SimpleHeightArray(heightMap.Width, heightMap.Height);
            var waterMap_2 = new SimpleHeightArray(heightMap.Width, heightMap.Height);

            var fluxMap       = new MySimpleArray <Vector4>(heightMap.Width, heightMap.Height);
            var velocityMap   = new MySimpleArray <Vector2>(heightMap.Width, heightMap.Height);
            var sedimentMap   = new SimpleHeightArray(heightMap.Width, heightMap.Height);
            var sedimentMap_1 = new SimpleHeightArray(heightMap.Width, heightMap.Height);

            for (int i = 0; i < stepCount; i++)
            {
                // water increment
                for (int y = 0; y < heightMap.Height; y++)
                {
                    for (int x = 0; x < heightMap.Width; x++)
                    {
                        var aPoint = new IntVector2(x, y);
                        waterMap_1.SetValue(aPoint, waterMap.GetValue(aPoint) + deltaT * constantWaterAdding);
                    }
                }

                // flow simulation
                for (int y = 0; y < heightMap.Height; y++)
                {
                    for (int x = 0; x < heightMap.Width; x++)
                    {
                        var aPoint = new IntVector2(x, y);
                        if (x == 10 && y == 10)
                        {
                            int yyy = 2;
                        }

                        Vector4 newFlux    = Vector4.zero;
                        var     neighbours = GetNeighbours(heightMap, aPoint);
                        foreach (var neighbour in neighbours)
                        {
                            var d_difference = (heightMap.GetValue(aPoint) + waterMap_1.GetValue(aPoint)) -
                                               (heightMap.GetValue(neighbour.Position) +
                                                waterMap_1.GetValue(neighbour.Position));

                            var d_flux     = fluxMap.GetValue(aPoint)[(int)neighbour.DirectionIndex];
                            var d_new_flux = Mathf.Max(0,
                                                       d_flux + deltaT * A_pipeCrossSection * (g_GravityAcceleration * d_difference) /
                                                       l_pipeLength);
                            newFlux[(int)neighbour.DirectionIndex] = d_new_flux;
                        }

                        var aD1      = waterMap_1.GetValue(aPoint);
                        var K_factor = Mathf.Min(1,
                                                 aD1 * (lX * lY) / ((newFlux[0] + newFlux[1] + newFlux[2] + newFlux[3]) * deltaT));
                        fluxMap.SetValue(aPoint, K_factor * newFlux);
                    }
                }

                // velocity calculation
                for (int y = 0; y < heightMap.Height; y++)
                {
                    for (int x = 0; x < heightMap.Width; x++)
                    {
                        var aPoint = new IntVector2(x, y);
                        if (x == 10 && y == 10)
                        {
                            int yyy = 2;
                        }

                        var neighbours = GetNeighbours(heightMap, aPoint);

                        var outFlow = VectorUtils.SumMembers(fluxMap.GetValue(aPoint));
                        var inFlow  =
                            neighbours.Select(c => fluxMap.GetValue(c.Position)[(int)c.DirectionIndex.GetOpposite()])
                            .Sum();

                        var aChangeOfWater = deltaT * (inFlow - outFlow);
                        waterMap_2.SetValue(aPoint,
                                            Mathf.Max(0, waterMap_1.GetValue(aPoint) + aChangeOfWater / (lX * lY)));

                        var horizontalFlux =
                            GetFlux(fluxMap, neighbours, MaiNeighbourDirection.LEFT, MaiNeighbourDirection.RIGHT) -
                            fluxMap.GetValue(aPoint)[(int)MaiNeighbourDirection.LEFT] +
                            fluxMap.GetValue(aPoint)[(int)MaiNeighbourDirection.RIGHT] -
                            GetFlux(fluxMap, neighbours, MaiNeighbourDirection.RIGHT, MaiNeighbourDirection.LEFT);

                        var deltaWx = horizontalFlux / 2;

                        var verticalFlux =
                            GetFlux(fluxMap, neighbours, MaiNeighbourDirection.DOWN, MaiNeighbourDirection.UP) -
                            fluxMap.GetValue(aPoint)[(int)MaiNeighbourDirection.DOWN] +
                            fluxMap.GetValue(aPoint)[(int)MaiNeighbourDirection.UP] -
                            GetFlux(fluxMap, neighbours, MaiNeighbourDirection.UP, MaiNeighbourDirection.DOWN);

                        var deltaWy = verticalFlux / 2;

                        var avgHeight = (waterMap_1.GetValue(aPoint) + waterMap_2.GetValue(aPoint)) / 2;

                        var newVelocity = new Vector2(
                            (deltaWx / (lX * avgHeight)),
                            (deltaWy / (lY * avgHeight))
                            );
                        velocityMap.SetValue(aPoint, newVelocity); //todo ograniczenie CFL
                    }
                }

                // sediment calc
                for (int y = 0; y < heightMap.Height; y++)
                {
                    for (int x = 0; x < heightMap.Width; x++)
                    {
                        var aPoint = new IntVector2(x, y);
                        if (x == 10 && y == 10)
                        {
                            int yyy = 2;
                        }
                        var aHeight = heightMap.GetValue(aPoint);

                        Vector3 upDir = new Vector3(0, 0, lY);
                        if (y != heightMap.Height - 1)
                        {
                            var upHeight = heightMap.GetValue(aPoint + new IntVector2(0, 1));
                            upDir[1] = upHeight - aHeight;
                        }

                        Vector3 rightDir = new Vector3(lX, 0, 0);
                        if (x != heightMap.Width - 1)
                        {
                            var rightHeight = heightMap.GetValue(aPoint + new IntVector2(1, 0));
                            rightDir[1] = rightHeight - aHeight;
                        }

                        var aNormal = Vector3.Cross(upDir, rightDir);

                        var baseNormal = new Vector3(0, 1, 0);

                        var cosAlpha = Vector3.Dot(baseNormal, aNormal) / (baseNormal.magnitude * aNormal.magnitude);
                        var sinAlpha = Math.Sqrt(1 - cosAlpha * cosAlpha);

                        //////// OTHER CALCULATING

                        var _o_notmal =
                            new Vector3(
                                heightMap.GetValueWithZeroInMissing(y, x + 1) -
                                heightMap.GetValueWithZeroInMissing(y, x - 1),
                                heightMap.GetValueWithZeroInMissing(y + 1, x) -
                                heightMap.GetValueWithZeroInMissing(y - 1, x), 2);
                        var o_normal2 = _o_notmal.normalized;

                        Vector3 up         = new Vector3(0, 1, 0);
                        float   cosa       = Vector3.Dot(o_normal2, up);
                        float   o_sinAlpha = Mathf.Sin(Mathf.Acos(cosa));


                        // todo kontrolne zwiększenie wody
                        var capacity = kc_SedimentCapacityConstant * sinAlpha *
                                       velocityMap.GetValue(aPoint).magnitude; //todo set minimum alpha

                        var suspendedSediment = sedimentMap.GetValue(aPoint);

                        if (capacity > suspendedSediment)
                        {
                            var sedimentChangeAmount = (float)(ks_DissolvingConstant * (capacity - suspendedSediment));
                            heightMap.AddValue(aPoint, -sedimentChangeAmount);
                            sedimentMap_1.AddValue(aPoint, sedimentChangeAmount);
                        }
                        else
                        {
                            var sedimentChangeAmount = (float)(kd_DepositionConstant * (suspendedSediment - capacity));
                            heightMap.AddValue(aPoint,
                                               sedimentChangeAmount); // sedimentChangeAmount jest ujemna, więc dodajemy teren
                            sedimentMap_1.AddValue(aPoint, -sedimentChangeAmount);
                        }
                    }
                }

                // sediment transportation
                for (int y = 0; y < heightMap.Height; y++)
                {
                    for (int x = 0; x < heightMap.Width; x++)
                    {
                        var aPoint = new IntVector2(x, y);
                        if (x == 10 && y == 10)
                        {
                            int yyy = 2;
                        }
                        var velocity = velocityMap.GetValue(aPoint);
                        sedimentMap.SetValue(aPoint,
                                             sedimentMap_1.GetValueWithIndexClamped(aPoint.ToFloatVec() - velocity * deltaT));
                    }
                }

                //evaporation
                for (int y = 0; y < heightMap.Height; y++)
                {
                    for (int x = 0; x < heightMap.Width; x++)
                    {
                        var aPoint = new IntVector2(x, y);
                        if (x == 10 && y == 10)
                        {
                            int yyy = 2;
                        }
                        waterMap.SetValue(aPoint, waterMap_2.GetValue(aPoint) * (1 - ke_EvaporationConstant * deltaT));
                    }
                }
            }

            //for (int y = 0; y < heightMap.Height; y++)
            //{
            //    for (int x = 0; x < heightMap.Width; x++)
            //    {
            //        var aPoint = new IntVector2(x,y);
            //        heightMap.AddValue(aPoint, sedimentMap.GetValue(aPoint));
            //    }
            //}
        }