etqw-sdk/source/idlib/math/Perlin.h

155 lines
4.4 KiB
C++

// Copyright (C) 2007 Id Software, Inc.
//
#ifndef __MATH_PERLIN_H__
#define __MATH_PERLIN_H__
/*
===============================================================================
Perlin 3D noise generator
===============================================================================
*/
class sdPerlin {
public:
//if alternative is true use other seed primes so we get a different noise shape
sdPerlin( float _persistence = 0.5f, int _octaves = 4, float _frequency = 1.0f );
void SetTileX( int tile );
void SetTileY( int tile );
void SetTileZ( int tile );
float NoiseFloat( const idVec3 &pos ); // random number in the range [-1.0f, 1.0f]
int NoiseInt( const idVec3 &pos, int max ); // random integer in the range [0, max]
float RawNoise( int x, int y, int z );
private:
float persistence;
float frequency;
int octaves;
int tilex;
int tiley;
int tilez;
int localtilex; //for lower octaves with increased frequency
int localtiley;
int localtilez;
float CosineInterp( float number1, float number2, float x );
//float SmoothedNoise( int x, int y, int z );
float InterpolatedNoise( float x, float y, float z );
};
ID_INLINE int sdPerlin::NoiseInt( const idVec3 &pos, int max ) {
return idMath::Ftoi( NoiseFloat( pos ) * max );
}
ID_INLINE float sdPerlin::CosineInterp( float number1, float number2, float x ) {
float f = ( 1 - idMath::Cos16( x * idMath::PI ) ) * 0.5f;
return number1 * ( 1 - f ) + number2 * f;
}
#if 0
const int PERLIN_RANDOM_SAMPLES = 256;
class sdPerlin2 {
public:
sdPerlin2( void );
static void Init( void );
float Noise( const idVec3& noisePos );
protected:
static bool inited;
static int p[ ( PERLIN_RANDOM_SAMPLES + 1 ) * 2 ];
static idVec3 g[ ( PERLIN_RANDOM_SAMPLES + 1 ) * 2 ];
};
#endif // 0
const int NOISE_WRAP_INDEX = 256;
const int NOISE_MOD_MASK = 255;
const int NOISE_LARGE_PWR2 = 4096;
class sdPerlin2 {
private:
unsigned long initialized;
unsigned long permutationTable[ NOISE_WRAP_INDEX* 2 + 2 ]; // permutation table
float gradientTable1d[ NOISE_WRAP_INDEX * 2 + 2 ]; // 1d gradient lookup table.
float gradientTable2d[ NOISE_WRAP_INDEX * 2 + 2 ][ 2 ]; // 2d gradient lookup table.
float gradientTable3d[ NOISE_WRAP_INDEX * 2 + 2 ][ 3 ]; // 3d gradient lookup table.
float RandNoiseFloat( void ); // generate a random float in [-1,1]
void Normalize2d( float* vector ); // normalize a 2d vector
void Normalize3d( float* vector ); // normalize a 3d vector
void GenerateLookupTables( void ); // fill in table entries
public:
sdPerlin2() :
initialized( 0 ) {
}
void Reseed( void ); // reseed random generator & regenerate tables
void Reseed( unsigned int rSeed ); // same, but with specified seed
float Noise1d( float* pos ); // 1D call using an array for passing pos
float Noise2d( float* pos ); // 2D call using an array for passing pos
float Noise3d( float* pos ); // 3D call using an array for passing pos
float Noise( float ); // use individual elements for passing pos
float Noise( float, float );
float Noise( float, float, float );
};
class sdPerlin3 {
public:
static float Noise1D( float* pos );
static float Noise2D( float* pos );
static float Noise3D( float* pos );
static float Noise( float x );
static float Noise( float x, float y );
static float Noise( float x, float y, float z );
private:
static float Fade( float t );
static float Lerp( float t, float a, float b );
static float Grad( int hash, float x, float y, float z );
private:
static int p[ 512 ];
};
ID_INLINE float sdPerlin3::Noise1D( float* pos ) {
return Noise( *pos );
}
ID_INLINE float sdPerlin3::Noise2D( float* pos ) {
return Noise( *pos, *(pos + 1) );
}
ID_INLINE float sdPerlin3::Noise3D( float* pos ) {
return Noise( *pos, *(pos + 1), *(pos + 2) );
}
ID_INLINE float sdPerlin3::Fade( float t ) {
return( t * t * t * ( t * ( t * 6 - 15 ) + 10 ) );
}
ID_INLINE float sdPerlin3::Lerp( float t, float a, float b ) {
return( a + t * ( b - a ) );
}
ID_INLINE float sdPerlin3::Grad( int hash, float x, float y, float z ) {
int h = hash & 14;
float u = h < 8 ? x : y;
float v = h < 4 ? y : ( h == 12 || h == 14 ? x : z );
return( ( ( h & 1 ) == 0 ? u : -u ) + ( ( h & 2 ) == 0 ? v : -v ) );
}
#endif //__MATH_PERLIN_H__