All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pepsoft.worldpainter.operations.Erode Maven / Gradle / Ivy

There is a newer version: 2.23.2
Show newest version
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.pepsoft.worldpainter.operations;

import org.pepsoft.worldpainter.Dimension;
import org.pepsoft.worldpainter.MapDragControl;
import org.pepsoft.worldpainter.RadiusControl;
import org.pepsoft.worldpainter.WorldPainter;

import java.util.Random;

/**
 *
 * @author pepijn
 */
public class Erode extends RadiusOperation {
    public Erode(WorldPainter view, RadiusControl radiusControl, MapDragControl mapDragControl) {
        super("Erode", "Erode the terrain", view, radiusControl, mapDragControl, 100, "operation.erode");
    }

    @Override
    protected void tick(int centreX, int centreY, boolean inverse, boolean first, float dynamicLevel) {
        final Dimension dimension = getDimension();
        if (dimension == null) {
            // Probably some kind of race condition
            return;
        }
        dimension.setEventsInhibited(true);
        try {
            int radius = getEffectiveRadius();
            for (int i = 0; i < ROUNDS; i++) {
                for (int x = centreX - radius; x <= centreX + radius; x++) {
                    for (int y = centreY - radius; y <= centreY + radius; y++) {
                        float strength = getStrength(centreX, centreY, x, y);
                        if ((strength == 1.0f) || (random.nextFloat() < strength)) {
                            for (int dx = -1; dx <= 1; dx++) {
                                for (int dy = -1; dy <= 1; dy++) {
                                    heightBuffer[dx + 1][dy + 1] = dimension.getRawHeightAt(x + dx, y + dy);
                                }
                            }
                            int lowestDx = 0, lowestDy = 0, lowestRawHeight = Integer.MAX_VALUE;
                            boolean reverseX = random.nextBoolean(), reverseY = random.nextBoolean();
                            if (reverseX) {
                                for (int dx = 2; dx >= 0; dx--) {
                                    if (reverseY) {
                                        for (int dy = 2; dy >= 0; dy--) {
                                            if (heightBuffer[dx][dy] < lowestRawHeight) {
                                                lowestRawHeight = heightBuffer[dx][dy];
                                                lowestDx = dx;
                                                lowestDy = dy;
                                            }
                                        }
                                    } else {
                                        for (int dy = 0; dy < 3; dy++) {
                                            if (heightBuffer[dx][dy] < lowestRawHeight) {
                                                lowestRawHeight = heightBuffer[dx][dy];
                                                lowestDx = dx;
                                                lowestDy = dy;
                                            }
                                        }
                                    }
                                }
                            } else {
                                for (int dx = 0; dx < 3; dx++) {
                                    if (reverseY) {
                                        for (int dy = 2; dy >= 0; dy--) {
                                            if (heightBuffer[dx][dy] < lowestRawHeight) {
                                                lowestRawHeight = heightBuffer[dx][dy];
                                                lowestDx = dx;
                                                lowestDy = dy;
                                            }
                                        }
                                    } else {
                                        for (int dy = 0; dy < 3; dy++) {
                                            if (heightBuffer[dx][dy] < lowestRawHeight) {
                                                lowestRawHeight = heightBuffer[dx][dy];
                                                lowestDx = dx;
                                                lowestDy = dy;
                                            }
                                        }
                                    }
                                }
                            }
                            if ((lowestDx != 1) || (lowestDy != 1)) {
                                int difference = heightBuffer[1][1] - heightBuffer[lowestDx][lowestDy];
                                int amount = Math.min((int) (difference / 2 / (((lowestDx != 1) && (lowestDy != 1)) ? ROOT_OF_TWO : 1)), ERODE_AMOUNT);
                                amount = (int) ((amount / 64f) * (amount / 64f) * 64);
                                if (amount > 0) {
                                    dimension.setRawHeightAt(x, y, heightBuffer[1][1] - amount);
                                    dimension.setRawHeightAt(x + lowestDx - 1, y + lowestDy - 1, heightBuffer[lowestDx][lowestDy] + amount);
                                }
                            }
                        }
                    }
                }
            }
        } finally {
            dimension.setEventsInhibited(false);
        }
    }

    private final int[][] heightBuffer = new int[3][3];
    private final Random random = new Random();
    
    private static final int ROUNDS = 1;
    private static final int ERODE_AMOUNT = 64;
    private static final float ROOT_OF_TWO = (float) Math.sqrt(2);
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy