public void processTerrain(ErosionProgressDelegate erosionProgressDelegate)
 {
     Terrain ter = (Terrain)GetComponent (typeof(Terrain));
     if (ter == null) {
         return;
     }
     try {
         // Pass the height array to the erosion script
         TerrainData terData = ter.terrainData;
         Tx = terData.heightmapWidth;
         Ty = terData.heightmapHeight;
         heightMap = terData.GetHeights (0, 0, Tx, Ty);
         waterMap = new float[Tx, Ty];
         sedimentMap = new float[Tx, Ty];
         waterErosion (waterErosionIterations, erosionProgressDelegate);
         // Apply it to the terrain object
         terData.SetHeights (0, 0, heightMap);
     } catch (Exception e) {
         Debug.LogError ("An error occurred: " + e);
     }
 }
    void waterErosion(int iterations, ErosionProgressDelegate erosionProgressDelegate)
    {
        for (int iter = 0; iter < iterations; iter++)
        {
            float percentComplete = (float)iter / (float)iterations;
            erosionProgressDelegate("Applying Water Erosion", "Applying water erosion.", iter, iterations, percentComplete);
            for (int y = 0; y < Ty; y++)
            {
                for (int x = 0; x < Tx; x++)
                {
                    waterMap [x, y]    = waterErosionRainfall;
                    sedimentMap [x, y] = 0.0f;
                }
            }

            int waterCounter = 100;
            do
            {
                waterExists = false;
                for (int y = 0; y < Ty; y++)
                {
                    for (int x = 0; x < Tx; x++)
                    {
                        moveWater(x, y);
                    }
                }
                waterCounter--;
            } while (waterExists && (waterCounter > 0));

            for (int y = 0; y < Ty; y++)
            {
                for (int x = 0; x < Tx; x++)
                {
                    addSediment(x, y);
                }
            }
        }
    }
    public void processTerrain(ErosionProgressDelegate erosionProgressDelegate)
    {
        Terrain ter = (Terrain)GetComponent(typeof(Terrain));

        if (ter == null)
        {
            return;
        }
        try {
            // Pass the height array to the erosion script
            TerrainData terData = ter.terrainData;
            Tx          = terData.heightmapWidth;
            Ty          = terData.heightmapHeight;
            heightMap   = terData.GetHeights(0, 0, Tx, Ty);
            waterMap    = new float[Tx, Ty];
            sedimentMap = new float[Tx, Ty];
            waterErosion(waterErosionIterations, erosionProgressDelegate);
            // Apply it to the terrain object
            terData.SetHeights(0, 0, heightMap);
        } catch (Exception e) {
            Debug.LogError("An error occurred: " + e);
        }
    }
Beispiel #4
0
 public void FullHydraulicErosion(int iterations, float rainfall, float evaporation, float solubility, float saturation)
 {
     erosionTypeInt = 1;
     erosionType = ErosionType.Hydraulic;
     hydraulicTypeInt = 1;
     hydraulicType = HydraulicType.Full;
     hydraulicIterations = iterations;
     hydraulicRainfall = rainfall;
     hydraulicEvaporation = evaporation;
     hydraulicSedimentSolubility = solubility;
     hydraulicSedimentSaturation = saturation;
     neighbourhood = Neighbourhood.Moore;
     ErosionProgressDelegate erosionProgressDelegate = new ErosionProgressDelegate(dummyErosionProgress);
     erodeAllTerrain(erosionProgressDelegate);
 }
Beispiel #5
0
 // -------------------------------------------------------------------------------------------------------- API FUNCTIONS
 public void FastThermalErosion(int iterations, float minSlope, float blendAmount)
 {
     erosionTypeInt = 0;
     erosionType = ErosionType.Thermal;
     thermalIterations = iterations;
     thermalMinSlope = minSlope;
     thermalFalloff = blendAmount;
     neighbourhood = Neighbourhood.Moore;
     ErosionProgressDelegate erosionProgressDelegate = new ErosionProgressDelegate(dummyErosionProgress);
     erodeAllTerrain(erosionProgressDelegate);
 }
Beispiel #6
0
 public void FastHydraulicErosion(int iterations, float maxSlope, float blendAmount)
 {
     erosionTypeInt = 1;
     erosionType = ErosionType.Hydraulic;
     hydraulicTypeInt = 0;
     hydraulicType = HydraulicType.Fast;
     hydraulicIterations = iterations;
     hydraulicMaxSlope = maxSlope;
     hydraulicFalloff = blendAmount;
     neighbourhood = Neighbourhood.Moore;
     ErosionProgressDelegate erosionProgressDelegate = new ErosionProgressDelegate(dummyErosionProgress);
     erodeAllTerrain(erosionProgressDelegate);
 }
Beispiel #7
0
 public void erodeAllTerrain(ErosionProgressDelegate erosionProgressDelegate)
 {
     erosionMode = ErosionMode.Filter;
     // Check enum vars...
     convertIntVarsToEnums();
     // Error checking...
     Terrain ter = (Terrain) GetComponent(typeof(Terrain));
     if (ter == null) {
         return;
     }
     try {
         TerrainData terData = ter.terrainData;
         int Tw = terData.heightmapWidth;
         int Th = terData.heightmapHeight;
         float[,] heightMap = terData.GetHeights(0, 0, Tw, Th);
         // Set the number of iterations and pass the height array to the appropriate erosion script...
         int iterations;
         switch (erosionType) {
             case ErosionType.Thermal:
             iterations = thermalIterations;
             heightMap = fastErosion(heightMap, new Vector2(Tw, Th), iterations, erosionProgressDelegate);
             break;
             case ErosionType.Hydraulic:
             iterations = hydraulicIterations;
             switch (hydraulicType) {
                 case HydraulicType.Fast:
                 heightMap = fastErosion(heightMap, new Vector2(Tw, Th), iterations, erosionProgressDelegate);
                 break;
                 case HydraulicType.Full:
                 heightMap = fullHydraulicErosion(heightMap, new Vector2(Tw, Th), iterations, erosionProgressDelegate);
                 break;
                 case HydraulicType.Velocity:
                 heightMap = velocityHydraulicErosion(heightMap, new Vector2(Tw, Th), iterations, erosionProgressDelegate);
                 break;
             }
             break;
             case ErosionType.Tidal:
             Vector3 terSize = terData.size;
             if (tidalSeaLevel >= transform.position.y && tidalSeaLevel <= transform.position.y + terSize.y) {
                 iterations = tidalIterations;
                 heightMap = fastErosion(heightMap, new Vector2(Tw, Th), iterations, erosionProgressDelegate);
             } else {
                 Debug.LogError("Sea level does not intersect terrain object. Erosion operation failed.");
             }
             break;
             case ErosionType.Wind:
             iterations = windIterations;
             heightMap = windErosion(heightMap, new Vector2(Tw, Th), iterations, erosionProgressDelegate);
             break;
             default:
             return;
         }
         // Apply it to the terrain object
         terData.SetHeights(0, 0, heightMap);
     }
     catch (Exception e) {
         Debug.LogError("An error occurred: "+e);
     }
 }
Beispiel #8
0
 // -------------------------------------------------------------------------------------------------------- WIND EROSION
 private float[,] windErosion(float[,] heightMap, Vector2 arraySize, int iterations, ErosionProgressDelegate erosionProgressDelegate)
 {
     Terrain ter = (Terrain) GetComponent(typeof(Terrain));
     TerrainData terData = ter.terrainData;
     Quaternion windQuaternion = Quaternion.Euler(0, (windDirection + 180.0f), 0);
     Vector3 windVector = windQuaternion * Vector3.forward;
     int Tw = (int) arraySize.x;
     int Th = (int) arraySize.y;
     float[,] stressMap = new float[Tw, Th];
     float[,] flowMap = new float[Tw, Th];
     float[,] velocityMap = new float[Tw, Th];
     float[,] velocityDiffMap = new float[Tw, Th];
     float[,] suspensionMap = new float[Tw, Th];
     float[,] suspensionDiffMap = new float[Tw, Th];
     float[,] heightDiffMap = new float[Tw, Th];
     int xNeighbours;
     int yNeighbours;
     int xShift;
     int yShift;
     int xIndex;
     int yIndex;
     int Mx;
     int My;
     float materialAtIndex;
     float velocityAtCell;
     // Zero maps...
     for (My = 0; My < Th; My++) {
         for (Mx = 0; Mx < Tw; Mx++) {
             stressMap[Mx, My] = 0.0f;
             flowMap[Mx, My] = 0.0f;
             velocityMap[Mx, My] = 0.0f;
             velocityDiffMap[Mx, My] = 0.0f;
             suspensionMap[Mx, My] = 0.0f;
             suspensionDiffMap[Mx, My] = 0.0f;
             heightDiffMap[Mx, My] = 0.0f;
         }
     }
     // Start iterations...
     for (int iter = 0; iter < iterations; iter++) {
         // Drop material...
         for (My = 0; My < Th; My++) {
             for (Mx = 0; Mx < Tw; Mx++) {
                 velocityAtCell = velocityMap[Mx, My];
                 float heightAtCell = heightMap[Mx, My];
                 float materialAtCell = suspensionMap[Mx, My];
                 float droppedMaterial = materialAtCell * windGravity; //  * 1.0f - (velocityAtCell)
                 suspensionMap[Mx, My] = materialAtCell - droppedMaterial;
                 heightMap[Mx, My] = heightAtCell + droppedMaterial;
             }
         }
         // Calculate stress and flow...
         for (My = 0; My < Th; My++) {
             for (Mx = 0; Mx < Tw; Mx++) {
                 float heightAtIndex = heightMap[Mx, My]; // ALTITUDE
                 Vector3 pNormal = terData.GetInterpolatedNormal((float) Mx / Tw, (float) My / Th); // NORMAL
                 float stress = (Vector3.Angle(pNormal, windVector) - 90) / 90;
                 if (stress < 0.0f) {
                     stress = 0.0f;
                 }
                 stressMap[Mx, My] = stress * heightAtIndex;
                 float flow = 1.0f - Mathf.Abs(Vector3.Angle(pNormal, windVector) - 90) / 90;
                 flowMap[Mx, My] = flow * heightAtIndex; // ^2
                 float inFlow = flow * heightAtIndex * windForce; // ^2
                 float velocityAtPoint = velocityMap[Mx, My];
                 float newVelocityAtPoint = velocityAtPoint + inFlow; // * UnityEngine.Random.value;
                 velocityMap[Mx, My] = newVelocityAtPoint;
                 // Lift material...
                 materialAtIndex = suspensionMap[Mx, My];
                 float liftedMaterial = windLift * newVelocityAtPoint; // * UnityEngine.Random.value;
                 if (materialAtIndex + liftedMaterial > windCapacity) {
                     liftedMaterial = windCapacity - materialAtIndex;
                 }
                 suspensionMap[Mx, My] = materialAtIndex + liftedMaterial;
                 heightMap[Mx, My] = heightAtIndex - liftedMaterial;
             }
         }
         // Calculate flow propagation...
         for (My = 0; My < Th; My++) {
             // y...
             if (My == 0) {
                 yNeighbours = 2;
                 yShift = 0;
                 yIndex = 0;
             } else if (My == Th - 1) {
                 yNeighbours = 2;
                 yShift = -1;
                 yIndex = 1;
             } else {
                 yNeighbours = 3;
                 yShift = -1;
                 yIndex = 1;
             }
             for (Mx = 0; Mx < Tw; Mx++) {
                 // x...
                 if (Mx == 0) {
                     xNeighbours = 2;
                     xShift = 0;
                     xIndex = 0;
                 } else if (Mx == Tw - 1) {
                     xNeighbours = 2;
                     xShift = -1;
                     xIndex = 1;
                 } else {
                     xNeighbours = 3;
                     xShift = -1;
                     xIndex = 1;
                 }
                 int Ny;
                 int Nx;
                 float flowAtIndex = flowMap[Mx, My];
                 float stressAtIndex = stressMap[Mx, My];
                 materialAtIndex = suspensionMap[Mx, My];
                 for (Ny = 0; Ny < yNeighbours; Ny++) {
                     for (Nx = 0; Nx < xNeighbours; Nx++) {
                         if (Nx != xIndex || Ny != yIndex) {
                             if (neighbourhood == Neighbourhood.Moore || (neighbourhood == Neighbourhood.VonNeumann && (Nx == xIndex || Ny == yIndex))) {
                                 Vector3 vectorToNeighbour = new Vector3(Nx + xShift, 0, -1 * (Ny + yShift));
                                 float pWeighting = (90 - Vector3.Angle(vectorToNeighbour, windVector)) / 90;
                                 if (pWeighting < 0.0f) {
                                     pWeighting = 0.0f;
                                 }
                                 // Propagate velocity...
                                 float propagatedVelocitySoFar = velocityDiffMap[Mx + Nx + xShift, My + Ny + yShift];
                                 float propagatedVelocity = pWeighting * (flowAtIndex - stressAtIndex) * 0.1f;
                                 if (propagatedVelocity < 0.0f) {
                                     propagatedVelocity = 0.0f;
                                 }
                                 float propagatedVelocityAfter = propagatedVelocitySoFar + propagatedVelocity;
                                 // Pass to difference map...
                                 velocityDiffMap[Mx + Nx + xShift, My + Ny + yShift] = propagatedVelocityAfter;
                                 // Lose velocity...
                                 float lostVelocitySoFar = velocityDiffMap[Mx, My];
                                 float lostVelocityAfter = lostVelocitySoFar - propagatedVelocity;
                                 // Pass to difference map...
                                 velocityDiffMap[Mx, My] = lostVelocityAfter;
                                 // Propagate material...
                                 float propagatedMaterialSoFar = suspensionDiffMap[Mx + Nx + xShift, My + Ny + yShift];
                                 float propagatedMaterial = materialAtIndex * propagatedVelocity;
                                 float propagatedMaterialAfter = propagatedMaterialSoFar + propagatedMaterial;
                                 // Pass to difference map...
                                 suspensionDiffMap[Mx + Nx + xShift, My + Ny + yShift] = propagatedMaterialAfter;
                                 // Lose material...
                                 float lostMaterialSoFar = suspensionDiffMap[Mx, My];
                                 float lostMaterialAfter = lostMaterialSoFar - propagatedMaterial;
                                 // Pass to difference map...
                                 suspensionDiffMap[Mx, My] = lostMaterialAfter;
                             }
                         }
                     }
                 }
             }
         }
         // Apply suspension difference map to suspension map...
         float suspensionAtCell;
         for (My = 0; My < Th; My++) {
             for (Mx = 0; Mx < Tw; Mx++) {
                 suspensionAtCell = suspensionMap[Mx, My] + suspensionDiffMap[Mx, My];
                 if (suspensionAtCell > 1.0f) {
                     suspensionAtCell = 1.0f;
                 } else if (suspensionAtCell < 0.0f) {
                     suspensionAtCell = 0.0f;
                 }
                 suspensionMap[Mx, My] = suspensionAtCell;
                 suspensionDiffMap[Mx, My] = 0.0f;
             }
         }
         // Apply velocity difference map to velocity map...
         for (My = 0; My < Th; My++) {
             for (Mx = 0; Mx < Tw; Mx++) {
                 velocityAtCell = velocityMap[Mx, My] + velocityDiffMap[Mx, My];
                 // Calculate entropy...
                 velocityAtCell *= 1.0f - windEntropy;
                 if (velocityAtCell > 1.0f) {
                     velocityAtCell = 1.0f;
                 } else if (velocityAtCell < 0.0f) {
                     velocityAtCell = 0.0f;
                 }
                 velocityMap[Mx, My] = velocityAtCell;
                 velocityDiffMap[Mx, My] = 0.0f;
             }
         }
         // Smooth...
         smoothIterations = 1;
         smoothBlend = 0.25f;
         float[,] smoothedHeightMap = (float[,]) heightMap.Clone();
         GeneratorProgressDelegate generatorProgressDelegate = new GeneratorProgressDelegate(dummyGeneratorProgress);
         smoothedHeightMap = smooth(smoothedHeightMap, arraySize, generatorProgressDelegate);
         // Combine...
         for (My = 0; My < Th; My++) {
             for (Mx = 0; Mx < Tw; Mx++) {
                 float oldHeightAtPoint = heightMap[Mx, My];
                 float newHeightAtPoint = smoothedHeightMap[Mx, My];
                 float blendAmount = stressMap[Mx, My] * windSmoothing;
                 float blendedHeightAtPoint = (newHeightAtPoint * blendAmount) + (oldHeightAtPoint * (1.0f - blendAmount));
                 heightMap[Mx, My] = blendedHeightAtPoint;
             }
         }
         // Update progress...
         float percentComplete = (float) iter / (float) iterations;
         erosionProgressDelegate("Applying Wind Erosion", "Applying wind erosion.", iter, iterations, percentComplete);
     }
     return heightMap;
 }
Beispiel #9
0
 // -------------------------------------------------------------------------------------------------------- HYDRAULIC (VELOCITY) EROSION
 private float[,] velocityHydraulicErosion(float[,] heightMap, Vector2 arraySize, int iterations, ErosionProgressDelegate erosionProgressDelegate)
 {
     int Tx = (int) arraySize.x;
     int Ty = (int) arraySize.y;
     float[,] precipitationMap = new float[Tx, Ty];
     float[,] slopeMap = new float[Tx, Ty];
     float[,] waterMap = new float[Tx, Ty];
     float[,] waterDiffMap = new float[Tx, Ty];
     float[,] velocityMap = new float[Tx, Ty];
     float[,] velocityDiffMap = new float[Tx, Ty];
     float[,] sedimentMap = new float[Tx, Ty];
     float[,] sedimentDiffMap = new float[Tx, Ty];
     int Mx;
     int My;
     int xNeighbours;
     int yNeighbours;
     int xShift;
     int yShift;
     int xIndex;
     int yIndex;
     float maxSediment;
     // Zero maps...
     for (My = 0; My < Ty; My++) {
         for (Mx = 0; Mx < Tx; Mx++) {
             waterMap[Mx, My] = 0.0f;
             waterDiffMap[Mx, My] = 0.0f;
             velocityMap[Mx, My] = 0.0f;
             velocityDiffMap[Mx, My] = 0.0f;
             sedimentMap[Mx, My] = 0.0f;
             sedimentDiffMap[Mx, My] = 0.0f;
         }
     }
     // Cache precipitation map...
     for (My = 0; My < Ty; My++) {
         for (Mx = 0; Mx < Tx; Mx++) {
             float precipitationAmount = heightMap[Mx, My];
             precipitationMap[Mx, My] = precipitationAmount;
         }
     }
     // Cache slope map and initialise velocity map...
     float tCumulative;
     int Nx;
     int Ny;
     float t;
     float heightAtIndex;
     float heightAtPoint;
     int nNeighbours;
     for (My = 0; My < Ty; My++) {
         // y...
         if (My == 0) {
             yNeighbours = 2;
             yShift = 0;
             yIndex = 0;
         } else if (My == Ty - 1) {
             yNeighbours = 2;
             yShift = -1;
             yIndex = 1;
         } else {
             yNeighbours = 3;
             yShift = -1;
             yIndex = 1;
         }
         for (Mx = 0; Mx < Tx; Mx++) {
             // x...
             if (Mx == 0) {
                 xNeighbours = 2;
                 xShift = 0;
                 xIndex = 0;
             } else if (Mx == Tx - 1) {
                 xNeighbours = 2;
                 xShift = -1;
                 xIndex = 1;
             } else {
                 xNeighbours = 3;
                 xShift = -1;
                 xIndex = 1;
             }
             // Calculate slope and create velocity map...
             tCumulative = 0.0f;
             heightAtIndex = heightMap[Mx + xIndex + xShift, My + yIndex + yShift]; // Get height at index
             nNeighbours = 0;
             for (Ny = 0; Ny < yNeighbours; Ny++) {
                 for (Nx = 0; Nx < xNeighbours; Nx++) {
                     if (Nx != xIndex || Ny != yIndex) {
                         if (neighbourhood == Neighbourhood.Moore || (neighbourhood == Neighbourhood.VonNeumann && (Nx == xIndex || Ny == yIndex))) {
                             heightAtPoint = heightMap[Mx + Nx + xShift, My + Ny + yShift]; // Get height at point
                             t = Mathf.Abs(heightAtIndex - heightAtPoint);
                             tCumulative += t;
                             nNeighbours++;
                         }
                     }
                 }
             }
             float tAverage = tCumulative / nNeighbours;
             slopeMap[Mx + xIndex + xShift, My + yIndex + yShift] = tAverage;
             // velocityMap[Mx + xIndex + xShift, My + yIndex + yShift] = Mathf.Min(tAverage * hydraulicVelocity, 1.0f);
         }
     }
     // Start iterations...
     for (int iter = 0; iter < iterations; iter++) {
         // Add water proportional to precipitation...
         for (My = 0; My < Ty; My++) {
             for (Mx = 0; Mx < Tx; Mx++) {
                 float waterAmount = waterMap[Mx, My] + precipitationMap[Mx, My] * hydraulicVelocityRainfall;
                 if (waterAmount > 1.0f) {
                     waterAmount = 1.0f;
                 }
                 waterMap[Mx, My] = waterAmount;
             }
         }
         // Dissolve material as sediment...
         for (My = 0; My < Ty; My++) {
             for (Mx = 0; Mx < Tx; Mx++) {
                 float sedimentAmount = sedimentMap[Mx, My];
                 maxSediment = waterMap[Mx, My] * hydraulicVelocitySedimentSaturation;
                 if (sedimentAmount < maxSediment) {
                     float erodedSediment = waterMap[Mx, My] * velocityMap[Mx, My] * hydraulicVelocitySedimentSolubility;
                     if (sedimentAmount + erodedSediment > maxSediment) {
                         erodedSediment = maxSediment - sedimentAmount;
                     }
                     heightAtIndex = heightMap[Mx, My];
                     if (erodedSediment > heightAtIndex) {
                         erodedSediment = heightAtIndex;
                     }
                     sedimentMap[Mx, My] = sedimentAmount + erodedSediment;
                     heightMap[Mx, My] = heightAtIndex - erodedSediment;
                 }
             }
         }
         // Calculate velocity and move water...
         for (My = 0; My < Ty; My++) {
             // y...
             if (My == 0) {
                 yNeighbours = 2;
                 yShift = 0;
                 yIndex = 0;
             } else if (My == Ty - 1) {
                 yNeighbours = 2;
                 yShift = -1;
                 yIndex = 1;
             } else {
                 yNeighbours = 3;
                 yShift = -1;
                 yIndex = 1;
             }
             for (Mx = 0; Mx < Tx; Mx++) {
                 // x...
                 if (Mx == 0) {
                     xNeighbours = 2;
                     xShift = 0;
                     xIndex = 0;
                 } else if (Mx == Tx - 1) {
                     xNeighbours = 2;
                     xShift = -1;
                     xIndex = 1;
                 } else {
                     xNeighbours = 3;
                     xShift = -1;
                     xIndex = 1;
                 }
                 // Calculate slope...
                 tCumulative = 0.0f;
                 heightAtIndex = heightMap[Mx, My]; // Get height at index
                 float hCumulative = heightAtIndex;
                 float waterAtIndex = waterMap[Mx, My]; // Get water at index
                 nNeighbours = 0;
                 float waterAtPoint;
                 for (Ny = 0; Ny < yNeighbours; Ny++) {
                     for (Nx = 0; Nx < xNeighbours; Nx++) {
                         if (Nx != xIndex || Ny != yIndex) {
                             if (neighbourhood == Neighbourhood.Moore || (neighbourhood == Neighbourhood.VonNeumann && (Nx == xIndex || Ny == yIndex))) {
                                 heightAtPoint = heightMap[Mx + Nx + xShift, My + Ny + yShift]; // Get height at point
                                 waterAtPoint = waterMap[Mx + Nx + xShift, My + Ny + yShift]; // Get water at point
                                 t = (heightAtIndex + waterAtIndex) - (heightAtPoint + waterAtPoint);
                                 // Only calculate downhill cells...
                                 if (t > 0) {
                                     tCumulative += t;
                                     hCumulative += heightAtIndex + waterAtIndex;
                                     nNeighbours++;
                                 }
                             }
                         }
                     }
                 }
                 float velocityAtIndex = velocityMap[Mx, My];
                 float slopeAtIndex = slopeMap[Mx, My];
                 float sedimentAtIndex = sedimentMap[Mx, My];
                 float totalVelocityAtIndex = velocityAtIndex + (hydraulicVelocity * slopeAtIndex);
                 // Calculate water to be transported away from the index...
                 float hAverage = hCumulative / (nNeighbours + 1);
                 float dWater = (heightAtIndex + waterAtIndex) - hAverage;
                 float transportedWater = Mathf.Min(waterAtIndex, dWater * (1.0f + velocityAtIndex));
                 float waterDiffAtIndexSoFar = waterDiffMap[Mx, My];
                 // Pass to difference map...
                 float waterAtIndexDiff = waterDiffAtIndexSoFar - transportedWater;
                 waterDiffMap[Mx, My] = waterAtIndexDiff;
                 float transferredVelocity = totalVelocityAtIndex * (transportedWater / waterAtIndex);
                 float transferredSediment = sedimentAtIndex * (transportedWater / waterAtIndex);
                 // Neighbours...
                 for (Ny = 0; Ny < yNeighbours; Ny++) {
                     for (Nx = 0; Nx < xNeighbours; Nx++) {
                         if (Nx != xIndex || Ny != yIndex) {
                             if (neighbourhood == Neighbourhood.Moore || (neighbourhood == Neighbourhood.VonNeumann && (Nx == xIndex || Ny == yIndex))) {
                                 heightAtPoint = heightMap[Mx + Nx + xShift, My + Ny + yShift]; // Get height at point
                                 waterAtPoint = waterMap[Mx + Nx + xShift, My + Ny + yShift]; // Get water at point
                                 t = (heightAtIndex + waterAtIndex) - (heightAtPoint + waterAtPoint);
                                 // Only affect downhill cells...
                                 if (t > 0.0f) {
                                     // Move water...
                                     float transportedWaterSoFar = waterDiffMap[Mx + Nx + xShift, My + Ny + yShift];
                                     float transportedWaterProportional = transportedWater * (t / tCumulative);
                                     float transportedWaterAfter = transportedWaterSoFar + transportedWaterProportional;
                                     // Pass to difference map...
                                     waterDiffMap[Mx + Nx + xShift, My + Ny + yShift] = transportedWaterAfter;
                                     // Transfer velocity...
                                     float transferredVelocitySoFar = velocityDiffMap[Mx + Nx + xShift, My + Ny + yShift];
                                     float transferredVelocityProportional = transferredVelocity * hydraulicMomentum * (t / tCumulative);
                                     float transferredVelocityAfter = transferredVelocitySoFar + transferredVelocityProportional;
                                     // Pass to difference map...
                                     velocityDiffMap[Mx + Nx + xShift, My + Ny + yShift] = transferredVelocityAfter;
                                     // Transfer sediment...
                                     float transferredSedimentSoFar = sedimentDiffMap[Mx + Nx + xShift, My + Ny + yShift];
                                     float transferredSedimentProportional = transferredSediment * hydraulicMomentum * (t / tCumulative);
                                     float transferredSedimentAfter = transferredSedimentSoFar + transferredSedimentProportional;
                                     // Pass to difference map...
                                     sedimentDiffMap[Mx + Nx + xShift, My + Ny + yShift] = transferredSedimentAfter;
                                 }
                             }
                         }
                     }
                 }
                 // Lose velocity at index...
                 float velocityDiffSoFar = velocityDiffMap[Mx, My];
                 velocityDiffMap[Mx, My] = velocityDiffSoFar - transferredVelocity;
             }
         }
         // Apply velocity difference map to velocity map...
         float velocityAtCell;
         for (My = 0; My < Ty; My++) {
             for (Mx = 0; Mx < Tx; Mx++) {
                 velocityAtCell = velocityMap[Mx, My] + velocityDiffMap[Mx, My];
                 // Calculate entropy...
                 velocityAtCell *= 1.0f - hydraulicEntropy;
                 if (velocityAtCell > 1.0f) {
                     velocityAtCell = 1.0f;
                 } else if (velocityAtCell < 0.0f) {
                     velocityAtCell = 0.0f;
                 }
                 velocityMap[Mx, My] = velocityAtCell;
                 velocityDiffMap[Mx, My] = 0.0f;
             }
         }
         // Apply water difference map to water map...
         float waterAtCell;
         for (My = 0; My < Ty; My++) {
             for (Mx = 0; Mx < Tx; Mx++) {
                 waterAtCell = waterMap[Mx, My] + waterDiffMap[Mx, My];
                 // Calculate evaporation...
                 float evaporatedWater = waterAtCell * hydraulicVelocityEvaporation;
                 waterAtCell -= evaporatedWater;
                 if (waterAtCell > 1.0f) {
                     waterAtCell = 1.0f;
                 } else if (waterAtCell < 0.0f) {
                     waterAtCell = 0.0f;
                 }
                 waterMap[Mx, My] = waterAtCell;
                 waterDiffMap[Mx, My] = 0.0f;
             }
         }
         // Apply sediment difference map to sediment map...
         float sedimentAtCell;
         for (My = 0; My < Ty; My++) {
             for (Mx = 0; Mx < Tx; Mx++) {
                 sedimentAtCell = sedimentMap[Mx, My] + sedimentDiffMap[Mx, My];
                 if (sedimentAtCell > 1.0f) {
                     sedimentAtCell = 1.0f;
                 } else if (sedimentAtCell < 0.0f) {
                     sedimentAtCell = 0.0f;
                 }
                 sedimentMap[Mx, My] = sedimentAtCell;
                 sedimentDiffMap[Mx, My] = 0.0f;
             }
         }
         // Deposit sediment...
         float heightAtCell;
         for (My = 0; My < Ty; My++) {
             for (Mx = 0; Mx < Tx; Mx++) {
                 maxSediment = waterMap[Mx, My] * hydraulicVelocitySedimentSaturation;
                 sedimentAtCell = sedimentMap[Mx, My];
                 if (sedimentAtCell > maxSediment) {
                     float depositedSediment = sedimentAtCell - maxSediment;
                     sedimentMap[Mx, My] = maxSediment;
                     heightAtCell = heightMap[Mx, My];
                     heightMap[Mx, My] = heightAtCell + depositedSediment;
                 }
             }
         }
         // Downcutting...
         for (My = 0; My < Ty; My++) {
             for (Mx = 0; Mx < Tx; Mx++) {
                 velocityAtCell = waterMap[Mx, My];
                 heightAtCell = heightMap[Mx, My];
                 float heightModifier = 1 - (Mathf.Abs(0.5f - heightAtCell) * 2);
                 float cutMaterial = hydraulicDowncutting * velocityAtCell * heightModifier;
                 heightAtCell -= cutMaterial;
                 heightMap[Mx, My] = heightAtCell;
             }
         }
         // Update progress...
         float percentComplete = (float) iter / (float) iterations;
         erosionProgressDelegate("Applying Hydraulic Erosion", "Applying hydraulic erosion.", iter, iterations, percentComplete);
     }
     return heightMap;
 }
Beispiel #10
0
 // -------------------------------------------------------------------------------------------------------- HYDRAULIC (FULL) EROSION
 private float[,] fullHydraulicErosion(float[,] heightMap, Vector2 arraySize, int iterations, ErosionProgressDelegate erosionProgressDelegate)
 {
     int Tx = (int) arraySize.x;
     int Ty = (int) arraySize.y;
     float[,] waterMap = new float[Tx, Ty];
     float[,] waterDiffMap = new float[Tx, Ty];
     float[,] sedimentMap = new float[Tx, Ty];
     float[,] sedimentDiffMap = new float[Tx, Ty];
     int Mx;
     int My;
     int xNeighbours;
     int yNeighbours;
     int xShift;
     int yShift;
     int xIndex;
     int yIndex;
     int Nx;
     int Ny;
     float t;
     float heightAtIndex;
     float heightAtPoint;
     int nNeighbours;
     float maxSediment;
     float sedimentAtCell;
     float heightAtCell;
     // Zero maps...
     for (My = 0; My < Ty; My++) {
         for (Mx = 0; Mx < Tx; Mx++) {
             waterMap[Mx, My] = 0.0f;
             waterDiffMap[Mx, My] = 0.0f;
             sedimentMap[Mx, My] = 0.0f;
             sedimentDiffMap[Mx, My] = 0.0f;
         }
     }
     // Start iterations...
     for (int iter = 0; iter < iterations; iter++) {
         // Add water proportional to precipitation...
         for (My = 0; My < Ty; My++) {
             for (Mx = 0; Mx < Tx; Mx++) {
                 float waterAmount = waterMap[Mx, My] + hydraulicRainfall;
                 if (waterAmount > 1.0f) {
                     waterAmount = 1.0f;
                 }
                 waterMap[Mx, My] = waterAmount;
             }
         }
         // Dissolve material as sediment...
         for (My = 0; My < Ty; My++) {
             for (Mx = 0; Mx < Tx; Mx++) {
                 float sedimentAmount = sedimentMap[Mx, My];
                 maxSediment = waterMap[Mx, My] * hydraulicSedimentSaturation;
                 if (sedimentAmount < maxSediment) {
                     float erodedSediment = waterMap[Mx, My] * hydraulicSedimentSolubility;
                     if (sedimentAmount + erodedSediment > maxSediment) {
                         erodedSediment = maxSediment - sedimentAmount;
                     }
                     heightAtIndex = heightMap[Mx, My];
                     if (erodedSediment > heightAtIndex) {
                         erodedSediment = heightAtIndex;
                     }
                     sedimentMap[Mx, My] = sedimentAmount + erodedSediment;
                     heightMap[Mx, My] = heightAtIndex - erodedSediment;
                 }
             }
         }
         // Find slope and move water...
         for (My = 0; My < Ty; My++) {
             // y...
             if (My == 0) {
                 yNeighbours = 2;
                 yShift = 0;
                 yIndex = 0;
             } else if (My == Ty - 1) {
                 yNeighbours = 2;
                 yShift = -1;
                 yIndex = 1;
             } else {
                 yNeighbours = 3;
                 yShift = -1;
                 yIndex = 1;
             }
             for (Mx = 0; Mx < Tx; Mx++) {
                 // x...
                 if (Mx == 0) {
                     xNeighbours = 2;
                     xShift = 0;
                     xIndex = 0;
                 } else if (Mx == Tx - 1) {
                     xNeighbours = 2;
                     xShift = -1;
                     xIndex = 1;
                 } else {
                     xNeighbours = 3;
                     xShift = -1;
                     xIndex = 1;
                 }
                 // Calculate slope...
                 float tCumulative = 0.0f;
                 float tMax = 0.0f;
                 heightAtIndex = heightMap[Mx + xIndex + xShift, My + yIndex + yShift]; // Get height at index
                 float waterAtIndex = waterMap[Mx + xIndex + xShift, My + yIndex + yShift]; // Get water at index
                 float waterAtPoint;
                 float hCumulative = heightAtIndex;
                 nNeighbours = 0;
                 for (Ny = 0; Ny < yNeighbours; Ny++) {
                     for (Nx = 0; Nx < xNeighbours; Nx++) {
                         if (Nx != xIndex || Ny != yIndex) {
                             if (neighbourhood == Neighbourhood.Moore || (neighbourhood == Neighbourhood.VonNeumann && (Nx == xIndex || Ny == yIndex))) {
                                 heightAtPoint = heightMap[Mx + Nx + xShift, My + Ny + yShift]; // Get height at point
                                 waterAtPoint = waterMap[Mx + Nx + xShift, My + Ny + yShift]; // Get water at point
                                 t = (heightAtIndex + waterAtIndex) - (heightAtPoint + waterAtPoint);
                                 if (t > 0) {
                                     tCumulative += t;
                                     hCumulative += heightAtPoint + waterAtPoint;
                                     nNeighbours++;
                                     if (t > tMax) {
                                         t = tMax;
                                     }
                                 }
                             }
                         }
                     }
                 }
                 // Calculate water to be transported away from the index...
                 float hAverage = hCumulative / (nNeighbours + 1);
                 float dWater = (heightAtIndex + waterAtIndex) - hAverage;
                 float transportedWater = Mathf.Min(waterAtIndex, dWater);
                 float waterDiffAtIndexSoFar = waterDiffMap[Mx + xIndex + xShift, My + yIndex + yShift];
                 float waterAtIndexDiff = waterDiffAtIndexSoFar - transportedWater;
                 // Pass to difference map...
                 waterDiffMap[Mx + xIndex + xShift, My + yIndex + yShift] = waterAtIndexDiff;
                 // Calculate sediment to be transported away from the index...
                 float sedimentAtIndex = sedimentMap[Mx + xIndex + xShift, My + yIndex + yShift];
                 float transportedSediment = sedimentAtIndex * (transportedWater / waterAtIndex);
                 float sedimentDiffAtIndexSoFar = sedimentDiffMap[Mx + xIndex + xShift, My + yIndex + yShift];
                 float sedimentAtIndexDiff = sedimentDiffAtIndexSoFar - transportedSediment;
                 // Pass to difference map...
                 sedimentDiffMap[Mx + xIndex + xShift, My + yIndex + yShift] = sedimentAtIndexDiff;
                 // Neighbours...
                 for (Ny = 0; Ny < yNeighbours; Ny++) {
                     for (Nx = 0; Nx < xNeighbours; Nx++) {
                         if (Nx != xIndex || Ny != yIndex) {
                             if (neighbourhood == Neighbourhood.Moore || (neighbourhood == Neighbourhood.VonNeumann && (Nx == xIndex || Ny == yIndex))) {
                                 heightAtPoint = heightMap[Mx + Nx + xShift, My + Ny + yShift]; // Get height at point
                                 waterAtPoint = waterMap[Mx + Nx + xShift, My + Ny + yShift]; // Get water at point
                                 t = (heightAtIndex + waterAtIndex) - (heightAtPoint + waterAtPoint);
                                 // Only affect downhill cells...
                                 if (t > 0) {
                                     // Move water...
                                     float transportedWaterSoFar = waterDiffMap[Mx + Nx + xShift, My + Ny + yShift];
                                     float transportedWaterProportional = transportedWater * (t / tCumulative);
                                     float transportedWaterAfter = transportedWaterSoFar + transportedWaterProportional;
                                     // Pass to difference map...
                                     waterDiffMap[Mx + Nx + xShift, My + Ny + yShift] = transportedWaterAfter;
                                     // Move sediment...
                                     float transportedSedimentSoFar = sedimentDiffMap[Mx + Nx + xShift, My + Ny + yShift];
                                     float transportedSedimentProportional = transportedSediment * (t / tCumulative);
                                     float transportedSedimentAfter = transportedSedimentSoFar + transportedSedimentProportional;
                                     // Pass to difference map...
                                     sedimentDiffMap[Mx + Nx + xShift, My + Ny + yShift] = transportedSedimentAfter;
                                 }
                             }
                         }
                     }
                 }
             }
         }
         // Apply water difference map to water map...
         float waterAtCell;
         for (My = 0; My < Ty; My++) {
             for (Mx = 0; Mx < Tx; Mx++) {
                 waterAtCell = waterMap[Mx, My] + waterDiffMap[Mx, My];
                 // Calculate evaporation...
                 float evaporatedWater = waterAtCell * hydraulicEvaporation;
                 waterAtCell -= evaporatedWater;
                 if (waterAtCell < 0.0f) {
                     waterAtCell = 0.0f;
                 }
                 waterMap[Mx, My] = waterAtCell;
                 waterDiffMap[Mx, My] = 0.0f;
             }
         }
         // Apply sediment difference map to sediment map...
         for (My = 0; My < Ty; My++) {
             for (Mx = 0; Mx < Tx; Mx++) {
                 sedimentAtCell = sedimentMap[Mx, My] + sedimentDiffMap[Mx, My];
                 if (sedimentAtCell > 1.0f) {
                     sedimentAtCell = 1.0f;
                 } else if (sedimentAtCell < 0.0f) {
                     sedimentAtCell = 0.0f;
                 }
                 sedimentMap[Mx, My] = sedimentAtCell;
                 sedimentDiffMap[Mx, My] = 0.0f;
             }
         }
         // Deposit sediment...
         for (My = 0; My < Ty; My++) {
             for (Mx = 0; Mx < Tx; Mx++) {
                 maxSediment = waterMap[Mx, My] * hydraulicSedimentSaturation;
                 sedimentAtCell = sedimentMap[Mx, My];
                 if (sedimentAtCell > maxSediment) {
                     float depositedSediment = sedimentAtCell - maxSediment;
                     sedimentMap[Mx, My] = maxSediment;
                     heightAtCell = heightMap[Mx, My];
                     heightMap[Mx, My] = heightAtCell + depositedSediment;
                 }
             }
         }
         // Update progress...
         float percentComplete = (float) iter / (float) iterations;
         erosionProgressDelegate("Applying Hydraulic Erosion", "Applying hydraulic erosion.", iter, iterations, percentComplete);
     }
     return heightMap;
 }
