Added cOctavedNoise template.
This allows us to use any noise generator in the combination of octaves.master
parent
faf0ce3d7f
commit
e9082263c9
174
src/Noise.cpp
174
src/Noise.cpp
|
@ -1043,10 +1043,6 @@ NOISE_DATATYPE cImprovedNoise::GetValueAt(int a_X, int a_Y, int a_Z)
|
||||||
a_Z = a_Z & 255;
|
a_Z = a_Z & 255;
|
||||||
int A = m_Perm[a_X] + a_Y;
|
int A = m_Perm[a_X] + a_Y;
|
||||||
int AA = m_Perm[A] + a_Z;
|
int AA = m_Perm[A] + a_Z;
|
||||||
int AB = m_Perm[A + 1] + a_Z;
|
|
||||||
int B = m_Perm[a_X + 1] + a_Y;
|
|
||||||
int BA = m_Perm[B] + a_Z;
|
|
||||||
int BB = m_Perm[B + 1] + a_Z;
|
|
||||||
|
|
||||||
return Grad(m_Perm[AA], 0, 0, 0);
|
return Grad(m_Perm[AA], 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
@ -1055,176 +1051,6 @@ NOISE_DATATYPE cImprovedNoise::GetValueAt(int a_X, int a_Y, int a_Z)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// cPerlinNoise:
|
|
||||||
|
|
||||||
cPerlinNoise::cPerlinNoise(void) :
|
|
||||||
m_Seed(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cPerlinNoise::cPerlinNoise(int a_Seed) :
|
|
||||||
m_Seed(a_Seed)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPerlinNoise::SetSeed(int a_Seed)
|
|
||||||
{
|
|
||||||
m_Seed = a_Seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPerlinNoise::AddOctave(float a_Frequency, float a_Amplitude)
|
|
||||||
{
|
|
||||||
m_Octaves.push_back(cOctave(m_Seed * ((int)m_Octaves.size() + 4) * 4 + 1024, a_Frequency, a_Amplitude));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPerlinNoise::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 ///< Workspace that this function can use and trash
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
if (m_Octaves.empty())
|
|
||||||
{
|
|
||||||
// No work to be done
|
|
||||||
ASSERT(!"Perlin: No octaves to generate!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShouldFreeWorkspace = (a_Workspace == nullptr);
|
|
||||||
int ArrayCount = a_SizeX * a_SizeY;
|
|
||||||
if (ShouldFreeWorkspace)
|
|
||||||
{
|
|
||||||
a_Workspace = new NOISE_DATATYPE[ArrayCount];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the first octave directly into array:
|
|
||||||
const cOctave & FirstOctave = m_Octaves.front();
|
|
||||||
|
|
||||||
FirstOctave.m_Noise.Generate2D(
|
|
||||||
a_Workspace, a_SizeX, a_SizeY,
|
|
||||||
a_StartX * FirstOctave.m_Frequency, a_EndX * FirstOctave.m_Frequency,
|
|
||||||
a_StartY * FirstOctave.m_Frequency, a_EndY * FirstOctave.m_Frequency
|
|
||||||
);
|
|
||||||
NOISE_DATATYPE Amplitude = FirstOctave.m_Amplitude;
|
|
||||||
for (int i = 0; i < ArrayCount; i++)
|
|
||||||
{
|
|
||||||
a_Array[i] = a_Workspace[i] * Amplitude;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add each octave:
|
|
||||||
for (cOctaves::const_iterator itr = m_Octaves.begin() + 1, end = m_Octaves.end(); itr != end; ++itr)
|
|
||||||
{
|
|
||||||
// Generate cubic noise for the octave:
|
|
||||||
itr->m_Noise.Generate2D(
|
|
||||||
a_Workspace, a_SizeX, a_SizeY,
|
|
||||||
a_StartX * itr->m_Frequency, a_EndX * itr->m_Frequency,
|
|
||||||
a_StartY * itr->m_Frequency, a_EndY * itr->m_Frequency
|
|
||||||
);
|
|
||||||
// Add the cubic noise into the output:
|
|
||||||
NOISE_DATATYPE Amplitude = itr->m_Amplitude;
|
|
||||||
for (int i = 0; i < ArrayCount; i++)
|
|
||||||
{
|
|
||||||
a_Array[i] += a_Workspace[i] * Amplitude;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ShouldFreeWorkspace)
|
|
||||||
{
|
|
||||||
delete[] a_Workspace;
|
|
||||||
a_Workspace = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPerlinNoise::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 ///< Workspace that this function can use and trash
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
if (m_Octaves.empty())
|
|
||||||
{
|
|
||||||
// No work to be done
|
|
||||||
ASSERT(!"Perlin: No octaves to generate!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShouldFreeWorkspace = (a_Workspace == nullptr);
|
|
||||||
int ArrayCount = a_SizeX * a_SizeY * a_SizeZ;
|
|
||||||
if (ShouldFreeWorkspace)
|
|
||||||
{
|
|
||||||
a_Workspace = new NOISE_DATATYPE[ArrayCount];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the first octave directly into array:
|
|
||||||
const cOctave & FirstOctave = m_Octaves.front();
|
|
||||||
|
|
||||||
FirstOctave.m_Noise.Generate3D(
|
|
||||||
a_Workspace, a_SizeX, a_SizeY, a_SizeZ,
|
|
||||||
a_StartX * FirstOctave.m_Frequency, a_EndX * FirstOctave.m_Frequency,
|
|
||||||
a_StartY * FirstOctave.m_Frequency, a_EndY * FirstOctave.m_Frequency,
|
|
||||||
a_StartZ * FirstOctave.m_Frequency, a_EndZ * FirstOctave.m_Frequency
|
|
||||||
);
|
|
||||||
NOISE_DATATYPE Amplitude = FirstOctave.m_Amplitude;
|
|
||||||
for (int i = 0; i < ArrayCount; i++)
|
|
||||||
{
|
|
||||||
a_Array[i] = a_Workspace[i] * Amplitude;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add each octave:
|
|
||||||
for (cOctaves::const_iterator itr = m_Octaves.begin() + 1, end = m_Octaves.end(); itr != end; ++itr)
|
|
||||||
{
|
|
||||||
// Generate cubic noise for the octave:
|
|
||||||
itr->m_Noise.Generate3D(
|
|
||||||
a_Workspace, a_SizeX, a_SizeY, a_SizeZ,
|
|
||||||
a_StartX * itr->m_Frequency, a_EndX * itr->m_Frequency,
|
|
||||||
a_StartY * itr->m_Frequency, a_EndY * itr->m_Frequency,
|
|
||||||
a_StartZ * itr->m_Frequency, a_EndZ * itr->m_Frequency
|
|
||||||
);
|
|
||||||
// Add the cubic noise into the output:
|
|
||||||
NOISE_DATATYPE Amplitude = itr->m_Amplitude;
|
|
||||||
for (int i = 0; i < ArrayCount; i++)
|
|
||||||
{
|
|
||||||
a_Array[i] += a_Workspace[i] * Amplitude;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ShouldFreeWorkspace)
|
|
||||||
{
|
|
||||||
delete[] a_Workspace;
|
|
||||||
a_Workspace = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// cRidgedMultiNoise:
|
// cRidgedMultiNoise:
|
||||||
|
|
||||||
|
|
98
src/Noise.h
98
src/Noise.h
|
@ -7,22 +7,10 @@
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
/** The datatype used by all the noise generators. */
|
||||||
|
typedef float NOISE_DATATYPE;
|
||||||
|
|
||||||
|
#include "OctavedNoise.h"
|
||||||
|
|
||||||
|
|
||||||
// Some settings
|
|
||||||
#define NOISE_DATATYPE float
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define INLINE __forceinline
|
|
||||||
#else
|
|
||||||
#define INLINE inline
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,20 +23,20 @@ public:
|
||||||
cNoise(const cNoise & a_Noise);
|
cNoise(const cNoise & a_Noise);
|
||||||
|
|
||||||
// The following functions, if not marked INLINE, are about 20 % slower
|
// The following functions, if not marked INLINE, are about 20 % slower
|
||||||
INLINE NOISE_DATATYPE IntNoise1D(int a_X) const;
|
inline NOISE_DATATYPE IntNoise1D(int a_X) const;
|
||||||
INLINE NOISE_DATATYPE IntNoise2D(int a_X, int a_Y) 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;
|
inline NOISE_DATATYPE IntNoise3D(int a_X, int a_Y, int a_Z) const;
|
||||||
|
|
||||||
// Return a float number in the specified range:
|
// Return a float number in the specified range:
|
||||||
INLINE NOISE_DATATYPE IntNoise2DInRange(int a_X, int a_Y, float a_Min, float a_Max) const
|
inline NOISE_DATATYPE IntNoise2DInRange(int a_X, int a_Y, float a_Min, float a_Max) const
|
||||||
{
|
{
|
||||||
return a_Min + std::abs(IntNoise2D(a_X, a_Y)) * (a_Max - a_Min);
|
return a_Min + std::abs(IntNoise2D(a_X, a_Y)) * (a_Max - a_Min);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: These functions have a mod8-irregular chance - each of the mod8 remainders has different chance of occurrence. Divide by 8 to rectify.
|
// Note: These functions have a mod8-irregular chance - each of the mod8 remainders has different chance of occurrence. Divide by 8 to rectify.
|
||||||
INLINE int IntNoise1DInt(int a_X) const;
|
inline int IntNoise1DInt(int a_X) const;
|
||||||
INLINE int IntNoise2DInt(int a_X, int a_Y) const;
|
inline int IntNoise2DInt(int a_X, int a_Y) const;
|
||||||
INLINE int IntNoise3DInt(int a_X, int a_Y, int a_Z) const;
|
inline int IntNoise3DInt(int a_X, int a_Y, int a_Z) const;
|
||||||
|
|
||||||
NOISE_DATATYPE LinearNoise1D(NOISE_DATATYPE a_X) const;
|
NOISE_DATATYPE LinearNoise1D(NOISE_DATATYPE a_X) const;
|
||||||
NOISE_DATATYPE CosineNoise1D(NOISE_DATATYPE a_X) const;
|
NOISE_DATATYPE CosineNoise1D(NOISE_DATATYPE a_X) const;
|
||||||
|
@ -61,9 +49,9 @@ public:
|
||||||
|
|
||||||
void SetSeed(int a_Seed) { m_Seed = a_Seed; }
|
void SetSeed(int a_Seed) { m_Seed = a_Seed; }
|
||||||
|
|
||||||
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 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 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);
|
inline static NOISE_DATATYPE LinearInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_Seed;
|
int m_Seed;
|
||||||
|
@ -197,65 +185,7 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cPerlinNoise
|
typedef cOctavedNoise<cCubicNoise> cPerlinNoise;
|
||||||
{
|
|
||||||
public:
|
|
||||||
cPerlinNoise(void);
|
|
||||||
cPerlinNoise(int a_Seed);
|
|
||||||
|
|
||||||
|
|
||||||
void SetSeed(int a_Seed);
|
|
||||||
|
|
||||||
void AddOctave(NOISE_DATATYPE a_Frequency, NOISE_DATATYPE a_Amplitude);
|
|
||||||
|
|
||||||
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 = nullptr ///< Workspace that this function can use and trash
|
|
||||||
) const;
|
|
||||||
|
|
||||||
|
|
||||||
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 = nullptr ///< Workspace that this function can use and trash
|
|
||||||
) const;
|
|
||||||
|
|
||||||
|
|
||||||
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 = nullptr ///< Workspace that this function can use and trash
|
|
||||||
) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class cOctave
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
cCubicNoise m_Noise;
|
|
||||||
|
|
||||||
NOISE_DATATYPE m_Frequency; // Coord multiplier
|
|
||||||
NOISE_DATATYPE m_Amplitude; // Value multiplier
|
|
||||||
|
|
||||||
cOctave(int a_Seed, NOISE_DATATYPE a_Frequency, NOISE_DATATYPE a_Amplitude) :
|
|
||||||
m_Noise(a_Seed),
|
|
||||||
m_Frequency(a_Frequency),
|
|
||||||
m_Amplitude(a_Amplitude)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
} ;
|
|
||||||
|
|
||||||
typedef std::vector<cOctave> cOctaves;
|
|
||||||
|
|
||||||
int m_Seed;
|
|
||||||
cOctaves m_Octaves;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
|
||||||
|
// OctavedNoise.h
|
||||||
|
|
||||||
|
// Implements the cOctavedNoise class template representing a noise generator that layers several octaves of another noise
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename N>
|
||||||
|
class cOctavedNoise
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cOctavedNoise(int a_Seed = 0):
|
||||||
|
m_Seed(a_Seed)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Sets a new seed for the generators. Relays the seed to all underlying octaves. */
|
||||||
|
void SetSeed(int a_Seed)
|
||||||
|
{
|
||||||
|
m_Seed = a_Seed;
|
||||||
|
for (auto oct: m_Octaves)
|
||||||
|
{
|
||||||
|
oct->SetSeed(a_Seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** */
|
||||||
|
void AddOctave(NOISE_DATATYPE a_Frequency, NOISE_DATATYPE a_Amplitude)
|
||||||
|
{
|
||||||
|
m_Octaves.emplace_back(m_Seed, a_Frequency, a_Amplitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 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
|
||||||
|
NOISE_DATATYPE * a_Workspace ///< Workspace that this function can use and trash. Must be valid.
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// Check that state is alright:
|
||||||
|
if (m_Octaves.empty())
|
||||||
|
{
|
||||||
|
ASSERT(!"Perlin: No octaves to generate!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate the workspace on the heap, if it wasn't given:
|
||||||
|
std::unique_ptr<NOISE_DATATYPE[]> workspaceHeap;
|
||||||
|
if (a_Workspace == nullptr)
|
||||||
|
{
|
||||||
|
workspaceHeap.reset(new NOISE_DATATYPE[a_SizeX * a_SizeY]);
|
||||||
|
a_Workspace = workspaceHeap.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the first octave directly into array:
|
||||||
|
const cOctave & FirstOctave = m_Octaves.front();
|
||||||
|
int ArrayCount = a_SizeX * a_SizeY;
|
||||||
|
FirstOctave.m_Noise.Generate2D(
|
||||||
|
a_Workspace, a_SizeX, a_SizeY,
|
||||||
|
a_StartX * FirstOctave.m_Frequency, a_EndX * FirstOctave.m_Frequency,
|
||||||
|
a_StartY * FirstOctave.m_Frequency, a_EndY * FirstOctave.m_Frequency
|
||||||
|
);
|
||||||
|
NOISE_DATATYPE Amplitude = FirstOctave.m_Amplitude;
|
||||||
|
for (int i = 0; i < ArrayCount; i++)
|
||||||
|
{
|
||||||
|
a_Array[i] = a_Workspace[i] * Amplitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add each octave:
|
||||||
|
for (cOctaves::const_iterator itr = m_Octaves.begin() + 1, end = m_Octaves.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
// Generate the noise for the octave:
|
||||||
|
itr->m_Noise.Generate2D(
|
||||||
|
a_Workspace, a_SizeX, a_SizeY,
|
||||||
|
a_StartX * itr->m_Frequency, a_EndX * itr->m_Frequency,
|
||||||
|
a_StartY * itr->m_Frequency, a_EndY * itr->m_Frequency
|
||||||
|
);
|
||||||
|
// Add it into the output:
|
||||||
|
NOISE_DATATYPE Amplitude = itr->m_Amplitude;
|
||||||
|
for (int i = 0; i < ArrayCount; i++)
|
||||||
|
{
|
||||||
|
a_Array[i] += a_Workspace[i] * Amplitude;
|
||||||
|
}
|
||||||
|
} // for itr - m_Octaves[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 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
|
||||||
|
NOISE_DATATYPE * a_Workspace = nullptr ///< Workspace that this function can use and trash, same size as a_Array
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// Check that state is alright:
|
||||||
|
if (m_Octaves.empty())
|
||||||
|
{
|
||||||
|
ASSERT(!"Perlin: No octaves to generate!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate the workspace on the heap, if it wasn't given:
|
||||||
|
std::unique_ptr<NOISE_DATATYPE[]> workspaceHeap;
|
||||||
|
if (a_Workspace == nullptr)
|
||||||
|
{
|
||||||
|
workspaceHeap.reset(new NOISE_DATATYPE[a_SizeX * a_SizeY * a_SizeZ]);
|
||||||
|
a_Workspace = workspaceHeap.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the first octave directly into array:
|
||||||
|
const cOctave & FirstOctave = m_Octaves.front();
|
||||||
|
int ArrayCount = a_SizeX * a_SizeY * a_SizeZ;
|
||||||
|
FirstOctave.m_Noise.Generate3D(
|
||||||
|
a_Workspace, a_SizeX, a_SizeY, a_SizeZ,
|
||||||
|
a_StartX * FirstOctave.m_Frequency, a_EndX * FirstOctave.m_Frequency,
|
||||||
|
a_StartY * FirstOctave.m_Frequency, a_EndY * FirstOctave.m_Frequency,
|
||||||
|
a_StartZ * FirstOctave.m_Frequency, a_EndZ * FirstOctave.m_Frequency
|
||||||
|
);
|
||||||
|
NOISE_DATATYPE Amplitude = FirstOctave.m_Amplitude;
|
||||||
|
for (int i = 0; i < ArrayCount; i++)
|
||||||
|
{
|
||||||
|
a_Array[i] = a_Workspace[i] * Amplitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add each octave:
|
||||||
|
for (cOctaves::const_iterator itr = m_Octaves.begin() + 1, end = m_Octaves.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
// Generate the noise for the octave:
|
||||||
|
itr->m_Noise.Generate3D(
|
||||||
|
a_Workspace, a_SizeX, a_SizeY, a_SizeZ,
|
||||||
|
a_StartX * itr->m_Frequency, a_EndX * itr->m_Frequency,
|
||||||
|
a_StartY * itr->m_Frequency, a_EndY * itr->m_Frequency,
|
||||||
|
a_StartZ * itr->m_Frequency, a_EndZ * itr->m_Frequency
|
||||||
|
);
|
||||||
|
// Add it into the output:
|
||||||
|
NOISE_DATATYPE Amplitude = itr->m_Amplitude;
|
||||||
|
for (int i = 0; i < ArrayCount; i++)
|
||||||
|
{
|
||||||
|
a_Array[i] += a_Workspace[i] * Amplitude;
|
||||||
|
}
|
||||||
|
} // for itr - m_Octaves[]
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** Stores information and state for one octave of the noise. */
|
||||||
|
class cOctave
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
N m_Noise;
|
||||||
|
|
||||||
|
/** Coord multiplier. */
|
||||||
|
NOISE_DATATYPE m_Frequency;
|
||||||
|
|
||||||
|
/** Value multiplier. */
|
||||||
|
NOISE_DATATYPE m_Amplitude;
|
||||||
|
|
||||||
|
cOctave(int a_Seed, NOISE_DATATYPE a_Frequency, NOISE_DATATYPE a_Amplitude) :
|
||||||
|
m_Noise(a_Seed),
|
||||||
|
m_Frequency(a_Frequency),
|
||||||
|
m_Amplitude(a_Amplitude)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
typedef std::vector<cOctave> cOctaves;
|
||||||
|
|
||||||
|
|
||||||
|
/** The seed used by the underlying generators. */
|
||||||
|
int m_Seed;
|
||||||
|
|
||||||
|
/** The octaves that compose this noise. */
|
||||||
|
cOctaves m_Octaves;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue