#undef n
}
+#define NOISE_SIZE 256
+#define NOISE_MASK 255
+float noise4f(float x, float y, float z, float w)
+{
+ int i;
+ int index[4][2];
+ float frac[4][2];
+ float v[4];
+ static float noisetable[NOISE_SIZE];
+ static int r[NOISE_SIZE];
+ // LordHavoc: this is inspired by code I saw in Quake3, however I think my
+ // version is much cleaner and substantially faster as well
+ //
+ // the following changes were made:
+ // 1. for the permutation indexing (r[] array in this code) I substituted
+ // the ^ operator (which never overflows) for the original addition and
+ // masking code, this should not have any effect on quality.
+ // 2. removed the outermost randomization array lookup.
+ // (it really wasn't necessary, it's fine if X indexes the array
+ // directly without permutation indexing)
+ // 3. reimplemented the blending using frac[] arrays rather than a macro.
+ // (the original macro read one parameter twice - not good)
+ // 4. cleaned up the code by using 4 nested loops to make it read nicer
+ // (but then I unrolled it completely for speed, it still looks nicer).
+ if (!noisetable[0])
+ {
+ // noisetable is a random-ish series of float values in +/- 1 range
+ for (i = 0;i < NOISE_SIZE;i++)
+ noisetable[i] = (rand() / (double)RAND_MAX) * 2 - 1;
+ // r is a remapping table to make each dimension of the index have different indexing behavior
+ for (i = 0;i < NOISE_SIZE;i++)
+ r[i] = (int)(rand() * (double)NOISE_MASK / (double)RAND_MAX);
+ }
+ frac[1][0] = x - floor(x);index[0][0] = (int)floor(x);
+ frac[1][1] = y - floor(y);index[1][0] = (int)floor(y);
+ frac[1][2] = z - floor(z);index[2][0] = (int)floor(z);
+ frac[1][3] = w - floor(w);index[3][0] = (int)floor(w);
+ for (i = 0;i < 4;i++)
+ frac[i][0] = 1 - frac[i][1];
+ for (i = 0;i < 4;i++)
+ index[i][1] = (index[i][0] < NOISE_SIZE - 1) ? (index[i][0] + 1) : 0;
+#if 1
+ // short version
+ v[0] = frac[1][0] * (frac[0][0] * noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][0]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][0]] ^ index[0][1]]) + frac[1][1] * (frac[0][0] * noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][1]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][1]] ^ index[0][1]]);
+ v[1] = frac[1][0] * (frac[0][0] * noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][0]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][0]] ^ index[0][1]]) + frac[1][1] * (frac[0][0] * noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][1]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][1]] ^ index[0][1]]);
+ v[2] = frac[1][0] * (frac[0][0] * noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][0]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][0]] ^ index[0][1]]) + frac[1][1] * (frac[0][0] * noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][1]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][1]] ^ index[0][1]]);
+ v[3] = frac[1][0] * (frac[0][0] * noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][0]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][0]] ^ index[0][1]]) + frac[1][1] * (frac[0][0] * noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][1]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][1]] ^ index[0][1]]);
+ return frac[3][0] * (frac[2][0] * v[0] + frac[2][1] * v[1]) + frac[3][1] * (frac[2][0] * v[2] + frac[2][1] * v[3]);
+#elif 1
+ // longer version
+ v[ 0] = noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][0]] ^ index[0][0]];
+ v[ 1] = noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][0]] ^ index[0][1]];
+ v[ 2] = noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][1]] ^ index[0][0]];
+ v[ 3] = noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][1]] ^ index[0][1]];
+ v[ 4] = noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][0]] ^ index[0][0]];
+ v[ 5] = noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][0]] ^ index[0][1]];
+ v[ 6] = noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][1]] ^ index[0][0]];
+ v[ 7] = noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][1]] ^ index[0][1]];
+ v[ 8] = noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][0]] ^ index[0][0]];
+ v[ 9] = noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][0]] ^ index[0][1]];
+ v[10] = noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][1]] ^ index[0][0]];
+ v[11] = noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][1]] ^ index[0][1]];
+ v[12] = noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][0]] ^ index[0][0]];
+ v[13] = noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][0]] ^ index[0][1]];
+ v[14] = noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][1]] ^ index[0][0]];
+ v[15] = noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][1]] ^ index[0][1]];
+ v[16] = frac[0][0] * v[ 0] + frac[0][1] * v[ 1];
+ v[17] = frac[0][0] * v[ 2] + frac[0][1] * v[ 3];
+ v[18] = frac[0][0] * v[ 4] + frac[0][1] * v[ 5];
+ v[19] = frac[0][0] * v[ 6] + frac[0][1] * v[ 7];
+ v[20] = frac[0][0] * v[ 8] + frac[0][1] * v[ 9];
+ v[21] = frac[0][0] * v[10] + frac[0][1] * v[11];
+ v[22] = frac[0][0] * v[12] + frac[0][1] * v[13];
+ v[23] = frac[0][0] * v[14] + frac[0][1] * v[15];
+ v[24] = frac[1][0] * v[16] + frac[1][1] * v[17];
+ v[25] = frac[1][0] * v[18] + frac[1][1] * v[19];
+ v[26] = frac[1][0] * v[20] + frac[1][1] * v[21];
+ v[27] = frac[1][0] * v[22] + frac[1][1] * v[23];
+ v[28] = frac[2][0] * v[24] + frac[2][1] * v[25];
+ v[29] = frac[2][0] * v[26] + frac[2][1] * v[27];
+ return frac[3][0] * v[28] + frac[3][1] * v[29];
+#else
+ // the algorithm...
+ for (l = 0;l < 2;l++)
+ {
+ for (k = 0;k < 2;k++)
+ {
+ for (j = 0;j < 2;j++)
+ {
+ for (i = 0;i < 2;i++)
+ v[l][k][j][i] = noisetable[r[r[r[index[l][3]] ^ index[k][2]] ^ index[j][1]] ^ index[i][0]];
+ v[l][k][j][2] = frac[0][0] * v[l][k][j][0] + frac[0][1] * v[l][k][j][1];
+ }
+ v[l][k][2][2] = frac[1][0] * v[l][k][0][2] + frac[1][1] * v[l][k][1][2];
+ }
+ v[l][2][2][2] = frac[2][0] * v[l][0][2][2] + frac[2][1] * v[l][1][2][2];
+ }
+ v[2][2][2][2] = frac[3][0] * v[0][2][2][2] + frac[3][1] * v[1][2][2][2];
+#endif
+}