/* * Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved. * * NVIDIA CORPORATION and its licensors retain all intellectual property * and proprietary rights in and to this software, related documentation * and any modifications thereto. Any use, reproduction, disclosure or * distribution of this software and related documentation without an express * license agreement from NVIDIA CORPORATION is strictly prohibited. */ #ifndef SIMPLEX_NOISE_H #define SIMPLEX_NOISE_H #include "PxVec4.h" namespace nvidia { namespace apex { class SimplexNoise { static const int X_NOISE_GEN = 1619; static const int Y_NOISE_GEN = 31337; static const int Z_NOISE_GEN = 6971; static const int W_NOISE_GEN = 1999; static const int SEED_NOISE_GEN = 1013; static const int SHIFT_NOISE_GEN = 8; PX_CUDA_CALLABLE static PX_INLINE int fastfloor(float x) { return (x >= 0) ? (int)x : (int)(x - 1); } public: // 4D simplex noise // returns: (x,y,z) = noise grad, w = noise value PX_CUDA_CALLABLE static physx::PxVec4 eval4D(float x, float y, float z, float w, int seed) { // The skewing and unskewing factors are hairy again for the 4D case const float F4 = (physx::PxSqrt(5.0f) - 1.0f) / 4.0f; const float G4 = (5.0f - physx::PxSqrt(5.0f)) / 20.0f; // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in float s = (x + y + z + w) * F4; // Factor for 4D skewing int ix = fastfloor(x + s); int iy = fastfloor(y + s); int iz = fastfloor(z + s); int iw = fastfloor(w + s); float t = (ix + iy + iz + iw) * G4; // Factor for 4D unskewing // Unskew the cell origin back to (x,y,z,w) space float x0 = x - (ix - t); // The x,y,z,w distances from the cell origin float y0 = y - (iy - t); float z0 = z - (iz - t); float w0 = w - (iw - t); int c = (x0 > y0) ? (1 << 0) : (1 << 2); c += (x0 > z0) ? (1 << 0) : (1 << 4); c += (x0 > w0) ? (1 << 0) : (1 << 6); c += (y0 > z0) ? (1 << 2) : (1 << 4); c += (y0 > w0) ? (1 << 2) : (1 << 6); c += (z0 > w0) ? (1 << 4) : (1 << 6); physx::PxVec4 res; res.setZero(); // Calculate the contribution from the five corners #ifdef __CUDACC__ #pragma unroll #endif for (int p = 4; p >= 0; --p) { int ixp = ((c >> 0) & 3) >= p ? 1 : 0; int iyp = ((c >> 2) & 3) >= p ? 1 : 0; int izp = ((c >> 4) & 3) >= p ? 1 : 0; int iwp = ((c >> 6) & 3) >= p ? 1 : 0; float xp = x0 - ixp + (4 - p) * G4; float yp = y0 - iyp + (4 - p) * G4; float zp = z0 - izp + (4 - p) * G4; float wp = w0 - iwp + (4 - p) * G4; float t = 0.6f - xp * xp - yp * yp - zp * zp - wp * wp; if (t > 0) { //get index int gradIndex = int(( X_NOISE_GEN * (ix + ixp) + Y_NOISE_GEN * (iy + iyp) + Z_NOISE_GEN * (iz + izp) + W_NOISE_GEN * (iw + iwp) + SEED_NOISE_GEN * seed) & 0xffffffff); gradIndex ^= (gradIndex >> SHIFT_NOISE_GEN); gradIndex &= 31; physx::PxVec4 g; { const int h = gradIndex; const int hs = 2 - (h >> 4); const int h1 = (h >> 3); g.x = (h1 == 0) ? 0.0f : ((h & 4) ? -1.0f : 1.0f); g.y = (h1 == 1) ? 0.0f : ((h & (hs << 1)) ? -1.0f : 1.0f); g.z = (h1 == 2) ? 0.0f : ((h & hs) ? -1.0f : 1.0f); g.w = (h1 == 3) ? 0.0f : ((h & 1) ? -1.0f : 1.0f); } float gdot = (g.x * xp + g.y * yp + g.z * zp + g.w * wp); float t2 = t * t; float t3 = t2 * t; float t4 = t3 * t; float dt4gdot = 8 * t3 * gdot; res.x += t4 * g.x - dt4gdot * xp; res.y += t4 * g.y - dt4gdot * yp; res.z += t4 * g.z - dt4gdot * zp; res.w += t4 * gdot; } } // scale the result to cover the range [-1,1] res *= 27; return res; } }; } } // namespace nvidia::apex #endif