+namespace {
+
+struct Interpolation {
+ /// sample points for interpolation
+ /// given coordinates should be the absoloute position of the chunk's (0,0,0) block
+ Interpolation(
+ const SimplexNoise &noise,
+ const glm::vec3 &base,
+ const Generator::Config::NoiseParam &conf
+ ) noexcept {
+ for (int z = 0; z < 5; ++z) {
+ for (int y = 0; y < 5; ++y) {
+ for (int x = 0; x < 5; ++x) {
+ samples[z][y][x] = OctaveNoise(
+ noise,
+ base + (glm::vec3(x, y, z) * 4.0f),
+ conf.octaves,
+ conf.persistence,
+ conf.frequency,
+ conf.amplitude,
+ conf.growth
+ );
+ }
+ }
+ }
+ }
+ float samples[5][5][5];
+};
+
+struct Parameters {
+ glm::ivec3 a;
+ glm::ivec3 b;
+ glm::ivec3 d;
+};
+
+struct Detail {
+ float humidity;
+ float temperature;
+ float richness;
+ float randomness;
+};
+
+}
+
+struct Generator::ValueField {
+
+ Interpolation solidity;
+ Interpolation humidity;
+ Interpolation temperature;
+ Interpolation richness;
+ Interpolation randomness;
+
+ static Parameters GetParams(const glm::ivec3 &pos) noexcept {
+ Parameters p;
+ p.a = pos / 4;
+ p.b = p.a + 1;
+ p.d = pos % 4;
+ return p;
+ }
+
+ static float Interpolate(const Interpolation &i, const Parameters &p) noexcept {
+ constexpr float A[4] = { 1.0f, 0.75f, 0.5f, 0.25f };
+ constexpr float B[4] = { 0.0f, 0.25f, 0.5f, 0.75f };
+ const float l1[4] = {
+ i.samples[p.a.z][p.a.y][p.a.x] * A[p.d.x] + i.samples[p.a.z][p.a.y][p.b.x] * B[p.d.x],
+ i.samples[p.a.z][p.b.y][p.a.x] * A[p.d.x] + i.samples[p.a.z][p.b.y][p.b.x] * B[p.d.x],
+ i.samples[p.b.z][p.a.y][p.a.x] * A[p.d.x] + i.samples[p.b.z][p.a.y][p.b.x] * B[p.d.x],
+ i.samples[p.b.z][p.b.y][p.a.x] * A[p.d.x] + i.samples[p.b.z][p.b.y][p.b.x] * B[p.d.x],
+ };
+ const float l2[2] = {
+ l1[0] * A[p.d.y] + l1[1] * B[p.d.y],
+ l1[2] * A[p.d.y] + l1[3] * B[p.d.y],
+ };
+ return l2[0] * A[p.d.z] + l2[1] * B[p.d.z];
+ }
+
+};
+