Go Down

Topic: porting perlin noise Java example doesn't work (Read 369 times) previous topic - next topic

kasperkamperman.com

I'm trying to use an fixed point implementation of Perlin Improved noise in Arduino.
http://mrl.nyu.edu/~perlin/noise/INoise.java

I've already simplified some part and made an Arduino simulator in Processing. In the original code (link above) the arrays are generated on setup, but I put the arrays already in the code . This is modification tested and works in Processing.

I would like to port the Processing to Arduino. Steps made:
- converted all the int's to long, since Java ints are 4 bytes and Arduino ints 2 bytes (but longs are 4 bytes).
- Replaced the Math.min function with the min function in Arduino.

I run the code on an Arduino Mega1280 (since the UNO has not enough memory). I will optimise later, but I first want to have a setup with the less changes possible working.

In Arduino and don't seem to get the right result.
Do I miss something when porting this code to Arduino?


In both my setups I print a result off the noise to the monitor (Serial.print and print).

The Processing code (copy and past this in Processing 2.0):

Code: [Select]

// this version works, but porting this to Arduino (in this case the Mega because of memory) not.

int 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,
 
  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
};

int fadeArray[] = {
0,    0,    0,    0,    0,    0,    0,    0,    1,    1,    2,    3,    3,    4,    6,    7,
9,    10,   12,   14,   17,   19,   22,   25,   29,   32,   36,   40,   45,   49,   54,   60,
65,   71,   77,   84,   91,   98,   105,  113,  121,  130,  139,  148,  158,  167,  178,  188,
199,  211,  222,  234,  247,  259,  273,  286,  300,  314,  329,  344,  359,  374,  390,  407,
424,  441,  458,  476,  494,  512,  531,  550,  570,  589,  609,  630,  651,  672,  693,  715,
737,  759,  782,  805,  828,  851,  875,  899,  923,  948,  973,  998,  1023, 1049, 1074, 1100,
1127, 1153, 1180, 1207, 1234, 1261, 1289, 1316, 1344, 1372, 1400, 1429, 1457, 1486, 1515, 1543,
1572, 1602, 1631, 1660, 1690, 1719, 1749, 1778, 1808, 1838, 1868, 1898, 1928, 1958, 1988, 2018,
2048, 2077, 2107, 2137, 2167, 2197, 2227, 2257, 2287, 2317, 2346, 2376, 2405, 2435, 2464, 2493,
2523, 2552, 2580, 2609, 2638, 2666, 2695, 2723, 2751, 2779, 2806, 2834, 2861, 2888, 2915, 2942,
2968, 2995, 3021, 3046, 3072, 3097, 3122, 3147, 3172, 3196, 3220, 3244, 3267, 3290, 3313, 3336,
3358, 3380, 3402, 3423, 3444, 3465, 3486, 3506, 3525, 3545, 3564, 3583, 3601, 3619, 3637, 3654,
3672, 3688, 3705, 3721, 3736, 3751, 3766, 3781, 3795, 3809, 3822, 3836, 3848, 3861, 3873, 3884,
3896, 3907, 3917, 3928, 3937, 3947, 3956, 3965, 3974, 3982, 3990, 3997, 4004, 4011, 4018, 4024,
4030, 4035, 4041, 4046, 4050, 4055, 4059, 4063, 4066, 4070, 4073, 4076, 4078, 4081, 4083, 4085,
4086, 4088, 4089, 4091, 4092, 4092, 4093, 4094, 4094, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
};

int amountOfLights = 20;

int perlinTimeInc = 1000;
int perlinXInc    = 1000;
int perlinTimePosition = 0;

void setup()
{ size(400,400);
 frameRate(25);
}

void draw()
{  
   for(int i=0;i<amountOfLights;i++)
   { int val = renderNoise(i*perlinXInc, 0, perlinTimePosition);
     
     if(val>127) print("*");
     else        print("-");
   }  
   
   // go a step further in time (input for y function in perlin noise)
   perlinTimePosition = perlinTimePosition + perlinTimeInc;  

   println();
}

int renderNoise(int x, int y, int z)
{ return 137 + (inoise(x, y, z)/512);
}

int inoise(int x, int y, int z) {

 int X = x>>16 & 255, Y = y>>16 & 255, Z = z>>16 & 255, N = 1<<16;
 x &= N-1; y &= N-1; z &= N-1;

 int u=fade(x),v=fade(y),w=fade(z), A=p[X  ]+Y, AA=p[A]+Z, AB=p[A+1]+Z,
                                    B=p[X+1]+Y, BA=p[B]+Z, BB=p[B+1]+Z;
 return lerp(w, lerp(v, lerp(u, grad(p[AA  ], x   , y   , z   ),  
                                grad(p[BA  ], x-N , y   , z   )),
                        lerp(u, grad(p[AB  ], x   , y-N , z   ),  
                                grad(p[BB  ], x-N , y-N , z   ))),
                lerp(v, lerp(u, grad(p[AA+1], x   , y   , z-N ),  
                                grad(p[BA+1], x-N , y   , z-N )),
                        lerp(u, grad(p[AB+1], x   , y-N , z-N ),
                                grad(p[BB+1], x-N , y-N , z-N ))));
}

int lerp(int t, int a, int b) { return a + (t * (b - a) >> 12); }

int grad(int hash, int x, int y, int z) {
 int h = hash&15, u = h<8?x:y, v = h<4?y:h==12||h==14?x:z;
 return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
}

int fade(int t) {
 int t0 = fadeArray[t >> 8], t1 = fadeArray[Math.min(255, (t >> 8) + 1)];
 return t0 + ( (t & 255) * (t1 - t0) >> 8 );
}


The Arduino code (in a reply, because message length is exceeded).

As attachment 2 screenshots with of the monitor (to see the smooth "perlin" movement in Processing).

kasperkamperman.com

The Arduino code (for what it's worth, since I hardly modified anything as you can read in my first post):

Code: [Select]

long 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,
 
  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,
};

long fadeArray[] = {
0,    0,    0,    0,    0,    0,    0,    0,    1,    1,    2,    3,    3,    4,    6,    7,
9,    10,   12,   14,   17,   19,   22,   25,   29,   32,   36,   40,   45,   49,   54,   60,
65,   71,   77,   84,   91,   98,   105,  113,  121,  130,  139,  148,  158,  167,  178,  188,
199,  211,  222,  234,  247,  259,  273,  286,  300,  314,  329,  344,  359,  374,  390,  407,
424,  441,  458,  476,  494,  512,  531,  550,  570,  589,  609,  630,  651,  672,  693,  715,
737,  759,  782,  805,  828,  851,  875,  899,  923,  948,  973,  998,  1023, 1049, 1074, 1100,
1127, 1153, 1180, 1207, 1234, 1261, 1289, 1316, 1344, 1372, 1400, 1429, 1457, 1486, 1515, 1543,
1572, 1602, 1631, 1660, 1690, 1719, 1749, 1778, 1808, 1838, 1868, 1898, 1928, 1958, 1988, 2018,
2048, 2077, 2107, 2137, 2167, 2197, 2227, 2257, 2287, 2317, 2346, 2376, 2405, 2435, 2464, 2493,
2523, 2552, 2580, 2609, 2638, 2666, 2695, 2723, 2751, 2779, 2806, 2834, 2861, 2888, 2915, 2942,
2968, 2995, 3021, 3046, 3072, 3097, 3122, 3147, 3172, 3196, 3220, 3244, 3267, 3290, 3313, 3336,
3358, 3380, 3402, 3423, 3444, 3465, 3486, 3506, 3525, 3545, 3564, 3583, 3601, 3619, 3637, 3654,
3672, 3688, 3705, 3721, 3736, 3751, 3766, 3781, 3795, 3809, 3822, 3836, 3848, 3861, 3873, 3884,
3896, 3907, 3917, 3928, 3937, 3947, 3956, 3965, 3974, 3982, 3990, 3997, 4004, 4011, 4018, 4024,
4030, 4035, 4041, 4046, 4050, 4055, 4059, 4063, 4066, 4070, 4073, 4076, 4078, 4081, 4083, 4085,
4086, 4088, 4089, 4091, 4092, 4092, 4093, 4094, 4094, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
};

int amountOfLights = 20;

long perlinTimeInc = 1000L;
long perlinXInc    = 1000L;
long perlinTimePosition = 0;

void setup()
{   Serial.begin(57600);
}

void loop()
{  
   for(int i=0;i<amountOfLights;i++)
   { int val = renderNoise(i*perlinXInc, 0, perlinTimePosition);
     
     if(val>127) Serial.print("*");
     else        Serial.print("-");
   }
   
   // go a step further in time (input for y function in perlin noise)
   perlinTimePosition = perlinTimePosition + perlinTimeInc;  
   
   Serial.println();
   
   delay(50);
}

int renderNoise(long x, long y, long z)
{ return 137 + (inoise(x, y, z)/512);
}

long inoise(long x, long y, long z)
{
 long X = x>>16 & 255, Y = y>>16 & 255, Z = z>>16 & 255, N = 1<<16;
 x &= N-1; y &= N-1; z &= N-1;

 long u=fade(x),v=fade(y),w=fade(z), A=p[X  ]+Y, AA=p[A]+Z, AB=p[A+1]+Z,
                                    B=p[X+1]+Y, BA=p[B]+Z, BB=p[B+1]+Z;
 return lerp(w, lerp(v, lerp(u, grad(p[AA  ], x   , y   , z   ),  
                                grad(p[BA  ], x-N , y   , z   )),
                        lerp(u, grad(p[AB  ], x   , y-N , z   ),  
                                grad(p[BB  ], x-N , y-N , z   ))),
                lerp(v, lerp(u, grad(p[AA+1], x   , y   , z-N ),  
                                grad(p[BA+1], x-N , y   , z-N )),
                        lerp(u, grad(p[AB+1], x   , y-N , z-N ),
                                grad(p[BB+1], x-N , y-N , z-N ))));
}
 
long lerp(long t, long a, long b) { return a + (t * (b - a) >> 12); }

long grad(long hash, long x, long y, long z)
{ long h = hash&15, u = h<8?x:y, v = h<4?y:h==12||h==14?x:z;
 return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
}

long fade(long t) {
 long t0 = fadeArray[t >> 8], t1 = fadeArray[min(255, (t >> 8) + 1)];
 return t0 + ( (t & 255) * (t1 - t0) >> 8 );
}


PeterH

Given that you have two implementations on different platforms and only one works, I suggest you set up a standard test case and add trace output to both implementations so that you can see at what point their behaviour diverges.
I only provide help via the forum - please do not contact me for private consultancy.

kasperkamperman.com

Hi Peter,
The code I've posted is my standard test case and in the screenshots I've showed the trace (and the difference). But I have no clue what goes wrong, probably something with different interpretation of datatypes?

AWOL

Are those tables constants?
Why aren't they in flash (PROGMEM) ?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

kasperkamperman.com

They are constants and in the end I will place them in Flash memory (I've already made a version that does that). But in order to compare good and create a minimal working version I've tried to make to versions that are equal in Processing/Arduino.

AWOL

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

kasperkamperman.com

Great, that works! I did it already with the upper integers, but overlooked this one.

Thanks.

Go Up