Skip to content

Instantly share code, notes, and snippets.

@linkdd
Created August 28, 2023 03:39
Show Gist options
  • Save linkdd/1ae43496cc6e675eea818cf4a9cb53eb to your computer and use it in GitHub Desktop.
Save linkdd/1ae43496cc6e675eea818cf4a9cb53eb to your computer and use it in GitHub Desktop.
Noise function for QR (Cubic/Axial) coordinate system (for hexagonal maps)
#pragma once
#include <algorithm>
#include <array>
#include <random>
#include <glm/vec3.hpp>
#include <hex/coords.hpp>
class qr_noise {
private:
static constexpr int PERMUTATIONS_SIZE = 256;
static constexpr int HASH_PRIME = 521; // first prime after PERMUTATIONS_SIZE * 2
static constexpr int GRADIENTS_SIZE = 32;
std::default_random_engine m_rnd_gen;
std::uniform_real_distribution<float> m_rnd_dist{-1.0f, 1.0f};
std::array<int, PERMUTATIONS_SIZE> m_permutations;
std::array<glm::vec3, GRADIENTS_SIZE> m_gradients;
public:
qr_noise(int seed) : m_rnd_gen(seed) {
init_permutations();
init_gradients();
}
float at(const hex::cubic &coord) {
float total = get_gradient_contribution(coord, hex::cubic(0, 0, 0));
for (auto& neighbor : coord.neighbors()) {
total += get_gradient_contribution(neighbor, coord - neighbor);
}
int n_points = 7;
return (total / n_points + 1.0f) / 2.0f;
}
private:
void init_permutations() {
for (int i = 0; i < PERMUTATIONS_SIZE; i++) {
m_permutations[i] = i;
}
std::shuffle(m_permutations.begin(), m_permutations.end(), m_rnd_gen);
}
void init_gradients() {
for (int i = 0; i < GRADIENTS_SIZE; i++) {
auto gradient = glm::vec3(
m_rnd_dist(m_rnd_gen),
m_rnd_dist(m_rnd_gen),
m_rnd_dist(m_rnd_gen)
);
m_gradients[i] = glm::normalize(gradient);
}
}
float get_gradient_contribution(const hex::cubic &coord, const hex::cubic &offset) {
auto gradient = get_gradient(coord);
return gradient.x * offset.q + gradient.y * offset.r + gradient.z * offset.s;
}
glm::vec3 get_gradient(const hex::cubic &coord) {
int h = get_hash(coord) % GRADIENTS_SIZE;
return m_gradients[h];
}
int get_hash(const hex::cubic &coord) {
int q = std::abs(coord.q) % HASH_PRIME;
int r = std::abs(coord.r) % HASH_PRIME;
int s = std::abs(coord.s) % HASH_PRIME;
int a = m_permutations[s % PERMUTATIONS_SIZE];
int b = m_permutations[(r + a) % PERMUTATIONS_SIZE];
int c = m_permutations[(q + b) % PERMUTATIONS_SIZE];
int d = m_permutations[c % PERMUTATIONS_SIZE];
return d;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment