// Standard Shell for C++ Courseware // Copyright 1997; modified June 2000 for CodeWarrior IDE 4.0 // College of Computer Science // Northeastern University Boston MA 02115 // This software may be used for educational purposes as long as this copyright // notice is retained at the top of all files // Should this software be modified, the words "Modified from Original" must be // included as a comment below this notice // All publication rights are retained. This software or its documentation may // not be published in any media either in whole or in part. /////////////////////////////////////////////////////////////////////////////// // C++2DNoise // Harriet Fell 8/9/2001; clouds revised 8/15/2001 /////////////////////////////////////////////////////////////////////////////// using namespace std; #include "SWindows.h" // set up for windows #include "IOTools.h" // tools for safe I/O #include "Graphics.h" // graphics functions & RGB definition #include "RGBNames.h" // RGB names #include "Random.h" // random numbers #include "FileTool.h" // file tools #include "Text.h" // fonts and text #include "Delay.h" // delay controls // globals const size = 39; // multiple of 3 for splines typedef double noiseArray[size + 1][size + 1]; noiseArray noiseR, noiseG, noiseB; // Each is a 40x40 array of randoms from 0 to 1 //double factorR, factorG, factorB, factor; // to set the proportions of Red, Green, Blue int divisor; // for spreading out the noise enum { Quit = 0, Noise = 1, Turbulence = 2, Marble = 3, Clouds = 4 }; // prototypes int main(); void setNoises(); // fill the noise arrays with random integers // Generate linear noise and turbulence from the noise array. // Return val between 0 and 1 double linearNoise (double u, double v, noiseArray noise); double Lturbulence(double u,double v, noiseArray noise); // sinusoidal functions to blend with turbulence double marble (double x, double y, noiseArray noise, int twist); double cloud (double x, double y, noiseArray noise, int fluff); // Scale color to 0 to 255 range RGB noiseColor(double x, double y); RGB turbulenceColor(double x, double y, int m); RGB marbleColor (double x, double y, int twist); RGB cloudColor(double x, double y, int fluff); // definitions int main() { // open text and drawing windows BigSquarePair(); // start random number generator SetRandomSeed(); //Fill the noise arrays setNoises(); int h, v; // pixel coordinates double x, y; // x = h/divisor, y= v/divisor are sent to LinearNoise function int m = 1; // scaling turbulence color int twist = 1; // for twistiness of marble int fluff = 1; // for fluffiness of cloud divisor = 1; int choice = Noise; do{ choice = RequestInt("Noise\t\t1\nTurbulence\t2\nMarble\t\t3\nClouds\t\t4\nQuit\t\t0\nChoose an action ", choice); divisor = RequestInt("Enter divisor = ", divisor); if (choice == Turbulence) m = RequestInt("color scale, 255 for smooth, greater for breaks", 255); if (choice == Marble) twist = RequestInt("for twistiness of marble, >= 1", twist); if (choice == Clouds) fluff = RequestInt("for fluffiness of clouds, >= 1", fluff); for (v = 0; v < 400; v++) for( h = 0; h < 400; h++){ x = (double)h / divisor; y = (double)v / divisor; if (choice == Noise) SetColorPixel(h, v, noiseColor(x,y)); else if (choice == Turbulence) SetColorPixel(h, v, turbulenceColor(x, y, m)); else if (choice == Marble) SetColorPixel(h, v, marbleColor(x, y, twist)); else if (choice == Clouds) SetColorPixel(h, v, cloudColor(x, y, fluff)); } } while (choice != Quit); // done PressReturn("Select 'quit' from the file menu to terminate."); return(0); } void setNoises(){ // fill the noise arrays with random integers int i, j; for (j = 0; j < size; j++) for (i = 0; i < size; i++){ noiseR[i][j] = RandomDouble(0, 1); noiseG[i][j] = RandomDouble(0, 1); noiseB[i][j] = RandomDouble(0, 1); } for (j = 0; j < size; j++){ noiseR[size][j] = noiseR[0][j]; // set the last row and column to match the first row and column noiseR[j][size] = noiseR[j][0]; noiseG[size][j] = noiseG[0][j]; noiseG[j][size] = noiseG[j][0]; noiseB[size][j] = noiseB[0][j]; noiseB[j][size] = noiseB[j][0]; } noiseR[size][size] = noiseR[0][0]; //set the last corner to complete the wrap noiseG[size][size] = noiseG[0][0]; noiseB[size][size] = noiseB[0][0]; } double linearNoise (double u, double v, noiseArray noise){ int iu, iv, ip, iq; double du, dv, bot, top; iu = trunc(u); // integer parts of u and v iv = trunc(v); du = u - iu; // fractional parts uf u and v dv = v - iv; iu = iu % size; // intergral parts of u and v iv = iv % size; // mapped to integers 0 to size - 1 ip = (iu + 1); // (ip, iu) lattice point one up and to right of (iu, iv) iq = (iv + 1); // top gets noise from linear function across the top of the square // | // (iu, iq)----(ip, iq) // | | | // | * | // | | | // (iu, iv)----(ip, iv) // | // bot gets noise from linear function across the bottom of the square // go a distance du along the top and bottom of the square bot = noise[iu][iv] + du * (noise[ip][iv] - noise[iu][iv]); top = noise[iu][iq] + du * (noise[ip][iq] - noise[iu][iq]); // use a linear function from bot to top // go a distance dv from bot to top return (bot + dv * (top - bot)); } RGB noiseColor(double x, double y){ // converts linear noise factors to 0 to 255 range for an RGB color. double factorR, factorG, factorB; // to set the proportions of Red, Green, Blue RGB myColor; factorR = linearNoise(x, y, noiseR); factorG = linearNoise(x, y, noiseG); factorB = linearNoise(x, y, noiseB); myColor.Set(round(factorR * 255), round(factorG * 255), round(factorB * 255)); return myColor; } double Lturbulence(double u,double v, noiseArray noise){ double t, scale; // LN(u, v) +LN(2u, 2v)/2 + LN(4u, 4v)/4 + ... // Value is between between 0 and 2. t = 0; for (scale = 1; scale >= (double)1 / divisor; scale /= 2) { t = t + linearNoise(u / scale, v / scale, noise) * scale; } return t/2; // value is between 0 and 1 } RGB turbulenceColor(double x, double y, int m){ // converts linear turbulence factors to 0 to 255 range for an RGB color. // m is a scale factor. m=255 gives smooth color of maximal brightness // Lower values give darker color. // Higher values give 'broken' but interesting color - caused by overflow double factorR, factorG, factorB; // to set the proportions of Red, Green, Blue RGB myColor; factorR = Lturbulence(x, y, noiseR); factorG = Lturbulence(x, y, noiseG); factorB = Lturbulence(x, y, noiseB); myColor.Set(round(factorR * m), round(factorG * m), round(factorB * m)); return myColor; } double marble (double x, double y, noiseArray noise, int twist){ // take the square root to fatten the green bands, leaving thin blue veins return sqrt(abs(sin(x + twist*Lturbulence(x, y, noise)))); } RGB marbleColor (double x, double y, int twist){ RGB myColor; double factorG = marble(x, y, noiseG, twist); // When factorG is 1, the color is cyan (0, 255, 255). // When factorG is 0, the color is blue (0, 0, 255). // The color changes linearly with factorG. myColor.Set(0, trunc(factorG*255), 255); return myColor; } double cloud (double x, double y, noiseArray noise, int fluff){ // return sin(x + Lturbulence(x, y, noise)); double r = sqrt((x-(double)200/divisor)*(x-(double)200/divisor) + (y-(double)200/divisor)*(y-(double)200/divisor)); return cos(r + fluff*Lturbulence(x, y, noise)); } RGB cloudColor(double x, double y, int fluff){ double factorB; // to set the proportions of Blue (really, to regulate the saturation) RGB myColor; factorB = abs(cloud(x, y, noiseR, fluff)); // When factorB is 1, the color is pale blue (127, 127, 255). // When factorB is 0, the color is white (255, 255, 255). // The color changes linearly with factorB. myColor.Set(127 + 128*(1 - factorB), 127 + 128*(1 - factorB), 255); return myColor; }
Harriet J. Fell
Last Updated: August 15, 11:43 a.m.
The URL for this document is:
http://www.ccs.neu.edu/home/fell/COM3370/noiseCode2.html