001/******************************************************************************* 002 * This software is provided as a supplement to the authors' textbooks on digital 003 * image processing published by Springer-Verlag in various languages and editions. 004 * Permission to use and distribute this software is granted under the BSD 2-Clause 005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 007 * Visit http://imagingbook.com for additional details. 008 *******************************************************************************/ 009 010package imagingbook.pub.noise.perlin; 011 012import imagingbook.pub.noise.hashing.HashFun; 013 014/** 015 * Gradient (Perlin) noise implementation. 016 * This class implements a 2D Perlin noise generator. 017 */ 018 019public class PerlinNoiseGen2d extends PerlinNoiseGen { 020 021 public PerlinNoiseGen2d(double f_min, double f_max, double persistence, HashFun hf) { 022 super(f_min, f_max, persistence, hf); 023 } 024 025 /** 026 * 2D combined (multi-frequency) Perlin noise function. 027 * @param x Interpolation position x. 028 * @param y Interpolation position y. 029 * @return The value of the combined Perlin 030 * noise function for the two-dimensional position (x,y). 031 */ 032 public double NOISE(double x, double y) { 033 double sum = 0; 034 for (int i=0; i<F.length; i++) { 035 sum = sum + A[i] * noise(F[i] * x, F[i] * y); 036 } 037 return sum; 038 } 039 040 /** 041 * 2D elementary (single-frequency) Perlin noise function. 042 * @param x Interpolation position x. 043 * @param y Interpolation position y. 044 * @return The value of the elementary Perlin 045 * noise function for the two-dimensional position (x,y). 046 */ 047 public double noise(double x, double y) { 048 int px = (int) ffloor(x); 049 int py = (int) ffloor(y); 050 double[] g00 = gradient(px, py); 051 double[] g10 = gradient(px+1, py); 052 double[] g01 = gradient(px, py+1); 053 double[] g11 = gradient(px+1, py+1); 054 double x01 = x-px; // x01 is in [0,1] 055 double y01 = y-py; // y01 is in [0,1] 056 double w00 = g00[0]*(x01) + g00[1]*(y01); 057 double w10 = g10[0]*(x01-1) + g10[1]*(y01); 058 double w01 = g01[0]*(x01) + g01[1]*(y01-1); 059 double w11 = g11[0]*(x01-1) + g11[1]*(y01-1); 060 return interpolate(x01, y01, w00, w10, w01, w11); 061 } 062 063 /** 064 * @param px discrete horiz. position 065 * @param py discrete vert. position 066 * @return A pseudo-random gradient vector for the discrete position (px,py). 067 */ 068 double[] gradient(int px, int py) { 069 double[] g = hashFun.hash(px,py); // hash() always returns a new double[] in [0,1] 070 g[0] = 2.0 * g[0] - 1; 071 g[1] = 2.0 * g[1] - 1; 072 return g; 073 } 074 075 /** 076 * Local interpolation function. 077 * @param x01 Horizontal interpolation position in [0,1] 078 * @param y01 Vertical interpolation position in [0,1] 079 * @param w00 Tangent value for position (0,0). 080 * @param w01 Tangent value for position (1,0). 081 * @param w10 Tangent value for position (0,1). 082 * @param w11 Tangent value for position (1,1). 083 * @return The interpolated noise value at position (x01,y01). 084 */ 085 double interpolate(double x01, double y01, double w00, double w10, double w01, double w11) { 086 double sx = this.s(x01); 087 double w0 = (1 - sx) * w00 + sx * w10; 088 double w1 = (1 - sx) * w01 + sx * w11; 089 double sy = this.s(y01); 090 double w = (1 - sy) * w0 + sy * w1; 091 return w; 092 } 093 094}