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}