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]); } }
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) }); }
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)); // } //} }