Created
August 28, 2023 03:39
-
-
Save linkdd/1ae43496cc6e675eea818cf4a9cb53eb to your computer and use it in GitHub Desktop.
Noise function for QR (Cubic/Axial) coordinate system (for hexagonal maps)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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