Skip to content

Instantly share code, notes, and snippets.

@Markyparky56
Forked from digitalshadow/OpenSimplexNoise.cs
Last active April 29, 2022 20:10
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Markyparky56/e0fd43e847ac53068603130df3e8e560 to your computer and use it in GitHub Desktop.
Save Markyparky56/e0fd43e847ac53068603130df3e8e560 to your computer and use it in GitHub Desktop.
OpenSimplex Noise Refactored for C++
#pragma once
/*******************************************************************************
OpenSimplex Noise in C++
Ported from https://gist.github.com/digitalshadow/134a3a02b67cecd72181
Originally from https://gist.github.com/KdotJPG/b1270127455a94ac5d19
Optimised by DigitalShadow
This version by Mark A. Ropper (Markyparky56)
*******************************************************************************/
#include <array>
#include <vector>
#include <memory> // unique_ptr
#include <ctime> // time for random seed
#if defined(__clang__) // Couldn't find one for clang
#define FORCE_INLINE inline
#elif defined(__GNUC__) || defined(__GNUG__)
#define FORCE_INLINE __attribute__((always_inline))
#elif defined(_MSC_VER)
#define FORCE_INLINE __forceinline
#endif
class OpenSimplexNoise
{
friend class StaticConstructor;
protected:
// Contribution structs
struct Contribution2
{
public:
double dx, dy;
int xsb, ysb;
Contribution2 *Next;
Contribution2(double multiplier, int _xsb, int _ysb)
: xsb(_xsb)
, ysb(_ysb)
, Next(nullptr)
{
dx = -_xsb - multiplier * SQUISH_2D;
dy = -_ysb - multiplier * SQUISH_2D;
}
~Contribution2()
{
if (Next != nullptr)
{
delete Next;
}
}
};
using pContribution2 = std::unique_ptr<Contribution2>;
struct Contribution3
{
public:
double dx, dy, dz;
int xsb, ysb, zsb;
Contribution3 *Next;
Contribution3(double multiplier, int _xsb, int _ysb, int _zsb)
: xsb(_xsb)
, ysb(_ysb)
, zsb(_zsb)
, Next(nullptr)
{
dx = -xsb - multiplier * SQUISH_3D;
dy = -ysb - multiplier * SQUISH_3D;
dz = -zsb - multiplier * SQUISH_3D;
}
~Contribution3()
{
if (Next != nullptr)
{
delete Next;
}
}
};
using pContribution3 = std::unique_ptr<Contribution3>;
struct Contribution4
{
public:
double dx, dy, dz, dw;
int xsb, ysb, zsb, wsb;
Contribution4 *Next;
Contribution4(double multiplier, int _xsb, int _ysb, int _zsb, int _wsb)
: xsb(_xsb)
, ysb(_ysb)
, zsb(_zsb)
, wsb(_wsb)
, Next(nullptr)
{
dx = -xsb - multiplier * SQUISH_4D;
dy = -ysb - multiplier * SQUISH_4D;
dz = -zsb - multiplier * SQUISH_4D;
dw = -wsb - multiplier * SQUISH_4D;
}
~Contribution4()
{
if (Next != nullptr)
{
delete Next;
}
}
};
using pContribution4 = std::unique_ptr<Contribution4>;
// Constants
static const double STRETCH_2D;
static const double STRETCH_3D;
static const double STRETCH_4D;
static const double SQUISH_2D;
static const double SQUISH_3D;
static const double SQUISH_4D;
static const double NORM_2D;
static const double NORM_3D;
static const double NORM_4D;
std::array<unsigned char, 256> perm;
std::array<unsigned char, 256> perm2D;
std::array<unsigned char, 256> perm3D;
std::array<unsigned char, 256> perm4D;
static std::array<double, 16> gradients2D;
static std::array<double, 72> gradients3D;
static std::array<double, 256> gradients4D;
static std::vector<Contribution2*> lookup2D;
static std::vector<Contribution3*> lookup3D;
static std::vector<Contribution4*> lookup4D;
static std::vector<pContribution2> contributions2D;
static std::vector<pContribution3> contributions3D;
static std::vector<pContribution4> contributions4D;
struct StaticConstructor
{
StaticConstructor()
{
gradients2D =
{
5, 2, 2, 5,
-5, 2, -2, 5,
5, -2, 2, -5,
-5, -2, -2, -5,
};
gradients3D =
{
-11, 4, 4, -4, 11, 4, -4, 4, 11,
11, 4, 4, 4, 11, 4, 4, 4, 11,
-11, -4, 4, -4, -11, 4, -4, -4, 11,
11, -4, 4, 4, -11, 4, 4, -4, 11,
-11, 4, -4, -4, 11, -4, -4, 4, -11,
11, 4, -4, 4, 11, -4, 4, 4, -11,
-11, -4, -4, -4, -11, -4, -4, -4, -11,
11, -4, -4, 4, -11, -4, 4, -4, -11,
};
gradients4D =
{
3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3,
-3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3,
3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3,
-3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3,
3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3,
-3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3,
3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3,
-3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3,
3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3,
-3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3,
3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3,
-3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3,
3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3,
-3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3,
3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3,
-3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3,
};
// Create Contribution2s for lookup2D
std::vector<std::vector<int>> base2D =
{
{ 1, 1, 0, 1, 0, 1, 0, 0, 0 },
{ 1, 1, 0, 1, 0, 1, 2, 1, 1 }
};
std::vector<int> p2D =
{
0, 0, 1, -1, 0, 0, -1, 1, 0, 2, 1, 1, 1, 2, 2, 0, 1, 2, 0, 2, 1, 0, 0, 0
};
std::vector<int> lookupPairs2D =
{
0, 1, 1, 0, 4, 1, 17, 0, 20, 2, 21, 2, 22, 5, 23, 5, 26, 4, 39, 3, 42, 4, 43, 3
};
contributions2D.resize(6);
for (int i = 0; i < static_cast<int>(p2D.size()); i += 4)
{
std::vector<int> baseSet = base2D[p2D[i]];
Contribution2 *previous = nullptr, *current = nullptr;
for (int k = 0; k < static_cast<int>(baseSet.size()); k += 3)
{
current =
new Contribution2(baseSet[k], baseSet[k + 1], baseSet[k + 2]);
if (previous == nullptr)
{
contributions2D[i / 4].reset(current);
}
else
{
previous->Next = current;
}
previous = current;
}
current->Next = new Contribution2(p2D[i + 1], p2D[i + 2], p2D[i + 3]);
}
lookup2D.resize(64);
for (int i = 0; i < static_cast<int>(lookupPairs2D.size()); i += 2)
{
lookup2D[lookupPairs2D[i]] =
contributions2D[lookupPairs2D[i + 1]].get();
}
// Create Contribution3s for lookup3D
std::vector<std::vector<int>> base3D =
{
{ 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1 },
{ 2, 1, 1, 0, 2, 1, 0, 1, 2, 0, 1, 1, 3, 1, 1, 1 },
{ 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 2, 1, 1, 0, 2, 1, 0, 1, 2, 0, 1, 1 }
};
std::vector<int> p3D =
{
0, 0, 1, -1, 0, 0, 1, 0, -1, 0, 0, -1, 1, 0, 0, 0, 1, -1, 0, 0, -1, 0, 1, 0, 0, -1, 1, 0, 2, 1, 1, 0, 1, 1, 1, -1, 0, 2, 1, 0, 1, 1, 1, -1, 1, 0, 2, 0, 1, 1, 1, -1, 1, 1, 1, 3, 2, 1, 0, 3, 1, 2, 0, 1, 3, 2, 0, 1, 3, 1, 0, 2, 1, 3, 0, 2, 1, 3, 0, 1, 2, 1, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1, 0, 1, 0, 2, 0, 2, 0, 1, 1, 0, 0, 1, 2, 0, 0, 2, 2, 0, 0, 0, 0, 1, 1, -1, 1, 2, 0, 0, 0, 0, 1, -1, 1, 1, 2, 0, 0, 0, 0, 1, 1, 1, -1, 2, 3, 1, 1, 1, 2, 0, 0, 2, 2, 3, 1, 1, 1, 2, 2, 0, 0, 2, 3, 1, 1, 1, 2, 0, 2, 0, 2, 1, 1, -1, 1, 2, 0, 0, 2, 2, 1, 1, -1, 1, 2, 2, 0, 0, 2, 1, -1, 1, 1, 2, 0, 0, 2, 2, 1, -1, 1, 1, 2, 0, 2, 0, 2, 1, 1, 1, -1, 2, 2, 0, 0, 2, 1, 1, 1, -1, 2, 0, 2, 0
};
std::vector<int> lookupPairs3D =
{
0, 2, 1, 1, 2, 2, 5, 1, 6, 0, 7, 0, 32, 2, 34, 2, 129, 1, 133, 1, 160, 5, 161, 5, 518, 0, 519, 0, 546, 4, 550, 4, 645, 3, 647, 3, 672, 5, 673, 5, 674, 4, 677, 3, 678, 4, 679, 3, 680, 13, 681, 13, 682, 12, 685, 14, 686, 12, 687, 14, 712, 20, 714, 18, 809, 21, 813, 23, 840, 20, 841, 21, 1198, 19, 1199, 22, 1226, 18, 1230, 19, 1325, 23, 1327, 22, 1352, 15, 1353, 17, 1354, 15, 1357, 17, 1358, 16, 1359, 16, 1360, 11, 1361, 10, 1362, 11, 1365, 10, 1366, 9, 1367, 9, 1392, 11, 1394, 11, 1489, 10, 1493, 10, 1520, 8, 1521, 8, 1878, 9, 1879, 9, 1906, 7, 1910, 7, 2005, 6, 2007, 6, 2032, 8, 2033, 8, 2034, 7, 2037, 6, 2038, 7, 2039, 6
};
contributions3D.resize(p3D.size() / 9);
for (int i = 0; i < static_cast<int>(p3D.size()); i += 9)
{
auto baseSet = base3D[p3D[i]];
Contribution3 *previous = nullptr, *current = nullptr;
for (int k = 0; k < static_cast<int>(baseSet.size()); k += 4)
{
current =
new Contribution3(baseSet[k], baseSet[k + 1],
baseSet[k + 2], baseSet[k + 3]);
if (previous == nullptr)
{
contributions3D[i / 9] = pContribution3(current);
}
else
{
previous->Next = current;
}
previous = current;
}
current->Next = new Contribution3(p3D[i + 1], p3D[i + 2], p3D[i + 3], p3D[i + 4]);
current->Next->Next = new Contribution3(p3D[i + 5], p3D[i + 6], p3D[i + 7], p3D[i + 8]);
}
lookup3D.resize(2048);
for (int i = 0; i < static_cast<int>(lookupPairs3D.size()); i += 2)
{
lookup3D[lookupPairs3D[i]] =
contributions3D[lookupPairs3D[i + 1]].get();
}
// Create Contribution4s for lookup4D
std::vector<std::vector<int>> base4D =
{
{ 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1 },
{ 3, 1, 1, 1, 0, 3, 1, 1, 0, 1, 3, 1, 0, 1, 1, 3, 0, 1, 1, 1, 4, 1, 1, 1, 1 },
{ 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 2, 1, 1, 0, 0, 2, 1, 0, 1, 0, 2, 1, 0, 0, 1, 2, 0, 1, 1, 0, 2, 0, 1, 0, 1, 2, 0, 0, 1, 1 },
{ 3, 1, 1, 1, 0, 3, 1, 1, 0, 1, 3, 1, 0, 1, 1, 3, 0, 1, 1, 1, 2, 1, 1, 0, 0, 2, 1, 0, 1, 0, 2, 1, 0, 0, 1, 2, 0, 1, 1, 0, 2, 0, 1, 0, 1, 2, 0, 0, 1, 1 }
};
std::vector<int> p4D =
{
0, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 1, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, 0, -1, 0, 1, 0, 0, 0, -1, 1, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 1, 0, 0, -1, 0, 1, 0, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 0, 2, 1, 0, 1, 0, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 0, 2, 0, 1, 1, 0, 1, -1, 1, 1, 0, 1, 0, 1, 1, -1, 0, 2, 1, 0, 0, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 0, 2, 0, 1, 0, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 0, 2, 0, 0, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 1, 4, 2, 1, 1, 0, 4, 1, 2, 1, 0, 4, 1, 1, 2, 0, 1, 4, 2, 1, 0, 1, 4, 1, 2, 0, 1, 4, 1, 1, 0, 2, 1, 4, 2, 0, 1, 1, 4, 1, 0, 2, 1, 4, 1, 0, 1, 2, 1, 4, 0, 2, 1, 1, 4, 0, 1, 2, 1, 4, 0, 1, 1, 2, 1, 2, 1, 1, 0, 0, 3, 2, 1, 0, 0, 3, 1, 2, 0, 0, 1, 2, 1, 0, 1, 0, 3, 2, 0, 1, 0, 3, 1, 0, 2, 0, 1, 2, 0, 1, 1, 0, 3, 0, 2, 1, 0, 3, 0, 1, 2, 0, 1, 2, 1, 0, 0, 1, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 1, 2, 0, 1, 0, 1, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 1, 2, 0, 0, 1, 1, 3, 0, 0, 2, 1, 3, 0, 0, 1, 2, 2, 3, 1, 1, 1, 0, 2, 1, 1, 1, -1, 2, 2, 0, 0, 0, 2, 3, 1, 1, 0, 1, 2, 1, 1, -1, 1, 2, 2, 0, 0, 0, 2, 3, 1, 0, 1, 1, 2, 1, -1, 1, 1, 2, 2, 0, 0, 0, 2, 3, 1, 1, 1, 0, 2, 1, 1, 1, -1, 2, 0, 2, 0, 0, 2, 3, 1, 1, 0, 1, 2, 1, 1, -1, 1, 2, 0, 2, 0, 0, 2, 3, 0, 1, 1, 1, 2, -1, 1, 1, 1, 2, 0, 2, 0, 0, 2, 3, 1, 1, 1, 0, 2, 1, 1, 1, -1, 2, 0, 0, 2, 0, 2, 3, 1, 0, 1, 1, 2, 1, -1, 1, 1, 2, 0, 0, 2, 0, 2, 3, 0, 1, 1, 1, 2, -1, 1, 1, 1, 2, 0, 0, 2, 0, 2, 3, 1, 1, 0, 1, 2, 1, 1, -1, 1, 2, 0, 0, 0, 2, 2, 3, 1, 0, 1, 1, 2, 1, -1, 1, 1, 2, 0, 0, 0, 2, 2, 3, 0, 1, 1, 1, 2, -1, 1, 1, 1, 2, 0, 0, 0, 2, 2, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 0, 0, 0, 0, 0, 2, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 0, 0, 0, 0, 0, 2, 1, -1, 1, 1, 0, 1, 0, 1, 1, -1, 0, 0, 0, 0, 0, 2, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 0, 0, 0, 0, 0, 2, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 0, 0, 0, 0, 0, 2, 1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 0, 0, 0, 0, 0, 2, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 2, 2, 0, 0, 0, 2, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 2, 2, 0, 0, 0, 2, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 2, 2, 0, 0, 0, 2, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 2, 0, 2, 0, 0, 2, 1, -1, 1, 1, 0, 1, 0, 1, 1, -1, 2, 0, 2, 0, 0, 2, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 2, 0, 2, 0, 0, 2, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 2, 0, 0, 2, 0, 2, 1, -1, 1, 1, 0, 1, 0, 1, 1, -1, 2, 0, 0, 2, 0, 2, 1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 2, 0, 0, 2, 0, 2, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 2, 0, 0, 0, 2, 2, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 2, 0, 0, 0, 2, 2, 1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 2, 0, 0, 0, 2, 3, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 2, 1, 1, 1, -1, 3, 1, 0, 1, 0, 0, 2, 0, 2, 0, 0, 2, 1, 1, 1, -1, 3, 1, 0, 0, 1, 0, 2, 0, 0, 2, 0, 2, 1, 1, 1, -1, 3, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 2, 1, 1, -1, 1, 3, 1, 0, 1, 0, 0, 2, 0, 2, 0, 0, 2, 1, 1, -1, 1, 3, 1, 0, 0, 0, 1, 2, 0, 0, 0, 2, 2, 1, 1, -1, 1, 3, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 2, 1, -1, 1, 1, 3, 1, 0, 0, 1, 0, 2, 0, 0, 2, 0, 2, 1, -1, 1, 1, 3, 1, 0, 0, 0, 1, 2, 0, 0, 0, 2, 2, 1, -1, 1, 1, 3, 1, 0, 1, 0, 0, 2, 0, 2, 0, 0, 2, -1, 1, 1, 1, 3, 1, 0, 0, 1, 0, 2, 0, 0, 2, 0, 2, -1, 1, 1, 1, 3, 1, 0, 0, 0, 1, 2, 0, 0, 0, 2, 2, -1, 1, 1, 1, 3, 3, 2, 1, 0, 0, 3, 1, 2, 0, 0, 4, 1, 1, 1, 1, 3, 3, 2, 0, 1, 0, 3, 1, 0, 2, 0, 4, 1, 1, 1, 1, 3, 3, 0, 2, 1, 0, 3, 0, 1, 2, 0, 4, 1, 1, 1, 1, 3, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 4, 1, 1, 1, 1, 3, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 4, 1, 1, 1, 1, 3, 3, 0, 0, 2, 1, 3, 0, 0, 1, 2, 4, 1, 1, 1, 1, 3, 3, 2, 1, 0, 0, 3, 1, 2, 0, 0, 2, 1, 1, 1, -1, 3, 3, 2, 0, 1, 0, 3, 1, 0, 2, 0, 2, 1, 1, 1, -1, 3, 3, 0, 2, 1, 0, 3, 0, 1, 2, 0, 2, 1, 1, 1, -1, 3, 3, 2, 1, 0, 0, 3, 1, 2, 0, 0, 2, 1, 1, -1, 1, 3, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 2, 1, 1, -1, 1, 3, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 2, 1, 1, -1, 1, 3, 3, 2, 0, 1, 0, 3, 1, 0, 2, 0, 2, 1, -1, 1, 1, 3, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 2, 1, -1, 1, 1, 3, 3, 0, 0, 2, 1, 3, 0, 0, 1, 2, 2, 1, -1, 1, 1, 3, 3, 0, 2, 1, 0, 3, 0, 1, 2, 0, 2, -1, 1, 1, 1, 3, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 2, -1, 1, 1, 1, 3, 3, 0, 0, 2, 1, 3, 0, 0, 1, 2, 2, -1, 1, 1, 1
};
std::vector<int> lookupPairs4D =
{
0, 3, 1, 2, 2, 3, 5, 2, 6, 1, 7, 1, 8, 3, 9, 2, 10, 3, 13, 2, 16, 3, 18, 3, 22, 1, 23, 1, 24, 3, 26, 3, 33, 2, 37, 2, 38, 1, 39, 1, 41, 2, 45, 2, 54, 1, 55, 1, 56, 0, 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 256, 3, 258, 3, 264, 3, 266, 3, 272, 3, 274, 3, 280, 3, 282, 3, 2049, 2, 2053, 2, 2057, 2, 2061, 2, 2081, 2, 2085, 2, 2089, 2, 2093, 2, 2304, 9, 2305, 9, 2312, 9, 2313, 9, 16390, 1, 16391, 1, 16406, 1, 16407, 1, 16422, 1, 16423, 1, 16438, 1, 16439, 1, 16642, 8, 16646, 8, 16658, 8, 16662, 8, 18437, 6, 18439, 6, 18469, 6, 18471, 6, 18688, 9, 18689, 9, 18690, 8, 18693, 6, 18694, 8, 18695, 6, 18696, 9, 18697, 9, 18706, 8, 18710, 8, 18725, 6, 18727, 6, 131128, 0, 131129, 0, 131130, 0, 131131, 0, 131132, 0, 131133, 0, 131134, 0, 131135, 0, 131352, 7, 131354, 7, 131384, 7, 131386, 7, 133161, 5, 133165, 5, 133177, 5, 133181, 5, 133376, 9, 133377, 9, 133384, 9, 133385, 9, 133400, 7, 133402, 7, 133417, 5, 133421, 5, 133432, 7, 133433, 5, 133434, 7, 133437, 5, 147510, 4, 147511, 4, 147518, 4, 147519, 4, 147714, 8, 147718, 8, 147730, 8, 147734, 8, 147736, 7, 147738, 7, 147766, 4, 147767, 4, 147768, 7, 147770, 7, 147774, 4, 147775, 4, 149509, 6, 149511, 6, 149541, 6, 149543, 6, 149545, 5, 149549, 5, 149558, 4, 149559, 4, 149561, 5, 149565, 5, 149566, 4, 149567, 4, 149760, 9, 149761, 9, 149762, 8, 149765, 6, 149766, 8, 149767, 6, 149768, 9, 149769, 9, 149778, 8, 149782, 8, 149784, 7, 149786, 7, 149797, 6, 149799, 6, 149801, 5, 149805, 5, 149814, 4, 149815, 4, 149816, 7, 149817, 5, 149818, 7, 149821, 5, 149822, 4, 149823, 4, 149824, 37, 149825, 37, 149826, 36, 149829, 34, 149830, 36, 149831, 34, 149832, 37, 149833, 37, 149842, 36, 149846, 36, 149848, 35, 149850, 35, 149861, 34, 149863, 34, 149865, 33, 149869, 33, 149878, 32, 149879, 32, 149880, 35, 149881, 33, 149882, 35, 149885, 33, 149886, 32, 149887, 32, 150080, 49, 150082, 48, 150088, 49, 150098, 48, 150104, 47, 150106, 47, 151873, 46, 151877, 45, 151881, 46, 151909, 45, 151913, 44, 151917, 44, 152128, 49, 152129, 46, 152136, 49, 152137, 46, 166214, 43, 166215, 42, 166230, 43, 166247, 42, 166262, 41, 166263, 41, 166466, 48, 166470, 43, 166482, 48, 166486, 43, 168261, 45, 168263, 42, 168293, 45, 168295, 42, 168512, 31, 168513, 28, 168514, 31, 168517, 28, 168518, 25, 168519, 25, 280952, 40, 280953, 39, 280954, 40, 280957, 39, 280958, 38, 280959, 38, 281176, 47, 281178, 47, 281208, 40, 281210, 40, 282985, 44, 282989, 44, 283001, 39, 283005, 39, 283208, 30, 283209, 27, 283224, 30, 283241, 27, 283256, 22, 283257, 22, 297334, 41, 297335, 41, 297342, 38, 297343, 38, 297554, 29, 297558, 24, 297562, 29, 297590, 24, 297594, 21, 297598, 21, 299365, 26, 299367, 23, 299373, 26, 299383, 23, 299389, 20, 299391, 20, 299584, 31, 299585, 28, 299586, 31, 299589, 28, 299590, 25, 299591, 25, 299592, 30, 299593, 27, 299602, 29, 299606, 24, 299608, 30, 299610, 29, 299621, 26, 299623, 23, 299625, 27, 299629, 26, 299638, 24, 299639, 23, 299640, 22, 299641, 22, 299642, 21, 299645, 20, 299646, 21, 299647, 20, 299648, 61, 299649, 60, 299650, 61, 299653, 60, 299654, 59, 299655, 59, 299656, 58, 299657, 57, 299666, 55, 299670, 54, 299672, 58, 299674, 55, 299685, 52, 299687, 51, 299689, 57, 299693, 52, 299702, 54, 299703, 51, 299704, 56, 299705, 56, 299706, 53, 299709, 50, 299710, 53, 299711, 50, 299904, 61, 299906, 61, 299912, 58, 299922, 55, 299928, 58, 299930, 55, 301697, 60, 301701, 60, 301705, 57, 301733, 52, 301737, 57, 301741, 52, 301952, 79, 301953, 79, 301960, 76, 301961, 76, 316038, 59, 316039, 59, 316054, 54, 316071, 51, 316086, 54, 316087, 51, 316290, 78, 316294, 78, 316306, 73, 316310, 73, 318085, 77, 318087, 77, 318117, 70, 318119, 70, 318336, 79, 318337, 79, 318338, 78, 318341, 77, 318342, 78, 318343, 77, 430776, 56, 430777, 56, 430778, 53, 430781, 50, 430782, 53, 430783, 50, 431000, 75, 431002, 72, 431032, 75, 431034, 72, 432809, 74, 432813, 69, 432825, 74, 432829, 69, 433032, 76, 433033, 76, 433048, 75, 433065, 74, 433080, 75, 433081, 74, 447158, 71, 447159, 68, 447166, 71, 447167, 68, 447378, 73, 447382, 73, 447386, 72, 447414, 71, 447418, 72, 447422, 71, 449189, 70, 449191, 70, 449197, 69, 449207, 68, 449213, 69, 449215, 68, 449408, 67, 449409, 67, 449410, 66, 449413, 64, 449414, 66, 449415, 64, 449416, 67, 449417, 67, 449426, 66, 449430, 66, 449432, 65, 449434, 65, 449445, 64, 449447, 64, 449449, 63, 449453, 63, 449462, 62, 449463, 62, 449464, 65, 449465, 63, 449466, 65, 449469, 63, 449470, 62, 449471, 62, 449472, 19, 449473, 19, 449474, 18, 449477, 16, 449478, 18, 449479, 16, 449480, 19, 449481, 19, 449490, 18, 449494, 18, 449496, 17, 449498, 17, 449509, 16, 449511, 16, 449513, 15, 449517, 15, 449526, 14, 449527, 14, 449528, 17, 449529, 15, 449530, 17, 449533, 15, 449534, 14, 449535, 14, 449728, 19, 449729, 19, 449730, 18, 449734, 18, 449736, 19, 449737, 19, 449746, 18, 449750, 18, 449752, 17, 449754, 17, 449784, 17, 449786, 17, 451520, 19, 451521, 19, 451525, 16, 451527, 16, 451528, 19, 451529, 19, 451557, 16, 451559, 16, 451561, 15, 451565, 15, 451577, 15, 451581, 15, 451776, 19, 451777, 19, 451784, 19, 451785, 19, 465858, 18, 465861, 16, 465862, 18, 465863, 16, 465874, 18, 465878, 18, 465893, 16, 465895, 16, 465910, 14, 465911, 14, 465918, 14, 465919, 14, 466114, 18, 466118, 18, 466130, 18, 466134, 18, 467909, 16, 467911, 16, 467941, 16, 467943, 16, 468160, 13, 468161, 13, 468162, 13, 468163, 13, 468164, 13, 468165, 13, 468166, 13, 468167, 13, 580568, 17, 580570, 17, 580585, 15, 580589, 15, 580598, 14, 580599, 14, 580600, 17, 580601, 15, 580602, 17, 580605, 15, 580606, 14, 580607, 14, 580824, 17, 580826, 17, 580856, 17, 580858, 17, 582633, 15, 582637, 15, 582649, 15, 582653, 15, 582856, 12, 582857, 12, 582872, 12, 582873, 12, 582888, 12, 582889, 12, 582904, 12, 582905, 12, 596982, 14, 596983, 14, 596990, 14, 596991, 14, 597202, 11, 597206, 11, 597210, 11, 597214, 11, 597234, 11, 597238, 11, 597242, 11, 597246, 11, 599013, 10, 599015, 10, 599021, 10, 599023, 10, 599029, 10, 599031, 10, 599037, 10, 599039, 10, 599232, 13, 599233, 13, 599234, 13, 599235, 13, 599236, 13, 599237, 13, 599238, 13, 599239, 13, 599240, 12, 599241, 12, 599250, 11, 599254, 11, 599256, 12, 599257, 12, 599258, 11, 599262, 11, 599269, 10, 599271, 10, 599272, 12, 599273, 12, 599277, 10, 599279, 10, 599282, 11, 599285, 10, 599286, 11, 599287, 10, 599288, 12, 599289, 12, 599290, 11, 599293, 10, 599294, 11, 599295, 10
};
contributions4D.resize(p4D.size() / 16);
for (int i = 0; i < static_cast<int>(p4D.size()); i += 16)
{
auto baseSet = base4D[p4D[i]];
Contribution4 *previous = nullptr, *current = nullptr;
for (int k = 0; k < static_cast<int>(baseSet.size()); k += 5)
{
current =
new Contribution4(baseSet[k], baseSet[k + 1],
baseSet[k + 2], baseSet[k + 3],
baseSet[k + 4]);
if (previous == nullptr)
{
contributions4D[i / 16] = pContribution4(current);
}
else
{
previous->Next = current;
}
previous = current;
}
current->Next =
new Contribution4(p4D[i + 1], p4D[i + 2],
p4D[i + 3], p4D[i + 4], p4D[i + 5]);
current->Next->Next =
new Contribution4(p4D[i + 6], p4D[i + 7],
p4D[i + 8], p4D[i + 9], p4D[i + 10]);
current->Next->Next->Next =
new Contribution4(p4D[i + 11], p4D[i + 12],
p4D[i + 13], p4D[i + 14], p4D[i + 15]);
}
lookup4D.resize(1048576);
for (int i = 0; i < static_cast<int>(lookupPairs4D.size()); i += 2)
{
lookup4D[lookupPairs4D[i]] =
contributions4D[lookupPairs4D[i+1]].get();
}
}
};
static StaticConstructor staticConstructor;
FORCE_INLINE static int FastFloor(double x)
{
int xi = static_cast<int>(x);
return x < xi ? xi - 1 : xi;
}
public:
OpenSimplexNoise()
: OpenSimplexNoise(static_cast<int64_t>(time(nullptr)))
{}
OpenSimplexNoise(int64_t seed)
{
std::array<char, 256> source;
for (int i = 0; i < 256; i++)
{
source[i] = i;
}
seed = seed * 6364136223846793005L + 1442695040888963407L;
seed = seed * 6364136223846793005L + 1442695040888963407L;
seed = seed * 6364136223846793005L + 1442695040888963407L;
for (int i = 255; i >= 0; i--)
{
seed = seed * 6364136223846793005L + 1442695040888963407L;
int r = static_cast<int>((seed + 31) % (i + 1));
if (r < 0)
{
r += (i + 1);
}
perm[i] = source[r];
perm2D[i] = perm[i] & 0x0E;
perm3D[i] = (perm[i] % 24) * 3;
perm4D[i] = perm[i] & 0xFC;
source[r] = source[i];
}
}
double Evaluate(double x, double y)
{
double stretchOffset = (x + y) * STRETCH_2D;
double xs = x + stretchOffset;
double ys = y + stretchOffset;
int xsb = FastFloor(xs);
int ysb = FastFloor(ys);
double squishOffset = (xsb + ysb) * SQUISH_2D;
double dx0 = x - (xsb + squishOffset);
double dy0 = y - (ysb + squishOffset);
double xins = xs - xsb;
double yins = ys - ysb;
double inSum = xins + yins;
int hash =
static_cast<int>(xins - yins + 1) |
static_cast<int>(inSum) << 1 |
static_cast<int>(inSum + yins) << 2 |
static_cast<int>(inSum + xins) << 4;
Contribution2 *c = lookup2D[hash];
double value = 0.0;
while (c != nullptr)
{
double dx = dx0 + c->dx;
double dy = dy0 + c->dy;
double attn = 2 - dx * dx - dy * dy;
if (attn > 0)
{
int px = xsb + c->xsb;
int py = ysb + c->ysb;
int i = perm2D[(perm[px & 0xFF] + py) & 0xFF];
double valuePart =
gradients2D[i ] * dx
+ gradients2D[i + 1] * dy;
attn *= attn;
value += attn * attn * valuePart;
}
c = c->Next;
}
return value * NORM_2D;
}
double Evaluate(double x, double y, double z)
{
double stretchOffset = (x + y + z) * STRETCH_3D;
double xs = x + stretchOffset;
double ys = y + stretchOffset;
double zs = z + stretchOffset;
int xsb = FastFloor(xs);
int ysb = FastFloor(ys);
int zsb = FastFloor(zs);
double squishOffset = (xsb + ysb + zsb) * SQUISH_3D;
double dx0 = x - (xsb + squishOffset);
double dy0 = y - (ysb + squishOffset);
double dz0 = z - (zsb + squishOffset);
double xins = xs - xsb;
double yins = ys - ysb;
double zins = zs - zsb;
double inSum = xins + yins + zins;
int hash =
static_cast<int>(yins - zins + 1) |
static_cast<int>(xins - yins + 1) << 1 |
static_cast<int>(xins - zins + 1) << 2 |
static_cast<int>(inSum) << 3 |
static_cast<int>(inSum + zins) << 5 |
static_cast<int>(inSum + yins) << 7 |
static_cast<int>(inSum + xins) << 9;
Contribution3 *c = lookup3D[hash];
double value = 0.0;
while (c != nullptr)
{
double dx = dx0 + c->dx;
double dy = dy0 + c->dy;
double dz = dz0 + c->dz;
double attn = 2 - dx * dx - dy * dy - dz * dz;
if (attn > 0)
{
int px = xsb + c->xsb;
int py = ysb + c->ysb;
int pz = zsb + c->zsb;
int i = perm3D[(perm[(perm[px & 0xFF] + py) & 0xFF] + pz) & 0xFF];
double valuePart =
gradients3D[i ] * dx
+ gradients3D[i + 1] * dy
+ gradients3D[i + 2] * dz;
attn *= attn;
value += attn * attn * valuePart;
}
c = c->Next;
}
return value * NORM_3D;
}
double Evaluate(double x, double y, double z, double w)
{
double stretchOffset = (x + y + z + w) * STRETCH_4D;
double xs = x + stretchOffset;
double ys = y + stretchOffset;
double zs = z + stretchOffset;
double ws = w + stretchOffset;
int xsb = FastFloor(xs);
int ysb = FastFloor(ys);
int zsb = FastFloor(zs);
int wsb = FastFloor(ws);
double squishOffset = (xsb + ysb + zsb + wsb) * SQUISH_4D;
double dx0 = x - (xsb + squishOffset);
double dy0 = y - (ysb + squishOffset);
double dz0 = z - (zsb + squishOffset);
double dw0 = w - (wsb + squishOffset);
double xins = xs - xsb;
double yins = ys - ysb;
double zins = zs - zsb;
double wins = ws - wsb;
double inSum = xins + yins + zins + wins;
int hash =
static_cast<int>(zins - wins + 1) |
static_cast<int>(yins - zins + 1) << 1 |
static_cast<int>(yins - wins + 1) << 2 |
static_cast<int>(xins - yins + 1) << 3 |
static_cast<int>(xins - zins + 1) << 4 |
static_cast<int>(xins - wins + 1) << 5 |
static_cast<int>(inSum) << 6 |
static_cast<int>(inSum + wins) << 8 |
static_cast<int>(inSum + zins) << 11 |
static_cast<int>(inSum + yins) << 14 |
static_cast<int>(inSum + xins) << 17;
Contribution4 *c = lookup4D[hash];
double value = 0.0;
while (c != nullptr)
{
double dx = dx0 + c->dx;
double dy = dy0 + c->dy;
double dz = dz0 + c->dz;
double dw = dw0 + c->dw;
double attn = 2 - dx *dx - dy * dy - dz * dz - dw * dw;
if (attn > 0)
{
int px = xsb + c->xsb;
int py = ysb + c->ysb;
int pz = zsb + c->zsb;
int pw = wsb + c->wsb;
int i = perm4D[(
perm[(
perm[(
perm[px & 0xFF] + py) & 0xFF]
+ pz) & 0xFF]
+ pw) & 0xFF];
double valuePart =
gradients4D[i] * dx
+ gradients4D[i + 1] * dy
+ gradients4D[i + 2] * dz
+ gradients4D[i + 3] * dw;
attn *= attn;
value += attn * attn * valuePart;
}
c = c->Next;
}
return value * NORM_4D;
}
};
#ifndef OPENSIMPLEXNOISE_STATIC_CONSTANTS
#define OPENSIMPLEXNOISE_STATIC_CONSTANTS
const double OpenSimplexNoise::STRETCH_2D = -0.211324865405187;
const double OpenSimplexNoise::STRETCH_3D = -1.0 / 6.0;
const double OpenSimplexNoise::STRETCH_4D = -0.138196601125011;
const double OpenSimplexNoise::SQUISH_2D = 0.366025403784439;
const double OpenSimplexNoise::SQUISH_3D = 1.0 / 3.0;
const double OpenSimplexNoise::SQUISH_4D = 0.309016994374947;
const double OpenSimplexNoise::NORM_2D = 1.0 / 47.0;
const double OpenSimplexNoise::NORM_3D = 1.0 / 103.0;
const double OpenSimplexNoise::NORM_4D = 1.0 / 30.0;
std::array<double, 16> OpenSimplexNoise::gradients2D;
std::array<double, 72> OpenSimplexNoise::gradients3D;
std::array<double, 256> OpenSimplexNoise::gradients4D;
std::vector<OpenSimplexNoise::Contribution2*> OpenSimplexNoise::lookup2D;
std::vector<OpenSimplexNoise::Contribution3*> OpenSimplexNoise::lookup3D;
std::vector<OpenSimplexNoise::Contribution4*> OpenSimplexNoise::lookup4D;
std::vector<OpenSimplexNoise::pContribution2> OpenSimplexNoise::contributions2D;
std::vector<OpenSimplexNoise::pContribution3> OpenSimplexNoise::contributions3D;
std::vector<OpenSimplexNoise::pContribution4> OpenSimplexNoise::contributions4D;
// Initialise our static tables
OpenSimplexNoise::StaticConstructor OpenSimplexNoise::staticConstructor;
#endif
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
@Markyparky56
Copy link
Author

Initial testing seems to be fairly good, will try to generate some pretty images tomorrow. Very promising speeds so far, remember to run without the debugger to get the most out of it.

@Markyparky56
Copy link
Author

Markyparky56 commented Mar 3, 2017

Changes with the latest revision as of 2017/03/03:
Fixed an issue with the p3D and lookupPairs3D arrays which I must have messed up when copying which caused some nasty artifacting
Put some of the arrays back on one line to reduce the line count a bit

Speed Tests!
data table
Values are in nanoseconds, averaged from the time taken to calculate 1,000,000 points.

2D Noise 512x512 Image
2dimg

3D Noise 512x512 Image
3dimg

4D Noise 512x512 Image
4dimg

@npiegdon
Copy link

This is great work!

I was hoping to add some noise features (and an example) to immediate2d and this would be perfect. It doesn't look like the "UNLICENSE" file made it over from DigitalShadow's gist, so I just wanted to double-check that the same (or similar) license still applied first. Thanks!

@Markyparky56
Copy link
Author

Markyparky56 commented Jan 25, 2018

@npiegdon the UNLICENSE file was added after I made this, I've now added it here as well. I look forward to seeing what you can do with this! If I remember right the STATIC_CONSTANTS stuff could be a bit iffy if you included it in multiple code files, so you may need to tweak how those are included. I've been working with FastNoise a lot lately, and looking at how it achieves its speed I may revisit this as I think it could benefit from some of those optimisations. P.s. replies without @ing don't notify, so if you want to contact me remember to @ me.

@john01dav
Copy link

Is there any reason that you have everything here in a header? It would work much better if there was a header and implementation file. If I try to include it in more than one place in my project (or in a header file, in case I want an OpenSimplexNoise object as a class member) it breaks and won't compile.

@Markyparky56
Copy link
Author

@john01dav Mostly because I did not know how to do header-only files at the time, I think I know how to fix this now actually. I'll see about revising this gist ASAP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment