// Persistence of Vision Ray Tracer Macro Definition File // File: ED_noise.inc // Vers: 3.1 // Desc: Perlin noise functions for the 8th Day Macro Library. // Functions in this file based upon an artile on Perlin Noise at: // 'The Good-Looking Textured Light-Sourced Bouncy Fun Smart & Stretchy Page' // http://freespace.virgin.net/hugo.elias/ // Date: January, 2000 // Auth: Lonnie Ezell // Single Inclusion check // this attempts to save parsing time by // limiting this file to being parsed only once // even when included in multiple files. #ifndef (ED_NOISE_INC) #declare ED_NOISE_INC = 1; //------------------------------ Includes ------------------------------// // Include our interpolation routines #include "8Dinterp.inc" //------------------------------ Declarations --------------------------// // This is number of functions being added together. #ifndef (ED_NOISE_Octaves) #declare ED_NOISE_Octaves = 5.0; #end // Amplitude tracks our current amplitude through each function #ifndef (ED_NOISE_Amplitude) #local ED_NOISE_Amplitude = 1.0; #end // Frequency tracks our current frequency through each function // (also known as persistence) #ifndef (ED_NOISE_Frequency) #declare ED_NOISE_Frequency = 1.0; #end //------------------------------ Macros --------------------------------// ///////////////////////////////////////////////// // MISCELANEOUS FUNCTIONS ///////////////////////////////////////////////// // InitNoise(n, octaves) - takes the number n and initializes // the randum number generators that will be needed. #macro ED_NOISE_Init(n, octs) // Store our number of octaves #declare ED_NOISE_Octaves = octs; // Create a holder for our array numbers #declare ED_NOISE_RandArray = array[10] // The first random seed is the number passed in (n). #declare ED_NOISE_RandArray[0] = seed(n); // The remaining values are based upon set modifications // to the passed number. This allows a single seed to // specify all other seeds, thus allowing the user to // only need to remember a single number, not a number // for each seed stream. #local i = 1; #while (i < ED_NOISE_Octaves) #local temp = ( (n * i) * (i + 1) / (i + 2) * (i + 1) ); #declare ED_NOISE_RandArray[i] = seed(temp); #local i = i + 1; #end #end // ED_Noise_Init(...) ///////////////////////////////////////////////// // RANDOM FUNCTIONS ///////////////////////////////////////////////// // Rand_1D - isn't needed. Simply uses POV's rand function! // Rand_2D - returns a random value between 0.0 and 1.0 // based on the x and y values given. octave is simply // the current octave being worked on. #macro ED_NOISE_Rand_2D(m_x, m_y, octave) // Our return value ( ( (rand(ED_NOISE_RandArray[octave])*x) + ( (rand(ED_NOISE_RandArray[octave]) * y) ) ) / 2.0 ) #end // ED_NOISE_Rand_2D(...) ///////////////////////////////////////////////// // SMOOTHING FUNCTIONS ///////////////////////////////////////////////// // Smooth_2D - returns the smoothed noise based upon the // x and y given. Octave is simply the current octave // being worked on. #macro ED_NOISE_Smooth_2D(m_x, m_y, octave) #local corners = ( ED_NOISE_Rand_2D(m_x - 1, m_y - 1, octave) + ED_NOISE_Rand_2D(m_x + 1, m_y - 1, octave) + ED_NOISE_Rand_2D(m_x - 1, m_y + 1, octave) + ED_NOISE_Rand_2D(m_x + 1, m_y + 1, octave) ) / 16; #local sides = ( ED_NOISE_Rand_2D(m_x - 1, m_y, octave) + ED_NOISE_Rand_2D(m_x + 1, m_y, octave) + ED_NOISE_Rand_2D(m_x, m_y - 1, octave) + ED_NOISE_Rand_2D(m_x, m_y + 1, octave) ) / 8; #local center = ED_NOISE_Rand_2D(m_x, m_y, octave) / 4; // Our return value ( corners + sides + center ) #end // EN_NOISE_Smooth_2D(...) ///////////////////////////////////////////////// // NOISE INTERPOLATION FUNCTIONS - uses // Interpolation functions from "8DInterp.inc" ///////////////////////////////////////////////// // Interp_2D #macro ED_NOISE_Interp_2D(m_x, m_y, octave) #local int_x = int(m_x); #local frac_x = m_x - int_x; #local int_y = int(m_y); #local frac_y = m_y - int_y; #local v1 = ED_NOISE_Smooth_2D(int_x, int_y, octave); #local v2 = ED_NOISE_Smooth_2D(int_x + 1, int_y, octave); #local v3 = ED_NOISE_Smooth_2D(int_x, int_y + 1, octave); #local v4 = ED_NOISE_Smooth_2D(int_x + 1, int_y + 1, octave); #local i1 = ED_CosineInterpolate(v1, v2, frac_x); #local i2 = ED_CosineInterpolate(v3, v4, frac_x); // Our return value ED_CosineInterpolate(i1, i2, frac_y) #end // ED_NOISE_Interp_2D(m_x, m_y, octave) ///////////////////////////////////////////////// // NOISE FUNCTIONS ///////////////////////////////////////////////// // Noise_2D - returns a Perlin Noise generated value // based upon the passed x & y values. #macro ED_NOISE_Noise_2D(m_x, m_y, persist) #declare ED_total = 0.0; #local i = 0; #local temp = 0.0; #while(i < ED_NOISE_Octaves) #local tx = m_x * pow(2, i); #local ty = m_y * pow(2, i); #local temp = ED_NOISE_Interp_2D(tx, ty, i) #local temp = temp * pow(persist, i) #declare ED_total = ED_total + temp; #local i = i + 1; #end // Our return value total #end // ED_NOISE_Noise_2D(...) #end // Single Inclusion block