2013-04-17 16:57:05 -04:00
|
|
|
|
|
|
|
// Noise.h
|
|
|
|
|
|
|
|
// Declares the cNoise, cCubicNoise and cPerlinNoise classes for generating noise
|
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
#pragma once
|
|
|
|
|
2014-07-27 14:08:33 -04:00
|
|
|
#include <cmath>
|
|
|
|
|
2014-11-17 17:02:53 -05:00
|
|
|
/** The datatype used by all the noise generators. */
|
|
|
|
typedef float NOISE_DATATYPE;
|
2014-07-27 14:08:33 -04:00
|
|
|
|
2014-11-17 17:02:53 -05:00
|
|
|
#include "OctavedNoise.h"
|
2014-11-18 03:49:53 -05:00
|
|
|
#include "RidgedNoise.h"
|
2012-06-14 09:06:06 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class cNoise
|
|
|
|
{
|
|
|
|
public:
|
2014-04-04 06:28:38 -04:00
|
|
|
cNoise(int a_Seed);
|
2013-04-22 15:25:57 -04:00
|
|
|
cNoise(const cNoise & a_Noise);
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2013-04-17 16:57:05 -04:00
|
|
|
// The following functions, if not marked INLINE, are about 20 % slower
|
2014-11-17 17:02:53 -05:00
|
|
|
inline NOISE_DATATYPE IntNoise1D(int a_X) const;
|
|
|
|
inline NOISE_DATATYPE IntNoise2D(int a_X, int a_Y) const;
|
|
|
|
inline NOISE_DATATYPE IntNoise3D(int a_X, int a_Y, int a_Z) const;
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2014-07-27 13:57:47 -04:00
|
|
|
// Return a float number in the specified range:
|
2014-11-17 17:02:53 -05:00
|
|
|
inline NOISE_DATATYPE IntNoise2DInRange(int a_X, int a_Y, float a_Min, float a_Max) const
|
2014-07-27 13:57:47 -04:00
|
|
|
{
|
|
|
|
return a_Min + std::abs(IntNoise2D(a_X, a_Y)) * (a_Max - a_Min);
|
|
|
|
}
|
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
// Note: These functions have a mod8-irregular chance - each of the mod8 remainders has different chance of occurrence. Divide by 8 to rectify.
|
2014-11-17 17:02:53 -05:00
|
|
|
inline int IntNoise1DInt(int a_X) const;
|
|
|
|
inline int IntNoise2DInt(int a_X, int a_Y) const;
|
|
|
|
inline int IntNoise3DInt(int a_X, int a_Y, int a_Z) const;
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2013-04-17 16:57:05 -04:00
|
|
|
NOISE_DATATYPE LinearNoise1D(NOISE_DATATYPE a_X) const;
|
|
|
|
NOISE_DATATYPE CosineNoise1D(NOISE_DATATYPE a_X) const;
|
|
|
|
NOISE_DATATYPE CubicNoise1D (NOISE_DATATYPE a_X) const;
|
|
|
|
NOISE_DATATYPE SmoothNoise1D(int a_X) const;
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2013-04-17 16:57:05 -04:00
|
|
|
NOISE_DATATYPE CubicNoise2D (NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y) const;
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2013-04-17 16:57:05 -04:00
|
|
|
NOISE_DATATYPE CubicNoise3D (NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y, NOISE_DATATYPE a_Z) const;
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2014-04-04 06:28:38 -04:00
|
|
|
void SetSeed(int a_Seed) { m_Seed = a_Seed; }
|
2012-07-22 14:48:59 -04:00
|
|
|
|
2014-11-17 17:02:53 -05:00
|
|
|
inline static NOISE_DATATYPE CubicInterpolate (NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_C, NOISE_DATATYPE a_D, NOISE_DATATYPE a_Pct);
|
|
|
|
inline static NOISE_DATATYPE CosineInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct);
|
|
|
|
inline static NOISE_DATATYPE LinearInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct);
|
2012-07-22 14:48:59 -04:00
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
private:
|
2014-04-04 06:28:38 -04:00
|
|
|
int m_Seed;
|
2013-04-17 16:57:05 -04:00
|
|
|
} ;
|
2012-06-14 09:06:06 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-04-16 16:47:43 -04:00
|
|
|
class cCubicNoise
|
|
|
|
{
|
|
|
|
public:
|
2014-11-18 06:07:08 -05:00
|
|
|
/** Maximum size of each dimension of the query arrays. */
|
|
|
|
static const int MAX_SIZE = 512;
|
2013-04-16 16:47:43 -04:00
|
|
|
|
|
|
|
|
2014-11-18 06:07:08 -05:00
|
|
|
/** Creates a new instance with the specified seed. */
|
2013-04-16 16:47:43 -04:00
|
|
|
cCubicNoise(int a_Seed);
|
|
|
|
|
|
|
|
|
2014-11-18 06:07:08 -05:00
|
|
|
/** Fills a 2D array with the values of the noise. */
|
2013-04-16 16:47:43 -04:00
|
|
|
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
|
2013-04-22 15:25:57 -04:00
|
|
|
NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY ///< Noise-space coords of the array in the Y direction
|
|
|
|
) const;
|
2013-04-16 16:47:43 -04:00
|
|
|
|
|
|
|
|
2014-11-18 06:07:08 -05:00
|
|
|
/** Fills a 3D array with the values of the noise. */
|
2013-04-16 16:47:43 -04:00
|
|
|
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
|
2013-04-22 15:25:57 -04:00
|
|
|
NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ ///< Noise-space coords of the array in the Z direction
|
|
|
|
) const;
|
2013-04-16 16:47:43 -04:00
|
|
|
|
|
|
|
protected:
|
|
|
|
|
2014-11-18 06:07:08 -05:00
|
|
|
/** Noise used for integral random values. */
|
|
|
|
cNoise m_Noise;
|
|
|
|
|
|
|
|
|
|
|
|
/** Calculates the integral and fractional parts along one axis.
|
|
|
|
a_Floor will receive the integral parts (array of a_Size ints).
|
|
|
|
a_Frac will receive the fractional parts (array of a_Size floats).
|
|
|
|
a_Same will receive the counts of items that have the same integral parts (array of up to a_Size ints).
|
|
|
|
a_NumSame will receive the count of a_Same elements (total count of different integral parts). */
|
2013-04-16 16:47:43 -04:00
|
|
|
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
|
2013-04-22 15:25:57 -04:00
|
|
|
) const;
|
2013-04-16 16:47:43 -04:00
|
|
|
} ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-11-17 10:50:28 -05:00
|
|
|
/** Improved noise, as described by Ken Perlin: http://mrl.nyu.edu/~perlin/paper445.pdf
|
|
|
|
Implementation adapted from Perlin's Java implementation: http://mrl.nyu.edu/~perlin/noise/ */
|
|
|
|
class cImprovedNoise
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** Constructs a new instance of the noise obbject.
|
|
|
|
Note that this operation is quite expensive (the permutation array being constructed). */
|
|
|
|
cImprovedNoise(int a_Seed);
|
|
|
|
|
|
|
|
|
|
|
|
/** Fills a 2D array with the values of the noise. */
|
|
|
|
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
|
|
|
|
) const;
|
|
|
|
|
|
|
|
|
|
|
|
/** Fills a 3D array with the values of the noise. */
|
|
|
|
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
|
|
|
|
) const;
|
|
|
|
|
|
|
|
/** Returns the value at the specified integral coords. Used for raw speed measurement. */
|
|
|
|
NOISE_DATATYPE GetValueAt(int a_X, int a_Y, int a_Z);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
/** The permutation table used by the noise function. Initialized using seed. */
|
|
|
|
int m_Perm[512];
|
|
|
|
|
|
|
|
|
|
|
|
/** Calculates the fade curve, 6 * t^5 - 15 * t^4 + 10 * t^3. */
|
|
|
|
inline static NOISE_DATATYPE Fade(NOISE_DATATYPE a_T)
|
|
|
|
{
|
|
|
|
return a_T * a_T * a_T * (a_T * (a_T * 6 - 15) + 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns the gradient value based on the hash. */
|
|
|
|
inline static NOISE_DATATYPE Grad(int a_Hash, NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y, NOISE_DATATYPE a_Z)
|
|
|
|
{
|
|
|
|
int hash = a_Hash % 16;
|
|
|
|
NOISE_DATATYPE u = (hash < 8) ? a_X : a_Y;
|
|
|
|
NOISE_DATATYPE v = (hash < 4) ? a_Y : (((hash == 12) || (hash == 14)) ? a_X : a_Z);
|
|
|
|
return (((hash & 1) == 0) ? u : -u) + (((hash & 2) == 0) ? v : -v);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-11-17 17:02:53 -05:00
|
|
|
typedef cOctavedNoise<cCubicNoise> cPerlinNoise;
|
2014-11-18 03:49:53 -05:00
|
|
|
typedef cOctavedNoise<cRidgedNoise<cCubicNoise>> cRidgedMultiNoise;
|
2013-04-16 16:47:43 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-04-17 16:57:05 -04:00
|
|
|
|
2014-07-17 16:15:34 -04:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2013-04-17 16:57:05 -04:00
|
|
|
// Inline function definitions:
|
|
|
|
// These need to be in the header, otherwise linker error occur in MSVC
|
|
|
|
|
|
|
|
NOISE_DATATYPE cNoise::IntNoise1D(int a_X) const
|
|
|
|
{
|
|
|
|
int x = ((a_X * m_Seed) << 13) ^ a_X;
|
2015-05-24 07:56:56 -04:00
|
|
|
return (1 - static_cast<NOISE_DATATYPE>((x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824);
|
2013-04-17 16:57:05 -04:00
|
|
|
// returns a float number in the range of [-1, 1]
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NOISE_DATATYPE cNoise::IntNoise2D(int a_X, int a_Y) const
|
|
|
|
{
|
|
|
|
int n = a_X + a_Y * 57 + m_Seed * 57 * 57;
|
|
|
|
n = (n << 13) ^ n;
|
2015-05-24 07:56:56 -04:00
|
|
|
return (1 - static_cast<NOISE_DATATYPE>((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824);
|
2013-04-17 16:57:05 -04:00
|
|
|
// returns a float number in the range of [-1, 1]
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NOISE_DATATYPE cNoise::IntNoise3D(int a_X, int a_Y, int a_Z) const
|
|
|
|
{
|
|
|
|
int n = a_X + a_Y * 57 + a_Z * 57 * 57 + m_Seed * 57 * 57 * 57;
|
|
|
|
n = (n << 13) ^ n;
|
2015-05-24 07:56:56 -04:00
|
|
|
return (static_cast<NOISE_DATATYPE>(1) -
|
2015-05-28 07:29:26 -04:00
|
|
|
static_cast<NOISE_DATATYPE>((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0f
|
|
|
|
);
|
2013-04-17 16:57:05 -04:00
|
|
|
// returns a float number in the range of [-1, 1]
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cNoise::IntNoise1DInt(int a_X) const
|
|
|
|
{
|
|
|
|
int x = ((a_X * m_Seed) << 13) ^ a_X;
|
|
|
|
return ((x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cNoise::IntNoise2DInt(int a_X, int a_Y) const
|
|
|
|
{
|
|
|
|
int n = a_X + a_Y * 57 + m_Seed * 57 * 57;
|
|
|
|
n = (n << 13) ^ n;
|
|
|
|
return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cNoise::IntNoise3DInt(int a_X, int a_Y, int a_Z) const
|
|
|
|
{
|
|
|
|
int n = a_X + a_Y * 57 + a_Z * 57 * 57 + m_Seed * 57 * 57 * 57;
|
|
|
|
n = (n << 13) ^ n;
|
|
|
|
return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NOISE_DATATYPE cNoise::CubicInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_C, NOISE_DATATYPE a_D, NOISE_DATATYPE a_Pct)
|
|
|
|
{
|
|
|
|
NOISE_DATATYPE P = (a_D - a_C) - (a_A - a_B);
|
|
|
|
NOISE_DATATYPE Q = (a_A - a_B) - P;
|
|
|
|
NOISE_DATATYPE R = a_C - a_A;
|
|
|
|
NOISE_DATATYPE S = a_B;
|
|
|
|
|
|
|
|
return ((P * a_Pct + Q) * a_Pct + R) * a_Pct + S;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NOISE_DATATYPE cNoise::CosineInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct)
|
|
|
|
{
|
2015-05-24 07:56:56 -04:00
|
|
|
const NOISE_DATATYPE ft = a_Pct * static_cast<NOISE_DATATYPE>(3.1415927);
|
|
|
|
const NOISE_DATATYPE f = static_cast<NOISE_DATATYPE>(static_cast<NOISE_DATATYPE>(1 - cos(ft)) * static_cast<NOISE_DATATYPE>(0.5));
|
2013-04-17 16:57:05 -04:00
|
|
|
return a_A * (1 - f) + a_B * f;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NOISE_DATATYPE cNoise::LinearInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct)
|
|
|
|
{
|
|
|
|
return a_A * (1 - a_Pct) + a_B * a_Pct;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-15 13:09:38 -04:00
|
|
|
|
2014-07-17 16:15:34 -04:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2013-05-15 13:09:38 -04:00
|
|
|
// Global functions:
|
|
|
|
|
2014-11-17 10:50:28 -05:00
|
|
|
/** Exports the noise array into a file.
|
|
|
|
a_Coeff specifies the value that each array value is multiplied by before being converted into a byte. */
|
2015-05-19 06:50:59 -04:00
|
|
|
extern void Debug2DNoise(const NOISE_DATATYPE * a_Array, size_t a_SizeX, size_t a_SizeY, const AString & a_FileNameBase, NOISE_DATATYPE a_Coeff = 32);
|
2014-11-17 10:50:28 -05:00
|
|
|
|
|
|
|
/** Exports the noise array into a set of files, ordered by XY and XZ.
|
|
|
|
a_Coeff specifies the value that each array value is multiplied by before being converted into a byte. */
|
2015-05-19 06:50:59 -04:00
|
|
|
extern void Debug3DNoise(const NOISE_DATATYPE * a_Array, size_t a_SizeX, size_t a_SizeY, size_t a_SizeZ, const AString & a_FileNameBase, NOISE_DATATYPE a_Coeff = 32);
|
2014-11-17 10:50:28 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Linearly interpolates between two values.
|
|
|
|
Assumes that a_Ratio is in range [0, 1]. */
|
|
|
|
inline NOISE_DATATYPE Lerp(NOISE_DATATYPE a_Val1, NOISE_DATATYPE a_Val2, NOISE_DATATYPE a_Ratio)
|
|
|
|
{
|
|
|
|
return a_Val1 + (a_Val2 - a_Val1) * a_Ratio;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Linearly interpolates between two values, clamping the ratio to [0, 1] first. */
|
|
|
|
inline NOISE_DATATYPE ClampedLerp(NOISE_DATATYPE a_Val1, NOISE_DATATYPE a_Val2, NOISE_DATATYPE a_Ratio)
|
|
|
|
{
|
|
|
|
if (a_Ratio < 0)
|
|
|
|
{
|
|
|
|
return a_Val1;
|
|
|
|
}
|
|
|
|
if (a_Ratio > 1)
|
|
|
|
{
|
|
|
|
return a_Val2;
|
|
|
|
}
|
|
|
|
return Lerp(a_Val1, a_Val2, a_Ratio);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-15 13:09:38 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|