Exemplo n.º 1
0
        private List <MaiNeighbour> GetNeighbours(SimpleHeightArray heightArray, IntVector2 center)
        {
            var heightArrayBoundaries = heightArray.Boundaries;
            var neighbours            = new List <MaiNeighbour>()
            {
                new MaiNeighbour()
                {
                    Position       = center + new IntVector2(-1, 0),
                    DirectionIndex = MaiNeighbourDirection.LEFT
                },
                new MaiNeighbour()
                {
                    Position       = center + new IntVector2(1, 0),
                    DirectionIndex = MaiNeighbourDirection.RIGHT
                },
                new MaiNeighbour()
                {
                    Position       = center + new IntVector2(0, 1),
                    DirectionIndex = MaiNeighbourDirection.UP
                },
                new MaiNeighbour()
                {
                    Position       = center + new IntVector2(0, -1),
                    DirectionIndex = MaiNeighbourDirection.DOWN
                },
            }.Where(c => { return(heightArrayBoundaries.AreValidIndexes(c.Position)); }).ToList();

            return(neighbours);
        }
Exemplo n.º 2
0
        public void ErodeOneStep()
        {
            var currentHeightArray = SimpleHeightArray.FromHeightmap(_currentHeightmap);
            var eroder             = new ThermalEroder();

            var extremes = new ArrayExtremes(1517, 6161);
            var tParam   = CalculateFromHillFactor(1, extremes, 24);

            Debug.Log("TPAN IS " + tParam);

            eroder.Erode(currentHeightArray, new ThermalErosionConfiguration()
            {
                StepCount = 5,
                CParam    = 0.3f,
                TParam    = tParam
            });

            var doneTexture =
                HeightmapUtils.CreateTextureFromHeightmap(
                    SimpleHeightArray.ToHeightmap(currentHeightArray));

            //_go.GetComponent<MeshRenderer>().material.SetTexture("_HeightmapTex0", _oldDoneTexture);
            _go.GetComponent <MeshRenderer>().material.SetTexture("_HeightmapTex1", doneTexture);
            _oldDoneTexture = doneTexture;
        }
Exemplo n.º 3
0
        public void Erode(SimpleHeightArray inHeightArray, ThermalErosionConfiguration configuration)
        {
            var tParam    = configuration.TParam;
            var cParam    = configuration.CParam;
            var stepCount = configuration.StepCount;
            var thermalErosionGroundMover = configuration.GroundMover;
            var neighbourChooser          = configuration.NeighboursChooser;

            var finalDifferenceArray = new SimpleHeightArray(inHeightArray.Width, inHeightArray.Height);

            for (int stepIndex = 0; stepIndex < stepCount; stepIndex++)
            {
                Parallel.For <SimpleHeightArray>(0, inHeightArray.Height,
                                                 new ParallelOptions {
                    MaxDegreeOfParallelism = 4
                },
                                                 () => new SimpleHeightArray(inHeightArray.Width, inHeightArray.Height),
                                                 (y, loop, localDifferenceArray) =>
                {
//                Parallel.For(0, inHeightArray.Height,new ParallelOptions { MaxDegreeOfParallelism = 3 }, y =>
//                for (int y = 0; y < inHeightArray.Height; y++)
//                {
                    for (int x = 0; x < inHeightArray.Width; x++)
                    {
                        var point      = new IntVector2(x, y);
                        var thisValue  = inHeightArray.GetValue(point);
                        var neighbours = configuration.NeighbourFinder.Find(inHeightArray, point)
                                         .Select(n => new NeighbourInfo(n, thisValue - inHeightArray.GetValue(n))).ToList();

                        neighbours = neighbours.Where(c => neighbourChooser.Choose(c, configuration)).ToList();
                        if (!neighbours.Any())
                        {
                            continue;
                        }

                        var changeArray = localDifferenceArray;
                        //changeArray = finalDifferenceArray;
                        thermalErosionGroundMover.Move(neighbours, configuration, changeArray, point);
                    }
                    return(localDifferenceArray);
                },
                                                 (localDifferenceArray) => { finalDifferenceArray.SumValue(localDifferenceArray); });


                for (int y = 0; y < inHeightArray.Height; y++)
                {
                    for (int x = 0; x < inHeightArray.Width; x++)
                    {
                        var point = new IntVector2(x, y);
                        inHeightArray.AddValue(point, finalDifferenceArray.GetValue(point));

                        finalDifferenceArray.SetValue(point, 0);
                    }
                }
            }
        }
Exemplo n.º 4
0
 public void SumValue(SimpleHeightArray localDifferenceArray)
 {
     for (int x = 0; x < localDifferenceArray.Width; x++)
     {
         for (int y = 0; y < localDifferenceArray.Height; y++)
         {
             AddValue(new IntVector2(x, y), localDifferenceArray.GetValue(x, y));
         }
     }
 }
Exemplo n.º 5
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)
     });
 }
Exemplo n.º 6
0
        public List <HeightmapArray> GenerateErodedArrays(HeightmapArray baseArray,
                                                          List <MeiHydraulicEroderConfiguration> configurations)
        {
            var msw = new MyStopWatch();
            List <HeightmapArray> outArray = new List <HeightmapArray>();
            int i = 0;

            foreach (var aConfiguration in configurations)
            {
                var copyArray          = MyArrayUtils.DeepClone(baseArray.HeightmapAsArray);
                var currentHeightArray = new SimpleHeightArray(copyArray);
                msw.StartSegment("eroding-" + i);
                var eroder = new MeiHydraulicEroder();
                eroder.Erode(currentHeightArray, aConfiguration);
                msw.StopSegment();

                outArray.Add(SimpleHeightArray.ToHeightmap(currentHeightArray));
                i++;
            }
            Debug.Log("T22: " + msw.CollectResults());
            return(outArray);
        }
Exemplo n.º 7
0
        public void AtOnceErode(SimpleHeightArray inHeightArray, ThermalErosionConfiguration configuration)
        {
            var tParam    = configuration.TParam;
            var cParam    = configuration.CParam;
            var stepCount = configuration.StepCount;

            for (int stepIndex = 0; stepIndex < stepCount; stepIndex++)
            {
                for (int y = 0; y < inHeightArray.Height; y++)
                {
                    for (int x = 0; x < inHeightArray.Width; x++)
                    {
                        var point      = new IntVector2(x, y);
                        var thisValue  = inHeightArray.GetValue(point);
                        var neighbours = configuration.NeighbourFinder.Find(inHeightArray, point).Select(n => new
                        {
                            point      = n,
                            difference = thisValue - inHeightArray.GetValue(n)
                        }).ToList();

                        neighbours = neighbours.Where(c => c.difference > tParam).ToList();
                        if (!neighbours.Any())
                        {
                            continue;
                        }
                        var dTotal = neighbours.Sum(c => c.difference);
                        var dMax   = neighbours.Max(c => c.difference);

                        foreach (var aNeighbour in neighbours)
                        {
                            var movedGround = cParam * (dMax - tParam) * (aNeighbour.difference / dTotal);
                            inHeightArray.AddValue(aNeighbour.point, movedGround);
                            inHeightArray.AddValue(point, -movedGround);
                        }
                    }
                }
            }
        }
