View difference between Paste ID: KsfZ99Xa and k4LSNDqv
SHOW: | | - or go back to the newest paste.
1
import java.util.Random;
2
3
public class PerlinNoise {
4
5
	final static int TABLE_SIZE = 64;
6
7
	private final static double WEIGHT(double T) {
8
		return ((2.0 * Math.abs(T) - 3.0) * (T) * (T) + 1.0);
9
	}
10
11
	private final int CLAMP(int val, int min, int max) {
12
		return ((val < min ? min : val) > max ? max : val);
13
	}
14
15
	private final double CLAMP(double val, double min, double max) {
16
		return ((val < min ? min : val) > max ? max : val);
17
	}
18
19
	final int SCALE_WIDTH = 128;
20
	final double MIN_SIZE = 0.1;
21
	final double MAX_SIZE = 16.0;
22
23
	private boolean tilable = false;
24
	private boolean turbulent = false;
25
	private long seed = 0;
26
	private int detail = 1;
27
	private double size = 8.0;
28
29
	private static int clip;
30
	private static double offset, factor;
31
	static int[] perm_tab = new int[TABLE_SIZE];
32
	static Vector2d[] grad_tab = new Vector2d[TABLE_SIZE];
33
34
	public PerlinNoise(long seed) {
35
		this.seed = seed;
36
		init();
37
	}
38
39
	public double noise2(double x, double y) {
40
		x /= 100;
41
		y /= 100;
42
		return noise(x, y);
43
	}
44
45
	void init() {
46
		int i, j, k, t;
47
		double m;
48
		Random r;
49
50
		r = new Random(seed);
51
52
		/* Force sane parameters */
53
		detail = CLAMP(detail, 0, 15);
54
		size = CLAMP(size, MIN_SIZE, MAX_SIZE);
55
56
		/* Set scaling factors */
57
		if (tilable) {
58
			this.size = Math.ceil(size);
59
			clip = (int) size;
60
		}
61
62
		/* Set totally empiric normalization values */
63
		if (turbulent) {
64
			offset = 0.0;
65
			factor = 1.0;
66
		} else {
67
			offset = 0.94;
68
			factor = 0.526;
69
		}
70
71
		/* Initialize the permutation table */
72
		for (i = 0; i < TABLE_SIZE; i++)
73
			perm_tab[i] = i;
74
75
		for (i = 0; i < (TABLE_SIZE >> 1); i++) {
76
			j = r.nextInt(TABLE_SIZE);
77
			k = r.nextInt(TABLE_SIZE);
78
			t = perm_tab[j];
79
			perm_tab[j] = perm_tab[k];
80
			perm_tab[k] = t;
81
		}
82
83
		/* Initialize the gradient table */
84
		for (i = 0; i < TABLE_SIZE; i++) {
85
			grad_tab[i] = new Vector2d();
86
			do {
87
				grad_tab[i].setX((r.nextDouble() * 2) - 1);
88
				grad_tab[i].setY((r.nextDouble() * 2) - 1);
89
				m = grad_tab[i].getX() * grad_tab[i].getX() + grad_tab[i].getY() * grad_tab[i].getY();
90
			} while (m == 0.0 || m > 1.0);
91
92
			m = 1.0 / Math.sqrt(m);
93
			grad_tab[i].setX(grad_tab[i].getX() * m);
94
			grad_tab[i].setY(grad_tab[i].getY() * m);
95
		}
96
97
		r = null;
98
	}
99
100
	double plain_noise(double x, double y, int s) {
101
		Vector2d v = new Vector2d();
102
		int a, b, i, j, n;
103
		double sum;
104
105
		sum = 0.0;
106
		x *= s;
107
		y *= s;
108
		a = (int) Math.floor(x);
109
		b = (int) Math.floor(y);
110
111
		for (i = 0; i < 2; i++)
112
			for (j = 0; j < 2; j++) {
113
				if (tilable)
114-
					// n = perm_tab[(((a + i) % (xclip * s)) + perm_tab[((b + j)
114+
115-
					// % (yclip * s)) % TABLE_SIZE]) % TABLE_SIZE];
115+
116
					n = perm_tab[betterMod(a + i + perm_tab[betterMod(b + j, TABLE_SIZE)], TABLE_SIZE)];
117
				v.setX(x - a - i);
118
				v.setY(y - b - j);
119
				sum += WEIGHT(v.getX()) * WEIGHT(v.getY()) * (grad_tab[n].getX() * v.getX() + grad_tab[n].getY() * v.getY());
120
			}
121
122
		return sum / s;
123
	}
124
        
125
        /** Modified modulus, so that negative numbers wrap correctly! */
126
	private int betterMod(int val, int range) {
127
		return (val % range + range) % range;
128
	}
129
130
	double noise(double x, double y) {
131
		int i;
132
		int s;
133
		double sum;
134
135
		s = 1;
136
		sum = 0.0;
137
		x *= size;
138
		y *= size;
139
140
		for (i = 0; i <= detail; i++) {
141
			if (turbulent)
142
				sum += Math.abs(plain_noise(x, y, s));
143
			else
144
				sum += plain_noise(x, y, s);
145
			s <<= 1;
146
		}
147
148
		return (sum + offset) * factor;
149
	}
150
}