Beispiel #11
0
 private float[,] fastErosion(float[,] heightMap, Vector2 arraySize, int iterations, ErosionProgressDelegate erosionProgressDelegate)
 {
     int Tw = (int) arraySize.y;
     int Th = (int) arraySize.x;
     float[,] heightDiffMap = new float[Tw, Th];
     Terrain ter = (Terrain) GetComponent(typeof(Terrain));
     TerrainData terData = ter.terrainData;
     Vector3 terSize = terData.size;
     float minSlopeBlendMin = 0.0f;
     float minSlopeBlendMax = 0.0f;
     float maxSlopeBlendMin = 0.0f;
     float maxSlopeBlendMax = 0.0f;
     float seaLevel = 0.0f;
     float lowerTidalLimit = 0.0f;
     float upperTidalLimit = 0.0f;
     float tidalRange = 0.0f;
     float cliffLimit = 0.0f;
     switch (erosionType) {
         case ErosionType.Thermal:
         minSlopeBlendMin = ((terSize.x / Tw) * Mathf.Tan(thermalMinSlope * Mathf.Deg2Rad)) / terSize.y;
         if (minSlopeBlendMin > 1.0f) {
             minSlopeBlendMin = 1.0f;
         }
         if (thermalFalloff == 1.0f) {
             thermalFalloff = 0.999f;
         }
         float thermalMaxSlope = thermalMinSlope + ((90 - thermalMinSlope) * thermalFalloff);
         minSlopeBlendMax = ((terSize.x / Tw) * Mathf.Tan(thermalMaxSlope * Mathf.Deg2Rad)) / terSize.y;
         if (minSlopeBlendMax > 1.0f) {
              minSlopeBlendMax = 1.0f;
         }
         break;
         case ErosionType.Hydraulic:
         maxSlopeBlendMax = ((terSize.x / Tw) * Mathf.Tan(hydraulicMaxSlope * Mathf.Deg2Rad)) / terSize.y;
         if (hydraulicFalloff == 0.0f) {
             hydraulicFalloff = 0.001f;
         }
         float hydraulicMinSlope = hydraulicMaxSlope * (1 - hydraulicFalloff);
         maxSlopeBlendMin = ((terSize.x / Tw) * Mathf.Tan(hydraulicMinSlope * Mathf.Deg2Rad)) / terSize.y;
         break;
         case ErosionType.Tidal:
         seaLevel = (tidalSeaLevel - transform.position.y) / (transform.position.y + terSize.y);
         lowerTidalLimit = (tidalSeaLevel - transform.position.y - tidalRangeAmount) / (transform.position.y + terSize.y);
         upperTidalLimit = (tidalSeaLevel - transform.position.y + tidalRangeAmount) / (transform.position.y + terSize.y);
         tidalRange = upperTidalLimit - seaLevel;
         cliffLimit = ((terSize.x / Tw) * Mathf.Tan(tidalCliffLimit * Mathf.Deg2Rad)) / terSize.y;
         break;
         default:
         return heightMap;
     }
     int xNeighbours;
     int yNeighbours;
     int xShift;
     int yShift;
     int xIndex;
     int yIndex;
     int Tx;
     int Ty;
     // Start iterations...
     for (int iter = 0; iter < iterations; iter++) {
         for (Ty = 0; Ty < Th; Ty++) {
             // y...
             if (Ty == 0) {
                 yNeighbours = 2;
                 yShift = 0;
                 yIndex = 0;
             } else if (Ty == Th - 1) {
                 yNeighbours = 2;
                 yShift = -1;
                 yIndex = 1;
             } else {
                 yNeighbours = 3;
                 yShift = -1;
                 yIndex = 1;
             }
             for (Tx = 0; Tx < Tw; Tx++) {
                 // x...
                 if (Tx == 0) {
                     xNeighbours = 2;
                     xShift = 0;
                     xIndex = 0;
                 } else if (Tx == Tw - 1) {
                     xNeighbours = 2;
                     xShift = -1;
                     xIndex = 1;
                 } else {
                     xNeighbours = 3;
                     xShift = -1;
                     xIndex = 1;
                 }
                 // Calculate slope...
                 float tMin = 1.0f;
                 float tMax = 0.0f;
                 float tCumulative = 0.0f;
                 int Ny;
                 int Nx;
                 float t;
                 float heightAtIndex = heightMap[Tx + xIndex + xShift, Ty + yIndex + yShift]; // Get height at index
                 float hCumulative = heightAtIndex;
                 int nNeighbours = 0;
                 for (Ny = 0; Ny < yNeighbours; Ny++) {
                     for (Nx = 0; Nx < xNeighbours; Nx++) {
                         if (Nx != xIndex || Ny != yIndex) {
                             if (neighbourhood == Neighbourhood.Moore || (neighbourhood == Neighbourhood.VonNeumann && (Nx == xIndex || Ny == yIndex))) {
                                 float heightAtPoint = heightMap[Tx + Nx + xShift, Ty + Ny + yShift]; // Get height at point
                                 // Tidal...
                                 hCumulative += heightAtPoint;
                                 // Others...
                                 t = heightAtIndex - heightAtPoint;
                                 if (t > 0) {
                                     tCumulative += t;
                                     if (t < tMin) {
                                         tMin = t;
                                     }
                                     if (t > tMax) {
                                         tMax = t;
                                     }
                                 }
                                 nNeighbours++;
                             }
                         }
                     }
                 }
                 float tAverage = tCumulative / nNeighbours;
                 // float tAverage = tMax;
                 // Erosion type...
                 bool doErode = false;
                 switch (erosionType) {
                     case ErosionType.Thermal:
                     if (tAverage >= minSlopeBlendMin) {
                         doErode = true;
                     }
                     break;
                     case ErosionType.Hydraulic:
                     if (tAverage > 0 && tAverage <= maxSlopeBlendMax) {
                         doErode = true;
                     }
                     break;
                     case ErosionType.Tidal:
                     if (tAverage > 0 && tAverage <= cliffLimit && heightAtIndex < upperTidalLimit && heightAtIndex > lowerTidalLimit) {
                         doErode = true;
                     }
                     break;
                     default:
                     return heightMap;
                 }
                 if (doErode) {
                     float blendAmount;
                     if (erosionType == ErosionType.Tidal) {
                         // Tidal...
                         float hAverage = hCumulative / (nNeighbours + 1);
                         float dTidalSeaLevel = Mathf.Abs(seaLevel - heightAtIndex);
                         blendAmount = dTidalSeaLevel / tidalRange;
                         float blendHeight = heightAtIndex * blendAmount + hAverage * (1 - blendAmount);
                         float blendTidalSeaLevel = Mathf.Pow(dTidalSeaLevel, 3);
                         heightMap[Tx + xIndex + xShift, Ty + yIndex + yShift] = seaLevel * blendTidalSeaLevel + blendHeight * (1 - blendTidalSeaLevel);
                     } else {
                         // Thermal or Hydraulic...
                         float blendRange;
                         if (erosionType == ErosionType.Thermal) {
                             if (tAverage > minSlopeBlendMax) {
                                 blendAmount = 1;
                             } else {
                                 blendRange = minSlopeBlendMax - minSlopeBlendMin;
                                 blendAmount = (tAverage - minSlopeBlendMin) / blendRange; // minSlopeBlendMin = 0; minSlopeBlendMax = 1
                             }
                         } else {
                             if (tAverage < maxSlopeBlendMin) {
                                 blendAmount = 1;
                             } else {
                                 blendRange = maxSlopeBlendMax - maxSlopeBlendMin;
                                 blendAmount = 1 - ((tAverage - maxSlopeBlendMin) / blendRange); // maxSlopeBlendMin = 1; maxSlopeBlendMax = 0
                             }
                         }
                         float m = tMin / 2 * blendAmount;
                         float pointValue = heightMap[Tx + xIndex + xShift, Ty + yIndex + yShift];
                         if (erosionMode == ErosionMode.Filter || (erosionMode == ErosionMode.Brush && useDifferenceMaps)) {
                             // Pass to difference map...
                             float heightDiffAtIndexSoFar = heightDiffMap[Tx + xIndex + xShift, Ty + yIndex + yShift];
                             float heightAtIndexDiff = heightDiffAtIndexSoFar - m;
                             heightDiffMap[Tx + xIndex + xShift, Ty + yIndex + yShift] = heightAtIndexDiff;
                         } else {
                             float pointValueAfter = pointValue - m;
                             if (pointValueAfter < 0) {
                                 pointValueAfter = 0;
                             }
                             heightMap[Tx + xIndex + xShift, Ty + yIndex + yShift] = pointValueAfter;
                         }
                         for (Ny = 0; Ny < yNeighbours; Ny++) {
                             for (Nx = 0; Nx < xNeighbours; Nx++) {
                                 if (Nx != xIndex || Ny != yIndex) {
                                     if (neighbourhood == Neighbourhood.Moore || (neighbourhood == Neighbourhood.VonNeumann && (Nx == xIndex || Ny == yIndex))) {
                                         float neighbourValue = heightMap[Tx + Nx + xShift, Ty + Ny + yShift];
                                         t = pointValue - neighbourValue;
                                         // Only move material downhill...
                                         if (t > 0) {
                                             float mProportional = m * (t / tCumulative);
                                             if (erosionMode == ErosionMode.Filter || (erosionMode == ErosionMode.Brush && useDifferenceMaps)) {
                                                 // Pass to difference map...
                                                 float heightDiffAtNeighbourSoFar = heightDiffMap[Tx + Nx + xShift, Ty + Ny + yShift];
                                                 float heightAtNeighbourDiff = heightDiffAtNeighbourSoFar + mProportional;
                                                 heightDiffMap[Tx + Nx + xShift, Ty + Ny + yShift] = heightAtNeighbourDiff;
                                             } else {
                                                 neighbourValue += mProportional;
                                                 if (neighbourValue < 0) {
                                                     neighbourValue = 0;
                                                 }
                                                 heightMap[Tx + Nx + xShift, Ty + Ny + yShift] = neighbourValue;
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
         if ((erosionMode == ErosionMode.Filter || (erosionMode == ErosionMode.Brush && useDifferenceMaps)) && erosionType != ErosionType.Tidal) {
             // Apply height difference map to height map...
             float heightAtCell;
             for (Ty = 0; Ty < Th; Ty++) {
                 for (Tx = 0; Tx < Tw; Tx++) {
                     heightAtCell = heightMap[Tx, Ty] + heightDiffMap[Tx, Ty];
                     if (heightAtCell > 1.0f) {
                         heightAtCell = 1.0f;
                     } else if (heightAtCell < 0.0f) {
                         heightAtCell = 0.0f;
                     }
                     heightMap[Tx, Ty] = heightAtCell;
                     heightDiffMap[Tx, Ty] = 0.0f;
                 }
             }
         }
         if (erosionMode == ErosionMode.Filter) {
             // Update progress...
             string titleString = "";
             string displayString = "";
             switch (erosionType) {
                 case ErosionType.Thermal:
                 titleString = "Applying Thermal Erosion";
                 displayString = "Applying thermal erosion.";
                 break;
                 case ErosionType.Hydraulic:
                 titleString = "Applying Hydraulic Erosion";
                 displayString = "Applying hydraulic erosion.";
                 break;
                 case ErosionType.Tidal:
                 titleString = "Applying Tidal Erosion";
                 displayString = "Applying tidal erosion.";
                 break;
                 default:
                 return heightMap;
             }
             float percentComplete = (float) iter / (float) iterations;
             erosionProgressDelegate(titleString, displayString, iter, iterations, percentComplete);
         }
     }
     return heightMap;
 }
Beispiel #12
0
 private void erodeTerrainWithBrush()
 {
     erosionMode = ErosionMode.Brush;
     // Error checking...
     Terrain ter = (Terrain) GetComponent(typeof(Terrain));
     if (ter == null) {
         return;
     }
     int Px = 0;
     int Py = 0;
     try {
         TerrainData terData = ter.terrainData;
         int Tw = terData.heightmapWidth;
         int Th = terData.heightmapHeight;
         Vector3 Ts = terData.size;
         int Sx = (int) Mathf.Floor((Tw / Ts.x) * brushSize);
         int Sy = (int) Mathf.Floor((Th / Ts.z) * brushSize);
         Vector3 localBrushPosition = transform.InverseTransformPoint(brushPosition);
         Px = (int) Mathf.Round((localBrushPosition.x / Ts.x) * Tw - (Sx / 2));
         Py = (int) Mathf.Round((localBrushPosition.z / Ts.z) * Th - (Sy / 2));
         if (Px < 0) {
             Sx = Sx + Px;
             Px = 0;
         }
         if (Py < 0) {
             Sy = Sy + Py;
             Py = 0;
         }
         if (Px + Sx > Tw) {
             Sx = Tw - Px;
         }
         if (Py + Sy > Th) {
             Sy = Th - Py;
         }
         float[,] heightMap = terData.GetHeights(Px, Py, Sx, Sy);
         Sx = heightMap.GetLength(1);
         Sy = heightMap.GetLength(0);
         // Pass the height array to the erosion script...
         float[,] erodedheightMap = (float[,]) heightMap.Clone();
         ErosionProgressDelegate erosionProgressDelegate = new ErosionProgressDelegate(dummyErosionProgress);
         erodedheightMap = fastErosion(erodedheightMap, new Vector2(Sx, Sy), 1, erosionProgressDelegate);
         // Apply it to the terrain object
         float sampleRadius = Sx / 2.0f;
         for (int Ty = 0; Ty < Sx; Ty++) {
             for (int Tx = 0; Tx < Sy; Tx++) {
                 float oldHeightAtPoint = heightMap[Tx, Ty];
                 float newHeightAtPoint = erodedheightMap[Tx, Ty];
                 float distancefromOrigin = Vector2.Distance(new Vector2(Tx, Ty), new Vector2(sampleRadius, sampleRadius));
                 float weightAtPoint = 1.0f - ((distancefromOrigin - (sampleRadius - (sampleRadius * brushSoftness))) / (sampleRadius * brushSoftness));
                 if (weightAtPoint < 0.0f) {
                     weightAtPoint = 0.0f;
                 } else if (weightAtPoint > 1.0f) {
                     weightAtPoint = 1.0f;
                 }
                 weightAtPoint *= brushOpacity;
                 float blendedHeightAtPoint = (newHeightAtPoint * weightAtPoint) + (oldHeightAtPoint * (1.0f - weightAtPoint));
                 heightMap[Tx, Ty] = blendedHeightAtPoint;
             }
         }
         terData.SetHeights(Px, Py, heightMap);
     }
     catch (Exception e) {
      	Debug.LogError("A brush error occurred: "+e);
     }
 }
Beispiel #13
0
 public void WindErosion(int iterations, float direction, float force, float lift, float gravity, float capacity, float entropy, float smoothing)
 {
     erosionTypeInt = 3;
     erosionType = ErosionType.Wind;
     windIterations = iterations;
     windDirection = direction;
     windForce = force;
     windLift = lift;
     windGravity = gravity;
     windCapacity = capacity;
     windEntropy = entropy;
     windSmoothing = smoothing;
     neighbourhood = Neighbourhood.Moore;
     ErosionProgressDelegate erosionProgressDelegate = new ErosionProgressDelegate(dummyErosionProgress);
     erodeAllTerrain(erosionProgressDelegate);
 }
Beispiel #14
0
 public void VelocityHydraulicErosion(int iterations, float rainfall, float evaporation, float solubility, float saturation, float velocity, float momentum, float entropy, float downcutting)
 {
     erosionTypeInt = 1;
     erosionType = ErosionType.Hydraulic;
     hydraulicTypeInt = 2;
     hydraulicType = HydraulicType.Velocity;
     hydraulicIterations = iterations;
     hydraulicVelocityRainfall = rainfall;
     hydraulicVelocityEvaporation = evaporation;
     hydraulicVelocitySedimentSolubility = solubility;
     hydraulicVelocitySedimentSaturation = saturation;
     hydraulicVelocity = velocity;
     hydraulicMomentum = momentum;
     hydraulicEntropy = entropy;
     hydraulicDowncutting = downcutting;
     neighbourhood = Neighbourhood.Moore;
     ErosionProgressDelegate erosionProgressDelegate = new ErosionProgressDelegate(dummyErosionProgress);
     erodeAllTerrain(erosionProgressDelegate);
 }
Beispiel #15
0
 public void TidalErosion(int iterations, float seaLevel, float tidalRange, float cliffLimit)
 {
     erosionTypeInt = 2;
     erosionType = ErosionType.Tidal;
     tidalIterations = iterations;
     tidalSeaLevel = seaLevel;
     tidalRangeAmount = tidalRange;
     tidalCliffLimit = cliffLimit;
     neighbourhood = Neighbourhood.Moore;
     ErosionProgressDelegate erosionProgressDelegate = new ErosionProgressDelegate(dummyErosionProgress);
     erodeAllTerrain(erosionProgressDelegate);
 }
Beispiel #16
0
    void waterErosion(int iterations, ErosionProgressDelegate erosionProgressDelegate)
    {
        for (int iter = 0; iter < iterations; iter++) {
            float percentComplete = (float)iter / (float)iterations;
            erosionProgressDelegate ("Applying Water Erosion", "Applying water erosion.", iter, iterations, percentComplete);
            for (int y = 0; y < Ty; y++) {
                for (int x = 0; x < Tx; x++) {
                    waterMap [x, y] = waterErosionRainfall;
                    sedimentMap [x, y] = 0.0f;
                }
            }

            int waterCounter = 100;
            do {
                waterExists = false;
                for (int y = 0; y < Ty; y++) {
                    for (int x = 0; x < Tx; x++) {
                        moveWater (x, y);
                    }
                }
                waterCounter--;
            } while (waterExists && (waterCounter > 0));

            for (int y = 0; y < Ty; y++) {
                for (int x = 0; x < Tx; x++) {
                    addSediment (x, y);
                }
            }
        }
    }