#pragma once // Some settings #define NOISE_USE_INLINE 1 #define NOISE_USE_SSE 0 #define NOISE_DATATYPE float // Do not touch #if NOISE_USE_INLINE #ifdef _MSC_VER #define __NOISE_INLINE__ __forceinline #else #define __NOISE_INLINE__ inline #endif // _MSC_VER #else #define __NOISE_INLINE__ #endif #if NOISE_USE_SSE #include #endif class cNoise { public: cNoise( unsigned int a_Seed ); #if NOISE_USE_SSE __m128 SSE_IntNoise2D( int a_X1, int a_Y1, int a_X2, int a_Y2, int a_X3, int a_Y3, int a_X4, int a_Y4 ) const; #endif __NOISE_INLINE__ float IntNoise( int a_X ) const; __NOISE_INLINE__ float IntNoise2D( int a_X, int a_Y ) const; __NOISE_INLINE__ float IntNoise3D( int a_X, int a_Y, int a_Z ) const; // Note: These functions have a mod8-irregular chance - each of the mod8 remainders has different chance of occurrence. Divide by 8 to rectify. __NOISE_INLINE__ int IntNoise1DInt( int a_X ) const; __NOISE_INLINE__ int IntNoise2DInt( int a_X, int a_Y ) const; __NOISE_INLINE__ int IntNoise3DInt( int a_X, int a_Y, int a_Z ) const; float LinearNoise1D( float a_X ) const; float CosineNoise1D( float a_X ) const; float CubicNoise1D( float a_X ) const; float SmoothNoise1D( int a_X ) const; float LinearNoise2D( float a_X, float a_Y ) const; float CosineNoise2D( float a_X, float a_Y ) const; float CubicNoise2D( float a_X, float a_Y ) const; float SSE_CubicNoise2D( float a_X, float a_Y ) const; float CosineNoise3D( float a_X, float a_Y, float a_Z ) const; float CubicNoise3D( float a_X, float a_Y, float a_Z ) const; void SetSeed( unsigned int a_Seed ) { m_Seed = a_Seed; } __NOISE_INLINE__ static float CubicInterpolate (float a_A, float a_B, float a_C, float a_D, float a_Pct); __NOISE_INLINE__ static float CosineInterpolate(float a_A, float a_B, float a_Pct); __NOISE_INLINE__ static float LinearInterpolate(float a_A, float a_B, float a_Pct); private: #if NOISE_USE_SSE __m128 CubicInterpolate4( const __m128 & a_A, const __m128 & a_B, const __m128 & a_C, const __m128 & a_D, float a_Pct ) const; #endif unsigned int m_Seed; }; /// Linearly interpolates values in the array between the anchor points extern void IntArrayLinearInterpolate2D( int * a_Array, int a_SizeX, int a_SizeY, // Dimensions of the array int a_AnchorStepX, int a_AnchorStepY // Distances between the anchor points in each direction ); /// Linearly interpolates values in the array between the anchor points; universal data type template void ArrayLinearInterpolate2D( TYPE * a_Array, int a_SizeX, int a_SizeY, // Dimensions of the array int a_AnchorStepX, int a_AnchorStepY // Distances between the anchor points in each direction ) { // First interpolate columns where the anchor points are: int LastYCell = a_SizeY - a_AnchorStepY; for (int y = 0; y < LastYCell; y += a_AnchorStepY) { int Idx = a_SizeX * y; for (int x = 0; x < a_SizeX; x += a_AnchorStepX) { TYPE StartValue = a_Array[Idx]; TYPE EndValue = a_Array[Idx + a_SizeX * a_AnchorStepY]; TYPE Diff = EndValue - StartValue; for (int CellY = 1; CellY < a_AnchorStepY; CellY++) { a_Array[Idx + a_SizeX * CellY] = StartValue + Diff * CellY / a_AnchorStepY; } // for CellY Idx += a_AnchorStepX; } // for x } // for y // Now interpolate in rows, each row has values in the anchor columns int LastXCell = a_SizeX - a_AnchorStepX; for (int y = 0; y < a_SizeY; y++) { int Idx = a_SizeX * y; for (int x = 0; x < LastXCell; x += a_AnchorStepX) { TYPE StartValue = a_Array[Idx]; TYPE EndValue = a_Array[Idx + a_AnchorStepX]; TYPE Diff = EndValue - StartValue; for (int CellX = 1; CellX < a_AnchorStepX; CellX++) { a_Array[Idx + CellX] = StartValue + CellX * Diff / a_AnchorStepX; } // for CellY Idx += a_AnchorStepX; } } } #if NOISE_USE_INLINE #include "Noise.inc" #endif class cCubicNoise { public: static const int MAX_SIZE = 512; ///< Maximum size of each dimension of the query arrays. cCubicNoise(int a_Seed); void Generate1D( NOISE_DATATYPE * a_Array, ///< Array to generate into int a_SizeX, ///< Count of the array NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array NOISE_DATATYPE * a_Workspace = NULL ///< Workspace that this function can use and trash ); void Generate2D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, ///< Count of the array, in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, ///< Noise-space coords of the array in the Y direction NOISE_DATATYPE * a_Workspace = NULL ///< Workspace that this function can use and trash ); void Generate3D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y + a_SizeX * a_SizeY * z] int a_SizeX, int a_SizeY, int a_SizeZ, ///< Count of the array, in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, ///< Noise-space coords of the array in the Y direction NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ, ///< Noise-space coords of the array in the Z direction NOISE_DATATYPE * a_Workspace = NULL ///< Workspace that this function can use and trash ); protected: typedef NOISE_DATATYPE Workspace1D[4]; typedef NOISE_DATATYPE Workspace2D[4][4]; cNoise m_Noise; // Used for integral rnd values /// Calculates the integral and fractional parts along one axis. void CalcFloorFrac( int a_Size, NOISE_DATATYPE a_Start, NOISE_DATATYPE a_End, int * a_Floor, NOISE_DATATYPE * a_Frac, int * a_Same, int & a_NumSame ); void UpdateWorkRnds2DX( Workspace2D & a_WorkRnds, Workspace1D & a_Interps, int a_LastFloorX, int a_NewFloorX, int a_FloorY, NOISE_DATATYPE a_FractionY ); } ; class cPerlinNoise { public: void Generate1D( NOISE_DATATYPE * a_Array, ///< Array to generate into int a_SizeX, ///< Count of the array NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array NOISE_DATATYPE * a_Workspace = NULL ///< Workspace that this function can use and trash ); void Generate2D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, ///< Count of the array, in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, ///< Noise-space coords of the array in the Y direction NOISE_DATATYPE * a_Workspace = NULL ///< Workspace that this function can use and trash ); void Generate3D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y + a_SizeX * a_SizeY * z] int a_SizeX, int a_SizeY, int a_SizeZ, ///< Count of the array, in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, ///< Noise-space coords of the array in the Y direction NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ, ///< Noise-space coords of the array in the Z direction NOISE_DATATYPE * a_Workspace = NULL ///< Workspace that this function can use and trash ); } ;