Go Down

### Topic: Perlin Noise Generator (Read 6220 times)previous topic - next topic

#### mikejedw

##### Oct 07, 2007, 04:53 pm
Hey all!

If you've worked with computer graphics, you've probably run across Perlin Noise before.  It's great for making clouds and other textures.  It's also a nice way to add the illusion of life to motion, etc. in a way that's a lot less random than, well, random().

I wrote the following Perlin Noise generator for the Arduino.  Now all the fun of Processing's noise() function is at your command on the chip!

Any additions, changes, corrections, etc. are highly appreciated.  And DEFINITELY let me know if you use this for something cool!

See:
http://freespace.virgin.net/hugo.elias/models/m_perlin.html

for the source of the algorithm I implemented and a great walkthrough of how to use it.

Code: [Select]
`/*copyright 2007 Mike EdwardsThis program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.*/#include <math.h>float x1,y1,x2,y2,persistence;int octaves;void setup(){  pinMode(5,OUTPUT);  pinMode(6,OUTPUT);  analogWrite(5,0);  analogWrite(6,0);  //persistence affects the degree to which the "finer" noise is seen  persistence = 0.25;  //octaves are the number of "layers" of noise that get computed  octaves = 3;}void loop(){  x1 = float(millis())/100.0f;  y1 = 10.0f;  x2 = float(millis())/100.0f;  y2 = 11.0f;  //PerlinNoise2 results in a float between -1 and 1  //below we convert to a n int between 0 and 255  int m = int(PerlinNoise2(x1,y1,persistence,octaves)*128+128);    int n = int(PerlinNoise2(x2,y2,persistence,octaves)*128+128);    analogWrite(5,m);  analogWrite(6,n);  delay(5);}//using the algorithm from http://freespace.virgin.net/hugo.elias/models/m_perlin.html// thanks to hugo eliasfloat Noise2(float x, float y){  long noise;  noise = x + y * 57;  noise = pow(noise << 13,noise);  return ( 1.0 - ( long(noise * (noise * noise * 15731L + 789221L) + 1376312589L) & 0x7fffffff) / 1073741824.0);}float SmoothNoise2(float x, float y){  float corners, sides, center;  corners = ( Noise2(x-1, y-1)+Noise2(x+1, y-1)+Noise2(x-1, y+1)+Noise2(x+1, y+1) ) / 16;  sides   = ( Noise2(x-1, y)  +Noise2(x+1, y)  +Noise2(x, y-1)  +Noise2(x, y+1) ) /  8;  center  =  Noise2(x, y) / 4;  return (corners + sides + center);}float InterpolatedNoise2(float x, float y){  float v1,v2,v3,v4,i1,i2,fractionX,fractionY;  long longX,longY;  longX = long(x);  fractionX = x - longX;  longY = long(y);  fractionY = y - longY;  v1 = SmoothNoise2(longX, longY);  v2 = SmoothNoise2(longX + 1, longY);  v3 = SmoothNoise2(longX, longY + 1);  v4 = SmoothNoise2(longX + 1, longY + 1);  i1 = Interpolate(v1 , v2 , fractionX);  i2 = Interpolate(v3 , v4 , fractionX);  return(Interpolate(i1 , i2 , fractionY));}float Interpolate(float a, float b, float x){  //cosine interpolations  return(CosineInterpolate(a, b, x));}float LinearInterpolate(float a, float b, float x){  return(a*(1-x) + b*x);}float CosineInterpolate(float a, float b, float x){  float ft = x * 3.1415927;  float f = (1 - cos(ft)) * .5;  return(a*(1-f) + b*f);}float PerlinNoise2(float x, float y, float persistance, int octaves){  float frequency, amplitude;  float total = 0.0;  for (int i = 0; i <= octaves - 1; i++)  {    frequency = pow(2,i);    amplitude = pow(persistence,i);    total = total + InterpolatedNoise2(x * frequency, y * frequency) * amplitude;  }  return(total);}`

#### hungerburg

#1
##### Oct 08, 2007, 09:43 am
Funny, I did that too, just weeks ago, its running fine for days and produces great curves... This (Kens) one could some time be part of gnu math.h, couldn't it? Somehow I cant get the formatting ok, does the board software unexpand blanks?

Code: [Select]
`#include <math.h>/* Ken Perlins improved noise   -  http://mrl.nyu.edu/~perlin/noise/ C-port:  http://www.fundza.com/c4serious/noise/perlin/perlin.html by Malcolm Kesson;   arduino port by Peter Chiochetti, Sep 2007 : -  make permutation constant byte, obsoletes init(), lookup % 256*/static const byte p[] = {   151,160,137,91,90, 15,131, 13,201,95,96,53,194,233, 7,225,140,36,103,30,69,142, 8,99,37,240,21,10,23,190, 6,148,247,120,234,75, 0,26,197,62,94,252,219,203,117, 35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166, 77,146,158,231,83,111,229,122, 60,211,133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161, 1,216,80,73,209,76,132,187,208, 89, 18,169,200,196,135,130,116,188,159, 86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,5,202,38,147,118,126,255,82,85,212,207,206, 59,227, 47,16,58,17,182,189, 28,42,223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43,172, 9,129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246, 97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,138,236,205, 93,222,114, 67,29,24, 72,243,141,128,195,78,66,215,61,156,180};double fade(double t){ return t * t * t * (t * (t * 6 - 15) + 10); }double lerp(double t, double a, double b){ return a + t * (b - a); }double grad(int hash, double x, double y, double z){int     h = hash & 15;          /* CONVERT LO 4 BITS OF HASH CODE */double  u = h < 8 ? x : y,      /* INTO 12 GRADIENT DIRECTIONS.   */          v = h < 4 ? y : h==12||h==14 ? x : z;return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);}#define P(x) p[(x) & 255]double pnoise(double x, double y, double z){int   X = (int)floor(x) & 255,             /* FIND UNIT CUBE THAT */      Y = (int)floor(y) & 255,             /* CONTAINS POINT.     */      Z = (int)floor(z) & 255;x -= floor(x);                             /* FIND RELATIVE X,Y,Z */y -= floor(y);                             /* OF POINT IN CUBE.   */z -= floor(z);double  u = fade(x),                       /* COMPUTE FADE CURVES */        v = fade(y),                       /* FOR EACH OF X,Y,Z.  */        w = fade(z);int  A = P(X)+Y,     AA = P(A)+Z,     AB = P(A+1)+Z,                        /* HASH COORDINATES OF */     B = P(X+1)+Y,     BA = P(B)+Z,     BB = P(B+1)+Z;                        /* THE 8 CUBE CORNERS, */return lerp(w,lerp(v,lerp(u, grad(P(AA  ), x, y, z),   /* AND ADD */                          grad(P(BA  ), x-1, y, z)),   /* BLENDED */              lerp(u, grad(P(AB  ), x, y-1, z),        /* RESULTS */                   grad(P(BB  ), x-1, y-1, z))),       /* FROM  8 */            lerp(v, lerp(u, grad(P(AA+1), x, y, z-1),  /* CORNERS */                 grad(P(BA+1), x-1, y, z-1)),          /* OF CUBE */              lerp(u, grad(P(AB+1), x, y-1, z-1),                   grad(P(BB+1), x-1, y-1, z-1))));}#define ledPin 13void blink(int dur){  pinMode(ledPin, OUTPUT);  digitalWrite(ledPin, HIGH);  delay(dur);  digitalWrite(ledPin, LOW);}void setup(){  Serial.begin(19200);  blink(1000);}/* Koordinatenpaare rechnen */void loop(){  double x, y;  static double i = 0;  blink(125);  i += 0.01;  // aktuelle Iteration ausgeben  Serial.print("# ");  Serial.println((long)(i*100));  // nÃ¤chsten Punkt berechnen  x = pnoise(i+sin(i), i+cos(i), i);  y = pnoise(i-sin(i), i-cos(i), i);  // aktuelle Koordinaten ausgeben  Serial.print(x);  Serial.print(" ");  Serial.println(y);}`

Go Up