001/*
002Copyright 2006 Jerry Huxtable
003
004Licensed under the Apache License, Version 2.0 (the "License");
005you may not use this file except in compliance with the License.
006You may obtain a copy of the License at
007
008   http://www.apache.org/licenses/LICENSE-2.0
009
010Unless required by applicable law or agreed to in writing, software
011distributed under the License is distributed on an "AS IS" BASIS,
012WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013See the License for the specific language governing permissions and
014limitations under the License.
015*/
016
017package com.jhlabs.math;
018
019import java.util.*;
020
021/**
022 * Perlin Noise functions
023 */
024public class Noise implements Function1D, Function2D, Function3D {
025
026        private static Random randomGenerator = new Random();
027        
028        public float evaluate(float x) {
029                return noise1(x);
030        }
031        
032        public float evaluate(float x, float y) {
033                return noise2(x, y);
034        }
035        
036        public float evaluate(float x, float y, float z) {
037                return noise3(x, y, z);
038        }
039        
040        /**
041         * Compute turbulence using Perlin noise.
042         * @param x the x value
043         * @param y the y value
044         * @param octaves number of octaves of turbulence
045         * @return turbulence value at (x,y)
046         */
047        public static float turbulence2(float x, float y, float octaves) {
048                float t = 0.0f;
049
050                for (float f = 1.0f; f <= octaves; f *= 2)
051                        t += Math.abs(noise2(f * x, f * y)) / f;
052                return t;
053        }
054
055        /**
056         * Compute turbulence using Perlin noise.
057         * @param x the x value
058         * @param y the y value
059         * @param octaves number of octaves of turbulence
060         * @return turbulence value at (x,y)
061         */
062        public static float turbulence3(float x, float y, float z, float octaves) {
063                float t = 0.0f;
064
065                for (float f = 1.0f; f <= octaves; f *= 2)
066                        t += Math.abs(noise3(f * x, f * y, f * z)) / f;
067                return t;
068        }
069
070        private final static int B = 0x100;
071        private final static int BM = 0xff;
072        private final static int N = 0x1000;
073
074        static int[] p = new int[B + B + 2];
075        static float[][] g3 = new float[B + B + 2][3];
076        static float[][] g2 = new float[B + B + 2][2];
077        static float[] g1 = new float[B + B + 2];
078        static boolean start = true;
079
080        private static float sCurve(float t) {
081                return t * t * (3.0f - 2.0f * t);
082        }
083        
084        /**
085         * Compute 1-dimensional Perlin noise.
086         * @param x the x value
087         * @return noise value at x in the range -1..1
088         */
089        public static float noise1(float x) {
090                int bx0, bx1;
091                float rx0, rx1, sx, t, u, v;
092
093                if (start) {
094                        start = false;
095                        init();
096                }
097
098                t = x + N;
099                bx0 = ((int)t) & BM;
100                bx1 = (bx0+1) & BM;
101                rx0 = t - (int)t;
102                rx1 = rx0 - 1.0f;
103
104                sx = sCurve(rx0);
105
106                u = rx0 * g1[p[bx0]];
107                v = rx1 * g1[p[bx1]];
108                return 2.3f*lerp(sx, u, v);
109        }
110
111        /**
112         * Compute 2-dimensional Perlin noise.
113         * @param x the x coordinate
114         * @param y the y coordinate
115         * @return noise value at (x,y)
116         */
117        public static float noise2(float x, float y) {
118                int bx0, bx1, by0, by1, b00, b10, b01, b11;
119                float rx0, rx1, ry0, ry1, q[], sx, sy, a, b, t, u, v;
120                int i, j;
121
122                if (start) {
123                        start = false;
124                        init();
125                }
126
127                t = x + N;
128                bx0 = ((int)t) & BM;
129                bx1 = (bx0+1) & BM;
130                rx0 = t - (int)t;
131                rx1 = rx0 - 1.0f;
132        
133                t = y + N;
134                by0 = ((int)t) & BM;
135                by1 = (by0+1) & BM;
136                ry0 = t - (int)t;
137                ry1 = ry0 - 1.0f;
138        
139                i = p[bx0];
140                j = p[bx1];
141
142                b00 = p[i + by0];
143                b10 = p[j + by0];
144                b01 = p[i + by1];
145                b11 = p[j + by1];
146
147                sx = sCurve(rx0);
148                sy = sCurve(ry0);
149
150                q = g2[b00]; u = rx0 * q[0] + ry0 * q[1];
151                q = g2[b10]; v = rx1 * q[0] + ry0 * q[1];
152                a = lerp(sx, u, v);
153
154                q = g2[b01]; u = rx0 * q[0] + ry1 * q[1];
155                q = g2[b11]; v = rx1 * q[0] + ry1 * q[1];
156                b = lerp(sx, u, v);
157
158                return 1.5f*lerp(sy, a, b);
159        }
160
161        /**
162         * Compute 3-dimensional Perlin noise.
163         * @param x the x coordinate
164         * @param y the y coordinate
165         * @param y the y coordinate
166         * @return noise value at (x,y,z)
167         */
168        public static float noise3(float x, float y, float z) {
169                int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
170                float rx0, rx1, ry0, ry1, rz0, rz1, q[], sy, sz, a, b, c, d, t, u, v;
171                int i, j;
172
173                if (start) {
174                        start = false;
175                        init();
176                }
177
178                t = x + N;
179                bx0 = ((int)t) & BM;
180                bx1 = (bx0+1) & BM;
181                rx0 = t - (int)t;
182                rx1 = rx0 - 1.0f;
183
184                t = y + N;
185                by0 = ((int)t) & BM;
186                by1 = (by0+1) & BM;
187                ry0 = t - (int)t;
188                ry1 = ry0 - 1.0f;
189        
190                t = z + N;
191                bz0 = ((int)t) & BM;
192                bz1 = (bz0+1) & BM;
193                rz0 = t - (int)t;
194                rz1 = rz0 - 1.0f;
195        
196                i = p[bx0];
197                j = p[bx1];
198
199                b00 = p[i + by0];
200                b10 = p[j + by0];
201                b01 = p[i + by1];
202                b11 = p[j + by1];
203
204                t  = sCurve(rx0);
205                sy = sCurve(ry0);
206                sz = sCurve(rz0);
207
208                q = g3[b00 + bz0]; u = rx0 * q[0] + ry0 * q[1] + rz0 * q[2];
209                q = g3[b10 + bz0]; v = rx1 * q[0] + ry0 * q[1] + rz0 * q[2];
210                a = lerp(t, u, v);
211
212                q = g3[b01 + bz0]; u = rx0 * q[0] + ry1 * q[1] + rz0 * q[2];
213                q = g3[b11 + bz0]; v = rx1 * q[0] + ry1 * q[1] + rz0 * q[2];
214                b = lerp(t, u, v);
215
216                c = lerp(sy, a, b);
217
218                q = g3[b00 + bz1]; u = rx0 * q[0] + ry0 * q[1] + rz1 * q[2];
219                q = g3[b10 + bz1]; v = rx1 * q[0] + ry0 * q[1] + rz1 * q[2];
220                a = lerp(t, u, v);
221
222                q = g3[b01 + bz1]; u = rx0 * q[0] + ry1 * q[1] + rz1 * q[2];
223                q = g3[b11 + bz1]; v = rx1 * q[0] + ry1 * q[1] + rz1 * q[2];
224                b = lerp(t, u, v);
225
226                d = lerp(sy, a, b);
227
228                return 1.5f*lerp(sz, c, d);
229        }
230
231        public static float lerp(float t, float a, float b) {
232                return a + t * (b - a);
233        }
234
235        private static void normalize2(float v[]) {
236                float s = (float)Math.sqrt(v[0] * v[0] + v[1] * v[1]);
237                v[0] = v[0] / s;
238                v[1] = v[1] / s;
239        }
240
241        static void normalize3(float v[]) {
242                float s = (float)Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
243                v[0] = v[0] / s;
244                v[1] = v[1] / s;
245                v[2] = v[2] / s;
246        }
247
248        private static int random() {
249                return randomGenerator.nextInt() & 0x7fffffff;
250        }
251        
252        private static void init() {
253                int i, j, k;
254
255                for (i = 0; i < B; i++) {
256                        p[i] = i;
257
258                        g1[i] = (float)((random() % (B + B)) - B) / B;
259
260                        for (j = 0; j < 2; j++)
261                                g2[i][j] = (float)((random() % (B + B)) - B) / B;
262                        normalize2(g2[i]);
263
264                        for (j = 0; j < 3; j++)
265                                g3[i][j] = (float)((random() % (B + B)) - B) / B;
266                        normalize3(g3[i]);
267                }
268
269                for (i = B-1; i >= 0; i--) {
270                        k = p[i];
271                        p[i] = p[j = random() % B];
272                        p[j] = k;
273                }
274
275                for (i = 0; i < B + 2; i++) {
276                        p[B + i] = p[i];
277                        g1[B + i] = g1[i];
278                        for (j = 0; j < 2; j++)
279                                g2[B + i][j] = g2[i][j];
280                        for (j = 0; j < 3; j++)
281                                g3[B + i][j] = g3[i][j];
282                }
283        }
284
285        /**
286         * Returns the minimum and maximum of a number of random values
287         * of the given function. This is useful for making some stab at
288         * normalising the function.
289         */
290        public static float[] findRange(Function1D f, float[] minmax) {
291                if (minmax == null)
292                        minmax = new float[2];
293                float min = 0, max = 0;
294                // Some random numbers here...
295                for (float x = -100; x < 100; x += 1.27139) {
296                        float n = f.evaluate(x);
297                        min = Math.min(min, n);
298                        max = Math.max(max, n);
299                }
300                minmax[0] = min;
301                minmax[1] = max;
302                return minmax;
303        }
304        
305        /**
306         * Returns the minimum and maximum of a number of random values
307         * of the given function. This is useful for making some stab at
308         * normalising the function.
309         */
310        public static float[] findRange(Function2D f, float[] minmax) {
311                if (minmax == null)
312                        minmax = new float[2];
313                float min = 0, max = 0;
314                // Some random numbers here...
315                for (float y = -100; y < 100; y += 10.35173) {
316                        for (float x = -100; x < 100; x += 10.77139) {
317                                float n = f.evaluate(x, y);
318                                min = Math.min(min, n);
319                                max = Math.max(max, n);
320                        }
321                }
322                minmax[0] = min;
323                minmax[1] = max;
324                return minmax;
325        }
326        
327}