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

org.pepsoft.util.PerlinNoise Maven / Gradle / Ivy

The newest version!
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.pepsoft.util;

import com.kenperlin.ImprovedNoise;
import org.pepsoft.util.mdc.MDCCapturingRuntimeException;
import org.pepsoft.util.mdc.MDCWrappingRuntimeException;

import java.io.*;

/**
 *
 * @author pepijn
 */
@SuppressWarnings("ConstantConditions") // Guaranteed by programmer
public final class PerlinNoise implements Serializable, Cloneable {
    public PerlinNoise(long seed) {
        this.seed = seed;
        improvedNoise = new ImprovedNoise(seed);
    }

    public long getSeed() {
        return seed;
    }

    public void setSeed(long seed) {
        if (seed != this.seed) {
            this.seed = seed;
            improvedNoise = new ImprovedNoise(seed);
        }
    }

    /**
     * Generates one dimensional noise. The input value is normalised to be
     * between 0 (inclusive) and 256 (exclusive), so the input should be
     * constrained to be between those values for best results (otherwise the
     * pattern will start to repeat).
     *
     * @param x The point for which to determine the noise value.
     * @return A noise value between -0.5 and 0.5.
     */
    public float getPerlinNoise(double x) {
        return (float) (improvedNoise.noise(x, 0, 0));
    }

    /**
     * Generates two dimensional noise. The input values are normalised to be
     * between 0 (inclusive) and 256 (exclusive), so the input should be
     * constrained to be between those values for best results (otherwise the
     * pattern will start to repeat).
     *
     * @param x The X coordinate of the point for which to determine the noise
     *     value.
     * @param y The Y coordinate of the point for which to determine the noise
     *     value.
     * @return A noise value between -0.5 and 0.5.
     */
    public float getPerlinNoise(double x, double y) {
        return (float) (improvedNoise.noise(x, y, 0) * FACTOR_2D);
    }

    /**
     * Generates three dimensional noise. The input values are normalised to be
     * between 0 (inclusive) and 256 (exclusive), so the input should be
     * constrained to be between those values for best results (otherwise the
     * pattern will start to repeat).
     *
     * @param x The X coordinate of the point for which to determine the noise
     *     value.
     * @param y The Y coordinate of the point for which to determine the noise
     *     value.
     * @param z The Z coordinate of the point for which to determine the noise
     *     value.
     * @return A noise value between -0.5 and 0.5.
     */
    public float getPerlinNoise(double x, double y, double z) {
        return (float) (improvedNoise.noise(x, y, z) * FACTOR_3D);
    }
    
    @Override
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            throw new MDCWrappingRuntimeException(e);
        }
    }

    public static float getLevelForPromillage(int promillage) {
        return getLevelForPromillage((float) promillage);
    }
    
    public static float getLevelForPromillage(float promillage) {
        if ((promillage < 0f) || (promillage > 1000f)) {
            throw new IllegalArgumentException();
        }
        promillage *= 10;
        if (promillage == (int) promillage) {
            return LEVEL_FOR_PROMILLAGE[(int) promillage];
        } else {
            float level1 = LEVEL_FOR_PROMILLAGE[(int) promillage];
            return level1 + (LEVEL_FOR_PROMILLAGE[((int) promillage) + 1] - level1) * (promillage - (int) promillage);
        }
    }
    
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();

        // Legacy maps
        if (improvedNoise == null) {
            improvedNoise = new ImprovedNoise(seed);
        }
    }

    private long seed;
    private ImprovedNoise improvedNoise;

    private static final double FACTOR_2D = 0.5;
    private static final double FACTOR_3D = 0.4824607142760952;
    private static final long serialVersionUID = 2011040701L;

    private static final float[] LEVEL_FOR_PROMILLAGE = new float[10001];
    
    static {
        // Initialise the array from a file, because it is too large to
        // initialise with a static initialiser. It generates a "code too large"
        // error.
        try {
            try (BufferedReader in = new BufferedReader(new InputStreamReader(PerlinNoise.class.getResourceAsStream("noiselevels.txt")))) {
                int index = 0;
                String line;
                while ((line = in.readLine()) != null) {
                    for (String token : line.split("[ ,]+")) {
                        LEVEL_FOR_PROMILLAGE[index++] = Float.parseFloat(token);
                    }
                }
            }
        } catch (IOException e) {
            throw new MDCCapturingRuntimeException("I/O error while trying to load noise levels from classpath", e);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy