00001 #ifndef PERLINNOISE_H
00002 #define PERLINNOISE_H
00003
00004 #include<cmath>
00005
00006
00012 class PerlinNoise
00013 {
00017 public:
00019
00022 PerlinNoise(const float persistence, const float frequency, const int octaves)
00023 :mPersistence(persistence),
00024 mFrequency(frequency),
00025 mOctaves(octaves)
00026 {}
00027
00030 ~PerlinNoise()
00031 {
00032 }
00033
00039 const float perlinNoise(float x, float y) const
00040 {
00041 float frequency = mFrequency;
00042 float total = 0.0;
00043 for (float round = 0.0f; round < mOctaves; round += 1.0f)
00044 {
00045 const float amplitude = powf(mPersistence, round);
00046
00047 total += interpolatedNoise(x * frequency, y * frequency) * amplitude;
00048 frequency *= 2;
00049 }
00050 return total;
00051 }
00052
00053
00059 const float perlinNoise3D(float x, float y, float z) const
00060 {
00061 float frequency = mFrequency;
00062 float total = 0.0;
00063 for (float round = 0.0f; round < mOctaves; round += 1.0f)
00064 {
00065 const float amplitude = powf(mPersistence, round);
00066
00067 total += interpolatedNoise3D(x * frequency, y * frequency, z * frequency) * amplitude;
00068 frequency *= 2;
00069 }
00070 return total;
00071 }
00072
00073 protected:
00074
00075 private:
00076 const float mPersistence;
00077 const float mFrequency;
00078 const int mOctaves;
00079
00080
00083 const float noise(const int x, const int y) const
00084 {
00085 int n = x + y * 57;
00086 n = n<<13 ^ n;
00087 return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);
00088 }
00089
00090
00093 const float cosInterpolate(const float a, const float b, const float x) const
00094 {
00095 float f = (1 - cosf(x*M_PI)) * 0.5;
00096 return a*(1-f) + b*f;
00097 }
00098
00099
00102 const float weightedNoise(const int x, const int y) const
00103 {
00104 const float corners = ( noise(x-1, y-1) + noise(x+1, y-1) + noise(x-1, y+1) + noise(x+1, y+1) ) / 16;
00105 const float sides = ( noise(x-1, y) + noise(x+1, y) + noise(x, y-1) + noise(x, y+1) ) / 8;
00106 const float center = noise(x, y) / 4;
00107 return corners + sides + center;
00108 }
00109
00110
00113 const float interpolatedNoise(const float x, const float y) const
00114 {
00115 const int intX = int(x);
00116 const float fracX = x - intX;
00117
00118 const int intY = int(y);
00119 const float fracY = y - intY;
00120
00121 const float v1 = weightedNoise(intX, intY);
00122 const float v2 = weightedNoise(intX + 1, intY);
00123 const float v3 = weightedNoise(intX, intY + 1);
00124 const float v4 = weightedNoise(intX + 1, intY + 1);
00125
00126 const float i1 = cosInterpolate(v1 , v2 , fracX);
00127 const float i2 = cosInterpolate(v3 , v4 , fracX);
00128
00129 return cosInterpolate(i1 , i2 , fracY);
00130 }
00131
00132
00133
00134
00135
00138 const float noise3D(const int x, const int y, const int z) const
00139 {
00140 int n = x + y * 57 + z * 63;
00141 n = n<<13 ^ n;
00142 return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);
00143 }
00144
00145
00146
00149 const float interpolatedNoise3D(const float x, const float y, const float z) const
00150 {
00151
00152 const int intX = int(x);
00153 const float fracX = x - intX;
00154
00155 const int intY = int(y);
00156 const float fracY = y - intY;
00157
00158 const int intZ = int(z);
00159 const float fracZ = z - intZ;
00160
00161 const float v1 = noise3D(intX, intY, intZ);
00162 const float v2 = noise3D(intX + 1, intY, intZ);
00163 const float v3 = noise3D(intX, intY + 1,intZ);
00164 const float v4 = noise3D(intX + 1, intY + 1,intZ);
00165
00166
00167 const float w1 = noise3D(intX, intY, intZ + 1);
00168 const float w2 = noise3D(intX + 1, intY, intZ + 1);
00169 const float w3 = noise3D(intX, intY + 1,intZ + 1);
00170 const float w4 = noise3D(intX + 1, intY + 1,intZ + 1);
00171 return lerp(fracZ, lerp(fracY, lerp(fracX, v1, v2), lerp(fracX, v3, v4)),
00172 lerp(fracY, lerp(fracX, w1, w2), lerp(fracX, w3, w4)));
00173 }
00174
00175 };
00176 #endif