/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.pepsoft.worldpainter.heightMaps;
import org.pepsoft.util.IconUtils;
import org.pepsoft.util.MathUtils;
import org.pepsoft.util.PerlinNoise;
import org.pepsoft.worldpainter.NoiseSettings;
import javax.swing.*;
import java.awt.*;
import java.util.Random;
import static org.pepsoft.worldpainter.Constants.LARGE_BLOBS;
/**
*
* @author pepijn
*/
public final class NoiseHeightMap extends AbstractHeightMap {
public NoiseHeightMap(NoiseSettings noiseSettings) {
this(null, noiseSettings.getRange() * 2, noiseSettings.getScale() / 5, noiseSettings.getRoughness() + 1, new Random().nextLong());
}
public NoiseHeightMap(NoiseSettings noiseSettings, long seedOffset) {
this(null, noiseSettings.getRange() * 2, noiseSettings.getScale() / 5, noiseSettings.getRoughness() + 1, seedOffset);
}
public NoiseHeightMap(String name, NoiseSettings noiseSettings) {
this(name, noiseSettings.getRange() * 2, noiseSettings.getScale() / 5, noiseSettings.getRoughness() + 1, new Random().nextLong());
}
public NoiseHeightMap(String name, NoiseSettings noiseSettings, long seedOffset) {
this(name, noiseSettings.getRange() * 2, noiseSettings.getScale() / 5, noiseSettings.getRoughness() + 1, seedOffset);
}
public NoiseHeightMap(float height, double scale, int octaves) {
this(null, height, scale, octaves, new Random().nextLong());
}
public NoiseHeightMap(float height, double scale, int octaves, long seedOffset) {
this(null, height, scale, octaves, seedOffset);
}
public NoiseHeightMap(String name, float height, double scale, int octaves) {
this(name, height, scale, octaves, new Random().nextLong());
}
public NoiseHeightMap(String name, float height, double scale, int octaves, long seedOffset) {
setName(name);
if (octaves > 10) {
throw new IllegalArgumentException("More than 10 octaves not supported");
}
this.height = height;
this.scale = scale;
this.octaves = octaves;
this.seedOffset = seedOffset;
perlinNoise = new PerlinNoise(seedOffset);
}
public float getHeight() {
return height;
}
public double getScale() {
return scale;
}
public int getOctaves() {
return octaves;
}
public long getSeedOffset() {
return seedOffset;
}
public void setOctaves(int octaves) {
this.octaves = octaves;
}
public void setHeight(float height) {
this.height = height;
}
public void setScale(double scale) {
this.scale = scale;
}
public void setSeedOffset(long seedOffset) {
if (seedOffset != this.seedOffset) {
this.seedOffset = seedOffset;
perlinNoise.setSeed(seed + seedOffset);
}
}
public void setNoiseSettings(NoiseSettings noiseSettings) {
height = noiseSettings.getRange() * 2;
scale = noiseSettings.getScale() / 5;
octaves = noiseSettings.getRoughness() + 1;
}
// HeightMap
@Override
public void setSeed(long seed) {
if (seed != this.seed) {
super.setSeed(seed);
perlinNoise.setSeed(seed + seedOffset);
}
}
@Override
public float getHeight(int x, int y) {
return getValue((double) x, (double) y);
}
@Override
public float getHeight(float x, float y) {
return getValue(x, y);
}
@Override
public int getColour(int x, int y) {
int value = MathUtils.clamp(0, (int) (getHeight(x, y) + 0.5f), 255);
return (value << 16) | (value << 8) | value;
}
@Override
public Rectangle getExtent() {
return null;
}
public float getValue(double x) {
if (octaves == 1) {
return (perlinNoise.getPerlinNoise(x / LARGE_BLOBS / scale) + 0.5f) * height;
} else {
float noise = 0;
for (int i = 0; i < octaves; i++) {
noise += perlinNoise.getPerlinNoise(x / LARGE_BLOBS / scale * FACTORS[i]);
}
noise /= octaves;
return (noise + 0.5f) * height;
}
}
public float getValue(double x, double y) {
if (octaves == 1) {
return (perlinNoise.getPerlinNoise(x / LARGE_BLOBS / scale, y / LARGE_BLOBS / scale) + 0.5f) * height;
} else {
float noise = 0;
for (int i = 0; i < octaves; i++) {
noise += perlinNoise.getPerlinNoise(x / LARGE_BLOBS / scale * FACTORS[i], y / LARGE_BLOBS / scale * FACTORS[i]);
}
noise /= octaves;
return (noise + 0.5f) * height;
}
}
public float getValue(double x, double y, double z) {
if (octaves == 1) {
return (perlinNoise.getPerlinNoise(x / LARGE_BLOBS / scale, y / LARGE_BLOBS / scale, z / LARGE_BLOBS / scale) + 0.5f) * height;
} else {
float noise = 0;
for (int i = 0; i < octaves; i++) {
noise += perlinNoise.getPerlinNoise(x / LARGE_BLOBS / scale * FACTORS[i], y / LARGE_BLOBS / scale * FACTORS[i], z / LARGE_BLOBS / scale * FACTORS[i]);
}
noise /= octaves;
return (noise + 0.5f) * height;
}
}
@Override
public NoiseHeightMap clone() {
NoiseHeightMap clone = new NoiseHeightMap(name, height, scale, octaves, seedOffset);
clone.setSeed(getSeed());
return clone;
}
@Override
public Icon getIcon() {
return ICON_NOISE_HEIGHTMAP;
}
@Override
public float[] getRange() {
return new float[] {0.0f, height};
}
private PerlinNoise perlinNoise;
private float height;
private double scale;
private int octaves;
private long seedOffset;
private static final int[] FACTORS = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512};
private static final long serialVersionUID = 1L;
private static final Icon ICON_NOISE_HEIGHTMAP = IconUtils.loadScaledIcon("org/pepsoft/worldpainter/icons/noise.png");
}