/* * Copyright (c) 2003-onwards Shaven Puppy Ltd * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of 'Shaven Puppy' nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package worm.generator; import com.shavenpuppy.jglib.interpolators.Interpolator; import com.shavenpuppy.jglib.interpolators.LinearInterpolator; /** * A class for making noise on the fly */ class PerlinNoise { private final Interpolator interpolator; // Used for interpolated noise. // Perlin noise parameters private final float persistence; private final int octaves; private final int scale; private final int seed; public PerlinNoise(int seed, int scale, int octaves, float persistence) { this(seed, scale, octaves, persistence, LinearInterpolator.instance); } public PerlinNoise( int seed, int scale, int octaves, float persistence, Interpolator i) { this.seed = seed; this.scale = scale; this.octaves = octaves; this.persistence = persistence; interpolator = i; } /** * Get the Perlin noise at a particular point. * Creation date: (30/03/2001 01:26:21) */ public float fireNoise(int x, int y) { float total = 0; float amplitude = persistence; int frequency = 1; for (int i = 0; i < octaves; i++) { total += Math.abs(interpolatedNoise(x * frequency, y * frequency)) * amplitude; amplitude /= 2.0f; frequency <<= 1; } return total; } /** * Returns interpolated noise (i.e. noise using fractional coordinates). */ public float interpolatedNoise(int x, int y) { int iX = x / scale; float fX = x % scale / (float) scale; int iY = y / scale; float fY = y % scale / (float) scale; float v1 = noise(iX, iY); float v2 = noise(iX + 1, iY); float v3 = noise(iX, iY + 1); float v4 = noise(iX + 1, iY + 1); float i1 = interpolator.interpolate(v1, v2, fX); float i2 = interpolator.interpolate(v3, v4, fX); return interpolator.interpolate(i1, i2, fY); } /** * Return the raw noise at a particular point */ public float noise(int x, int y) { int n = x + y * (57 + seed); n = n << 13 ^ n; return 1.0f - (n * (n * n * 15731 + 789221) + 1376312589 & 0x7fffffff) / 1073741824.0f; } /** * Get the Perlin noise at a particular point. * Creation date: (30/03/2001 01:26:21) */ public float perlinNoise(int x, int y) { float total = 0; float amplitude = 1.0f; int frequency = 1; for (int i = 0; i < octaves; i++) { total += interpolatedNoise(x * frequency, y * frequency) * amplitude; amplitude *= persistence; frequency <<= 1; } return total; } /** * Returns interpolated noise (i.e. noise using fractional coordinates). */ public float smoothInterpolatedNoise(int x, int y) { int iX = x / scale; float fX = x % scale / (float) scale; int iY = y / scale; float fY = y % scale / (float) scale; float v1 = smoothNoise(iX, iY); float v2 = smoothNoise(iX + 1, iY); float v3 = smoothNoise(iX, iY + 1); float v4 = smoothNoise(iX + 1, iY + 1); float i1 = interpolator.interpolate(v1, v2, fX); float i2 = interpolator.interpolate(v3, v4, fX); return interpolator.interpolate(i1, i2, fY); } public float smoothNoise(int x, int y) { float corners = (noise(x - 1, y - 1) + noise(x + 1, y - 1) + noise(x - 1, y + 1) + noise(x + 1, y + 1)) / 16.0f; float sides = (noise(x - 1, y) + noise(x + 1, y) + noise(x, y - 1) + noise(x, y + 1)) / 8.0f; float center = noise(x, y) / 4.0f; return corners + sides + center; } }