szdytom 06a60b1a19
feat: Xoroshiro128++ Random Engine
Signed-off-by: szdytom <szdytom@qq.com>
2025-08-02 00:05:12 +08:00

115 lines
3.0 KiB
C++

#ifndef ISTD_TILEMAP_NOISE_H
#define ISTD_TILEMAP_NOISE_H
#include "xoroshiro.h"
#include <cstdint>
#include <vector>
namespace istd {
class PerlinNoise {
private:
std::vector<int> permutation_;
// Helper functions for Perlin noise calculation
double fade(double t) const;
double lerp(double t, double a, double b) const;
double grad(int hash, double x, double y) const;
public:
/**
* @brief Construct a PerlinNoise generator with the given seed
* @param rng Random number generator for noise
*/
explicit PerlinNoise(Xoroshiro128PP rng);
PerlinNoise() = default;
/**
* @brief Generate 2D Perlin noise value at the given coordinates
* @param x X coordinate
* @param y Y coordinate
* @return Noise value between 0.0 and 1.0
*/
double noise(double x, double y) const;
/**
* @brief Generate octave noise (multiple frequencies combined)
* @param x X coordinate
* @param y Y coordinate
* @param octaves Number of octaves to combine
* @param persistence How much each octave contributes
* @return Noise value between 0.0 and 1.0
*/
double octave_noise(
double x, double y, int octaves, double persistence
) const;
};
/**
* @brief A wrapper that provides uniform distribution mapping for Perlin noise
*
* This class samples the noise distribution and builds a CDF (Cumulative
* Distribution Function) to map the non-uniform Perlin noise values to a
* uniform [0,1] distribution using quantiles.
*/
class UniformPerlinNoise {
private:
PerlinNoise noise_;
Xoroshiro128PP calibrate_rng_;
std::vector<double> cdf_values_; // Sorted noise values for CDF
bool is_calibrated_;
// Parameters used for calibration
double scale_;
int octaves_;
double persistence_;
public:
/**
* @brief Construct a UniformPerlinNoise generator
* @param seed Random seed for noise generation
*/
explicit UniformPerlinNoise(Xoroshiro128PP rng);
UniformPerlinNoise() = default;
/**
* @brief Calibrate the noise distribution by sampling
* @param scale The scale parameter that will be used for generation
* @param octaves Number of octaves for octave noise
* @param persistence Persistence for octave noise
* @param sample_size Number of samples to use for CDF (default: 10000)
*/
void calibrate(
double scale, int octaves, double persistence, int sample_size = 10000
);
/**
* @brief Generate uniform noise value at the given coordinates
* @param x X coordinate
* @param y Y coordinate
* @return Uniformly distributed noise value between 0.0 and 1.0
* @note Must call calibrate() first
*/
double uniform_noise(double x, double y) const;
/**
* @brief Check if the noise generator has been calibrated
*/
bool is_calibrated() const {
return is_calibrated_;
}
private:
/**
* @brief Map a raw noise value to uniform distribution using the CDF
* @param raw_value Raw noise value from Perlin noise
* @return Uniformly distributed value between 0.0 and 1.0
*/
double map_to_uniform(double raw_value) const;
};
} // namespace istd
#endif