001    /*
002    *
003    
004    Licensed under the Apache License, Version 2.0 (the "License");
005    you may not use this file except in compliance with the License.
006    You may obtain a copy of the License at
007    
008       http://www.apache.org/licenses/LICENSE-2.0
009    
010    Unless required by applicable law or agreed to in writing, software
011    distributed under the License is distributed on an "AS IS" BASIS,
012    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013    See the License for the specific language governing permissions and
014    limitations under the License.
015    */
016    
017    package railo.runtime.img.math;
018    
019    import java.util.Random;
020    
021    /**
022     * Perlin Noise functions
023     */
024    public 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    }