PerlinNoise.cpp 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. #include "PerlinNoise.h"
  2. #include <random>
  3. #include <algorithm>
  4. PerlinNoise::PerlinNoise( int seed )
  5. : Noise()
  6. {
  7. this->seed = seed;
  8. p.resize( 256 );
  9. std::iota( p.begin(), p.end(), 0 );
  10. std::default_random_engine engine( seed );
  11. std::shuffle( p.begin(), p.end(), engine );
  12. p.insert( p.end(), p.begin(), p.end() );
  13. }
  14. int PerlinNoise::getSeed() const
  15. {
  16. return seed;
  17. }
  18. double PerlinNoise::getNoise( double x, double y, double z ) const
  19. {
  20. // Find the unit cube that contains the point
  21. int X = (int)floor( x ) & 255;
  22. int Y = (int)floor( y ) & 255;
  23. int Z = (int)floor( z ) & 255;
  24. // Find relative x, y,z of point in cube
  25. x -= floor( x );
  26. y -= floor( y );
  27. z -= floor( z );
  28. // Compute fade curves for each of x, y, z
  29. double u = fade( x );
  30. double v = fade( y );
  31. double w = fade( z );
  32. // Hash coordinates of the 8 cube corners
  33. int A = p[ X ] + Y;
  34. int AA = p[ A ] + Z;
  35. int AB = p[ A + 1 ] + Z;
  36. int B = p[ X + 1 ] + Y;
  37. int BA = p[ B ] + Z;
  38. int BB = p[ B + 1 ] + Z;
  39. // Add blended results from 8 corners of cube
  40. double res = lerp( w, lerp( v, lerp( u, grad( p[ AA ], x, y, z ), grad( p[ BA ], x - 1, y, z ) ), lerp( u, grad( p[ AB ], x, y - 1, z ), grad( p[ BB ], x - 1, y - 1, z ) ) ), lerp( v, lerp( u, grad( p[ AA + 1 ], x, y, z - 1 ), grad( p[ BA + 1 ], x - 1, y, z - 1 ) ), lerp( u, grad( p[ AB + 1 ], x, y - 1, z - 1 ), grad( p[ BB + 1 ], x - 1, y - 1, z - 1 ) ) ) );
  41. return ( res + 1.0 ) / 2.0;
  42. }
  43. double PerlinNoise::fade( double t ) const
  44. {
  45. return t * t * t * ( t * ( t * 6 - 15 ) + 10 );
  46. }
  47. double PerlinNoise::lerp( double t, double a, double b ) const
  48. {
  49. return a + t * ( b - a );
  50. }
  51. double PerlinNoise::grad( int hash, double x, double y, double z ) const
  52. {
  53. int h = hash & 15;
  54. // Convert lower 4 bits of hash into 12 gradient directions
  55. double u = h < 8 ? x : y,
  56. v = h < 4 ? y : h == 12 || h == 14 ? x : z;
  57. return ( ( h & 1 ) == 0 ? u : -u ) + ( ( h & 2 ) == 0 ? v : -v );
  58. }