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}