OK, so here's the problem:
I'm making a game with randomly generated terrain. The terrain is generated once and saved to disk/SD card. It does this quite nicely :)
To do this, I run a SplashScreenActivity which runs my opening splashscreen, the world creation or the world loading, depending on how it is started. The actual procedural generation is done using 4D Simplex Noise using a class written by Stefan Gustavson and ptimised by Peter Eastman (and optimised and speeded up by at least 50% by myself, pulling variables out and making them static ... but the problem I'm about to describe happened before those changes).
Basically I use their noise function to fill tiles with noise. In my world creation loop I loop through all the tiles and per tile I run through all the pixels, calling the SimplexNoise4D.noise(x,y,z,w) function of the class to fill each pixel (I'm planning on sending a xyzw-per-pixel collection to the class so it can run the method on that for faster access).
Anyway, this all works great. But when I exit my game activity and return to the main menu, if I try to run the world creation again, accessing the SimplexNoise class methods (the .noise method and the internal methods it uses) is SLOW!!! The only way to get the calls to run at normal speed is to exit the whole application (kill it using a task manager) and restart the application. Then, the first time I run it, tile creation is as fast as it should be. Using debugging/method profilling ect, it seems the calls to the .noise method and it's calls to the dot methods take a huge amount of time the second time I try to run the whole world creation thing.
So, again, The first time I loop through and access using SimplexNoise.noise(xyzw), it runs fine. Accessing it for all pixels in all the tiles a second time however (after being ingame), and all method calls to the class take FOREVER.
Does anyone know why this happens and how I can stop it from happening?
-EDIT- Just to clear things up, the application works like this: mainmenuActivity ->chooseWorldSizeActivity->Splashscreen which creates world with a lot of calls to SimplexNoise.noise(xywz)->exit splashscreen->start game Activity.
This works fine and at speed. If, however, I then quit the gameActivity (which goes to main menu), then ->selectWordlSizeActivity->splashscreenActivity, now the calls to SimplexNoise.noise(xyzw) take forever to complete. If I stop the whole application (using a atskkiller), then world creation takes the normal time to run again. And I can't really find out why! -/EDIT-
The calling loop (in the doInBackground() of an ASyncTask) just is:
for(loop over rows of tiles)
for(loop over column tiles)
for(each pixel)
create x, y, z, w;
SimplexNoise.noise(xyzw);
The Simplex Noise class looks like this:
`
public final class SimplexNoise4D { // Simplex noise in 2D, 3D and 4D
private static final Grad grad3[] = {new Grad(1,1,0),new Grad(-1,1,0),new Grad(1,-1,0),new Grad(-1,-1,0),
new Grad(1,0,1),new Grad(-1,0,1),new Grad(1,0,-1),new Grad(-1,0,-1),
new Grad(0,1,1),new Grad(0,-1,1),new Grad(0,1,-1),new Grad(0,-1,-1)};
private static final Grad grad4[]= {new Grad(0,1,1,1),new Grad(0,1,1,-1),new Grad(0,1,-1,1),new Grad(0,1,-1,-1),
new Grad(0,-1,1,1),new Grad(0,-1,1,-1),new Grad(0,-1,-1,1),new Grad(0,-1,-1,-1),
new Grad(1,0,1,1),new Grad(1,0,1,-1),new Grad(1,0,-1,1),new Grad(1,0,-1,-1),
new Grad(-1,0,1,1),new Grad(-1,0,1,-1),new Grad(-1,0,-1,1),new Grad(-1,0,-1,-1),
new Grad(1,1,0,1),new Grad(1,1,0,-1),new Grad(1,-1,0,1),new Grad(1,-1,0,-1),
new Grad(-1,1,0,1),new Grad(-1,1,0,-1),new Grad(-1,-1,0,1),new Grad(-1,-1,0,-1),
new Grad(1,1,1,0),new Grad(1,1,-1,0),new Grad(1,-1,1,0),new Grad(1,-1,-1,0),
new Grad(-1,1,1,0),new Grad(-1,1,-1,0),new Grad(-1,-1,1,0),new Grad(-1,-1,-1,0)};
private static final short 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};
// To remove the need for index wrapping, double the permutation table length
private static short perm[] = new short[512];
private static short permMod12[] = new short[512];
static {
for(int i=0; i<512; i++)
{
perm[i]=p[i & 255];
permMod12[i] = (short)(perm[i] % 12);
}
}
// Skewing and unskewing factors for 2, 3, and 4 dimensions
private static final double F2 = 0.5*(Math.sqrt(3.0)-1.0);
private static final double G2 = (3.0-Math.sqrt(3.0))/6.0;
private static final double F3 = 1.0/3.0;
private static final double G3 = 1.0/6.0;
private static final double F4 = (Math.sqrt(5.0)-1.0)/4.0;
private static final double G4 = (5.0-Math.sqrt(5.0))/20.0;
// This method is a *lot* faster than using (int)Math.floor(x)
private static int fastfloor(double x) {
int xi = (int)x;
return x<xi ? xi-1 : xi;
}
private static double dot(Grad g, double x, double y) {
return g.x*x + g.y*y; }
private static double dot(Grad g, double x, double y, double z) {
return g.x*x + g.y*y + g.z*z; }
private static double dot(Grad g, double x, double y, double z, double w) {
return g.x*x + g.y*y + g.z*z + g.w*w; }
private static double n0, n1, n2, n3, n4; // Noise contributions from the five corners
private static double s;// Factor for 4D skewing
private static int i;
private static int j;
private static int k;
private static int l;
private static double t; // Factor for 4D unskewing
private static double X0; // Unskew the cell origin back to (x,y,z,w) space
private static double Y0;
private static double Z0;
private static double W0;
private static double x0; // The x,y,z,w distances from the cell origin
private static double y0;
private static double z0;
private static double w0;
private static int rankx;
private static int ranky;
private static int rankz;
private static int rankw;
private static int i1, j1, k1, l1; // The integer offsets for the second simplex corner
private static int i2, j2, k2, l2; // The integer offsets for the third simplex corner
private static int i3, j3, k3, l3; // The integer offsets for the fourth simplex corner
private static double x1; // Offsets for second corner in (x,y,z,w) coords
private static double y1;
private static double z1;
private static double w1;
private static double x2; // Offsets for third corner in (x,y,z,w) coords
private static double y2;
private static double z2;
private static double w2;
private static double x3; // Offsets for fourth corner in (x,y,z,w) coords
private static double y3;
private static double z3;
private static double w3;
private static double x4; // Offsets for last corner in (x,y,z,w) coords
private static double y4;
private static double z4;
private static double w4;
// Work out the hashed gradient indices of the five simplex corners
private static int ii;
private static int jj;
private static int kk;
private static int ll;
private static int gi0;
private static int gi1;
private static int gi2;
private static int gi3;
private static int gi4;
private static double t0;
private static double t1;
private static double t2;
private static double t3;
private static double t4;
// 4D simplex noise, better simplex rank ordering method 2012-03-09
public static double noise(double x, double y, double z, double w) {
////double n0, n1, n2, n3, n4; // Noise contributions from the five corners
// Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
////double s = (x + y + z + w) * F4; // Factor for 4D skewing
s = (x + y + z + w) * F4; // Factor for 4D skewing
/*int i = fastfloor(x + s);
int j = fastfloor(y + s);
int k = fastfloor(z + s);
int l = fastfloor(w + s);
double t = (i + j + k + l) * G4; // Factor for 4D unskewing
double X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
double Y0 = j - t;
double Z0 = k - t;
double W0 = l - t;
double x0 = x - X0; // The x,y,z,w distances from the cell origin
double y0 = y - Y0;
double z0 = z - Z0;
double w0 = w - W0;*/
i = fastfloor(x + s);
j = fastfloor(y + s);
k = fastfloor(z + s);
l = fastfloor(w + s);
t = (i + j + k + l) * G4; // Factor for 4D unskewing
X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
Y0 = j - t;
Z0 = k - t;
W0 = l - t;
x0 = x - X0; // The x,y,z,w distances from the cell origin
y0 = y - Y0;
z0 = z - Z0;
w0 = w - W0;
// For the 4D case, the simplex is a 4D shape I won't even try to describe.
// To find out which of the 24 possible simplices we're in, we need to
// determine the magnitude ordering of x0, y0, z0 and w0.
// Six pair-wise comparisons are performed between each possible pair
// of the four coordinates, and the results are used to rank the numbers.
/*int rankx = 0;
int ranky = 0;
int rankz = 0;
int rankw = 0;
if(x0 > y0) rankx++; else ranky++;
if(x0 > z0) rankx++; else rankz++;
if(x0 > w0) rankx++; else rankw++;
if(y0 > z0) ranky++; else rankz++;
if(y0 > w0) ranky++; else rankw++;
if(z0 > w0) rankz++; else rankw++;
int i1, j1, k1, l1; // The integer offsets for the second simplex corner
int i2, j2, k2, l2; // The integer offsets for the third simplex corner
int i3, j3, k3, l3; // The integer offsets for the fourth simplex corner*/
rankx = 0;
ranky = 0;
rankz = 0;
rankw = 0;
if(x0 > y0) rankx++; else ranky++;
if(x0 > z0) rankx++; else rankz++;
if(x0 > w0) rankx++; else rankw++;
if(y0 > z0) ranky++; else rankz++;
if(y0 > w0) ranky++; else rankw++;
if(z0 > w0) rankz++; else rankw++;
// simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
// Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
// impossible. Only the 24 indices which have non-zero entries make any sense.
// We use a thresholding to set the coordinates in turn from the largest magnitude.
// Rank 3 denotes the largest coordinate.
i1 = rankx >= 3 ? 1 : 0;
j1 = ranky >= 3 ? 1 : 0;
k1 = rankz >= 3 ? 1 : 0;
l1 = rankw >= 3 ? 1 : 0;
// Rank 2 denotes the second largest coordinate.
i2 = rankx >= 2 ? 1 : 0;
j2 = ranky >= 2 ? 1 : 0;
k2 = rankz >= 2 ? 1 : 0;
l2 = rankw >= 2 ? 1 : 0;
// Rank 1 denotes the second smallest coordinate.
i3 = rankx >= 1 ? 1 : 0;
j3 = ranky >= 1 ? 1 : 0;
k3 = rankz >= 1 ? 1 : 0;
l3 = rankw >= 1 ? 1 : 0;
// The fifth corner has all coordinate offsets = 1, so no need to compute that.
/*double x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
double y1 = y0 - j1 + G4;
double z1 = z0 - k1 + G4;
double w1 = w0 - l1 + G4;
double x2 = x0 - i2 + 2.0*G4; // Offsets for third corner in (x,y,z,w) coords
double y2 = y0 - j2 + 2.0*G4;
double z2 = z0 - k2 + 2.0*G4;
double w2 = w0 - l2 + 2.0*G4;
double x3 = x0 - i3 + 3.0*G4; // Offsets for fourth corner in (x,y,z,w) coords
double y3 = y0 - j3 + 3.0*G4;
double z3 = z0 - k3 + 3.0*G4;
double w3 = w0 - l3 + 3.0*G4;
double x4 = x0 - 1.0 + 4.0*G4; // Offsets for last corner in (x,y,z,w) coords
double y4 = y0 - 1.0 + 4.0*G4;
double z4 = z0 - 1.0 + 4.0*G4;
double w4 = w0 - 1.0 + 4.0*G4;
// Work out the hashed gradient indices of the five simplex corners
int ii = i & 255;
int jj = j & 255;
int kk = k & 255;
int ll = l & 255;
int gi0 = perm[ii+perm[jj+perm[kk+perm[ll]]]] % 32;
int gi1 = perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]] % 32;
int gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]] % 32;
int gi3 = perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]] % 32;
int gi4 = perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]] % 32;*/
x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
y1 = y0 - j1 + G4;
z1 = z0 - k1 + G4;
w1 = w0 - l1 + G4;
x2 = x0 - i2 + 2.0*G4; // Offsets for third corner in (x,y,z,w) coords
y2 = y0 - j2 + 2.0*G4;
z2 = z0 - k2 + 2.0*G4;
w2 = w0 - l2 + 2.0*G4;
x3 = x0 - i3 + 3.0*G4; // Offsets for fourth corner in (x,y,z,w) coords
y3 = y0 - j3 + 3.0*G4;
z3 = z0 - k3 + 3.0*G4;
w3 = w0 - l3 + 3.0*G4;
x4 = x0 - 1.0 + 4.0*G4; // Offsets for last corner in (x,y,z,w) coords
y4 = y0 - 1.0 + 4.0*G4;
z4 = z0 - 1.0 + 4.0*G4;
w4 = w0 - 1.0 + 4.0*G4;
// Work out the hashed gradient indices of the five simplex corners
ii = i & 255;
jj = j & 255;
kk = k & 255;
ll = l & 255;
gi0 = perm[ii+perm[jj+perm[kk+perm[ll]]]] % 32;
gi1 = perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]] % 32;
gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]] % 32;
gi3 = perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]] % 32;
gi4 = perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]] % 32;
// Calculate the contribution from the five corners
/*double t0 = 0.6 - x0*x0 - y0*y0 - z0*z0 - w0*w0;
if(t0<0) n0 = 0.0;
else {
t0 *= t0;
n0 = t0 * t0 * dot(grad4[gi0], x0, y0, z0, w0);
}
double t1 = 0.6 - x1*x1 - y1*y1 - z1*z1 - w1*w1;
if(t1<0) n1 = 0.0;
else {
t1 *= t1;
n1 = t1 * t1 * dot(grad4[gi1], x1, y1, z1, w1);
}
double t2 = 0.6 - x2*x2 - y2*y2 - z2*z2 - w2*w2;
if(t2<0) n2 = 0.0;
else {
t2 *= t2;
n2 = t2 * t2 * dot(grad4[gi2], x2, y2, z2, w2);
}
double t3 = 0.6 - x3*x3 - y3*y3 - z3*z3 - w3*w3;
if(t3<0) n3 = 0.0;
else {
t3 *= t3;
n3 = t3 * t3 * dot(grad4[gi3], x3, y3, z3, w3);
}
double t4 = 0.6 - x4*x4 - y4*y4 - z4*z4 - w4*w4;
if(t4<0) n4 = 0.0;
else {
t4 *= t4;
n4 = t4 * t4 * dot(grad4[gi4], x4, y4, z4, w4);
}*/
t0 = 0.6 - x0*x0 - y0*y0 - z0*z0 - w0*w0;
if(t0<0) n0 = 0.0;
else {
t0 *= t0;
n0 = t0 * t0 * dot(grad4[gi0], x0, y0, z0, w0);
}
t1 = 0.6 - x1*x1 - y1*y1 - z1*z1 - w1*w1;
if(t1<0) n1 = 0.0;
else {
t1 *= t1;
n1 = t1 * t1 * dot(grad4[gi1], x1, y1, z1, w1);
}
t2 = 0.6 - x2*x2 - y2*y2 - z2*z2 - w2*w2;
if(t2<0) n2 = 0.0;
else {
t2 *= t2;
n2 = t2 * t2 * dot(grad4[gi2], x2, y2, z2, w2);
}
t3 = 0.6 - x3*x3 - y3*y3 - z3*z3 - w3*w3;
if(t3<0) n3 = 0.0;
else {
t3 *= t3;
n3 = t3 * t3 * dot(grad4[gi3], x3, y3, z3, w3);
}
t4 = 0.6 - x4*x4 - y4*y4 - z4*z4 - w4*w4;
if(t4<0) n4 = 0.0;
else {
t4 *= t4;
n4 = t4 * t4 * dot(grad4[gi4], x4, y4, z4, w4);
}
// Sum up and scale the result to cover the range [-1,1]
return 27.0 * (n0 + n1 + n2 + n3 + n4);
}
// Inner class to speed up gradient computations
// (array access is a lot slower than member access)
private static class Grad
{
double x, y, z, w;
Grad(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
Grad(double x, double y, double z, double w)
{
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
}
}
`
OK, so here's the problem:
I'm making a game with randomly generated terrain. The terrain is generated once and saved to disk/SD card. It does this quite nicely :)
To do this, I run a SplashScreenActivity which runs my opening splashscreen, the world creation or the world loading, depending on how it is started. The actual procedural generation is done using 4D Simplex Noise using a class written by Stefan Gustavson and ptimised by Peter Eastman (and optimised and speeded up by at least 50% by myself, pulling variables out and making them static ... but the problem I'm about to describe happened before those changes).
Basically I use their noise function to fill tiles with noise. In my world creation loop I loop through all the tiles and per tile I run through all the pixels, calling the SimplexNoise4D.noise(x,y,z,w) function of the class to fill each pixel (I'm planning on sending a xyzw-per-pixel collection to the class so it can run the method on that for faster access).
Anyway, this all works great. But when I exit my game activity and return to the main menu, if I try to run the world creation again, accessing the SimplexNoise class methods (the .noise method and the internal methods it uses) is SLOW!!! The only way to get the calls to run at normal speed is to exit the whole application (kill it using a task manager) and restart the application. Then, the first time I run it, tile creation is as fast as it should be. Using debugging/method profilling ect, it seems the calls to the .noise method and it's calls to the dot methods take a huge amount of time the second time I try to run the whole world creation thing.
So, again, The first time I loop through and access using SimplexNoise.noise(xyzw), it runs fine. Accessing it for all pixels in all the tiles a second time however (after being ingame), and all method calls to the class take FOREVER.
Does anyone know why this happens and how I can stop it from happening?
-EDIT- Just to clear things up, the application works like this: mainmenuActivity ->chooseWorldSizeActivity->Splashscreen which creates world with a lot of calls to SimplexNoise.noise(xywz)->exit splashscreen->start game Activity.
This works fine and at speed. If, however, I then quit the gameActivity (which goes to main menu), then ->selectWordlSizeActivity->splashscreenActivity, now the calls to SimplexNoise.noise(xyzw) take forever to complete. If I stop the whole application (using a atskkiller), then world creation takes the normal time to run again. And I can't really find out why! -/EDIT-
The calling loop (in the doInBackground() of an ASyncTask) just is:
for(loop over rows of tiles)
for(loop over column tiles)
for(each pixel)
create x, y, z, w;
SimplexNoise.noise(xyzw);
The Simplex Noise class looks like this:
`
public final class SimplexNoise4D { // Simplex noise in 2D, 3D and 4D
private static final Grad grad3[] = {new Grad(1,1,0),new Grad(-1,1,0),new Grad(1,-1,0),new Grad(-1,-1,0),
new Grad(1,0,1),new Grad(-1,0,1),new Grad(1,0,-1),new Grad(-1,0,-1),
new Grad(0,1,1),new Grad(0,-1,1),new Grad(0,1,-1),new Grad(0,-1,-1)};
private static final Grad grad4[]= {new Grad(0,1,1,1),new Grad(0,1,1,-1),new Grad(0,1,-1,1),new Grad(0,1,-1,-1),
new Grad(0,-1,1,1),new Grad(0,-1,1,-1),new Grad(0,-1,-1,1),new Grad(0,-1,-1,-1),
new Grad(1,0,1,1),new Grad(1,0,1,-1),new Grad(1,0,-1,1),new Grad(1,0,-1,-1),
new Grad(-1,0,1,1),new Grad(-1,0,1,-1),new Grad(-1,0,-1,1),new Grad(-1,0,-1,-1),
new Grad(1,1,0,1),new Grad(1,1,0,-1),new Grad(1,-1,0,1),new Grad(1,-1,0,-1),
new Grad(-1,1,0,1),new Grad(-1,1,0,-1),new Grad(-1,-1,0,1),new Grad(-1,-1,0,-1),
new Grad(1,1,1,0),new Grad(1,1,-1,0),new Grad(1,-1,1,0),new Grad(1,-1,-1,0),
new Grad(-1,1,1,0),new Grad(-1,1,-1,0),new Grad(-1,-1,1,0),new Grad(-1,-1,-1,0)};
private static final short 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};
// To remove the need for index wrapping, double the permutation table length
private static short perm[] = new short[512];
private static short permMod12[] = new short[512];
static {
for(int i=0; i<512; i++)
{
perm[i]=p[i & 255];
permMod12[i] = (short)(perm[i] % 12);
}
}
// Skewing and unskewing factors for 2, 3, and 4 dimensions
private static final double F2 = 0.5*(Math.sqrt(3.0)-1.0);
private static final double G2 = (3.0-Math.sqrt(3.0))/6.0;
private static final double F3 = 1.0/3.0;
private static final double G3 = 1.0/6.0;
private static final double F4 = (Math.sqrt(5.0)-1.0)/4.0;
private static final double G4 = (5.0-Math.sqrt(5.0))/20.0;
// This method is a *lot* faster than using (int)Math.floor(x)
private static int fastfloor(double x) {
int xi = (int)x;
return x<xi ? xi-1 : xi;
}
private static double dot(Grad g, double x, double y) {
return g.x*x + g.y*y; }
private static double dot(Grad g, double x, double y, double z) {
return g.x*x + g.y*y + g.z*z; }
private static double dot(Grad g, double x, double y, double z, double w) {
return g.x*x + g.y*y + g.z*z + g.w*w; }
private static double n0, n1, n2, n3, n4; // Noise contributions from the five corners
private static double s;// Factor for 4D skewing
private static int i;
private static int j;
private static int k;
private static int l;
private static double t; // Factor for 4D unskewing
private static double X0; // Unskew the cell origin back to (x,y,z,w) space
private static double Y0;
private static double Z0;
private static double W0;
private static double x0; // The x,y,z,w distances from the cell origin
private static double y0;
private static double z0;
private static double w0;
private static int rankx;
private static int ranky;
private static int rankz;
private static int rankw;
private static int i1, j1, k1, l1; // The integer offsets for the second simplex corner
private static int i2, j2, k2, l2; // The integer offsets for the third simplex corner
private static int i3, j3, k3, l3; // The integer offsets for the fourth simplex corner
private static double x1; // Offsets for second corner in (x,y,z,w) coords
private static double y1;
private static double z1;
private static double w1;
private static double x2; // Offsets for third corner in (x,y,z,w) coords
private static double y2;
private static double z2;
private static double w2;
private static double x3; // Offsets for fourth corner in (x,y,z,w) coords
private static double y3;
private static double z3;
private static double w3;
private static double x4; // Offsets for last corner in (x,y,z,w) coords
private static double y4;
private static double z4;
private static double w4;
// Work out the hashed gradient indices of the five simplex corners
private static int ii;
private static int jj;
private static int kk;
private static int ll;
private static int gi0;
private static int gi1;
private static int gi2;
private static int gi3;
private static int gi4;
private static double t0;
private static double t1;
private static double t2;
private static double t3;
private static double t4;
// 4D simplex noise, better simplex rank ordering method 2012-03-09
public static double noise(double x, double y, double z, double w) {
////double n0, n1, n2, n3, n4; // Noise contributions from the five corners
// Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
////double s = (x + y + z + w) * F4; // Factor for 4D skewing
s = (x + y + z + w) * F4; // Factor for 4D skewing
/*int i = fastfloor(x + s);
int j = fastfloor(y + s);
int k = fastfloor(z + s);
int l = fastfloor(w + s);
double t = (i + j + k + l) * G4; // Factor for 4D unskewing
double X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
double Y0 = j - t;
double Z0 = k - t;
double W0 = l - t;
double x0 = x - X0; // The x,y,z,w distances from the cell origin
double y0 = y - Y0;
double z0 = z - Z0;
double w0 = w - W0;*/
i = fastfloor(x + s);
j = fastfloor(y + s);
k = fastfloor(z + s);
l = fastfloor(w + s);
t = (i + j + k + l) * G4; // Factor for 4D unskewing
X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
Y0 = j - t;
Z0 = k - t;
W0 = l - t;
x0 = x - X0; // The x,y,z,w distances from the cell origin
y0 = y - Y0;
z0 = z - Z0;
w0 = w - W0;
// For the 4D case, the simplex is a 4D shape I won't even try to describe.
// To find out which of the 24 possible simplices we're in, we need to
// determine the magnitude ordering of x0, y0, z0 and w0.
// Six pair-wise comparisons are performed between each possible pair
// of the four coordinates, and the results are used to rank the numbers.
/*int rankx = 0;
int ranky = 0;
int rankz = 0;
int rankw = 0;
if(x0 > y0) rankx++; else ranky++;
if(x0 > z0) rankx++; else rankz++;
if(x0 > w0) rankx++; else rankw++;
if(y0 > z0) ranky++; else rankz++;
if(y0 > w0) ranky++; else rankw++;
if(z0 > w0) rankz++; else rankw++;
int i1, j1, k1, l1; // The integer offsets for the second simplex corner
int i2, j2, k2, l2; // The integer offsets for the third simplex corner
int i3, j3, k3, l3; // The integer offsets for the fourth simplex corner*/
rankx = 0;
ranky = 0;
rankz = 0;
rankw = 0;
if(x0 > y0) rankx++; else ranky++;
if(x0 > z0) rankx++; else rankz++;
if(x0 > w0) rankx++; else rankw++;
if(y0 > z0) ranky++; else rankz++;
if(y0 > w0) ranky++; else rankw++;
if(z0 > w0) rankz++; else rankw++;
// simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
// Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
// impossible. Only the 24 indices which have non-zero entries make any sense.
// We use a thresholding to set the coordinates in turn from the largest magnitude.
// Rank 3 denotes the largest coordinate.
i1 = rankx >= 3 ? 1 : 0;
j1 = ranky >= 3 ? 1 : 0;
k1 = rankz >= 3 ? 1 : 0;
l1 = rankw >= 3 ? 1 : 0;
// Rank 2 denotes the second largest coordinate.
i2 = rankx >= 2 ? 1 : 0;
j2 = ranky >= 2 ? 1 : 0;
k2 = rankz >= 2 ? 1 : 0;
l2 = rankw >= 2 ? 1 : 0;
// Rank 1 denotes the second smallest coordinate.
i3 = rankx >= 1 ? 1 : 0;
j3 = ranky >= 1 ? 1 : 0;
k3 = rankz >= 1 ? 1 : 0;
l3 = rankw >= 1 ? 1 : 0;
// The fifth corner has all coordinate offsets = 1, so no need to compute that.
/*double x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
double y1 = y0 - j1 + G4;
double z1 = z0 - k1 + G4;
double w1 = w0 - l1 + G4;
double x2 = x0 - i2 + 2.0*G4; // Offsets for third corner in (x,y,z,w) coords
double y2 = y0 - j2 + 2.0*G4;
double z2 = z0 - k2 + 2.0*G4;
double w2 = w0 - l2 + 2.0*G4;
double x3 = x0 - i3 + 3.0*G4; // Offsets for fourth corner in (x,y,z,w) coords
double y3 = y0 - j3 + 3.0*G4;
double z3 = z0 - k3 + 3.0*G4;
double w3 = w0 - l3 + 3.0*G4;
double x4 = x0 - 1.0 + 4.0*G4; // Offsets for last corner in (x,y,z,w) coords
double y4 = y0 - 1.0 + 4.0*G4;
double z4 = z0 - 1.0 + 4.0*G4;
double w4 = w0 - 1.0 + 4.0*G4;
// Work out the hashed gradient indices of the five simplex corners
int ii = i & 255;
int jj = j & 255;
int kk = k & 255;
int ll = l & 255;
int gi0 = perm[ii+perm[jj+perm[kk+perm[ll]]]] % 32;
int gi1 = perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]] % 32;
int gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]] % 32;
int gi3 = perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]] % 32;
int gi4 = perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]] % 32;*/
x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
y1 = y0 - j1 + G4;
z1 = z0 - k1 + G4;
w1 = w0 - l1 + G4;
x2 = x0 - i2 + 2.0*G4; // Offsets for third corner in (x,y,z,w) coords
y2 = y0 - j2 + 2.0*G4;
z2 = z0 - k2 + 2.0*G4;
w2 = w0 - l2 + 2.0*G4;
x3 = x0 - i3 + 3.0*G4; // Offsets for fourth corner in (x,y,z,w) coords
y3 = y0 - j3 + 3.0*G4;
z3 = z0 - k3 + 3.0*G4;
w3 = w0 - l3 + 3.0*G4;
x4 = x0 - 1.0 + 4.0*G4; // Offsets for last corner in (x,y,z,w) coords
y4 = y0 - 1.0 + 4.0*G4;
z4 = z0 - 1.0 + 4.0*G4;
w4 = w0 - 1.0 + 4.0*G4;
// Work out the hashed gradient indices of the five simplex corners
ii = i & 255;
jj = j & 255;
kk = k & 255;
ll = l & 255;
gi0 = perm[ii+perm[jj+perm[kk+perm[ll]]]] % 32;
gi1 = perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]] % 32;
gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]] % 32;
gi3 = perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]] % 32;
gi4 = perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]] % 32;
// Calculate the contribution from the five corners
/*double t0 = 0.6 - x0*x0 - y0*y0 - z0*z0 - w0*w0;
if(t0<0) n0 = 0.0;
else {
t0 *= t0;
n0 = t0 * t0 * dot(grad4[gi0], x0, y0, z0, w0);
}
double t1 = 0.6 - x1*x1 - y1*y1 - z1*z1 - w1*w1;
if(t1<0) n1 = 0.0;
else {
t1 *= t1;
n1 = t1 * t1 * dot(grad4[gi1], x1, y1, z1, w1);
}
double t2 = 0.6 - x2*x2 - y2*y2 - z2*z2 - w2*w2;
if(t2<0) n2 = 0.0;
else {
t2 *= t2;
n2 = t2 * t2 * dot(grad4[gi2], x2, y2, z2, w2);
}
double t3 = 0.6 - x3*x3 - y3*y3 - z3*z3 - w3*w3;
if(t3<0) n3 = 0.0;
else {
t3 *= t3;
n3 = t3 * t3 * dot(grad4[gi3], x3, y3, z3, w3);
}
double t4 = 0.6 - x4*x4 - y4*y4 - z4*z4 - w4*w4;
if(t4<0) n4 = 0.0;
else {
t4 *= t4;
n4 = t4 * t4 * dot(grad4[gi4], x4, y4, z4, w4);
}*/
t0 = 0.6 - x0*x0 - y0*y0 - z0*z0 - w0*w0;
if(t0<0) n0 = 0.0;
else {
t0 *= t0;
n0 = t0 * t0 * dot(grad4[gi0], x0, y0, z0, w0);
}
t1 = 0.6 - x1*x1 - y1*y1 - z1*z1 - w1*w1;
if(t1<0) n1 = 0.0;
else {
t1 *= t1;
n1 = t1 * t1 * dot(grad4[gi1], x1, y1, z1, w1);
}
t2 = 0.6 - x2*x2 - y2*y2 - z2*z2 - w2*w2;
if(t2<0) n2 = 0.0;
else {
t2 *= t2;
n2 = t2 * t2 * dot(grad4[gi2], x2, y2, z2, w2);
}
t3 = 0.6 - x3*x3 - y3*y3 - z3*z3 - w3*w3;
if(t3<0) n3 = 0.0;
else {
t3 *= t3;
n3 = t3 * t3 * dot(grad4[gi3], x3, y3, z3, w3);
}
t4 = 0.6 - x4*x4 - y4*y4 - z4*z4 - w4*w4;
if(t4<0) n4 = 0.0;
else {
t4 *= t4;
n4 = t4 * t4 * dot(grad4[gi4], x4, y4, z4, w4);
}
// Sum up and scale the result to cover the range [-1,1]
return 27.0 * (n0 + n1 + n2 + n3 + n4);
}
// Inner class to speed up gradient computations
// (array access is a lot slower than member access)
private static class Grad
{
double x, y, z, w;
Grad(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
Grad(double x, double y, double z, double w)
{
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
}
}
`
0 commentaires:
Enregistrer un commentaire