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