/* Copyright (C) 2011 Garrett Fleenor 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 3.0 of the License, or (at your option) any later version. 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 (COPYING.txt) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA This is a port of libnoise ( http://libnoise.sourceforge.net/index.html ). Original implementation by Jason Bevins */ package com.bioxx.libnoise; public class Noise { public static final int X_NOISE_GEN = 1619; public static final int Y_NOISE_GEN = 31337; public static final int Z_NOISE_GEN = 6971; public static final int SEED_NOISE_GEN = 1013; public static final int SHIFT_NOISE_GEN = 8; /** * Generates a gradient-coherent-noise value from the coordinates of a * three-dimensional input value. * * @param x The @a x coordinate of the input value. * @param y The @a y coordinate of the input value. * @param z The @a z coordinate of the input value. * @param seed The random number seed. * @param noiseQuality The quality of the coherent-noise. * @return The generated gradient-coherent-noise value. * * The return value ranges from -1.0 to +1.0. * * For an explanation of the difference between <i>gradient</i> * noise and <i>value</i> noise, see the comments for the * GradientNoise3D() function. */ public static double GradientCoherentNoise3D(double x, double y, double z, long seed, NoiseQuality quality) { // Create a unit-length cube aligned along an integer boundary. This cube // surrounds the input point. int x0 = ((x > 0.0) ? (int) x : (int) x - 1); int x1 = x0 + 1; int y0 = ((y > 0.0) ? (int) y : (int) y - 1); int y1 = y0 + 1; int z0 = ((z > 0.0) ? (int) z : (int) z - 1); int z1 = z0 + 1; // Map the difference between the coordinates of the input value and the // coordinates of the cube's outer-lower-left vertex onto an S-curve. double xs, ys, zs; if (quality == NoiseQuality.FAST) { xs = (x - (double)x0); ys = (y - (double)y0); zs = (z - (double)z0); } else if (quality == NoiseQuality.STANDARD) { xs = Utils.SCurve3(x - (double)x0); ys = Utils.SCurve3(y - (double)y0); zs = Utils.SCurve3(z - (double)z0); } else { xs = Utils.SCurve5(x - (double)x0); ys = Utils.SCurve5(y - (double)y0); zs = Utils.SCurve5(z - (double)z0); } // Now calculate the noise values at each vertex of the cube. To generate // the coherent-noise value at the input point, interpolate these eight // noise values using the S-curve value as the interpolant (trilinear // interpolation.) double n0, n1, ix0, ix1, iy0, iy1; n0 = GradientNoise3D(x, y, z, x0, y0, z0, seed); n1 = GradientNoise3D(x, y, z, x1, y0, z0, seed); ix0 = Utils.LinearInterp(n0, n1, xs); n0 = GradientNoise3D(x, y, z, x0, y1, z0, seed); n1 = GradientNoise3D(x, y, z, x1, y1, z0, seed); ix1 = Utils.LinearInterp(n0, n1, xs); iy0 = Utils.LinearInterp(ix0, ix1, ys); n0 = GradientNoise3D(x, y, z, x0, y0, z1, seed); n1 = GradientNoise3D(x, y, z, x1, y0, z1, seed); ix0 = Utils.LinearInterp(n0, n1, xs); n0 = GradientNoise3D(x, y, z, x0, y1, z1, seed); n1 = GradientNoise3D(x, y, z, x1, y1, z1, seed); ix1 = Utils.LinearInterp(n0, n1, xs); iy1 = Utils.LinearInterp(ix0, ix1, ys); return Utils.LinearInterp(iy0, iy1, zs); } /** * Generates a gradient-noise value from the coordinates of a * three-dimensional input value and the integer coordinates of a nearby * three-dimensional value. * * @param fx The floating-point @a x coordinate of the input value. * @param fy The floating-point @a y coordinate of the input value. * @param fz The floating-point @a z coordinate of the input value. * @param ix The integer @a x coordinate of a nearby value. * @param iy The integer @a y coordinate of a nearby value. * @param iz The integer @a z coordinate of a nearby value. * @param seed The random number seed. * @return The generated gradient-noise value. * * The difference between fx and ix must be less than or equal to * one. The difference between @a fy and @a iy must be less than or * equal to one. The difference between @a fz and @a iz must be less * than or equal to one. * * A <i>gradient</i>-noise function generates better-quality noise * than a <i>value</i>-noise function. Most noise modules use * gradient noise for this reason, although it takes much longer to * calculate. * * The return value ranges from -1.0 to +1.0. * * This function generates a gradient-noise value by performing the * following steps: - It first calculates a random normalized vector * based on the nearby integer value passed to this function. - It * then calculates a new value by adding this vector to the nearby * integer value passed to this function. - It then calculates the * dot product of the above-generated value and the floating-point * input value passed to this function. * * A noise function differs from a random-number generator because * it always returns the same output value if the same input value * is passed to it. */ public static double GradientNoise3D(double fx, double fy, double fz, int ix, int iy, int iz, long seed) { // Randomly generate a gradient vector given the integer coordinates of the // input value. This implementation generates a random number and uses it // as an index into a normalized-vector lookup table. int vectorIndex = (int)(X_NOISE_GEN * ix + Y_NOISE_GEN * iy + Z_NOISE_GEN * iz + SEED_NOISE_GEN * seed); vectorIndex ^= (vectorIndex >> SHIFT_NOISE_GEN); vectorIndex &= 0xff; double xvGradient = Utils.RandomVectors[(vectorIndex << 2)]; double yvGradient = Utils.RandomVectors[(vectorIndex << 2) + 1]; double zvGradient = Utils.RandomVectors[(vectorIndex << 2) + 2]; // Set up us another vector equal to the distance between the two vectors // passed to this function. double xvPoint = (fx - ix); double yvPoint = (fy - iy); double zvPoint = (fz - iz); // Now compute the dot product of the gradient vector with the distance // vector. The resulting value is gradient noise. Apply a scaling value // so that this noise value ranges from -1.0 to 1.0. return ((xvGradient * xvPoint) + (yvGradient * yvPoint) + (zvGradient * zvPoint)) * 2.12; } /** * Generates an integer-noise value from the coordinates of a * three-dimensional input value. * * @param x The integer @a x coordinate of the input value. * @param y The integer @a y coordinate of the input value. * @param z The integer @a z coordinate of the input value. * @param seed A random number seed. * @return The generated integer-noise value. * * The return value ranges from 0 to 2147483647. * * A noise function differs from a random-number generator because * it always returns the same output value if the same input value * is passed to it. */ public static long IntValueNoise3D(int x, int y, int z, long seed) { // All constants are primes and must remain prime in order for this noise // function to work correctly. long n = (X_NOISE_GEN * x + Y_NOISE_GEN * y + Z_NOISE_GEN * z + SEED_NOISE_GEN * seed) & 0x7fffffffffffffffL; n = (n >> 13) ^ n; return (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffffffffffffL; } /** * Generates a value-coherent-noise value from the coordinates of a * three-dimensional input value. * * @param x The @a x coordinate of the input value. * @param y The @a y coordinate of the input value. * @param z The @a z coordinate of the input value. * @param seed The random number seed. * @param noiseQuality The quality of the coherent-noise. * @return The generated value-coherent-noise value. * * The return value ranges from -1.0 to +1.0. * * For an explanation of the difference between <i>gradient</i> * noise and <i>value</i> noise, see the comments for the * GradientNoise3D() function. */ public static double ValueCoherentNoise3D(double x, double y, double z, long seed, NoiseQuality quality) { // Create a unit-length cube aligned along an integer boundary. This cube // surrounds the input point. int x0 = (x > 0.0 ? (int) x : (int) x - 1); int x1 = x0 + 1; int y0 = (y > 0.0 ? (int) y : (int) y - 1); int y1 = y0 + 1; int z0 = (z > 0.0 ? (int) z : (int) z - 1); int z1 = z0 + 1; // Map the difference between the coordinates of the input value and the // coordinates of the cube's outer-lower-left vertex onto an S-curve. double xs, ys, zs; if (quality == NoiseQuality.FAST) { xs = (x - x0); ys = (y - y0); zs = (z - z0); } else if (quality == NoiseQuality.STANDARD) { xs = Utils.SCurve3(x - x0); ys = Utils.SCurve3(y - y0); zs = Utils.SCurve3(z - z0); } else { xs = Utils.SCurve5(x - x0); ys = Utils.SCurve5(y - y0); zs = Utils.SCurve5(z - z0); } // Now calculate the noise values at each vertex of the cube. To generate // the coherent-noise value at the input point, interpolate these eight // noise values using the S-curve value as the interpolant (trilinear // interpolation.) double n0, n1, ix0, ix1, iy0, iy1; n0 = ValueNoise3D(x0, y0, z0, seed); n1 = ValueNoise3D(x1, y0, z0, seed); ix0 = Utils.LinearInterp(n0, n1, xs); n0 = ValueNoise3D(x0, y1, z0, seed); n1 = ValueNoise3D(x1, y1, z0, seed); ix1 = Utils.LinearInterp(n0, n1, xs); iy0 = Utils.LinearInterp(ix0, ix1, ys); n0 = ValueNoise3D(x0, y0, z1, seed); n1 = ValueNoise3D(x1, y0, z1, seed); ix0 = Utils.LinearInterp(n0, n1, xs); n0 = ValueNoise3D(x0, y1, z1, seed); n1 = ValueNoise3D(x1, y1, z1, seed); ix1 = Utils.LinearInterp(n0, n1, xs); iy1 = Utils.LinearInterp(ix0, ix1, ys); return Utils.LinearInterp(iy0, iy1, zs); } /** * Generates a value-noise value from the coordinates of a three-dimensional * input value. * * @param x The @a x coordinate of the input value. * @param y The @a y coordinate of the input value. * @param z The @a z coordinate of the input value. * @param seed A random number seed. * @return The generated value-noise value. * * The return value ranges from -1.0 to +1.0. * * A noise function differs from a random-number generator because * it always returns the same output value if the same input value * is passed to it. */ public static double ValueNoise3D(int x, int y, int z, long seed) { return 1.0 - (IntValueNoise3D(x, y, z, seed) / 4611686018427387904.0); } }