n/fractal: fix musgrave (aka rigid multifractal)
This commit is contained in:
parent
62000f50a2
commit
fedbef630b
@ -19,30 +19,25 @@
|
|||||||
#include "debug.hpp"
|
#include "debug.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
using util::noise::fractal;
|
using util::noise::fractal;
|
||||||
using util::noise::fbm;
|
using util::noise::fbm;
|
||||||
using util::noise::musgrave;
|
using util::noise::rmf;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <typename T>
|
||||||
fractal<T>::fractal (unsigned _octaves,
|
fractal<T>::fractal ():
|
||||||
T _frequency,
|
seed (rand ())
|
||||||
T _lacunarity):
|
|
||||||
octaves (_octaves),
|
|
||||||
frequency (_frequency),
|
|
||||||
lacunarity (_lacunarity)
|
|
||||||
{ ; }
|
{ ; }
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
fractal<T>::fractal ():
|
fractal<T>::fractal (seed_t _seed):
|
||||||
octaves (1),
|
seed (_seed)
|
||||||
frequency (T(0.1)),
|
|
||||||
lacunarity (T(0.6))
|
|
||||||
{ ; }
|
{ ; }
|
||||||
|
|
||||||
|
|
||||||
@ -73,15 +68,27 @@ template <typename T, typename B>
|
|||||||
fbm<T,B>::fbm (unsigned _octaves,
|
fbm<T,B>::fbm (unsigned _octaves,
|
||||||
T _frequency,
|
T _frequency,
|
||||||
T _lacunarity,
|
T _lacunarity,
|
||||||
|
T _amplitude,
|
||||||
|
T _gain,
|
||||||
seed_t _seed):
|
seed_t _seed):
|
||||||
fractal<T> (_octaves, _frequency, _lacunarity),
|
fractal<T> (_seed),
|
||||||
|
octaves (_octaves),
|
||||||
|
frequency (_frequency),
|
||||||
|
lacunarity (_lacunarity),
|
||||||
|
amplitude (_amplitude),
|
||||||
|
gain (_gain),
|
||||||
basis (_seed)
|
basis (_seed)
|
||||||
{ ; }
|
{
|
||||||
|
CHECK_NEQ (octaves, 0);
|
||||||
|
CHECK_NEQ (frequency, 0);
|
||||||
|
CHECK_NEQ (amplitude, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T, typename B>
|
template <typename T, typename B>
|
||||||
fbm<T,B>::fbm ()
|
fbm<T,B>::fbm ():
|
||||||
|
fbm<T,B> (8, T(0.1), 2, 1, 1/T(2), rand ())
|
||||||
{ ; }
|
{ ; }
|
||||||
|
|
||||||
|
|
||||||
@ -90,17 +97,14 @@ template <typename T, typename B>
|
|||||||
T
|
T
|
||||||
fbm<T,B>::operator() (T x, T y) const {
|
fbm<T,B>::operator() (T x, T y) const {
|
||||||
T total = 0;
|
T total = 0;
|
||||||
T f = this->frequency;
|
T f = frequency;
|
||||||
T a = 1;
|
T a = amplitude;
|
||||||
T a_sum = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < this->octaves; ++i) {
|
for (size_t i = 0; i < octaves; ++i) {
|
||||||
total += basis (x * f, y * f) * a;
|
total += basis (x * f, y * f) * a;
|
||||||
|
|
||||||
f *= 2;
|
f *= lacunarity;
|
||||||
|
a *= gain;
|
||||||
a_sum += a;
|
|
||||||
a *= this->lacunarity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
@ -111,84 +115,93 @@ fbm<T,B>::operator() (T x, T y) const {
|
|||||||
template struct util::noise::fbm<float, util::noise::cellular<float>>;
|
template struct util::noise::fbm<float, util::noise::cellular<float>>;
|
||||||
template struct util::noise::fbm<float, util::noise::gradient<float,util::lerp::linear>>;
|
template struct util::noise::fbm<float, util::noise::gradient<float,util::lerp::linear>>;
|
||||||
template struct util::noise::fbm<float, util::noise::gradient<float,util::lerp::quintic>>;
|
template struct util::noise::fbm<float, util::noise::gradient<float,util::lerp::quintic>>;
|
||||||
|
template struct util::noise::fbm<float, util::noise::value<float,util::lerp::trunc>>;
|
||||||
template struct util::noise::fbm<float, util::noise::value<float,util::lerp::linear>>;
|
template struct util::noise::fbm<float, util::noise::value<float,util::lerp::linear>>;
|
||||||
template struct util::noise::fbm<float, util::noise::value<float,util::lerp::quintic>>;
|
template struct util::noise::fbm<float, util::noise::value<float,util::lerp::quintic>>;
|
||||||
|
|
||||||
template struct util::noise::fbm<double, util::noise::cellular<double>>;
|
template struct util::noise::fbm<double, util::noise::cellular<double>>;
|
||||||
template struct util::noise::fbm<double, util::noise::gradient<double,util::lerp::linear>>;
|
template struct util::noise::fbm<double, util::noise::gradient<double,util::lerp::linear>>;
|
||||||
template struct util::noise::fbm<double, util::noise::gradient<double,util::lerp::quintic>>;
|
template struct util::noise::fbm<double, util::noise::gradient<double,util::lerp::quintic>>;
|
||||||
|
template struct util::noise::fbm<double, util::noise::value<double,util::lerp::trunc>>;
|
||||||
template struct util::noise::fbm<double, util::noise::value<double,util::lerp::linear>>;
|
template struct util::noise::fbm<double, util::noise::value<double,util::lerp::linear>>;
|
||||||
template struct util::noise::fbm<double, util::noise::value<double,util::lerp::quintic>>;
|
template struct util::noise::fbm<double, util::noise::value<double,util::lerp::quintic>>;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T, typename B>
|
template <typename T, typename B>
|
||||||
musgrave<T,B>::musgrave (unsigned _octaves,
|
rmf<T,B>::rmf (unsigned _octaves,
|
||||||
T _frequency,
|
T _frequency,
|
||||||
T _lacunarity,
|
T _lacunarity,
|
||||||
|
T _amplitude,
|
||||||
|
T _gain,
|
||||||
seed_t _seed):
|
seed_t _seed):
|
||||||
fractal<T> (_octaves, _frequency, _lacunarity),
|
fractal<T> (_seed),
|
||||||
|
octaves (_octaves),
|
||||||
|
frequency (_frequency),
|
||||||
|
lacunarity (_lacunarity),
|
||||||
|
amplitude (_amplitude),
|
||||||
|
gain (_gain),
|
||||||
basis (_seed)
|
basis (_seed)
|
||||||
{ ; }
|
{ ; }
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T, typename B>
|
template <typename T, typename B>
|
||||||
musgrave<T,B>::musgrave ()
|
rmf<T,B>::rmf ():
|
||||||
|
rmf<T,B> (6, T(1), 2, 1, T(2), rand ())
|
||||||
{ ; }
|
{ ; }
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T, typename B>
|
template <typename T, typename B>
|
||||||
T
|
T
|
||||||
musgrave<T,B>::operator() (T x, T y) const {
|
rmf<T,B>::operator() (T x, T y) const {
|
||||||
T total = 0;
|
T H = 1;
|
||||||
T f = this->frequency;
|
T exponents[octaves];
|
||||||
T a = 1;
|
T offset = 1;
|
||||||
|
|
||||||
T weight = 1;
|
T f = 1.f;
|
||||||
T offset = 1;
|
for (size_t i = 0; i < octaves; ++i) {
|
||||||
T gain = 2;
|
exponents[i] = std::pow (f, -H);
|
||||||
|
f *= lacunarity;
|
||||||
|
}
|
||||||
|
|
||||||
T signal;
|
T signal = 0, result = 0, weight = 1;
|
||||||
|
|
||||||
signal = basis (x * f, y * f);
|
x *= frequency;
|
||||||
signal = std::fabs (signal);
|
y *= frequency;
|
||||||
signal = offset - signal;
|
|
||||||
signal *= signal;
|
|
||||||
total = signal;
|
|
||||||
|
|
||||||
for (size_t i = 1; i < this->octaves; ++i) {
|
for (size_t i = 0; i < octaves; ++i) {
|
||||||
f *= 2;
|
signal = basis (x, y);
|
||||||
a *= this->lacunarity;
|
signal = std::fabs (signal);
|
||||||
|
signal = offset - signal;
|
||||||
|
|
||||||
|
signal *= signal;
|
||||||
|
signal *= weight;
|
||||||
|
|
||||||
weight = signal * gain;
|
weight = signal * gain;
|
||||||
weight = limit (weight, 0, 1);
|
weight = limit (weight, 0, 1);
|
||||||
|
|
||||||
signal = basis (x * f, y * f);
|
result += signal * exponents[i];
|
||||||
signal = std::fabs (signal);
|
|
||||||
signal = offset - signal;
|
|
||||||
signal *= signal;
|
|
||||||
|
|
||||||
signal *= weight;
|
x *= lacunarity;
|
||||||
total += signal * a;
|
y *= lacunarity;
|
||||||
total = limit (total, 0, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return total;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template struct util::noise::musgrave<float, util::noise::cellular<float>>;
|
template struct util::noise::rmf<float, util::noise::cellular<float>>;
|
||||||
template struct util::noise::musgrave<float, util::noise::gradient<float,util::lerp::linear>>;
|
template struct util::noise::rmf<float, util::noise::gradient<float,util::lerp::linear>>;
|
||||||
template struct util::noise::musgrave<float, util::noise::gradient<float,util::lerp::quintic>>;
|
template struct util::noise::rmf<float, util::noise::gradient<float,util::lerp::quintic>>;
|
||||||
template struct util::noise::musgrave<float, util::noise::value<float,util::lerp::linear>>;
|
template struct util::noise::rmf<float, util::noise::value<float,util::lerp::linear>>;
|
||||||
template struct util::noise::musgrave<float, util::noise::value<float,util::lerp::quintic>>;
|
template struct util::noise::rmf<float, util::noise::value<float,util::lerp::quintic>>;
|
||||||
|
|
||||||
template struct util::noise::musgrave<double, util::noise::cellular<double>>;
|
template struct util::noise::rmf<double, util::noise::cellular<double>>;
|
||||||
template struct util::noise::musgrave<double, util::noise::gradient<double,util::lerp::linear>>;
|
template struct util::noise::rmf<double, util::noise::gradient<double,util::lerp::linear>>;
|
||||||
template struct util::noise::musgrave<double, util::noise::gradient<double,util::lerp::quintic>>;
|
template struct util::noise::rmf<double, util::noise::gradient<double,util::lerp::quintic>>;
|
||||||
template struct util::noise::musgrave<double, util::noise::value<double,util::lerp::linear>>;
|
template struct util::noise::rmf<double, util::noise::value<double,util::lerp::linear>>;
|
||||||
template struct util::noise::musgrave<double, util::noise::value<double,util::lerp::quintic>>;
|
template struct util::noise::rmf<double, util::noise::value<double,util::lerp::quintic>>;
|
||||||
|
|
||||||
|
@ -24,21 +24,28 @@ namespace util {
|
|||||||
/// Base noise summation
|
/// Base noise summation
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct fractal {
|
struct fractal {
|
||||||
fractal (unsigned octaves,
|
using seed_t = uint64_t;
|
||||||
T frequency,
|
|
||||||
T lacunarity);
|
fractal (seed_t);
|
||||||
fractal ();
|
fractal ();
|
||||||
virtual ~fractal ();
|
virtual ~fractal ();
|
||||||
|
|
||||||
unsigned octaves;
|
|
||||||
T frequency;
|
|
||||||
T lacunarity;
|
|
||||||
|
|
||||||
virtual T operator() (T x, T y) const = 0;
|
virtual T operator() (T x, T y) const = 0;
|
||||||
|
|
||||||
|
seed_t seed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Fractal Brownian Motion summation.
|
/// Fractal Brownian Motion summation.
|
||||||
|
///
|
||||||
|
/// Sum progressive layers of a noise basis with scaling frequency
|
||||||
|
/// and amplitude.
|
||||||
|
///
|
||||||
|
/// octaves: count of layers to be summed
|
||||||
|
/// frequency: point scaling factor for the base octave
|
||||||
|
/// lacunarity: per octave frequency scaling factor
|
||||||
|
/// amplitude: maximum absolute value of the noise
|
||||||
|
/// gain: per octave amplitude scaling factor. typically 1/f.
|
||||||
template <typename T, typename B>
|
template <typename T, typename B>
|
||||||
struct fbm : public fractal<T> {
|
struct fbm : public fractal<T> {
|
||||||
using seed_t = typename basis<T>::seed_t;
|
using seed_t = typename basis<T>::seed_t;
|
||||||
@ -46,24 +53,48 @@ namespace util {
|
|||||||
fbm (unsigned octaves,
|
fbm (unsigned octaves,
|
||||||
T frequency,
|
T frequency,
|
||||||
T lacunarity,
|
T lacunarity,
|
||||||
|
T amplitude,
|
||||||
|
T gain,
|
||||||
seed_t seed);
|
seed_t seed);
|
||||||
fbm ();
|
fbm ();
|
||||||
|
|
||||||
|
unsigned octaves;
|
||||||
|
|
||||||
|
T frequency;
|
||||||
|
T lacunarity;
|
||||||
|
|
||||||
|
T amplitude;
|
||||||
|
T gain;
|
||||||
|
|
||||||
B basis;
|
B basis;
|
||||||
virtual T operator() (T x, T y) const override;
|
virtual T operator() (T x, T y) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Rigid Multifractal noise summation.
|
/// Rigid Multifractal noise summation, based on Musgrave's algorithm
|
||||||
|
///
|
||||||
|
/// octaves: count of layers to be summed
|
||||||
|
/// frequency: point scaling factor for the base octave
|
||||||
|
/// lacunarity: per octave frequency scaling factor
|
||||||
template <typename T, typename B>
|
template <typename T, typename B>
|
||||||
struct musgrave : public fractal<T> {
|
struct rmf : public fractal<T> {
|
||||||
using seed_t = typename basis<T>::seed_t;
|
using seed_t = typename basis<T>::seed_t;
|
||||||
|
|
||||||
musgrave (unsigned octaves,
|
rmf (unsigned octaves,
|
||||||
T frequency,
|
T frequency,
|
||||||
T lacunarity,
|
T lacunarity,
|
||||||
|
T amplitude,
|
||||||
|
T gain,
|
||||||
seed_t seed);
|
seed_t seed);
|
||||||
musgrave ();
|
rmf ();
|
||||||
|
|
||||||
|
unsigned octaves;
|
||||||
|
|
||||||
|
T frequency;
|
||||||
|
T lacunarity;
|
||||||
|
|
||||||
|
T amplitude;
|
||||||
|
T gain;
|
||||||
|
|
||||||
B basis;
|
B basis;
|
||||||
virtual T operator() (T x, T y) const override;
|
virtual T operator() (T x, T y) const override;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user