/* * HaoRan ImageFilter Classes v0.4 * Copyright (C) 2012 Zhenjun Dai * * 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. * * 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. */ package com.marshalchen.common.uimodule.ImageFilter.Textures; //http://www.student.kuleuven.ac.be/~m0216922/CG/perlinnoise.html /// <summary> /// Perlin Noise function /// </summary> /// /// <remarks>The class represents Gaussian function.</remarks> /// public class PerlinNoise { private double initFrequency = 1.0 / 16; private double initAmplitude = 1.0; private double persistance = 0.65; private int octaves = 4; /// <summary> /// Initializes a new instance of the <see cref="PerlinNoise"/> class /// </summary> /// public PerlinNoise( ) { } /// <summary> /// Initializes a new instance of the <see cref="PerlinNoise"/> class /// </summary> /// /// <param name="initFrequency">Initial frequency</param> /// <param name="initAmplitude">Initial amplitude</param> /// <param name="persistance">Persistance</param> /// <param name="octaves">Octaves</param> /// public PerlinNoise( double initFrequency, double initAmplitude, double persistance, int octaves ) { this.initFrequency = initFrequency; this.initAmplitude = initAmplitude; this.persistance = persistance; this.octaves = Math.max( 1, octaves ); } /// <summary> /// 1-D Perlin noise function /// </summary> /// /// <param name="x">x value</param> /// /// <returns>Returns function's value at point <b>x</b>.</returns> /// public double Function( double x ) { double frequency = initFrequency; double amplitude = initAmplitude; double sum = 0; // octaves for ( int i = 0; i < octaves; i++ ) { sum += SmoothedNoise( x * frequency ) * amplitude; frequency *= 2; amplitude *= persistance; } return sum; } /// <summary> /// 2-D Perlin noise function /// </summary> /// /// <param name="x">x value</param> /// <param name="y">y value</param> /// /// <returns>Returns function's value at point <b>(x, y)</b>.</returns> /// public double Function2D( double x, double y ) { double frequency = initFrequency; double amplitude = initAmplitude; double sum = 0; // octaves for ( int i = 0; i < octaves; i++ ) { sum += SmoothedNoise( x * frequency, y * frequency ) * amplitude; frequency *= 2; amplitude *= persistance; } return sum; } /// <summary> /// Ordinary noise function /// </summary> private double Noise( int x ) { int n = ( x << 13 ) ^ x; return ( 1.0 - ( ( n * ( n * n * 15731 + 789221 ) + 1376312589 ) & 0x7fffffff ) / 1073741824.0 ); } private double Noise( int x, int y ) { int n = x + y * 57; n = ( n << 13 ) ^ n ; return ( 1.0 - ( ( n * ( n * n * 15731 + 789221 ) + 1376312589 ) & 0x7fffffff ) / 1073741824.0 ); } /// <summary> /// Smoothed noise /// </summary> private double SmoothedNoise( double x ) { int xInt = (int) x; double xFrac = x - xInt; return CosineInterpolate( Noise( xInt ) , Noise( xInt + 1 ), xFrac ); } private double SmoothedNoise( double x, double y ) { int xInt = (int) x; int yInt = (int) y; double xFrac = x - xInt; double yFrac = y - yInt; // get four noise values double x0y0 = Noise( xInt , yInt ); double x1y0 = Noise( xInt + 1, yInt ); double x0y1 = Noise( xInt , yInt + 1 ); double x1y1 = Noise( xInt + 1, yInt + 1) ; // x interpolation double v1 = CosineInterpolate( x0y0, x1y0, xFrac ); double v2 = CosineInterpolate( x0y1, x1y1, xFrac ); // y interpolation return CosineInterpolate( v1, v2, yFrac ); } /// <summary> /// Cosine interpolation /// </summary> private double CosineInterpolate( double x1, double x2, double a ) { double f = ( 1 - Math.cos( a * Math.PI ) ) * 0.5; return x1 * ( 1 - f ) + x2 * f; } }