Main Page Class List Class Members

- Main Page
- User's Guide
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

# sdk/extensions/authoring/source/NvBlastExtAuthoringPerlinNoise.h

Go to the documentation of this file.

    00001 // This code contains NVIDIA Confidential Information and is disclosed to you
    00002 // under a form of NVIDIA software license agreement provided separately to you.
    00003 //
    00004 // Notice
    00005 // NVIDIA Corporation and its licensors retain all intellectual property and
    00006 // proprietary rights in and to this software and related documentation and
    00007 // any modifications thereto. Any use, reproduction, disclosure, or
    00008 // distribution of this software and related documentation without an express
    00009 // license agreement from NVIDIA Corporation is strictly prohibited.
    00010 //
    00011 // ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
    00012 // NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
    00013 // THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
    00014 // MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
    00015 //
    00016 // Information and code furnished is believed to be accurate and reliable.
    00017 // However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
    00018 // information or for any infringement of patents or other rights of third parties that may
    00019 // result from its use. No license is granted by implication or otherwise under any patent
    00020 // or patent rights of NVIDIA Corporation. Details are subject to change without notice.
    00021 // This code supersedes and replaces all information previously supplied.
    00022 // NVIDIA Corporation products are not authorized for use as critical
    00023 // components in life support devices or systems without express written approval of
    00024 // NVIDIA Corporation.
    00025 //
    00026 // Copyright (c) 2020 NVIDIA Corporation. All rights reserved.
    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     Noise generation routines, copied from Apex.
    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         Reset state of noise generator
    00138         \param[in] octaves Number of noise octaves
    00139         \param[in] frequency Frequency of noise
    00140         \param[in] amplitude Amplitude of noise
    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     // Permutation vector
    00224     int                             p[(unsigned)(PERLIN_NOISE_SAMPLE_TABLE + PERLIN_NOISE_SAMPLE_TABLE + 2)];
    00225     // Gradient vector
    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     // 4D simplex noise
    00269     // returns: (x,y,z) = noise grad, w = noise value
    00270
    00280     physx::PxVec4 eval4D(float x, float y, float z, float w, int seed)
    00281     {
    00282         // The skewing and unskewing factors are hairy again for the 4D case
    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         // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
    00286         float s = (x + y + z + w) * F4; // Factor for 4D skewing
    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; // Factor for 4D unskewing
    00292                                             // Unskew the cell origin back to (x,y,z,w) space
    00293         float x0 = x - (ix - tu); // The x,y,z,w distances from the cell origin
    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         // Calculate the contribution from the five corners
    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                 //get index
    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         // scale the result to cover the range [-1,1]
    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     } // Blast namespace
    00386 } // Nv namespace
    00387
    00388
    00389
    00390 #endif

Copyright © 2015-2017 NVIDIA Corporation, 2701 San Tomas Expressway, Santa Clara, CA 95050 U.S.A. All rights reserved. www.nvidia.com