Skip to content
This repository has been archived by the owner on Dec 5, 2018. It is now read-only.

noise(x, y) always return 0.46875 #241

Open
bofeng opened this issue May 30, 2016 · 5 comments
Open

noise(x, y) always return 0.46875 #241

bofeng opened this issue May 30, 2016 · 5 comments
Labels

Comments

@bofeng
Copy link

bofeng commented May 30, 2016

The java version works well, but the js version, everytime call noise(x, y), it returns 0.46875

for (int x = 0; x < 5; x++) {
    for (int y = 0; y < 5; y++) {
        n = noise(x, y);
        text("number: " + n, 10, 10 * i);
        i = i + 1;
    }
}

Run it here : http://sketchpad.cc/sp/pad/view/mPI5P5i6so/latest

@teo1978
Copy link

teo1978 commented May 30, 2016

Looks like it has to do with x and y being integer. If you add 0.99 instead of 1 in each iteration, the resulting values do change.

@Pomax Pomax added the bug label May 30, 2016
@bofeng
Copy link
Author

bofeng commented May 30, 2016

@teo1978 Thanks, it is wired though, still a bug ... besides even change it to noise(x - 0.01, y - 0.01), the number it generated is still around 0.46875, while the Java version is much more random

processing-bug

@teo1978
Copy link

teo1978 commented May 30, 2016

still a bug

Of course! I have no idea whether the values generated by processing.js make some sense (I mean, if they are valid Perlin noise according to a different "scale" or whatever) or if it's completely broken. But either way, as long as it does not generate exactly the same values as the Java version for any given input and seed, it's of course a bug.

@Pomax
Copy link
Member

Pomax commented May 31, 2016

They should make sense, since they're proper Perlin noise, but it's possible that there are subtle bugs in the implementation on

p.noise = function(x, y, z) {
, which makes use of the generator defined at
// Noise functions and helpers
function PerlinNoise(seed) {
var rnd = seed !== undef ? new Marsaglia(seed, (seed<<16)+(seed>>16)) : Marsaglia.createRandomized();
var i, j;
// http://www.noisemachine.com/talk1/17b.html
// http://mrl.nyu.edu/~perlin/noise/
// generate permutation
var perm = new Uint8Array(512);
for(i=0;i<256;++i) { perm[i] = i; }
for(i=0;i<256;++i) {
// NOTE: we can only do this because we've made sure the Marsaglia generator
// gives us numbers where the last byte in a pseudo-random number is
// still pseudo-random. If no 2nd argument is passed in the constructor,
// that is no longer the case and this pair swap will always run identically.
var t = perm[j = rnd.intGenerator() & 0xFF];
perm[j] = perm[i];
perm[i] = t;
}
// copy to avoid taking mod in perm[0];
for(i=0;i<256;++i) { perm[i + 256] = perm[i]; }
function grad3d(i,x,y,z) {
var h = i & 15; // convert into 12 gradient directions
var 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);
}
function grad2d(i,x,y) {
var v = (i & 1) === 0 ? x : y;
return (i&2) === 0 ? -v : v;
}
function grad1d(i,x) {
return (i&1) === 0 ? -x : x;
}
function lerp(t,a,b) { return a + t * (b - a); }
this.noise3d = function(x, y, z) {
var X = Math.floor(x)&255, Y = Math.floor(y)&255, Z = Math.floor(z)&255;
x -= Math.floor(x); y -= Math.floor(y); z -= Math.floor(z);
var fx = (3-2*x)*x*x, fy = (3-2*y)*y*y, fz = (3-2*z)*z*z;
var p0 = perm[X]+Y, p00 = perm[p0] + Z, p01 = perm[p0 + 1] + Z,
p1 = perm[X + 1] + Y, p10 = perm[p1] + Z, p11 = perm[p1 + 1] + Z;
return lerp(fz,
lerp(fy, lerp(fx, grad3d(perm[p00], x, y, z), grad3d(perm[p10], x-1, y, z)),
lerp(fx, grad3d(perm[p01], x, y-1, z), grad3d(perm[p11], x-1, y-1,z))),
lerp(fy, lerp(fx, grad3d(perm[p00 + 1], x, y, z-1), grad3d(perm[p10 + 1], x-1, y, z-1)),
lerp(fx, grad3d(perm[p01 + 1], x, y-1, z-1), grad3d(perm[p11 + 1], x-1, y-1,z-1))));
};
this.noise2d = function(x, y) {
var X = Math.floor(x)&255, Y = Math.floor(y)&255;
x -= Math.floor(x); y -= Math.floor(y);
var fx = (3-2*x)*x*x, fy = (3-2*y)*y*y;
var p0 = perm[X]+Y, p1 = perm[X + 1] + Y;
return lerp(fy,
lerp(fx, grad2d(perm[p0], x, y), grad2d(perm[p1], x-1, y)),
lerp(fx, grad2d(perm[p0 + 1], x, y-1), grad2d(perm[p1 + 1], x-1, y-1)));
};
this.noise1d = function(x) {
var X = Math.floor(x)&255;
x -= Math.floor(x);
var fx = (3-2*x)*x*x;
return lerp(fx, grad1d(perm[X], x), grad1d(perm[X+1], x-1));
};
}

The code given uses x,y so that means we're triggering sum += effect * (1 + generator.noise2d(k*x, k*y))/2; break;, with the definition for noise2d being:

    function(x, y) {
      var X = Math.floor(x)&255, Y = Math.floor(y)&255;
      x -= Math.floor(x); y -= Math.floor(y);
      var fx = (3-2*x)*x*x, fy = (3-2*y)*y*y;
      var p0 = perm[X]+Y, p1 = perm[X + 1] + Y;
      return lerp(fy,
        lerp(fx, grad2d(perm[p0], x, y), grad2d(perm[p1], x-1, y)),
        lerp(fx, grad2d(perm[p0 + 1], x, y-1), grad2d(perm[p1 + 1], x-1, y-1)));
    }

These seem likely culprits:

x -= Math.floor(x);
y -= Math.floor(y);

After all, if the inputs are integer then the result of this is always going to be the same as (0,0)

@Pomax
Copy link
Member

Pomax commented Jun 1, 2016

@GoToLoop I've removed our comments that were veering off topic, as they contributed nothing to this specific bug report. As always, if you want to discuss the structure of the Processing.js project, its development process, what is missing, and how Pjs ties into Processing itself (short version: it doesn't), feel free to file one or more separate new issues for that. This issue is for tracking a bug in the code for p.noise.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants