// 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