summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattes D <github@xoft.cz>2014-11-17 16:50:28 +0100
committerMattes D <github@xoft.cz>2014-11-17 16:50:28 +0100
commitf9cfc36643b7cc0a2b8f46455d452beb6e444e0d (patch)
treef1463ba7da2afbfaf85cee045191f3e41b6a2abe
parentFixed a wrong assert in cClientHandle::SetViewDistance(). (diff)
downloadcuberite-f9cfc36643b7cc0a2b8f46455d452beb6e444e0d.tar
cuberite-f9cfc36643b7cc0a2b8f46455d452beb6e444e0d.tar.gz
cuberite-f9cfc36643b7cc0a2b8f46455d452beb6e444e0d.tar.bz2
cuberite-f9cfc36643b7cc0a2b8f46455d452beb6e444e0d.tar.lz
cuberite-f9cfc36643b7cc0a2b8f46455d452beb6e444e0d.tar.xz
cuberite-f9cfc36643b7cc0a2b8f46455d452beb6e444e0d.tar.zst
cuberite-f9cfc36643b7cc0a2b8f46455d452beb6e444e0d.zip
-rw-r--r--src/Generating/Noise3DGenerator.cpp37
-rw-r--r--src/Generating/Noise3DGenerator.h6
-rw-r--r--src/Noise.cpp274
-rw-r--r--src/Noise.h105
4 files changed, 376 insertions, 46 deletions
diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp
index f2af75999..654e9d01f 100644
--- a/src/Generating/Noise3DGenerator.cpp
+++ b/src/Generating/Noise3DGenerator.cpp
@@ -61,35 +61,6 @@ public:
-/** Linearly interpolates between two values.
-Assumes that a_Ratio is in range [0, 1]. */
-inline static 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 static 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);
-}
-
-
-
-
-
////////////////////////////////////////////////////////////////////////////////
// cNoise3DGenerator:
@@ -249,10 +220,10 @@ void cNoise3DGenerator::GenerateNoiseArray(int a_ChunkX, int a_ChunkZ, NOISE_DAT
NOISE_DATATYPE NoiseW[DIM_X * DIM_Y * DIM_Z]; // Workspace that the noise calculation can use and trash
// Our noise array has different layout, XZY, instead of regular chunk's XYZ, that's why the coords are "renamed"
- NOISE_DATATYPE StartX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width)) / m_FrequencyX;
- NOISE_DATATYPE EndX = ((NOISE_DATATYPE)((a_ChunkX + 1) * cChunkDef::Width) - 1) / m_FrequencyX;
- NOISE_DATATYPE StartZ = ((NOISE_DATATYPE)(a_ChunkZ * cChunkDef::Width)) / m_FrequencyZ;
- NOISE_DATATYPE EndZ = ((NOISE_DATATYPE)((a_ChunkZ + 1) * cChunkDef::Width) - 1) / m_FrequencyZ;
+ NOISE_DATATYPE StartX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width)) / m_FrequencyX;
+ NOISE_DATATYPE EndX = ((NOISE_DATATYPE)((a_ChunkX + 1) * cChunkDef::Width)) / m_FrequencyX;
+ NOISE_DATATYPE StartZ = ((NOISE_DATATYPE)(a_ChunkZ * cChunkDef::Width)) / m_FrequencyZ;
+ NOISE_DATATYPE EndZ = ((NOISE_DATATYPE)((a_ChunkZ + 1) * cChunkDef::Width)) / m_FrequencyZ;
NOISE_DATATYPE StartY = 0;
NOISE_DATATYPE EndY = ((NOISE_DATATYPE)256) / m_FrequencyY;
diff --git a/src/Generating/Noise3DGenerator.h b/src/Generating/Noise3DGenerator.h
index ba541fbcc..92cfc32b7 100644
--- a/src/Generating/Noise3DGenerator.h
+++ b/src/Generating/Noise3DGenerator.h
@@ -34,9 +34,9 @@ public:
protected:
// Linear interpolation step sizes, must be divisors of cChunkDef::Width and cChunkDef::Height, respectively:
- static const int UPSCALE_X = 8;
- static const int UPSCALE_Y = 4;
- static const int UPSCALE_Z = 8;
+ static const int UPSCALE_X = 4;
+ static const int UPSCALE_Y = 8;
+ static const int UPSCALE_Z = 4;
// Linear interpolation buffer dimensions, calculated from the step sizes:
static const int DIM_X = 1 + cChunkDef::Width / UPSCALE_X;
diff --git a/src/Noise.cpp b/src/Noise.cpp
index 8fcfe2920..56d39395d 100644
--- a/src/Noise.cpp
+++ b/src/Noise.cpp
@@ -2,6 +2,7 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Noise.h"
+#include "OSSupport\Timer.h"
#define FAST_FLOOR(x) (((x) < 0) ? (((int)x) - 1) : ((int)x))
@@ -9,10 +10,110 @@
+#if 0
+/** cImprovedPerlin noise test suite:
+- Generate a rather large 2D and 3D noise array and output it to a file
+- Compare performance of cCubicNoise and cImprovedNoise, both in single-value and 3D-array usages */
+static class cImprovedPerlinNoiseTest
+{
+public:
+ cImprovedPerlinNoiseTest(void)
+ {
+ printf("Performing Improved Perlin Noise tests...\n");
+ TestImage();
+ TestSpeed();
+ TestSpeedArr();
+ printf("Improved Perlin Noise tests complete.\n");
+ }
+
+
+ /** Tests the noise by generating 2D and 3D images and dumping them to files. */
+ void TestImage(void)
+ {
+ static const int SIZE_X = 256;
+ static const int SIZE_Y = 256;
+ static const int SIZE_Z = 16;
+
+ cImprovedNoise noise(1);
+ std::unique_ptr<NOISE_DATATYPE[]> arr(new NOISE_DATATYPE[SIZE_X * SIZE_Y * SIZE_Z]);
+ noise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, 0, 14, 0, 14, 0, 14);
+ Debug3DNoise(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, "ImprovedPerlinNoiseTest3D", 128);
+ noise.Generate2D(arr.get(), SIZE_X, SIZE_Y, 0, 14, 15, 28);
+ Debug2DNoise(arr.get(), SIZE_X, SIZE_Y, "ImprovedPerlinNoiseTest2D", 128);
+ }
+
+
+ /** Tests the speeds of cImprovedPerlin and cCubicNoise when generating individual values. */
+ void TestSpeed(void)
+ {
+ cImprovedNoise improvedNoise(1);
+ cNoise noise(1);
+ cTimer timer;
+
+ // Measure the improvedNoise:
+ NOISE_DATATYPE sum = 0;
+ long long start = timer.GetNowTime();
+ for (int i = 0; i < 100000000; i++)
+ {
+ sum += improvedNoise.GetValueAt(i, 0, -i);
+ }
+ long long finish = timer.GetNowTime();
+ printf("cImprovedNoise took %.2f seconds; total is %f.\n", static_cast<float>(finish - start) / 1000.0f, sum);
+
+ // Measure the cubicNoise:
+ sum = 0;
+ start = timer.GetNowTime();
+ for (int i = 0; i < 100000000; i++)
+ {
+ sum += noise.IntNoise3D(i, 0, -i);
+ }
+ finish = timer.GetNowTime();
+ printf("cCubicNoise took %.2f seconds; total is %f.\n", static_cast<float>(finish - start) / 1000.0f, sum);
+ }
+
+
+ /** Tests the speeds of cImprovedPerlin and cCubicNoise when generating arrays. */
+ void TestSpeedArr(void)
+ {
+ static const int SIZE_X = 256;
+ static const int SIZE_Y = 256;
+ static const int SIZE_Z = 16;
+
+ std::unique_ptr<NOISE_DATATYPE[]> arr(new NOISE_DATATYPE[SIZE_X * SIZE_Y * SIZE_Z]);
+ cTimer timer;
+ cImprovedNoise improvedNoise(1);
+ cCubicNoise cubicNoise(1);
+
+ // Measure the improvedNoise:
+ long long start = timer.GetNowTime();
+ for (int i = 0; i < 40; i++)
+ {
+ improvedNoise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, 0, 14, 0, 14, 0, 14);
+ }
+ long long finish = timer.GetNowTime();
+ printf("cImprovedNoise(arr) took %.2f seconds.\n", static_cast<float>(finish - start) / 1000.0f);
+
+ // Measure the cubicNoise:
+ start = timer.GetNowTime();
+ for (int i = 0; i < 40; i++)
+ {
+ cubicNoise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, 0, 14, 0, 14, 0, 14);
+ }
+ finish = timer.GetNowTime();
+ printf("cCubicNoise(arr) took %.2f seconds.\n", static_cast<float>(finish - start) / 1000.0f);
+ }
+} g_Test;
+
+#endif
+
+
+
+
+
////////////////////////////////////////////////////////////////////////////////
// Globals:
-void Debug3DNoise(const NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, int a_SizeZ, const AString & a_FileNameBase)
+void Debug3DNoise(const NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, int a_SizeZ, const AString & a_FileNameBase, NOISE_DATATYPE a_Coeff)
{
const int BUF_SIZE = 512;
ASSERT(a_SizeX <= BUF_SIZE); // Just stretch it, if needed
@@ -29,7 +130,7 @@ void Debug3DNoise(const NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, int
unsigned char buf[BUF_SIZE];
for (int x = 0; x < a_SizeX; x++)
{
- buf[x] = (unsigned char)(std::min(255, std::max(0, (int)(128 + 32 * a_Noise[idx++]))));
+ buf[x] = static_cast<unsigned char>(Clamp((int)(128 + a_Coeff * a_Noise[idx++]), 0, 255));
}
f1.Write(buf, a_SizeX);
} // for y
@@ -50,7 +151,7 @@ void Debug3DNoise(const NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, int
unsigned char buf[BUF_SIZE];
for (int x = 0; x < a_SizeX; x++)
{
- buf[x] = (unsigned char)(std::min(255, std::max(0, (int)(128 + 32 * a_Noise[idx++]))));
+ buf[x] = static_cast<unsigned char>(Clamp((int)(128 + a_Coeff * a_Noise[idx++]), 0, 255));
}
f2.Write(buf, a_SizeX);
} // for z
@@ -65,7 +166,7 @@ void Debug3DNoise(const NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, int
-void Debug2DNoise(const NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, const AString & a_FileNameBase)
+void Debug2DNoise(const NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, const AString & a_FileNameBase, NOISE_DATATYPE a_Coeff)
{
const int BUF_SIZE = 512;
ASSERT(a_SizeX <= BUF_SIZE); // Just stretch it, if needed
@@ -79,7 +180,7 @@ void Debug2DNoise(const NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, cons
unsigned char buf[BUF_SIZE];
for (int x = 0; x < a_SizeX; x++)
{
- buf[x] = (unsigned char)(std::min(255, std::max(0, (int)(128 + 32 * a_Noise[idx++]))));
+ buf[x] = static_cast<unsigned char>(Clamp((int)(128 + a_Coeff * a_Noise[idx++]), 0, 255));
}
f1.Write(buf, a_SizeX);
} // for y
@@ -792,6 +893,169 @@ void cCubicNoise::CalcFloorFrac(
////////////////////////////////////////////////////////////////////////////////
+// cImprovedNoise:
+
+cImprovedNoise::cImprovedNoise(int a_Seed)
+{
+ // Initialize the permutations with identity:
+ for (int i = 0; i < 256; i++)
+ {
+ m_Perm[i] = i;
+ }
+
+ // Randomize the permutation table - swap each element with a random other element:
+ cNoise noise(a_Seed);
+ for (int i = 0; i < 256; i++)
+ {
+ int rnd = (noise.IntNoise1DInt(i) / 7) % 256;
+ std::swap(m_Perm[i], m_Perm[rnd]);
+ }
+
+ // Copy the lower 256 entries into upper 256 entries:
+ for (int i = 0; i < 256; i++)
+ {
+ m_Perm[i + 256] = m_Perm[i];
+ }
+}
+
+
+
+
+
+void cImprovedNoise::Generate2D(
+ NOISE_DATATYPE * a_Array,
+ int a_SizeX, int a_SizeY,
+ NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX,
+ NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY
+) const
+{
+ size_t idx = 0;
+ for (int y = 0; y < a_SizeY; y++)
+ {
+ NOISE_DATATYPE ratioY = static_cast<NOISE_DATATYPE>(y) / (a_SizeY - 1);
+ NOISE_DATATYPE noiseY = Lerp(a_StartY, a_EndY, ratioY);
+ int noiseYInt = FAST_FLOOR(noiseY);
+ int yCoord = noiseYInt & 255;
+ NOISE_DATATYPE noiseYFrac = noiseY - noiseYInt;
+ NOISE_DATATYPE fadeY = Fade(noiseYFrac);
+ for (int x = 0; x < a_SizeX; x++)
+ {
+ NOISE_DATATYPE ratioX = static_cast<NOISE_DATATYPE>(x) / (a_SizeX - 1);
+ NOISE_DATATYPE noiseX = Lerp(a_StartX, a_EndX, ratioX);
+ int noiseXInt = FAST_FLOOR(noiseX);
+ int xCoord = noiseXInt & 255;
+ NOISE_DATATYPE noiseXFrac = noiseX - noiseXInt;
+ NOISE_DATATYPE fadeX = Fade(noiseXFrac);
+
+ // Hash the coordinates:
+ int A = m_Perm[xCoord] + yCoord;
+ int AA = m_Perm[A];
+ int AB = m_Perm[A + 1];
+ int B = m_Perm[xCoord + 1] + yCoord;
+ int BA = m_Perm[B];
+ int BB = m_Perm[B + 1];
+
+ // Lerp the gradients:
+ a_Array[idx++] = Lerp(
+ Lerp(Grad(m_Perm[AA], noiseXFrac, noiseYFrac, 0), Grad(m_Perm[BA], noiseXFrac - 1, noiseYFrac, 0), fadeX),
+ Lerp(Grad(m_Perm[AB], noiseXFrac, noiseYFrac - 1, 0), Grad(m_Perm[BB], noiseXFrac - 1, noiseYFrac - 1, 0), fadeX),
+ fadeY
+ );
+ } // for x
+ } // for y
+}
+
+
+
+
+
+void cImprovedNoise::Generate3D(
+ NOISE_DATATYPE * a_Array,
+ int a_SizeX, int a_SizeY, int a_SizeZ,
+ NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX,
+ NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY,
+ NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ
+) const
+{
+ size_t idx = 0;
+ for (int z = 0; z < a_SizeZ; z++)
+ {
+ NOISE_DATATYPE ratioZ = static_cast<NOISE_DATATYPE>(z) / (a_SizeZ - 1);
+ NOISE_DATATYPE noiseZ = Lerp(a_StartZ, a_EndZ, ratioZ);
+ int noiseZInt = FAST_FLOOR(noiseZ);
+ int zCoord = noiseZInt & 255;
+ NOISE_DATATYPE noiseZFrac = noiseZ - noiseZInt;
+ NOISE_DATATYPE fadeZ = Fade(noiseZFrac);
+ for (int y = 0; y < a_SizeY; y++)
+ {
+ NOISE_DATATYPE ratioY = static_cast<NOISE_DATATYPE>(y) / (a_SizeY - 1);
+ NOISE_DATATYPE noiseY = Lerp(a_StartY, a_EndY, ratioY);
+ int noiseYInt = FAST_FLOOR(noiseY);
+ int yCoord = noiseYInt & 255;
+ NOISE_DATATYPE noiseYFrac = noiseY - noiseYInt;
+ NOISE_DATATYPE fadeY = Fade(noiseYFrac);
+ for (int x = 0; x < a_SizeX; x++)
+ {
+ NOISE_DATATYPE ratioX = static_cast<NOISE_DATATYPE>(x) / (a_SizeX - 1);
+ NOISE_DATATYPE noiseX = Lerp(a_StartX, a_EndX, ratioX);
+ int noiseXInt = FAST_FLOOR(noiseX);
+ int xCoord = noiseXInt & 255;
+ NOISE_DATATYPE noiseXFrac = noiseX - noiseXInt;
+ NOISE_DATATYPE fadeX = Fade(noiseXFrac);
+
+ // Hash the coordinates:
+ int A = m_Perm[xCoord] + yCoord;
+ int AA = m_Perm[A] + zCoord;
+ int AB = m_Perm[A + 1] + zCoord;
+ int B = m_Perm[xCoord + 1] + yCoord;
+ int BA = m_Perm[B] + zCoord;
+ int BB = m_Perm[B + 1] + zCoord;
+
+ // Lerp the gradients:
+ // TODO: This may be optimized by swapping the coords and recalculating most lerps only "once every x"
+ a_Array[idx++] = Lerp(
+ Lerp(
+ Lerp(Grad(m_Perm[AA], noiseXFrac, noiseYFrac, noiseZFrac), Grad(m_Perm[BA], noiseXFrac - 1, noiseYFrac, noiseZFrac), fadeX),
+ Lerp(Grad(m_Perm[AB], noiseXFrac, noiseYFrac - 1, noiseZFrac), Grad(m_Perm[BB], noiseXFrac - 1, noiseYFrac - 1, noiseZFrac), fadeX),
+ fadeY
+ ),
+ Lerp(
+ Lerp(Grad(m_Perm[AA + 1], noiseXFrac, noiseYFrac, noiseZFrac - 1), Grad(m_Perm[BA + 1], noiseXFrac - 1, noiseYFrac, noiseZFrac - 1), fadeX),
+ Lerp(Grad(m_Perm[AB + 1], noiseXFrac, noiseYFrac - 1, noiseZFrac - 1), Grad(m_Perm[BB + 1], noiseXFrac - 1, noiseYFrac - 1, noiseZFrac - 1), fadeX),
+ fadeY
+ ),
+ fadeZ
+ );
+ } // for x
+ } // for y
+ } // for z
+}
+
+
+
+
+
+NOISE_DATATYPE cImprovedNoise::GetValueAt(int a_X, int a_Y, int a_Z)
+{
+ // Hash the coordinates:
+ a_X = a_X & 255;
+ a_Y = a_Y & 255;
+ a_Z = a_Z & 255;
+ int A = m_Perm[a_X] + a_Y;
+ 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);
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
// cPerlinNoise:
cPerlinNoise::cPerlinNoise(void) :
diff --git a/src/Noise.h b/src/Noise.h
index b7a90d5b7..3c5caded7 100644
--- a/src/Noise.h
+++ b/src/Noise.h
@@ -140,6 +140,63 @@ protected:
+/** 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);
+ }
+};
+
+
+
+
+
class cPerlinNoise
{
public:
@@ -155,7 +212,7 @@ public:
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
+ NOISE_DATATYPE * a_Workspace = nullptr ///< Workspace that this function can use and trash
) const;
@@ -164,7 +221,7 @@ public:
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
+ NOISE_DATATYPE * a_Workspace = nullptr ///< Workspace that this function can use and trash
) const;
@@ -174,7 +231,7 @@ public:
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
+ NOISE_DATATYPE * a_Workspace = nullptr ///< Workspace that this function can use and trash
) const;
protected:
@@ -376,8 +433,46 @@ NOISE_DATATYPE cNoise::LinearInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B,
////////////////////////////////////////////////////////////////////////////////
// Global functions:
-extern void Debug2DNoise(const NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, const AString & a_FileNameBase);
-extern void Debug3DNoise(const NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, int a_SizeZ, const AString & a_FileNameBase);
+/** 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. */
+extern void Debug2DNoise(const NOISE_DATATYPE * a_Array, int a_SizeX, int a_SizeY, const AString & a_FileNameBase, NOISE_DATATYPE a_Coeff = 32);
+
+/** 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. */
+extern void Debug3DNoise(const NOISE_DATATYPE * a_Array, int a_SizeX, int a_SizeY, int a_SizeZ, const AString & a_FileNameBase, NOISE_DATATYPE a_Coeff = 32);
+
+
+
+
+/** 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);
+}
+
+
+
+
+