Browse Source

perlin noise function pull request by Jack Mott but deleted before I could pull it

Sean Barrett 8 years ago
parent
commit
a2bc1eabec
1 changed files with 106 additions and 12 deletions
  1. 106 12
      stb_perlin.h

+ 106 - 12
stb_perlin.h

@@ -1,4 +1,4 @@
-// stb_perlin.h - v0.2 - perlin noise
+// stb_perlin.h - v0.3 - perlin noise
 // public domain single-file C implementation by Sean Barrett
 // public domain single-file C implementation by Sean Barrett
 //
 //
 // LICENSE
 // LICENSE
@@ -9,8 +9,8 @@
 // to create the implementation,
 // to create the implementation,
 //     #define STB_PERLIN_IMPLEMENTATION
 //     #define STB_PERLIN_IMPLEMENTATION
 // in *one* C/CPP file that includes this file.
 // in *one* C/CPP file that includes this file.
-
-
+//
+//
 // Documentation:
 // Documentation:
 //
 //
 // float  stb_perlin_noise3( float x,
 // float  stb_perlin_noise3( float x,
@@ -31,22 +31,55 @@
 // 0 to mean "don't care". (The noise always wraps every 256 due
 // 0 to mean "don't care". (The noise always wraps every 256 due
 // details of the implementation, even if you ask for larger or no
 // details of the implementation, even if you ask for larger or no
 // wrapping.)
 // wrapping.)
+//
+// Fractal Noise:
+//
+// Three common fractal noise functions are included, which produce 
+// a wide variety of nice effects depending on the parameters 
+// provided. Note that each function will call stb_perlin_noise3 
+// 'octaves' times, so this parameter will affect runtime.
+//
+// float stb_perlin_ridge_noise3(float x, float y, float z,
+//                               float lacunarity, float gain, float offset, int octaves,
+//                               int x_wrap, int y_wrap, int z_wrap);
+//
+// float stb_perlin_fbm_noise3(float x, float y, float z,
+//                             float lacunarity, float gain, int octaves,
+//                             int x_wrap, int y_wrap, int z_wrap);
+//
+// float stb_perlin_turbulence_noise3(float x, float y, float z,
+//                                    float lacunarity, float gain,int octaves,
+//                                    int x_wrap, int y_wrap, int z_wrap);
+//
+// Typical values to start playing with:
+//     octaves    =   6     -- number of "octaves" of noise3() to sum
+//     lacunarity = ~ 2.0   -- spacing between successive octaves (use exactly 2.0 for wrapping output)
+//     gain       =   0.5   -- relative weighting applied to each successive octave
+//     offset     =   1.0?  -- used to invert the ridges, may need to be larger, not sure
+//    
+//
+// Contributors:
+//    Jack Mott - additional noise functions
+//
 
 
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
-extern "C" float stb_perlin_noise3(float x, float y, float z, int x_wrap=0, int y_wrap=0, int z_wrap=0);
-#else
+extern "C" {
+#endif
 extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap);
 extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap);
+extern float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap);
+extern float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap);
+extern float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap);
+#ifdef __cplusplus
+}
 #endif
 #endif
 
 
 #ifdef STB_PERLIN_IMPLEMENTATION
 #ifdef STB_PERLIN_IMPLEMENTATION
 
 
-#include <math.h> // floor()
-
 // not same permutation table as Perlin's reference to avoid copyright issues;
 // not same permutation table as Perlin's reference to avoid copyright issues;
 // Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/
 // Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/
 // @OPTIMIZE: should this be unsigned char instead of int for cache?
 // @OPTIMIZE: should this be unsigned char instead of int for cache?
-static int stb__perlin_randtab[512] =
+static unsigned char stb__perlin_randtab[512] =
 {
 {
    23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, 
    23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, 
    152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, 
    152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, 
@@ -89,6 +122,12 @@ static float stb__perlin_lerp(float a, float b, float t)
    return a + (b-a) * t;
    return a + (b-a) * t;
 }
 }
 
 
