private Vector3 GetGradient(ErosionRegion region)
    {
        Dictionary <Vector3, float> heightDiffs = new Dictionary <Vector3, float>();
        float totalHeightDiff = 0;

        foreach (ErosionRegion adjacentNode in region.AdjacentRegions)
        {
            float heightDiff = adjacentNode.Elevation - position.Elevation;
            heightDiffs.Add(Vector3.Normalize(adjacentNode.Center - position.Center), heightDiff);
            totalHeightDiff += Math.Abs(heightDiff);
        }

        Vector3 gradient = new Vector3(0, 0, 0);

        foreach (Vector3 direction in heightDiffs.Keys)
        {
            gradient += direction * heightDiffs[direction] / totalHeightDiff;
        }

        if (gradient == Vector3.Zero || totalHeightDiff == 0)
        {
            gradient.X = (float)(random.NextDouble() * 2 - 1);
            gradient.Y = (float)(random.NextDouble() * 2 - 1);
            gradient   = Vector3.Normalize(gradient) * Settings.inertia / (1 - Settings.inertia);
            return(gradient);
        }

        return(Vector3.Normalize(gradient));
    }
 private void UpdateValues(ErosionRegion newPosition, Vector3 newDirection, float newVelocity, float newVolume)
 {
     position  = newPosition;
     direction = newDirection;
     velocity  = newVelocity;
     volume    = newVolume;
 }
예제 #3
0
    private void Simulate()
    {
        WaterDroplet.Settings = ReadSettings();
        ErosionRegion.SetErosionRadius(root.Q <SliderInt>("erosionRadius").value);

        int  numDrops = root.Q <SliderInt>("numDrops").value;
        bool useGPU   = root.Q <Toggle>("useGPU").value;

        display.Simulate(numDrops, useGPU);
    }
    private void Erode(float dropSedimentCapacity, float heightDiff)
    {
        float erosit = Math.Min((dropSedimentCapacity - sediment) * Settings.erosion, -heightDiff);

        foreach (KeyValuePair <ErosionRegion, float> kvp in position.ErosionWeights)
        {
            ErosionRegion location = kvp.Key;
            float         weight   = kvp.Value;
            location.Elevation -= erosit * weight;
        }
        sediment += erosit;
    }
    private void SimulationStep()
    {
        Vector3 gradient     = GetGradient(position);
        Vector3 newDirection = Vector3.Normalize(direction * Settings.inertia - gradient * (1f - Settings.inertia));

        ErosionRegion newPosition = FindNextLocation(newDirection);

        float heightDiff = newPosition.Elevation - position.Elevation;

        SimulateHydraulicAction(heightDiff);

        float newVelocity = (float)Math.Sqrt(Math.Max(0, Math.Pow(velocity, 2) - heightDiff * Settings.gravity));
        float newVolume   = volume * (1 - Settings.evaporation);

        UpdateValues(newPosition, newDirection, newVelocity, newVolume);
    }
    private ErosionRegion FindNextLocation(Vector3 newDirection)
    {
        ErosionRegion newPosition = position;
        float         maxCosTheta = float.MinValue;

        foreach (ErosionRegion adjacentRegion in position.AdjacentRegions)
        {
            Vector3 direction = Vector3.Normalize(adjacentRegion.Center - position.Center);
            float   cosTheta  = Vector3.Dot(direction, newDirection);
            if (cosTheta > maxCosTheta)
            {
                maxCosTheta = cosTheta;
                newPosition = adjacentRegion;
            }
        }
        return(newPosition);
    }
    public void SimulateErosionComputeShader(int numIterations)
    {
        GenerateHexagon();

        if (numIterations == 0)
        {
            return;
        }

        int numThreads = System.Math.Max(numIterations / 1024, 1);

        ErosionRegion[] values = erosionRegions.Values.ToArray();
        Dictionary <ErosionRegion, int> regionMap = new Dictionary <ErosionRegion, int>();

        for (int i = 0; i < values.Length; i++)
        {
            regionMap.Add(values[i], i);
        }

        int[] randomRegionIndicies = new int[numIterations];
        Random.InitState(0);
        for (int i = 0; i < numIterations; i++)
        {
            randomRegionIndicies[i] = Random.Range(0, values.Length);
        }
        ComputeBuffer randomBuffer = new ComputeBuffer(numIterations, sizeof(int));

        randomBuffer.SetData(randomRegionIndicies);
        erosion.SetBuffer(0, "random", randomBuffer);

        ComputeBuffer regionBuffer = new ComputeBuffer(values.Length, sizeof(float) * 4 + sizeof(int) * 7);

        ErosionRegionCompute[] computeRegions = new ErosionRegionCompute[values.Length];

        for (int i = 0; i < values.Length; i++)
        {
            ErosionRegion        region = values[i];
            ErosionRegionCompute r      = new ErosionRegionCompute
            {
                position  = new Vector3(region.Center.X, region.Center.Y, region.Center.Z),
                elevation = region.Elevation
            };
            for (int j = 0; j < 6; j++)
            {
                ErosionRegion erosionRegion = region;
                try
                {
                    erosionRegion = region.AdjacentRegions[j];
                }
                catch (System.Exception)
                {
                    // Less than 6 adjacent regions, ignore
                }

                int index = regionMap[erosionRegion];
                switch (j)
                {
                case 0: r.adjacentRegion1 = index; break;

                case 1: r.adjacentRegion2 = index; break;

                case 2: r.adjacentRegion3 = index; break;

                case 3: r.adjacentRegion4 = index; break;

                case 4: r.adjacentRegion5 = index; break;

                case 5: r.adjacentRegion6 = index; break;
                }
            }
            r.numAdjRegions   = region.AdjacentRegions.Count;
            computeRegions[i] = r;
        }

        regionBuffer.SetData(computeRegions);
        erosion.SetBuffer(0, "regions", regionBuffer);

        erosion.SetInt("lifetime", WaterDroplet.Settings.lifetime);
        erosion.SetFloat("inertia", WaterDroplet.Settings.inertia);
        erosion.SetFloat("gravity", WaterDroplet.Settings.gravity);
        erosion.SetFloat("evaporation", WaterDroplet.Settings.evaporation);
        erosion.SetFloat("capacity", WaterDroplet.Settings.capacity);
        erosion.SetFloat("erosion", WaterDroplet.Settings.erosion);
        erosion.SetFloat("deposition", WaterDroplet.Settings.deposition);
        erosion.SetFloat("minErosion", WaterDroplet.Settings.minErosion);

        erosion.Dispatch(0, numThreads, 1, 1);

        regionBuffer.GetData(computeRegions);

        for (int i = 0; i < computeRegions.Length; i++)
        {
            values[i].Elevation = computeRegions[i].elevation;
        }

        regionBuffer.Release();
        randomBuffer.Release();
    }
 public WaterDroplet(ErosionRegion region)
 {
     position  = region;
     random    = new Random((int)(position.Center.X * position.Center.Y));
     direction = Vector3.Normalize(new Vector3((float)(random.NextDouble() * 2 - 1), (float)(random.NextDouble() * 2 - 1), 0));
 }