Exemplo n.º 8
0
        public TerrainErosionDebugOutput ErodeWithDebug(SimpleHeightArray heightMap,
                                                        MeiHydraulicEroderConfiguration configuration)
        {
            var debugOutput = new TerrainErosionDebugOutput();
            var sb          = new StringBuilder();

            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 Vector4ArrayTODO(heightMap.Width, heightMap.Height);
            var velocityMap   = new VectorArrayTODO(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++)
            {
                if (i >= 0)
                {
                    // water increment
                    for (int y = 0; y < heightMap.Height; y++)
                    {
                        for (int x = 0; x < heightMap.Width; x++)
                        {
                            var aPoint    = new IntVector2(x, y);
                            var oldValue  = waterMap.GetValue(aPoint);
                            var newAmount = oldValue + deltaT * constantWaterAdding;
                            waterMap_1.SetValue(aPoint, newAmount);
                            if (x == 10 && y == 10)
                            {
                                var settings = DebugGetMapValues(x, y, waterMap, waterMap_1, waterMap_2, fluxMap,
                                                                 velocityMap, sedimentMap, sedimentMap_1);
                                int yyy = 2;
                            }
                        }
                    }
                }
                else
                {
                    MyArrayUtils.Copy(waterMap.Array, waterMap_1.Array);
                }

                debugOutput.AddArray("waterMap", SimpleHeightArray.ToHeightmap(waterMap_1), i);
                debugOutput.AddArray("heightMap", SimpleHeightArray.ToHeightmap(heightMap), i);
                debugOutput.AddArray("sedimentMap", SimpleHeightArray.ToHeightmap(sedimentMap), i);

                var speedMap = new float[sedimentMap.Width, sedimentMap.Height];
                for (int x = 0; x < sedimentMap.Width; x++)
                {
                    for (int y = 0; y < sedimentMap.Height; y++)
                    {
                        speedMap[x, y] = velocityMap.GetValue(x, y).magnitude;
                    }
                }
                debugOutput.AddArray("speedMap", new HeightmapArray(speedMap), i);

                // flow simulation
                int onesCount = 0;
                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)
                        {
                            var settings = DebugGetMapValues(x, y, waterMap, waterMap_1, waterMap_2, fluxMap,
                                                             velocityMap, sedimentMap, sedimentMap_1);
                            Debug.Log("T44. W0: " + waterMap.GetValue(aPoint) + " w1: " + waterMap_1.GetValue(aPoint));
                            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);
                            Preconditions.Assert(!float.IsNaN(d_new_flux), "");
                            newFlux[(int)neighbour.DirectionIndex] = d_new_flux;
                        }

                        var   aD1      = waterMap_1.GetValue(aPoint);
                        var   fluxSum  = VectorUtils.SumMembers(newFlux);
                        float K_factor = 0;
                        if (fluxSum != 0)
                        {
                            K_factor = Mathf.Min(1,
                                                 aD1 * (lX * lY) / (fluxSum * deltaT));
                        }
                        if (K_factor > 0.99999)
                        {
                            onesCount++;
                        }
                        fluxMap.SetValue(aPoint, K_factor * newFlux);
                    }
                }
                Debug.Log("t66: onesCount is " + onesCount);

                // 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)
                        {
                            var settings = DebugGetMapValues(x, y, waterMap, waterMap_1, waterMap_2, fluxMap,
                                                             velocityMap, sedimentMap, sedimentMap_1);
                            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))
                            );
                        if (float.IsNaN(newVelocity.magnitude))
                        {
                            newVelocity = Vector2.zero;
                        }
                        velocityMap.SetValue(aPoint, newVelocity); //todo ograniczenie CFL
                    }
                }

                var erodedAmountMap     = new float[sedimentMap.Width, sedimentMap.Height];
                var depositionAmountMap = new float[sedimentMap.Width, sedimentMap.Height];

                // 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)
                        {
                            var settings = DebugGetMapValues(x, y, waterMap, waterMap_1, waterMap_2, fluxMap,
                                                             velocityMap, sedimentMap, sedimentMap_1);
                            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 * Mathf.Max(o_sinAlpha, 0.1f) *
                                       velocityMap.GetValue(aPoint).magnitude; //todo set minimum alpha

                        var suspendedSediment = sedimentMap.GetValue(aPoint);

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

                debugOutput.AddArray("erodedAmount", new HeightmapArray(erodedAmountMap), i);
                debugOutput.AddArray("depositedAmount", new HeightmapArray(depositionAmountMap), i);

                // 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)
                        {
                            var settings = DebugGetMapValues(x, y, waterMap, waterMap_1, waterMap_2, fluxMap,
                                                             velocityMap, sedimentMap, sedimentMap_1);
                            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)
                        {
                            var settings = DebugGetMapValues(x, y, waterMap, waterMap_1, waterMap_2, fluxMap,
                                                             velocityMap, sedimentMap, sedimentMap_1);
                            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));
            //    }
            //}
            //Debug.Log("t23: " + sb.ToString());
            return(debugOutput);
        }
