Main Page Class List Class Members

NvBlastExtAuthoringPerlinNoise.h
Go to the documentation of this file.
1 // This code contains NVIDIA Confidential Information and is disclosed to you
2 // under a form of NVIDIA software license agreement provided separately to you.
3 //
4 // Notice
5 // NVIDIA Corporation and its licensors retain all intellectual property and
6 // proprietary rights in and to this software and related documentation and
7 // any modifications thereto. Any use, reproduction, disclosure, or
8 // distribution of this software and related documentation without an express
9 // license agreement from NVIDIA Corporation is strictly prohibited.
10 //
11 // ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
12 // NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
13 // THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
14 // MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
15 //
16 // Information and code furnished is believed to be accurate and reliable.
17 // However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
18 // information or for any infringement of patents or other rights of third parties that may
19 // result from its use. No license is granted by implication or otherwise under any patent
20 // or patent rights of NVIDIA Corporation. Details are subject to change without notice.
21 // This code supersedes and replaces all information previously supplied.
22 // NVIDIA Corporation products are not authorized for use as critical
23 // components in life support devices or systems without express written approval of
24 // NVIDIA Corporation.
25 //
26 // Copyright (c) 2020 NVIDIA Corporation. All rights reserved.
27
28
29 #ifndef NVBLASTEXTAUTHORINGPERLINNOISE_H
30 #define NVBLASTEXTAUTHORINGPERLINNOISE_H
31
32 #include <NvBlastExtAuthoringFractureTool.h>
33
34 #include <PxVec4.h>
35 #include <PxVec3.h>
36
37 #define PERLIN_NOISE_SAMPLE_TABLE 512
38 using physx::PxVec3;
39 namespace Nv
40 {
41 namespace Blast
42 {
43
44 /***********
45 Noise generation routines, copied from Apex.
46 */
47
48
49 NV_INLINE float at3(const float& rx, const float& ry, const float& rz, const PxVec3 q)
50 {
51 return rx * q[0] + ry * q[1] + rz * q[2];
52 }
53
54 NV_INLINE float fade(float t) { return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f); }
55
56 NV_INLINE float lerp(float t, float a, float b) { return a + t * (b - a); }
57
58 NV_INLINE void setup(int i, PxVec3 point, float& t, int& b0, int& b1, float& r0, float& r1)
59 {
60 t = point[i] + (0x1000);
61 b0 = ((int)t) & (PERLIN_NOISE_SAMPLE_TABLE - 1);
62 b1 = (b0 + 1) & (PERLIN_NOISE_SAMPLE_TABLE - 1);
63 r0 = t - (int)t;
64 r1 = r0 - 1.0f;
65 }
66
67
68 NV_INLINE float noiseSample(PxVec3 point, int* p, PxVec3* g)
69 {
70 int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
71 float rx0, rx1, ry0, ry1, rz0, rz1, sy, sz, a, b, c, d, t, u, v;
72 PxVec3 q;
73 int i, j;
74
75 setup(0, point, t, bx0, bx1, rx0, rx1);
76 setup(1, point, t, by0, by1, ry0, ry1);
77 setup(2, point, t, bz0, bz1, rz0, rz1);
78
79 i = p[bx0];
80 j = p[bx1];
81
82 b00 = p[i + by0];
83 b10 = p[j + by0];
84 b01 = p[i + by1];
85 b11 = p[j + by1];
86
87 t = fade(rx0);
88 sy = fade(ry0);
89 sz = fade(rz0);
90
91 q = g[b00 + bz0]; u = at3(rx0, ry0, rz0, q);
92 q = g[b10 + bz0]; v = at3(rx1, ry0, rz0, q);
93 a = lerp(t, u, v);
94
95 q = g[b01 + bz0]; u = at3(rx0, ry1, rz0, q);
96 q = g[b11 + bz0]; v = at3(rx1, ry1, rz0, q);
97 b = lerp(t, u, v);
98
99 c = lerp(sy, a, b);
100
101 q = g[b00 + bz1]; u = at3(rx0, ry0, rz1, q);
102 q = g[b10 + bz1]; v = at3(rx1, ry0, rz1, q);
103 a = lerp(t, u, v);
104
105 q = g[b01 + bz1]; u = at3(rx0, ry1, rz1, q);
106 q = g[b11 + bz1]; v = at3(rx1, ry1, rz1, q);
107 b = lerp(t, u, v);
108
109 d = lerp(sy, a, b);
110
111 return lerp(sz, c, d);
112 }
113
117 class PerlinNoise
118 {
119 public:
126 PerlinNoise(Nv::Blast::RandomGeneratorBase* rnd, int octaves = 1, float frequency = 1., float amplitude = 1.)
127 : mRnd(rnd),
128 mOctaves(octaves),
129 mFrequency(frequency),
130 mAmplitude(amplitude),
131 mbInit(false)
132 {
133
134 }
135
136 /*
137 Reset state of noise generator
138 \param[in] octaves Number of noise octaves
139 \param[in] frequency Frequency of noise
140 \param[in] amplitude Amplitude of noise
141 */
142 void reset(int octaves = 1, float frequency = 1.f, float amplitude = 1.f)
143 {
144 mOctaves = octaves;
145 mFrequency = frequency;
146 mAmplitude = amplitude;
147 init();
148 }
149
153 float sample(const physx::PxVec3& point)
154 {
155 return perlinNoise(point);
156 }
157
158 private:
159 PerlinNoise& operator=(const PerlinNoise&);
160
161 float perlinNoise(physx::PxVec3 point)
162 {
163 if (!mbInit)
164 init();
165
166 const int octaves = mOctaves;
167 const float frequency = mFrequency;
168 float amplitude = mAmplitude;
169 float result = 0.0f;
170
171 point *= frequency;
172
173 for (int i = 0; i < octaves; ++i)
174 {
175 PxVec3 lpnt;
176 lpnt[0] = point.x;
177 lpnt[1] = point.y;
178 lpnt[2] = point.z;
179 result += (noiseSample(lpnt, p, g)) * amplitude;
180 point *= 2.0f;
181 amplitude *= 0.5f;
182 }
183 return result;
184 }
185
186 void init(void)
187 {
188 mbInit = true;
189
190 unsigned i, j;
191 int k;
192
193 for (i = 0; i < (unsigned)PERLIN_NOISE_SAMPLE_TABLE; i++)
194 {
195 p[i] = (int)i;
196 for (j = 0; j < 3; ++j)
197 g[i][j] = mRnd->getRandomValue();
198 g[i].normalize();
199 }
200
201 while (--i)
202 {
203 k = p[i];
204 j = static_cast<uint32_t>(mRnd->getRandomValue() * PERLIN_NOISE_SAMPLE_TABLE);
205 p[i] = p[j];
206 p[j] = k;
207 }
208
209 for (i = 0; i < PERLIN_NOISE_SAMPLE_TABLE + 2; ++i)
210 {
211 p[(unsigned)PERLIN_NOISE_SAMPLE_TABLE + i] = p[i];
212 for (j = 0; j < 3; ++j)
213 g[(unsigned)PERLIN_NOISE_SAMPLE_TABLE + i][j] = g[i][j];
214 }
215
216 }
217
218 Nv::Blast::RandomGeneratorBase* mRnd;
219 int mOctaves;
220 float mFrequency;
221 float mAmplitude;
222
223 // Permutation vector
224 int p[(unsigned)(PERLIN_NOISE_SAMPLE_TABLE + PERLIN_NOISE_SAMPLE_TABLE + 2)];
225 // Gradient vector
226 PxVec3 g[(unsigned)(PERLIN_NOISE_SAMPLE_TABLE + PERLIN_NOISE_SAMPLE_TABLE + 2)];
227
228 bool mbInit;
229 };
230
231
235 class SimplexNoise
236 {
237
238 int32_t mOctaves;
239 float mAmplitude;
240 float mFrequency;
241 int32_t mSeed;
242
243 static const int X_NOISE_GEN = 1619;
244 static const int Y_NOISE_GEN = 31337;
245 static const int Z_NOISE_GEN = 6971;
246 static const int W_NOISE_GEN = 1999;
247 static const int SEED_NOISE_GEN = 1013;
248 static const int SHIFT_NOISE_GEN = 8;
249
250 NV_INLINE int fastfloor(float x)
251 {
252 return (x >= 0) ? (int)x : (int)(x - 1);
253 }
254
255 SimplexNoise& operator=(const SimplexNoise&)
256 {
257 return *this;
258 }
259
260 public:
267 SimplexNoise(float ampl, float freq, int32_t octaves, int32_t seed) : mOctaves(octaves), mAmplitude(ampl), mFrequency(freq), mSeed(seed) {};
268 // 4D simplex noise
269 // returns: (x,y,z) = noise grad, w = noise value
270
280 physx::PxVec4 eval4D(float x, float y, float z, float w, int seed)
281 {
282 // The skewing and unskewing factors are hairy again for the 4D case
283 const float F4 = (physx::PxSqrt(5.0f) - 1.0f) / 4.0f;
284 const float G4 = (5.0f - physx::PxSqrt(5.0f)) / 20.0f;
285 // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
286 float s = (x + y + z + w) * F4; // Factor for 4D skewing
287 int ix = fastfloor(x + s);
288 int iy = fastfloor(y + s);
289 int iz = fastfloor(z + s);
290 int iw = fastfloor(w + s);
291 float tu = (ix + iy + iz + iw) * G4; // Factor for 4D unskewing
292 // Unskew the cell origin back to (x,y,z,w) space
293 float x0 = x - (ix - tu); // The x,y,z,w distances from the cell origin
294 float y0 = y - (iy - tu);
295 float z0 = z - (iz - tu);
296 float w0 = w - (iw - tu);
297
298 int c = (x0 > y0) ? (1 << 0) : (1 << 2);
299 c += (x0 > z0) ? (1 << 0) : (1 << 4);
300 c += (x0 > w0) ? (1 << 0) : (1 << 6);
301 c += (y0 > z0) ? (1 << 2) : (1 << 4);
302 c += (y0 > w0) ? (1 << 2) : (1 << 6);
303 c += (z0 > w0) ? (1 << 4) : (1 << 6);
304
305 physx::PxVec4 res;
306 res.setZero();
307
308 // Calculate the contribution from the five corners
309 for (int p = 4; p >= 0; --p)
310 {
311 int ixp = ((c >> 0) & 3) >= p ? 1 : 0;
312 int iyp = ((c >> 2) & 3) >= p ? 1 : 0;
313 int izp = ((c >> 4) & 3) >= p ? 1 : 0;
314 int iwp = ((c >> 6) & 3) >= p ? 1 : 0;
315
316 float xp = x0 - ixp + (4 - p) * G4;
317 float yp = y0 - iyp + (4 - p) * G4;
318 float zp = z0 - izp + (4 - p) * G4;
319 float wp = w0 - iwp + (4 - p) * G4;
320
321 float t = 0.6f - xp * xp - yp * yp - zp * zp - wp * wp;
322 if (t > 0)
323 {
324 //get index
325 int gradIndex = int((
326 X_NOISE_GEN * (ix + ixp)
327 + Y_NOISE_GEN * (iy + iyp)
328 + Z_NOISE_GEN * (iz + izp)
329 + W_NOISE_GEN * (iw + iwp)
330 + SEED_NOISE_GEN * seed)
331 & 0xffffffff);
332 gradIndex ^= (gradIndex >> SHIFT_NOISE_GEN);
333 gradIndex &= 31;
334
335 physx::PxVec4 g;
336 {
337 const int h = gradIndex;
338 const int hs = 2 - (h >> 4);
339 const int h1 = (h >> 3);
340 g.x = (h1 == 0) ? 0.0f : ((h & 4) ? -1.0f : 1.0f);
341 g.y = (h1 == 1) ? 0.0f : ((h & (hs << 1)) ? -1.0f : 1.0f);
342 g.z = (h1 == 2) ? 0.0f : ((h & hs) ? -1.0f : 1.0f);
343 g.w = (h1 == 3) ? 0.0f : ((h & 1) ? -1.0f : 1.0f);
344 }
345 float gdot = (g.x * xp + g.y * yp + g.z * zp + g.w * wp);
346
347 float t2 = t * t;
348 float t3 = t2 * t;
349 float t4 = t3 * t;
350
351 float dt4gdot = 8 * t3 * gdot;
352
353 res.x += t4 * g.x - dt4gdot * xp;
354 res.y += t4 * g.y - dt4gdot * yp;
355 res.z += t4 * g.z - dt4gdot * zp;
356 res.w += t4 * gdot;
357 }
358 }
359 // scale the result to cover the range [-1,1]
360 res *= 27;
361 return res;
362 }
363
369 float sample(physx::PxVec3 p)
370 {
371 p *= mFrequency;
372 float result = 0.0f;
373 float alpha = 1;
374 for (int32_t i = 1; i <= mOctaves; ++i)
375 {
376 result += eval4D(p.x * i, p.y * i, p.z * i, i * 5.0f, mSeed).w * alpha;
377 alpha *= 0.45;
378 }
379 return result * mAmplitude;
380 }
381
382 };
383
384
385 } // Blast namespace
386 } // Nv namespace
387
388
389
390 #endif
Nv::Blast::SimplexNoise::SimplexNoise
SimplexNoise(float ampl, float freq, int32_t octaves, int32_t seed)
Definition: NvBlastExtAuthoringPerlinNoise.h:267
Nv::Blast::SimplexNoise::eval4D
physx::PxVec4 eval4D(float x, float y, float z, float w, int seed)
Definition: NvBlastExtAuthoringPerlinNoise.h:280
x
SIMD_FORCE_INLINE const btScalar & x() const
Return the x value.
Definition: btVector3.h:275
Nv::Blast::SimplexNoise::sample
float sample(physx::PxVec3 p)
Definition: NvBlastExtAuthoringPerlinNoise.h:369
Nv::Blast::setup
NV_INLINE void setup(int i, PxVec3 point, float &t, int &b0, int &b1, float &r0, float &r1)
Definition: NvBlastExtAuthoringPerlinNoise.h:58
Nv::Blast::RandomGeneratorBase
Definition: NvBlastExtAuthoringFractureTool.h:66
Nv::Blast::RandomGeneratorBase::getRandomValue
virtual float getRandomValue()=0
PERLIN_NOISE_SAMPLE_TABLE
#define PERLIN_NOISE_SAMPLE_TABLE
Definition: NvBlastExtAuthoringPerlinNoise.h:37
Nv::Blast::noiseSample
NV_INLINE float noiseSample(PxVec3 point, int *p, PxVec3 *g)
Definition: NvBlastExtAuthoringPerlinNoise.h:68
Nv::Blast::lerp
NV_INLINE float lerp(float t, float a, float b)
Definition: NvBlastExtAuthoringPerlinNoise.h:56
NvBlastExtAuthoringFractureTool.h
Nv::Blast::at3
NV_INLINE float at3(const float &rx, const float &ry, const float &rz, const PxVec3 q)
Definition: NvBlastExtAuthoringPerlinNoise.h:49
y
SIMD_FORCE_INLINE const btScalar & y() const
Return the y value.
Definition: btVector3.h:277
Nv::Blast::PerlinNoise::reset
void reset(int octaves=1, float frequency=1.f, float amplitude=1.f)
Definition: NvBlastExtAuthoringPerlinNoise.h:142
Nv::Blast::fade
NV_INLINE float fade(float t)
Definition: NvBlastExtAuthoringPerlinNoise.h:54
NV_INLINE
#define NV_INLINE
Definition: NvPreprocessor.h:350
Nv::Blast::PerlinNoise
Definition: NvBlastExtAuthoringPerlinNoise.h:117
Nv::Blast::PerlinNoise::PerlinNoise
PerlinNoise(Nv::Blast::RandomGeneratorBase *rnd, int octaves=1, float frequency=1., float amplitude=1.)
Definition: NvBlastExtAuthoringPerlinNoise.h:126
z
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition: btVector3.h:279
Nv::Blast::SimplexNoise
Definition: NvBlastExtAuthoringPerlinNoise.h:235
Nv::Blast::PerlinNoise::sample
float sample(const physx::PxVec3 &point)
Definition: NvBlastExtAuthoringPerlinNoise.h:153
w
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btVector3.h:281
Nv
Definition: NvBlastArray.h:37