| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- // Modified from original
- /*
- Based in part on Perlin noise
- http ://mrl.nyu.edu/~perlin/doc/oscar.html#noise
- Copyright(c) Ken Perlin
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"),
- to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- IN THE SOFTWARE.
- */
- #ifndef CRYINCLUDE_CRYCOMMON_PNOISE3_H
- #define CRYINCLUDE_CRYCOMMON_PNOISE3_H
- #pragma once
- #include <Random.h>
- #define NOISE_TABLE_SIZE 256
- #define NOISE_MASK (NOISE_TABLE_SIZE-1)
- namespace
- {
- const int kDefaultSeed=0;
- }
- //////////////////////////////////////////////////////////////////////////
- class CPNoise3
- {
- public:
- CPNoise3(void)
- {
- SetSeedAndReinitialize(kDefaultSeed);
- }
- //////////////////////////////////////////////////////////////////////////
- // 1D quality noise generator, good for many situations like up/down movements,
- // flickering/ambient lights etc.
- // A typical usage would be to pass system time multiplied by a frequency value, like:
- // float fRes=pNoise->Noise1D(fCurrentTime*fFreq);
- // the lower the frequency, the smoother the output
- inline float Noise1D(float x)
- {
- // Compute what gradients to use
- int qx0 = (int)floorf(x);
- int qx1 = qx0 + 1;
- float tx0 = x - (float)qx0;
- float tx1 = tx0 - 1;
- // Make sure we don't come outside the lookup table
- qx0 = qx0 & NOISE_MASK;
- qx1 = qx1 & NOISE_MASK;
- // Compute the dotproduct between the vectors and the gradients
- float v0 = m_gx[qx0]*tx0;
- float v1 = m_gx[qx1]*tx1;
- // Modulate with the weight function
- float wx = (3 - 2*tx0)*tx0*tx0;
- float v = v0 - wx*(v0 - v1);
- return v;
- }
- //////////////////////////////////////////////////////////////////////////
- // 2D quality noise generator, twice slower than Noise1D.
- // A typical usage would be to pass 2d coordinates multiplied by a frequency value, like:
- // float fRes=pNoise->Noise2D(fX*fFreq,fY*fFreq);
- inline float Noise2D(float x, float y)
- {
- // Compute what gradients to use
- int qx0 = (int)floorf(x);
- int qx1 = qx0 + 1;
- float tx0 = x - (float)qx0;
- float tx1 = tx0 - 1;
- int qy0 = (int)floorf(y);
- int qy1 = qy0 + 1;
- float ty0 = y - (float)qy0;
- float ty1 = ty0 - 1;
- // Make sure we don't come outside the lookup table
- qx0 = qx0 & NOISE_MASK;
- qx1 = qx1 & NOISE_MASK;
- qy0 = qy0 & NOISE_MASK;
- qy1 = qy1 & NOISE_MASK;
- // Permutate values to get pseudo randomly chosen gradients
- int q00 = m_p[(qy0 + m_p[qx0]) & NOISE_MASK];
- int q01 = m_p[(qy0 + m_p[qx1]) & NOISE_MASK];
- int q10 = m_p[(qy1 + m_p[qx0]) & NOISE_MASK];
- int q11 = m_p[(qy1 + m_p[qx1]) & NOISE_MASK];
- // Compute the dotproduct between the vectors and the gradients
- float v00 = m_gx[q00]*tx0 + m_gy[q00]*ty0;
- float v01 = m_gx[q01]*tx1 + m_gy[q01]*ty0;
- float v10 = m_gx[q10]*tx0 + m_gy[q10]*ty1;
- float v11 = m_gx[q11]*tx1 + m_gy[q11]*ty1;
- // Modulate with the weight function
- float wx = (3 - 2*tx0)*tx0*tx0;
- float v0 = v00 - wx*(v00 - v01);
- float v1 = v10 - wx*(v10 - v11);
- float wy = (3 - 2*ty0)*ty0*ty0;
- float v = v0 - wy*(v0 - v1);
- return v;
- }
- //////////////////////////////////////////////////////////////////////////
- // 3D quality noise generator, twice slower than Noise2D, so use with care...
- // A typical usage would be to pass 3d coordinates multiplied by a frequency value, like:
- // float fRes=pNoise->Noise2D(fX*fFreq,fY*fFreq,fZ*fFreq);
- inline float Noise3D(float x, float y, float z)
- {
- // Compute what gradients to use
- int qx0 = (int)floorf(x);
- int qx1 = qx0 + 1;
- float tx0 = x - (float)qx0;
- float tx1 = tx0 - 1;
- int qy0 = (int)floorf(y);
- int qy1 = qy0 + 1;
- float ty0 = y - (float)qy0;
- float ty1 = ty0 - 1;
- int qz0 = (int)floorf(z);
- int qz1 = qz0 + 1;
- float tz0 = z - (float)qz0;
- float tz1 = tz0 - 1;
- // Make sure we don't come outside the lookup table
- qx0 = qx0 & NOISE_MASK;
- qx1 = qx1 & NOISE_MASK;
- qy0 = qy0 & NOISE_MASK;
- qy1 = qy1 & NOISE_MASK;
- qz0 = qz0 & NOISE_MASK;
- qz1 = qz1 & NOISE_MASK;
- // Permutate values to get pseudo randomly chosen gradients
- int q000 = m_p[(qz0 + m_p[(qy0 + m_p[qx0]) & NOISE_MASK]) & NOISE_MASK];
- int q001 = m_p[(qz0 + m_p[(qy0 + m_p[qx1]) & NOISE_MASK]) & NOISE_MASK];
- int q010 = m_p[(qz0 + m_p[(qy1 + m_p[qx0]) & NOISE_MASK]) & NOISE_MASK];
- int q011 = m_p[(qz0 + m_p[(qy1 + m_p[qx1]) & NOISE_MASK]) & NOISE_MASK];
- int q100 = m_p[(qz1 + m_p[(qy0 + m_p[qx0]) & NOISE_MASK]) & NOISE_MASK];
- int q101 = m_p[(qz1 + m_p[(qy0 + m_p[qx1]) & NOISE_MASK]) & NOISE_MASK];
- int q110 = m_p[(qz1 + m_p[(qy1 + m_p[qx0]) & NOISE_MASK]) & NOISE_MASK];
- int q111 = m_p[(qz1 + m_p[(qy1 + m_p[qx1]) & NOISE_MASK]) & NOISE_MASK];
- // Compute the dotproduct between the vectors and the gradients
- float v000 = m_gx[q000]*tx0 + m_gy[q000]*ty0 + m_gz[q000]*tz0;
- float v001 = m_gx[q001]*tx1 + m_gy[q001]*ty0 + m_gz[q001]*tz0;
- float v010 = m_gx[q010]*tx0 + m_gy[q010]*ty1 + m_gz[q010]*tz0;
- float v011 = m_gx[q011]*tx1 + m_gy[q011]*ty1 + m_gz[q011]*tz0;
- float v100 = m_gx[q100]*tx0 + m_gy[q100]*ty0 + m_gz[q100]*tz1;
- float v101 = m_gx[q101]*tx1 + m_gy[q101]*ty0 + m_gz[q101]*tz1;
- float v110 = m_gx[q110]*tx0 + m_gy[q110]*ty1 + m_gz[q110]*tz1;
- float v111 = m_gx[q111]*tx1 + m_gy[q111]*ty1 + m_gz[q111]*tz1;
- // Modulate with the weight function
- float wx = (3 - 2*tx0)*tx0*tx0;
- float v00 = v000 - wx*(v000 - v001);
- float v01 = v010 - wx*(v010 - v011);
- float v10 = v100 - wx*(v100 - v101);
- float v11 = v110 - wx*(v110 - v111);
- float wy = (3 - 2*ty0)*ty0*ty0;
- float v0 = v00 - wy*(v00 - v01);
- float v1 = v10 - wy*(v10 - v11);
- float wz = (3 - 2*tz0)*tz0*tz0;
- float v = v0 - wz*(v0 - v1);
- return v;
- }
- //////////////////////////////////////////////////////////////////////////
- // this needs to be called only once and it's already done by crysystem in the singleton constructor
- // Note that every time the initialization function gets called, the PRNG will return
- // different values, thus creating different gradients. Not a bad thing but probably
- // not your expected behavior
- inline void SetSeedAndReinitialize(uint seedValue)
- {
- int i, j, nSwap;
- m_random_generator.Seed(seedValue);
- // Initialize the permutation table
- for(i = 0; i < NOISE_TABLE_SIZE; i++)
- m_p[i] = static_cast<unsigned char>(i);
- for(i = 0; i < NOISE_TABLE_SIZE; i++)
- {
- j = (m_random_generator.GenerateUint32())&NOISE_MASK;
- nSwap = m_p[i];
- m_p[i] = m_p[j];
- m_p[j] = static_cast<unsigned char>(nSwap);
- }
- // Generate the gradient lookup tables
- for(i = 0; i < NOISE_TABLE_SIZE; i++)
- {
- // Ken Perlin proposes that the gradients are taken from the unit
- // circle/sphere for 2D/3D.
- // So lets generate a good pseudo-random vector and normalize it
- Vec3 v;
- // cry_frand is in the 0..1 range
- v.x=-0.5f+m_random_generator.GenerateFloat();
- v.y=-0.5f+m_random_generator.GenerateFloat();
- v.z=-0.5f+m_random_generator.GenerateFloat();
- v.Normalize();
- m_gx[i] = v.x;
- m_gy[i] = v.y;
- m_gz[i] = v.z;
- }
- }
- private:
- CRndGen m_random_generator;
- // Permutation table
- unsigned char m_p[NOISE_TABLE_SIZE];
- // Gradients
- float m_gx[NOISE_TABLE_SIZE];
- float m_gy[NOISE_TABLE_SIZE];
- float m_gz[NOISE_TABLE_SIZE];
- };
- #endif // CRYINCLUDE_CRYCOMMON_PNOISE3_H
|