Exemplo n.º 9
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));
            //    }
            //}
        }
Exemplo n.º 10
0
 public List <IntVector2> Find(SimpleHeightArray inHeightArray, IntVector2 point)
 {
     return(_findFunc(inHeightArray, point));
 }
Exemplo n.º 11
0
        public DebuggableHydraulicEroderOutput Erode(SimpleHeightArray heightMap,
                                                     HydraulicEroderConfiguration configuration, int snapshotFrequencies)
        {
            List <SimpleHeightArray> WaterSnapshots    = new List <SimpleHeightArray>();
            List <SimpleHeightArray> SedimentSnapshots = new List <SimpleHeightArray>();


            float krParam = configuration.kr_ConstantWaterAddition;
            float ksParam = configuration.ks_GroundToSedimentFactor;
            float keParam = configuration.ke_WaterEvaporationFactor;
            float kcParam = configuration.kc_MaxSedimentationFactor;
            bool  finalSedimentationToGround = configuration.FinalSedimentationToGround;
            int   stepCount = configuration.StepCount;
            ErodedNeighbourFinder neighbourFinder = configuration.NeighbourFinder;

            var waterMap            = new SimpleHeightArray(heightMap.Width, heightMap.Height);
            var sedimentMap         = new SimpleHeightArray(heightMap.Width, heightMap.Height);
            var sedimentAdditionMap = new SimpleHeightArray(heightMap.Width, heightMap.Height);
            var waterAdditionMap    = new SimpleHeightArray(heightMap.Width, heightMap.Height);

            for (int i = 0; i < stepCount; i++)
            {
                for (int y = 0; y < heightMap.Height; y++)
                {
                    for (int x = 0; x < heightMap.Width; x++)
                    {
                        var point = new IntVector2(x, y);
                        if (configuration.WaterGenerator == HydraulicEroderWaterGenerator.FirstFrame)
                        {
                            if (i == 0)
                            {
                                waterMap.AddValue(point, krParam);
                            }
                        }
                        else
                        {
                            waterMap.AddValue(point, krParam);
                        }

                        float amountChangedToSediment = ksParam * waterMap.GetValue(point);
                        heightMap.AddValue(point, -amountChangedToSediment);
                        sedimentMap.AddValue(point, amountChangedToSediment);
                    }
                }

                if (i == 0)
                {
                    WaterSnapshots.Add(new SimpleHeightArray(MyArrayUtils.DeepClone <float>(waterMap.Array)));
                    SedimentSnapshots.Add(new SimpleHeightArray(MyArrayUtils.DeepClone <float>(sedimentMap.Array)));
                }


                for (int y = 0; y < heightMap.Height; y++)
                {
                    for (int x = 0; x < heightMap.Width; x++)
                    {
                        var point = new IntVector2(x, y);

                        var neighbourPoints = neighbourFinder.Find(heightMap, point);

                        var pTotalHeight = heightMap.GetValue(point) + waterMap.GetValue(point);

                        var neighbours = neighbourPoints.Select(nPoint => new
                        {
                            Point                 = nPoint,
                            TotalHeight           = heightMap.GetValue(nPoint) + waterMap.GetValue(nPoint),
                            TotalHeightDifference = pTotalHeight - (heightMap.GetValue(nPoint) +
                                                                    waterMap.GetValue(nPoint)),
                        }).Where(c => c.TotalHeightDifference > 0).ToList();
                        if (!neighbours.Any())
                        {
                            continue;
                        }

                        var dTotalHeightDiffSum = neighbours.Sum(c => c.TotalHeightDifference);
                        var avgTotalHeight      = (neighbours.Sum(c => c.TotalHeight) + pTotalHeight) /
                                                  (neighbours.Count + 1);

                        var pSediment = sedimentMap.GetValue(point);
                        var pWater    = waterMap.GetValue(point);
                        if (pWater < 0.00000001f)
                        {
                            continue;
                        }
                        var pDeltaA = pTotalHeight - avgTotalHeight;
                        var pMin    = Mathf.Min(pDeltaA, pWater);

                        if (configuration.DestinationFinder == HydraulicEroderWaterDestinationFinder.OnlyBest)
                        {
                            var bestNeighbour = neighbours.OrderByDescending(c => c.TotalHeightDifference).First();
                            var nMovedWater   = pMin;
                            var addedSediment = pSediment * (nMovedWater / pWater);
                            waterAdditionMap.AddValue(bestNeighbour.Point, nMovedWater);
                            sedimentAdditionMap.AddValue(bestNeighbour.Point, addedSediment);

                            sedimentAdditionMap.AddValue(point, -addedSediment);
                            waterAdditionMap.AddValue(point, -pMin);
                        }
                        else
                        {
                            var movedSedimentSum = 0f;
                            foreach (var aNeighbour in neighbours)
                            {
                                var nMovedWater   = pMin * (aNeighbour.TotalHeightDifference / dTotalHeightDiffSum);
                                var addedSediment = pSediment * (nMovedWater / pWater);
                                movedSedimentSum += addedSediment;
                                waterAdditionMap.AddValue(aNeighbour.Point, nMovedWater);
                                sedimentAdditionMap.AddValue(aNeighbour.Point, addedSediment);
                            }
                            sedimentAdditionMap.AddValue(point, -movedSedimentSum);
                            waterAdditionMap.AddValue(point, -pMin);
                        }
                    }
                }

                for (int y = 0; y < heightMap.Height; y++)
                {
                    for (int x = 0; x < heightMap.Width; x++)
                    {
                        var point = new IntVector2(x, y);
                        waterMap.AddValue(point, waterAdditionMap.GetValue(point));
                        waterAdditionMap.SetValue(point, 0);

                        sedimentMap.AddValue(point, sedimentAdditionMap.GetValue(point));
                        sedimentAdditionMap.SetValue(point, 0);
                    }
                }

                for (int y = 0; y < heightMap.Height; y++)
                {
                    for (int x = 0; x < heightMap.Width; x++)
                    {
                        var point  = new IntVector2(x, y);
                        var pWater = waterMap.GetValue(point);
                        var waterAfterEvaporation = pWater * (1 - keParam);
                        waterMap.SetValue(point, waterAfterEvaporation);

                        var pSedimentMax  = kcParam * waterAfterEvaporation;
                        var pSediment     = sedimentMap.GetValue(point);
                        var deltaSediment = Mathf.Max(0, pSediment - pSedimentMax);
                        sedimentMap.AddValue(point, -deltaSediment);
                        heightMap.AddValue(point, deltaSediment);
                    }
                }

                if (i % snapshotFrequencies == 0)
                {
                    WaterSnapshots.Add(new SimpleHeightArray(MyArrayUtils.DeepClone <float>(waterMap.Array)));
                    SedimentSnapshots.Add(new SimpleHeightArray(MyArrayUtils.DeepClone <float>(sedimentMap.Array)));
                }
            }

            if (finalSedimentationToGround)
            {
                for (int y = 0; y < heightMap.Height; y++)
                {
                    for (int x = 0; x < heightMap.Width; x++)
                    {
                        var point = new IntVector2(x, y);
                        heightMap.AddValue(point, sedimentMap.GetValue(point));
                    }
                }
            }
            return(new DebuggableHydraulicEroderOutput()
            {
                SedimentSnapshots = SedimentSnapshots,
                WaterSnapshots = WaterSnapshots
            });
        }
