00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef NVBLASTEXTAUTHORINGPERLINNOISE_H
00030 #define NVBLASTEXTAUTHORINGPERLINNOISE_H
00031
00032 #include <NvBlastExtAuthoringFractureTool.h>
00033
00034 #include <PxVec4.h>
00035 #include <PxVec3.h>
00036
00037 #define PERLIN_NOISE_SAMPLE_TABLE 512
00038 using physx::PxVec3;
00039 namespace Nv
00040 {
00041 namespace Blast
00042 {
00043
00044
00045
00046
00047
00048
00049 NV_INLINE float at3(const float& rx, const float& ry, const float& rz, const PxVec3 q)
00050 {
00051 return rx * q[0] + ry * q[1] + rz * q[2];
00052 }
00053
00054 NV_INLINE float fade(float t) { return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f); }
00055
00056 NV_INLINE float lerp(float t, float a, float b) { return a + t * (b - a); }
00057
00058 NV_INLINE void setup(int i, PxVec3 point, float& t, int& b0, int& b1, float& r0, float& r1)
00059 {
00060 t = point[i] + (0x1000);
00061 b0 = ((int)t) & (PERLIN_NOISE_SAMPLE_TABLE - 1);
00062 b1 = (b0 + 1) & (PERLIN_NOISE_SAMPLE_TABLE - 1);
00063 r0 = t - (int)t;
00064 r1 = r0 - 1.0f;
00065 }
00066
00067
00068 NV_INLINE float noiseSample(PxVec3 point, int* p, PxVec3* g)
00069 {
00070 int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
00071 float rx0, rx1, ry0, ry1, rz0, rz1, sy, sz, a, b, c, d, t, u, v;
00072 PxVec3 q;
00073 int i, j;
00074
00075 setup(0, point, t, bx0, bx1, rx0, rx1);
00076 setup(1, point, t, by0, by1, ry0, ry1);
00077 setup(2, point, t, bz0, bz1, rz0, rz1);
00078
00079 i = p[bx0];
00080 j = p[bx1];
00081
00082 b00 = p[i + by0];
00083 b10 = p[j + by0];
00084 b01 = p[i + by1];
00085 b11 = p[j + by1];
00086
00087 t = fade(rx0);
00088 sy = fade(ry0);
00089 sz = fade(rz0);
00090
00091 q = g[b00 + bz0]; u = at3(rx0, ry0, rz0, q);
00092 q = g[b10 + bz0]; v = at3(rx1, ry0, rz0, q);
00093 a = lerp(t, u, v);
00094
00095 q = g[b01 + bz0]; u = at3(rx0, ry1, rz0, q);
00096 q = g[b11 + bz0]; v = at3(rx1, ry1, rz0, q);
00097 b = lerp(t, u, v);
00098
00099 c = lerp(sy, a, b);
00100
00101 q = g[b00 + bz1]; u = at3(rx0, ry0, rz1, q);
00102 q = g[b10 + bz1]; v = at3(rx1, ry0, rz1, q);
00103 a = lerp(t, u, v);
00104
00105 q = g[b01 + bz1]; u = at3(rx0, ry1, rz1, q);
00106 q = g[b11 + bz1]; v = at3(rx1, ry1, rz1, q);
00107 b = lerp(t, u, v);
00108
00109 d = lerp(sy, a, b);
00110
00111 return lerp(sz, c, d);
00112 }
00113
00117 class PerlinNoise
00118 {
00119 public:
00126 PerlinNoise(Nv::Blast::RandomGeneratorBase* rnd, int octaves = 1, float frequency = 1., float amplitude = 1.)
00127 : mRnd(rnd),
00128 mOctaves(octaves),
00129 mFrequency(frequency),
00130 mAmplitude(amplitude),
00131 mbInit(false)
00132 {
00133
00134 }
00135
00136
00137
00138
00139
00140
00141
00142 void reset(int octaves = 1, float frequency = 1.f, float amplitude = 1.f)
00143 {
00144 mOctaves = octaves;
00145 mFrequency = frequency;
00146 mAmplitude = amplitude;
00147 init();
00148 }
00149
00153 float sample(const physx::PxVec3& point)
00154 {
00155 return perlinNoise(point);
00156 }
00157
00158 private:
00159 PerlinNoise& operator=(const PerlinNoise&);
00160
00161 float perlinNoise(physx::PxVec3 point)
00162 {
00163 if (!mbInit)
00164 init();
00165
00166 const int octaves = mOctaves;
00167 const float frequency = mFrequency;
00168 float amplitude = mAmplitude;
00169 float result = 0.0f;
00170
00171 point *= frequency;
00172
00173 for (int i = 0; i < octaves; ++i)
00174 {
00175 PxVec3 lpnt;
00176 lpnt[0] = point.x;
00177 lpnt[1] = point.y;
00178 lpnt[2] = point.z;
00179 result += (noiseSample(lpnt, p, g)) * amplitude;
00180 point *= 2.0f;
00181 amplitude *= 0.5f;
00182 }
00183 return result;
00184 }
00185
00186 void init(void)
00187 {
00188 mbInit = true;
00189
00190 unsigned i, j;
00191 int k;
00192
00193 for (i = 0; i < (unsigned)PERLIN_NOISE_SAMPLE_TABLE; i++)
00194 {
00195 p[i] = (int)i;
00196 for (j = 0; j < 3; ++j)
00197 g[i][j] = mRnd->getRandomValue();
00198 g[i].normalize();
00199 }
00200
00201 while (--i)
00202 {
00203 k = p[i];
00204 j = static_cast<uint32_t>(mRnd->getRandomValue() * PERLIN_NOISE_SAMPLE_TABLE);
00205 p[i] = p[j];
00206 p[j] = k;
00207 }
00208
00209 for (i = 0; i < PERLIN_NOISE_SAMPLE_TABLE + 2; ++i)
00210 {
00211 p[(unsigned)PERLIN_NOISE_SAMPLE_TABLE + i] = p[i];
00212 for (j = 0; j < 3; ++j)
00213 g[(unsigned)PERLIN_NOISE_SAMPLE_TABLE + i][j] = g[i][j];
00214 }
00215
00216 }
00217
00218 Nv::Blast::RandomGeneratorBase* mRnd;
00219 int mOctaves;
00220 float mFrequency;
00221 float mAmplitude;
00222
00223
00224 int p[(unsigned)(PERLIN_NOISE_SAMPLE_TABLE + PERLIN_NOISE_SAMPLE_TABLE + 2)];
00225
00226 PxVec3 g[(unsigned)(PERLIN_NOISE_SAMPLE_TABLE + PERLIN_NOISE_SAMPLE_TABLE + 2)];
00227
00228 bool mbInit;
00229 };
00230
00231
00235 class SimplexNoise
00236 {
00237
00238 int32_t mOctaves;
00239 float mAmplitude;
00240 float mFrequency;
00241 int32_t mSeed;
00242
00243 static const int X_NOISE_GEN = 1619;
00244 static const int Y_NOISE_GEN = 31337;
00245 static const int Z_NOISE_GEN = 6971;
00246 static const int W_NOISE_GEN = 1999;
00247 static const int SEED_NOISE_GEN = 1013;
00248 static const int SHIFT_NOISE_GEN = 8;
00249
00250 NV_INLINE int fastfloor(float x)
00251 {
00252 return (x >= 0) ? (int)x : (int)(x - 1);
00253 }
00254
00255 SimplexNoise& operator=(const SimplexNoise&)
00256 {
00257 return *this;
00258 }
00259
00260 public:
00267 SimplexNoise(float ampl, float freq, int32_t octaves, int32_t seed) : mOctaves(octaves), mAmplitude(ampl), mFrequency(freq), mSeed(seed) {};
00268
00269
00270
00280 physx::PxVec4 eval4D(float x, float y, float z, float w, int seed)
00281 {
00282
00283 const float F4 = (physx::PxSqrt(5.0f) - 1.0f) / 4.0f;
00284 const float G4 = (5.0f - physx::PxSqrt(5.0f)) / 20.0f;
00285
00286 float s = (x + y + z + w) * F4;
00287 int ix = fastfloor(x + s);
00288 int iy = fastfloor(y + s);
00289 int iz = fastfloor(z + s);
00290 int iw = fastfloor(w + s);
00291 float tu = (ix + iy + iz + iw) * G4;
00292
00293 float x0 = x - (ix - tu);
00294 float y0 = y - (iy - tu);
00295 float z0 = z - (iz - tu);
00296 float w0 = w - (iw - tu);
00297
00298 int c = (x0 > y0) ? (1 << 0) : (1 << 2);
00299 c += (x0 > z0) ? (1 << 0) : (1 << 4);
00300 c += (x0 > w0) ? (1 << 0) : (1 << 6);
00301 c += (y0 > z0) ? (1 << 2) : (1 << 4);
00302 c += (y0 > w0) ? (1 << 2) : (1 << 6);
00303 c += (z0 > w0) ? (1 << 4) : (1 << 6);
00304
00305 physx::PxVec4 res;
00306 res.setZero();
00307
00308
00309 for (int p = 4; p >= 0; --p)
00310 {
00311 int ixp = ((c >> 0) & 3) >= p ? 1 : 0;
00312 int iyp = ((c >> 2) & 3) >= p ? 1 : 0;
00313 int izp = ((c >> 4) & 3) >= p ? 1 : 0;
00314 int iwp = ((c >> 6) & 3) >= p ? 1 : 0;
00315
00316 float xp = x0 - ixp + (4 - p) * G4;
00317 float yp = y0 - iyp + (4 - p) * G4;
00318 float zp = z0 - izp + (4 - p) * G4;
00319 float wp = w0 - iwp + (4 - p) * G4;
00320
00321 float t = 0.6f - xp * xp - yp * yp - zp * zp - wp * wp;
00322 if (t > 0)
00323 {
00324
00325 int gradIndex = int((
00326 X_NOISE_GEN * (ix + ixp)
00327 + Y_NOISE_GEN * (iy + iyp)
00328 + Z_NOISE_GEN * (iz + izp)
00329 + W_NOISE_GEN * (iw + iwp)
00330 + SEED_NOISE_GEN * seed)
00331 & 0xffffffff);
00332 gradIndex ^= (gradIndex >> SHIFT_NOISE_GEN);
00333 gradIndex &= 31;
00334
00335 physx::PxVec4 g;
00336 {
00337 const int h = gradIndex;
00338 const int hs = 2 - (h >> 4);
00339 const int h1 = (h >> 3);
00340 g.x = (h1 == 0) ? 0.0f : ((h & 4) ? -1.0f : 1.0f);
00341 g.y = (h1 == 1) ? 0.0f : ((h & (hs << 1)) ? -1.0f : 1.0f);
00342 g.z = (h1 == 2) ? 0.0f : ((h & hs) ? -1.0f : 1.0f);
00343 g.w = (h1 == 3) ? 0.0f : ((h & 1) ? -1.0f : 1.0f);
00344 }
00345 float gdot = (g.x * xp + g.y * yp + g.z * zp + g.w * wp);
00346
00347 float t2 = t * t;
00348 float t3 = t2 * t;
00349 float t4 = t3 * t;
00350
00351 float dt4gdot = 8 * t3 * gdot;
00352
00353 res.x += t4 * g.x - dt4gdot * xp;
00354 res.y += t4 * g.y - dt4gdot * yp;
00355 res.z += t4 * g.z - dt4gdot * zp;
00356 res.w += t4 * gdot;
00357 }
00358 }
00359
00360 res *= 27;
00361 return res;
00362 }
00363
00369 float sample(physx::PxVec3 p)
00370 {
00371 p *= mFrequency;
00372 float result = 0.0f;
00373 float alpha = 1;
00374 for (int32_t i = 1; i <= mOctaves; ++i)
00375 {
00376 result += eval4D(p.x * i, p.y * i, p.z * i, i * 5.0f, mSeed).w * alpha;
00377 alpha *= 0.45;
00378 }
00379 return result * mAmplitude;
00380 }
00381
00382 };
00383
00384
00385 }
00386 }
00387
00388
00389
00390 #endif