porting perlin noise Java example doesn't work

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):

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

arduino monitor.png

processing monitor.png

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

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 );
}

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.

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?

Are those tables constants?
Why aren't they in flash (PROGMEM) ?

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.

Try N = 1L << 16;

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

Thanks.