Exemplo n.º 12
0
 public void Move(List <ThermalEroder.NeighbourInfo> neighbours, ThermalErosionConfiguration configuration,
                  SimpleHeightArray outArray, IntVector2 point)
 {
     _func(neighbours, configuration, outArray, point);
 }
Exemplo n.º 13
0
        public void Start_Hydraulic_Debuggable()
        {
            var heightTexture1 = SavingFileManager.LoadPngTextureFromFile(@"C:\inz\cont\smallCut.png", 240,
                                                                          240, TextureFormat.RGBA32, true, true);
            var heightmap1 = HeightmapUtils.CreateHeightmapArrayFromTexture(heightTexture1);

            //DiamondSquareCreator creator = new DiamondSquareCreator(new RandomProvider(22));
            //var heightmap2 = creator.CreateDiamondSquareNoiseArray(new IntVector2(240, 240), 64);
            //MyArrayUtils.Multiply(heightmap2.HeightmapAsArray, 0.1f);

            var tParam = EroderDebugObject.CalculateFromHillFactor(1, new ArrayExtremes(0, 5000), 24);

            var extents = MyArrayUtils.CalculateExtremes(heightmap1.HeightmapAsArray);

            MyArrayUtils.Normalize(heightmap1.HeightmapAsArray);

            var configuration =
                new HydraulicEroderConfiguration()
            {
                StepCount                  = 20,
                NeighbourFinder            = NeighbourFinders.Big9Finder,
                kr_ConstantWaterAddition   = 0.001f,
                ks_GroundToSedimentFactor  = 1f,
                ke_WaterEvaporationFactor  = 0.05f,
                kc_MaxSedimentationFactor  = 0.8f,
                FinalSedimentationToGround = false,
                WaterGenerator             = HydraulicEroderWaterGenerator.FirstFrame,
                DestinationFinder          = HydraulicEroderWaterDestinationFinder.OnlyBest
            };

            var copyArray          = MyArrayUtils.DeepClone(heightmap1.HeightmapAsArray);
            var currentHeightArray = new SimpleHeightArray(copyArray);
            var eroder             = new DebuggableHydraulicEroder();
            var debuggingOutput    = eroder.Erode(currentHeightArray, configuration, 1);

            var sedimentExtentsArr = debuggingOutput.SedimentSnapshots
                                     .Select(c => MyArrayUtils.CalculateExtremes(c.Array)).ToList();
            var sedimentExtents = new ArrayExtremes(sedimentExtentsArr.Min(c => c.Min),
                                                    sedimentExtentsArr.Max(c => c.Max));

            debuggingOutput.SedimentSnapshots.ForEach(c => MyArrayUtils.Normalize(c.Array, sedimentExtents));

            var waterExtentsArr = debuggingOutput.WaterSnapshots.Select(c => MyArrayUtils.CalculateExtremes(c.Array))
                                  .ToList();
            var waterExtents = new ArrayExtremes(waterExtentsArr.Min(c => c.Min), waterExtentsArr.Max(c => c.Max));

            debuggingOutput.WaterSnapshots.ForEach(c => MyArrayUtils.Normalize(c.Array, waterExtents));


            _go = GameObject.CreatePrimitive(PrimitiveType.Quad);
            var material = new Material(Shader.Find("Custom/Terrain/Terrain_Debug_Comparision_StepByStep"));

            _go.GetComponent <MeshRenderer>().material = material;
            _go.name = "Terrain";
            _go.transform.localRotation          = Quaternion.Euler(0, 0, 0);
            _go.transform.localScale             = new Vector3(10, 1, 10);
            _go.transform.localPosition          = new Vector3(0, 0, 0);
            _go.GetComponent <MeshFilter>().mesh = PlaneGenerator.CreateFlatPlaneMesh(240, 240);

            MyHeightTextureArray heightTextureArray =
                new MyHeightTextureArray(240, 240, 2, TextureFormat.ARGB32, false, true);

            heightTextureArray.AddElementArray(heightmap1, 0);
            heightTextureArray.AddElementArray(new HeightmapArray(currentHeightArray.Array), 1);
            _go.GetComponent <MeshRenderer>().material
            .SetTexture("_HeightmapTexArray", heightTextureArray.ApplyAndRetrive());


            MyHeightTextureArray waterArray = new MyHeightTextureArray(240, 240, debuggingOutput.WaterSnapshots.Count,
                                                                       TextureFormat.ARGB32, false, true);
            int i = 0;

            foreach (var waterSnapshot in debuggingOutput.WaterSnapshots)
            {
                waterArray.AddElementArray(new HeightmapArray(waterSnapshot.Array), i);
                i++;
            }
            _go.GetComponent <MeshRenderer>().material.SetTexture("_WaterArray", waterArray.ApplyAndRetrive());


            MyHeightTextureArray sedimentArray = new MyHeightTextureArray(240, 240,
                                                                          debuggingOutput.SedimentSnapshots.Count, TextureFormat.ARGB32, false, true);
            int j = 0;

            foreach (var sedimentSnapshot in debuggingOutput.SedimentSnapshots)
            {
                sedimentArray.AddElementArray(new HeightmapArray(sedimentSnapshot.Array), j);
                j++;
            }
            _go.GetComponent <MeshRenderer>().material.SetTexture("_SedimentArray", sedimentArray.ApplyAndRetrive());
        }