+static int stb__perlin_fastfloor(float a)
+{
+	int ai = (int) a;
+	return (a < ai) ? ai-1 : ai;
+}
+
 // different grad function from Perlin's, but easy to modify to match reference
 // different grad function from Perlin's, but easy to modify to match reference
 static float stb__perlin_grad(int hash, float x, float y, float z)
 static float stb__perlin_grad(int hash, float x, float y, float z)
 {
 {
@@ -110,7 +149,7 @@ static float stb__perlin_grad(int hash, float x, float y, float z)
 
 
    // perlin's gradient has 12 cases so some get used 1/16th of the time
    // perlin's gradient has 12 cases so some get used 1/16th of the time
    // and some 2/16ths. We reduce bias by changing those fractions
    // and some 2/16ths. We reduce bias by changing those fractions
-   // to 5/16ths and 6/16ths, and the same 4 cases get the extra weight.
+   // to 5/64ths and 6/64ths, and the same 4 cases get the extra weight.
    static unsigned char indices[64] =
    static unsigned char indices[64] =
    {
    {
       0,1,2,3,4,5,6,7,8,9,10,11,
       0,1,2,3,4,5,6,7,8,9,10,11,
@@ -122,6 +161,7 @@ static float stb__perlin_grad(int hash, float x, float y, float z)
    };
    };
 
 
    // if you use reference permutation table, change 63 below to 15 to match reference
    // if you use reference permutation table, change 63 below to 15 to match reference
+   // (this is why the ordering of the table above is funky)
    float *grad = basis[indices[hash & 63]];
    float *grad = basis[indices[hash & 63]];
    return grad[0]*x + grad[1]*y + grad[2]*z;
    return grad[0]*x + grad[1]*y + grad[2]*z;
 }
 }
@@ -136,9 +176,9 @@ float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z
    unsigned int x_mask = (x_wrap-1) & 255;
    unsigned int x_mask = (x_wrap-1) & 255;
    unsigned int y_mask = (y_wrap-1) & 255;
    unsigned int y_mask = (y_wrap-1) & 255;
    unsigned int z_mask = (z_wrap-1) & 255;
    unsigned int z_mask = (z_wrap-1) & 255;
-   int px = (int) floor(x);
-   int py = (int) floor(y);
-   int pz = (int) floor(z);
+   int px = stb__perlin_fastfloor(x);
+   int py = stb__perlin_fastfloor(y);
+   int pz = stb__perlin_fastfloor(z);
    int x0 = px & x_mask, x1 = (px+1) & x_mask;
    int x0 = px & x_mask, x1 = (px+1) & x_mask;
    int y0 = py & y_mask, y1 = (py+1) & y_mask;
    int y0 = py & y_mask, y1 = (py+1) & y_mask;
    int z0 = pz & z_mask, z1 = (pz+1) & z_mask;
    int z0 = pz & z_mask, z1 = (pz+1) & z_mask;
@@ -177,6 +217,60 @@ float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z
 
 
    return stb__perlin_lerp(n0,n1,u);
    return stb__perlin_lerp(n0,n1,u);
 }
 }
+
+float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap)
+{
+   int i;
+   float frequency = 1.0f;
+   float prev = 1.0f;
+   float amplitude = 0.5f;
+   float sum = 0.0f;
+
+   for (i = 0; i < octaves; i++) {
+      float r = (float)(stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap));
+      r = r<0 ? -r : r; // fabs()
+      r = offset - r;
+      r = r*r;
+      sum += r*amplitude*prev;
+      prev = r;
+      frequency *= lacunarity;
+      amplitude *= gain;
+   }
+   return sum;
+}
+
+float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap)
+{
+   int i;
+   float frequency = 1.0f;
+   float amplitude = 1.0f;
+   float sum = 0.0f;
+   
+   for (i = 0; i < octaves; i++) {
+      sum += stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude;
+      frequency *= lacunarity;
+      amplitude *= gain;
+   }
+   return sum;
+}
+
+float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap)
+{
+   int i;
+   float frequency = 1.0f;
+   float amplitude = 1.0f;
+   float sum = 0.0f;
+   
+   for (i = 0; i < octaves; i++) {
+      float r = stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude;
+      r = r<0 ? -r : r; // fabs()
+      sum += r;
+      frequency *= lacunarity;
+      amplitude *= gain;
+   }
+   return sum;
+}
+
 #endif  // STB_PERLIN_IMPLEMENTATION
 #endif  // STB_PERLIN_IMPLEMENTATION
 
 
 /*
 /*