/* * __ .__ .__ ._____. * _/ |_ _______ __|__| ____ | | |__\_ |__ ______ * \ __\/ _ \ \/ / |/ ___\| | | || __ \ / ___/ * | | ( <_> > <| \ \___| |_| || \_\ \\___ \ * |__| \____/__/\_ \__|\___ >____/__||___ /____ > * \/ \/ \/ \/ * * Copyright (c) 2006-2011 Karsten Schmidt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * http://creativecommons.org/licenses/LGPL/2.1/ * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ package toxi.math.noise; import java.util.Random; import toxi.math.SinCosLUT; /** * PERLIN NOISE taken from the java port I originally did for PApplet, based on * an implementation by the german demo group farbrausch as used in their demo * "Art": http://www.farb-rausch.de/fr010src.zip */ public class PerlinNoise { /** * */ protected static final int PERLIN_YWRAPB = 4; /** * */ protected static final int PERLIN_YWRAP = 1 << PERLIN_YWRAPB; /** * */ protected static final int PERLIN_ZWRAPB = 8; /** * */ protected static final int PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB; /** * */ protected static final int PERLIN_SIZE = 4095; private static final float PERLIN_MIN_AMPLITUDE = 0.001f; /** * */ protected int perlin_octaves = 4; // default to medium smooth /** * */ protected float perlin_amp_falloff = 0.5f; // 50% reduction/octave // [toxi 031112] // new vars needed due to recent change of cos table in PGraphics protected int perlin_TWOPI, /** * */ /** * */ perlin_PI; /** * */ protected float[] perlin_cosTable; /** * */ protected float perlin[]; /** * */ protected Random perlinRandom; /** * */ public PerlinNoise() { noiseSeed(System.nanoTime()); } /** * Computes the Perlin noise function value at point x. * @param x * @return */ public float noise(float x) { // is this legit? it's a dumb way to do it (but repair it later) return noise(x, 0f, 0f); } /** * Computes the Perlin noise function value at the point x, y. * @param x * @param y * @return */ public float noise(float x, float y) { return noise(x, y, 0f); } /** * Computes the Perlin noise function value at x, y, z. * @param x * @param y * @param z * @return */ public float noise(float x, float y, float z) { if (perlin == null) { if (perlinRandom == null) { perlinRandom = new Random(); } perlin = new float[PERLIN_SIZE + 1]; for (int i = 0; i < PERLIN_SIZE + 1; i++) { perlin[i] = perlinRandom.nextFloat(); // (float)Math.random(); } // [toxi 031112] // noise broke due to recent change of cos table in PGraphics // this will take care of it perlin_cosTable = SinCosLUT.getDefaultInstance().getSinLUT(); perlin_TWOPI = perlin_PI = SinCosLUT.getDefaultInstance() .getPeriod(); 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; float xf = (x - xi); float yf = (y - yi); float zf = (z - zi); float rxf, ryf; float r = 0; float ampl = 0.5f; float 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; // break if amp has no more impact if (ampl < PERLIN_MIN_AMPLITUDE) { break; } 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 float noise_fsc(float i) { // using bagel's cosine table instead return 0.5f * (1.0f - perlin_cosTable[(int) ((i + 0.5f) * 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 /** * * @param lod */ public void noiseDetail(int lod) { if (lod > 0) { perlin_octaves = lod; } } /** * * @param lod * @param falloff */ public void noiseDetail(int lod, float falloff) { if (lod > 0) { perlin_octaves = lod; } if (falloff > 0) { perlin_amp_falloff = falloff; } } /** * * @param what */ public final void noiseSeed(long what) { if (perlinRandom == null) { perlinRandom = new Random(); } perlinRandom.setSeed(what); perlin = null; } }