Exemplo n.º 14
0
        public void Start_Mai_Debug()
        {
            var heightTexture1 = SavingFileManager.LoadPngTextureFromFile(@"C:\inz\cont\smallCut.png", 240,
                                                                          240, TextureFormat.RGBA32, true, true);
            var heightmap1 = HeightmapUtils.CreateHeightmapArrayFromTexture(heightTexture1);

            //DiamondSquareCreator creator = new DiamondSquareCreator(new RandomProvider(22));
            //var heightmap2 = creator.CreateDiamondSquareNoiseArray(new IntVector2(240, 240), 64);
            //MyArrayUtils.Multiply(heightmap2.HeightmapAsArray, 0.1f);
            //HeightmapArray workingHeightmap = LoadHeightmapFromTextureFile(@"C:\inz\cont\temp3.png");
            HeightmapArray workingHeightmap = heightmap1;

            MyArrayUtils.Normalize(workingHeightmap.HeightmapAsArray);
            MyArrayUtils.InvertNormalized(workingHeightmap.HeightmapAsArray);
            HeightmapArray originalMap = new HeightmapArray(MyArrayUtils.DeepClone(workingHeightmap.HeightmapAsArray));

            MyArrayUtils.Multiply(workingHeightmap.HeightmapAsArray, 400);

            var configuration = new MeiHydraulicEroderConfiguration()
            {
                StepCount           = 50,
                A_PipeCrossSection  = 0.05f,
                ConstantWaterAdding = 1 / 64f,
                GravityAcceleration = 9.81f,
                DeltaT                   = 1f,
                DepositionConstant       = 0.0001f * 12 * 2f,
                DissolvingConstant       = 0.0001f * 12 * 2f,
                EvaporationConstant      = 0.05f * 10,
                GridSize                 = new Vector2(1, 1),
                L_PipeLength             = 1,
                SedimentCapacityConstant = 250
            };

            var eroder    = new MeiHydraulicEroder();
            var debOutput = eroder.ErodeWithDebug(SimpleHeightArray.FromHeightmap(workingHeightmap), configuration);

            MyArrayUtils.Multiply(workingHeightmap.HeightmapAsArray, 1f / 400);
            debOutput.NormalizeInGroups();


            _go = GameObject.CreatePrimitive(PrimitiveType.Quad);
            var material = new Material(Shader.Find("Custom/Terrain/Terrain_Mei_Debug_Comparision_StepByStep"));

            _go.GetComponent <MeshRenderer>().material = material;
            _go.name = "Terrain";
            _go.transform.localRotation          = Quaternion.Euler(0, 0, 0);
            _go.transform.localScale             = new Vector3(10, 1, 10);
            _go.transform.localPosition          = new Vector3(0, 0, 0);
            _go.GetComponent <MeshFilter>().mesh = PlaneGenerator.CreateFlatPlaneMesh(240, 240);

            MyHeightTextureArray heightTextureArray =
                new MyHeightTextureArray(240, 240, 2, TextureFormat.ARGB32, false, true);

            heightTextureArray.AddElementArray(originalMap, 0);
            heightTextureArray.AddElementArray(workingHeightmap, 1);
            _go.GetComponent <MeshRenderer>().material
            .SetTexture("_HeightmapTexArray", heightTextureArray.ApplyAndRetrive());


            var arrayListsCount  = debOutput.OneArrayListCount;
            var arrayListsLength = debOutput.OneArrayListLength;
            MyHeightTextureArray detailHeightTexturesArray =
                new MyHeightTextureArray(240, 240, arrayListsCount * arrayListsLength, TextureFormat.ARGB32, false,
                                         true);

            foreach (var snapshot in debOutput.ArraysDict.Values.SelectMany(c => c))
            {
                detailHeightTexturesArray.AddElementArray(snapshot);
            }
            _go.GetComponent <MeshRenderer>().material
            .SetTexture("_DetailTexArray", detailHeightTexturesArray.ApplyAndRetrive());
            _go.GetComponent <MeshRenderer>().material.SetFloat("_DetailTexLength", arrayListsLength);
        }
Exemplo n.º 15
0
 public static HeightmapArray ToHeightmap(SimpleHeightArray sourceArray)
 {
     return(new HeightmapArray(sourceArray._array));
 }
Exemplo n.º 16
0
        public void Erode(SimpleHeightArray inHeightArray, ThermalErosionConfiguration configuration)
        {
            var tParam    = configuration.TParam;
            var cParam    = configuration.CParam;
            var stepCount = configuration.StepCount;

            var finalDifferenceArray = new SimpleHeightArray(inHeightArray.Width, inHeightArray.Height);

            for (int stepIndex = 0; stepIndex < stepCount; stepIndex++)
            {
                Parallel.For <SimpleHeightArray>(0, inHeightArray.Height,
                                                 new ParallelOptions {
                    MaxDegreeOfParallelism = 4
                },
                                                 () => new SimpleHeightArray(inHeightArray.Width, inHeightArray.Height),
                                                 (y, loop, localDifferenceArray) =>
                {
//                Parallel.For(0, inHeightArray.Height,new ParallelOptions { MaxDegreeOfParallelism = 3 }, y =>
//                for (int y = 0; y < inHeightArray.Height; y++)
//                {
                    for (int x = 0; x < inHeightArray.Width; x++)
                    {
                        var point      = new IntVector2(x, y);
                        var thisValue  = inHeightArray.GetValue(point);
                        var neighbours = configuration.NeighbourFinder.Find(inHeightArray, point).Select(n => new
                        {
                            point      = n,
                            difference = thisValue - inHeightArray.GetValue(n)
                        }).ToList();

                        neighbours = neighbours.Where(c => c.difference < tParam && c.difference > 0).ToList();
                        if (!neighbours.Any())
                        {
                            continue;
                        }
                        var dTotal = neighbours.Sum(c => c.difference);
                        var dMax   = neighbours.Max(c => c.difference);

                        foreach (var aNeighbour in neighbours)
                        {
                            var movedGround = cParam * (dMax) * (aNeighbour.difference / dTotal);

                            //finalDifferenceArray.AddValue(aNeighbour.point, movedGround);
                            //finalDifferenceArray.AddValue(point, -movedGround);

                            localDifferenceArray.AddValue(aNeighbour.point, movedGround);
                            localDifferenceArray.AddValue(point, -movedGround);
                        }
                    }
                    return(localDifferenceArray);
                },
                                                 (localDifferenceArray) => { finalDifferenceArray.SumValue(localDifferenceArray); });


                for (int y = 0; y < inHeightArray.Height; y++)
                {
                    for (int x = 0; x < inHeightArray.Width; x++)
                    {
                        var point = new IntVector2(x, y);
                        inHeightArray.AddValue(point, finalDifferenceArray.GetValue(point));

                        finalDifferenceArray.SetValue(point, 0);
                    }
                }
            }
        }