// PERLIN NOISE
//Sourced directly from processing.core implementation (PApplet.java):
//https://code.google.com/p/processing/source/browse/trunk/processing/core/src/processing/core/PApplet.java
package com.pixelmaid.dresscode.drawing.math;
import java.util.Random;
public class PerlinNoise {
//////////////////////////////////////////////////////////////
static final int PERLIN_YWRAPB = 4;
static final int PERLIN_YWRAP = 1<<PERLIN_YWRAPB;
static final int PERLIN_ZWRAPB = 8;
static final int PERLIN_ZWRAP = 1<<PERLIN_ZWRAPB;
static final int PERLIN_SIZE = 4095;
int perlin_octaves = 4; // default to medium smooth
double perlin_amp_falloff = 0.5f; // 50% reduction/octave
// new vars needed due to recent change of cos table in PGraphics
int perlin_TWOPI, perlin_PI;
double[] perlin_cosTable;
double[] perlin;
static final double DEG_TO_RAD = Math.PI/180.0;
static final double RAD_TO_DEG = 180.0/Math.PI;
static final protected double sinLUT[];
static final protected double cosLUT[];
static final protected double SINCOS_PRECISION = 0.5f;
static final protected int SINCOS_LENGTH = (int) (360f / SINCOS_PRECISION);
static {
sinLUT = new double[SINCOS_LENGTH];
cosLUT = new double[SINCOS_LENGTH];
for (int i = 0; i < SINCOS_LENGTH; i++) {
sinLUT[i] = (double) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION);
cosLUT[i] = (double) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION);
}
}
Random perlinRandom;
/**
*/
public double noise(double x) {
// is this legit? it's a dumb way to do it (but repair it later)
return noise(x, 0f, 0f);
}
/**
*/
public double noise(double x, double y) {
return noise(x, y, 0f);
}
/**
* ( begin auto-generated from noise.xml )
*
* Returns the Perlin noise value at specified coordinates. Perlin noise is
* a random sequence generator producing a more natural ordered, harmonic
* succession of numbers compared to the standard <b>random()</b> function.
* It was invented by Ken Perlin in the 1980s and been used since in
* graphical applications to produce procedural textures, natural motion,
* shapes, terrains etc.<br /><br /> The main difference to the
* <b>random()</b> function is that Perlin noise is defined in an infinite
* n-dimensional space where each pair of coordinates corresponds to a
* fixed semi-random value (fixed only for the lifespan of the program).
* The resulting value will always be between 0.0 and 1.0. Processing can
* compute 1D, 2D and 3D noise, depending on the number of coordinates
* given. The noise value can be animated by moving through the noise space
* as demonstrated in the example above. The 2nd and 3rd dimension can also
* be interpreted as time.<br /><br />The actual noise is structured
* similar to an audio signal, in respect to the function's use of
* frequencies. Similar to the concept of harmonics in physics, perlin
* noise is computed over several octaves which are added together for the
* final result. <br /><br />Another way to adjust the character of the
* resulting sequence is the scale of the input coordinates. As the
* function works within an infinite space the value of the coordinates
* doesn't matter as such, only the distance between successive coordinates
* does (eg. when using <b>noise()</b> within a loop). As a general rule
* the smaller the difference between coordinates, the smoother the
* resulting noise sequence will be. Steps of 0.005-0.03 work best for most
* applications, but this will differ depending on use.
*
* ( end auto-generated )
*
* @webref math:random
* @param x x-coordinate in noise space
* @param y y-coordinate in noise space
* @param z z-coordinate in noise space
* @see PApplet#noiseSeed(long)
* @see PApplet#noiseDetail(int, double)
* @see PApplet#random(double,double)
*/
public double noise(double x, double y, double z) {
if (perlin == null) {
if (perlinRandom == null) {
perlinRandom = new Random();
}
perlin = new double[PERLIN_SIZE + 1];
for (int i = 0; i < PERLIN_SIZE + 1; i++) {
perlin[i] = perlinRandom.nextDouble(); //(double)Math.random();
}
// [toxi 031112]
// noise broke due to recent change of cos table in PGraphics
// this will take care of it
perlin_cosTable = cosLUT;
perlin_TWOPI = perlin_PI = SINCOS_LENGTH;
perlin_PI >>= 1;
}
if (x<0) x=-x;
if (y<0) y=-y;
if (z<0) z=-z;
int xi=(int)x, yi=(int)y, zi=(int)z;
double xf = x - xi;
double yf = y - yi;
double zf = z - zi;
double rxf, ryf;
double r=0;
double ampl=0.5f;
double n1,n2,n3;
for (int i=0; i<perlin_octaves; i++) {
int of=xi+(yi<<PERLIN_YWRAPB)+(zi<<PERLIN_ZWRAPB);
rxf=noise_fsc(xf);
ryf=noise_fsc(yf);
n1 = perlin[of&PERLIN_SIZE];
n1 += rxf*(perlin[(of+1)&PERLIN_SIZE]-n1);
n2 = perlin[(of+PERLIN_YWRAP)&PERLIN_SIZE];
n2 += rxf*(perlin[(of+PERLIN_YWRAP+1)&PERLIN_SIZE]-n2);
n1 += ryf*(n2-n1);
of += PERLIN_ZWRAP;
n2 = perlin[of&PERLIN_SIZE];
n2 += rxf*(perlin[(of+1)&PERLIN_SIZE]-n2);
n3 = perlin[(of+PERLIN_YWRAP)&PERLIN_SIZE];
n3 += rxf*(perlin[(of+PERLIN_YWRAP+1)&PERLIN_SIZE]-n3);
n2 += ryf*(n3-n2);
n1 += noise_fsc(zf)*(n2-n1);
r += n1*ampl;
ampl *= perlin_amp_falloff;
xi<<=1; xf*=2;
yi<<=1; yf*=2;
zi<<=1; zf*=2;
if (xf>=1.0f) { xi++; xf--; }
if (yf>=1.0f) { yi++; yf--; }
if (zf>=1.0f) { zi++; zf--; }
}
return r;
}
// [toxi 031112]
// now adjusts to the size of the cosLUT used via
// the new variables, defined above
private double noise_fsc(double i) {
// using bagel's cosine table instead
return 0.5f*(1.0f-perlin_cosTable[(int)(i*perlin_PI)%perlin_TWOPI]);
}
// [toxi 040903]
// make perlin noise quality user controlled to allow
// for different levels of detail. lower values will produce
// smoother results as higher octaves are surpressed
/**
* ( begin auto-generated from noiseDetail.xml )
*
* Adjusts the character and level of detail produced by the Perlin noise
* function. Similar to harmonics in physics, noise is computed over
* several octaves. Lower octaves contribute more to the output signal and
* as such define the overal intensity of the noise, whereas higher octaves
* create finer grained details in the noise sequence. By default, noise is
* computed over 4 octaves with each octave contributing exactly half than
* its predecessor, starting at 50% strength for the 1st octave. This
* falloff amount can be changed by adding an additional function
* parameter. Eg. a falloff factor of 0.75 means each octave will now have
* 75% impact (25% less) of the previous lower octave. Any value between
* 0.0 and 1.0 is valid, however note that values greater than 0.5 might
* result in greater than 1.0 values returned by <b>noise()</b>.<br /><br
* />By changing these parameters, the signal created by the <b>noise()</b>
* function can be adapted to fit very specific needs and characteristics.
*
* ( end auto-generated )
* @webref math:random
* @param lod number of octaves to be used by the noise
* @param falloff falloff factor for each octave
* @see PApplet#noise(double, double, double)
*/
public void noiseDetail(int lod) {
if (lod>0) perlin_octaves=lod;
}
/**
* @param falloff falloff factor for each octave
*/
public void noiseDetail(int lod, double falloff) {
if (lod>0) perlin_octaves=lod;
if (falloff>0) perlin_amp_falloff=falloff;
}
/**
* ( begin auto-generated from noiseSeed.xml )
*
* Sets the seed value for <b>noise()</b>. By default, <b>noise()</b>
* produces different results each time the program is run. Set the
* <b>value</b> parameter to a constant to return the same pseudo-random
* numbers each time the software is run.
*
* ( end auto-generated )
* @webref math:random
* @param seed seed value
* @see PApplet#noise(double, double, double)
* @see PApplet#noiseDetail(int, double)
* @see PApplet#random(double,double)
* @see PApplet#randomSeed(long)
*/
public void noiseSeed(long seed) {
if (perlinRandom == null) perlinRandom = new Random();
perlinRandom.setSeed(seed);
// force table reset after changing the random number seed [0122]
perlin = null;
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
}