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.Hash32Shift; 013import imagingbook.pub.noise.hashing.HashFun; 014 015/** 016 * Gradient (Perlin) noise implementation. 017 * This is the super-class for all other Perlin noise 018 * generators (1D, 2D, N-dimensional). 019 */ 020 021public abstract class PerlinNoiseGen { 022 023 final double f_min; 024 final double f_max; 025 final double persistence; // persistence (phi) 026 double[] F; // frequencies f_i 027 double[] A; // amplitudes a_i 028 029 HashFun hashFun; 030 public boolean VERBOSE = false; // for debugging only 031 032 PerlinNoiseGen(double f_min, double f_max, double persistence, HashFun hash) { 033 this.f_min = f_min; 034 this.f_max = f_max; 035 this.persistence = persistence; 036 this.hashFun = (hash != null) ? hash : new Hash32Shift(); // default 037 this.makeFrequencies(f_min, f_max, persistence); 038 } 039 040 /** 041 * Perlin's improved "fading" function s(x) 042 * @param x interpolation position in [0,1] 043 * @return s(x) = 10 x^3 - 15 x^4 + 6 x^5 044 */ 045 double s(double x) { 046 return x * x * x * (x * (x * 6 - 15) + 10); // s(x) = 10 x^3 - 15 x^4 + 6 x^5 047 } 048 049 void makeFrequencies(double fmin, double fmax, double persistence) { 050 int oct = getFrequencySteps(f_min, f_max); 051 if (oct < 1) { 052 throw new IllegalArgumentException("f_max is smaller than f_min"); 053 } 054 F = new double[oct]; 055 A = new double[oct]; 056 int n = 0; 057 double f = f_min; 058 double a = 1; 059 while (f <= f_max && n < oct) { 060 F[n] = f; 061 A[n] = a; 062 n = n + 1; 063 f = 2 * f; 064 a = persistence * a; 065 } 066 } 067 068 // ----------------- UTILITY METHODS ---------------------------- 069 070 /** 071 * The number of frequency steps, given fmin and fmax. 072 * 073 * @param fmin min. frequency 074 * @param fmax max. frequency 075 * @return number of frequency steps 076 */ 077 public int getFrequencySteps(double fmin, double fmax) { // TODO: should not be public! 078 int i = 0; 079 double f = fmin; 080 while (f <= fmax) { 081 i = i + 1; 082 f = 2 * f; 083 } 084 return i; 085 } 086 087 /** 088 * @return An array with the frequencies f_i used for generating 089 * the noise function. 090 */ 091 public double[] getFrequencies() { 092 return F; 093 } 094 095 /** 096 * @return An array with the amplitudes a_i used for generating 097 * the noise function. 098 */ 099 public double[] getAmplitudes() { 100 return A; 101 } 102 103 /** 104 * Fast floor method (by Gustavson?) 105 * @param x argument 106 * @return floor(x), works for pos. and neg. x. 107 */ 108 int ffloor(double x) { 109 int xint = (int) x; 110 return (xint < x) ? xint : xint - 1; 111 } 112 113// public static void main(String[] args) { // TODO: delete 114// double f_min = 0.01; 115// double f_max = 0.015; 116// int octaves = getFrequencySteps(f_min, f_max); 117// System.out.format("fmin=%f fmax=%f octaves= %d", f_min, f_max, octaves); 118// } 119 120}