n/fractal: fix musgrave (aka rigid multifractal)

This commit is contained in:
Danny Robson 2015-05-26 16:31:30 +10:00
parent 62000f50a2
commit fedbef630b
2 changed files with 114 additions and 70 deletions

View File

@ -19,30 +19,25 @@
#include "debug.hpp"
#include <algorithm>
#include <cmath>
using util::noise::fractal;
using util::noise::fbm;
using util::noise::musgrave;
using util::noise::rmf;
///////////////////////////////////////////////////////////////////////////////
template <typename T>
fractal<T>::fractal (unsigned _octaves,
T _frequency,
T _lacunarity):
octaves (_octaves),
frequency (_frequency),
lacunarity (_lacunarity)
fractal<T>::fractal ():
seed (rand ())
{ ; }
//-----------------------------------------------------------------------------
template <typename T>
fractal<T>::fractal ():
octaves (1),
frequency (T(0.1)),
lacunarity (T(0.6))
fractal<T>::fractal (seed_t _seed):
seed (_seed)
{ ; }
@ -73,15 +68,27 @@ template <typename T, typename B>
fbm<T,B>::fbm (unsigned _octaves,
T _frequency,
T _lacunarity,
T _amplitude,
T _gain,
seed_t _seed):
fractal<T> (_octaves, _frequency, _lacunarity),
fractal<T> (_seed),
octaves (_octaves),
frequency (_frequency),
lacunarity (_lacunarity),
amplitude (_amplitude),
gain (_gain),
basis (_seed)
{ ; }
{
CHECK_NEQ (octaves, 0);
CHECK_NEQ (frequency, 0);
CHECK_NEQ (amplitude, 0);
}
//-----------------------------------------------------------------------------
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
fbm<T,B>::operator() (T x, T y) const {
T total = 0;
T f = this->frequency;
T a = 1;
T a_sum = 0;
T f = frequency;
T a = amplitude;
for (size_t i = 0; i < this->octaves; ++i) {
for (size_t i = 0; i < octaves; ++i) {
total += basis (x * f, y * f) * a;
f *= 2;
a_sum += a;
a *= this->lacunarity;
f *= lacunarity;
a *= gain;
}
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::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::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::quintic>>;
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::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::quintic>>;
///////////////////////////////////////////////////////////////////////////////
template <typename T, typename B>
musgrave<T,B>::musgrave (unsigned _octaves,
rmf<T,B>::rmf (unsigned _octaves,
T _frequency,
T _lacunarity,
T _amplitude,
T _gain,
seed_t _seed):
fractal<T> (_octaves, _frequency, _lacunarity),
fractal<T> (_seed),
octaves (_octaves),
frequency (_frequency),
lacunarity (_lacunarity),
amplitude (_amplitude),
gain (_gain),
basis (_seed)
{ ; }
//-----------------------------------------------------------------------------
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>
T
musgrave<T,B>::operator() (T x, T y) const {
T total = 0;
T f = this->frequency;
T a = 1;
rmf<T,B>::operator() (T x, T y) const {
T H = 1;
T exponents[octaves];
T offset = 1;
T weight = 1;
T offset = 1;
T gain = 2;
T f = 1.f;
for (size_t i = 0; i < octaves; ++i) {
exponents[i] = std::pow (f, -H);
f *= lacunarity;
}
T signal;
T signal = 0, result = 0, weight = 1;
signal = basis (x * f, y * f);
signal = std::fabs (signal);
signal = offset - signal;
signal *= signal;
total = signal;
x *= frequency;
y *= frequency;
for (size_t i = 1; i < this->octaves; ++i) {
f *= 2;
a *= this->lacunarity;
for (size_t i = 0; i < octaves; ++i) {
signal = basis (x, y);
signal = std::fabs (signal);
signal = offset - signal;
signal *= signal;
signal *= weight;
weight = signal * gain;
weight = limit (weight, 0, 1);
signal = basis (x * f, y * f);
signal = std::fabs (signal);
signal = offset - signal;
signal *= signal;
result += signal * exponents[i];
signal *= weight;
total += signal * a;
total = limit (total, 0, 1);
x *= lacunarity;
y *= lacunarity;
}
return total;
return result;
}
//-----------------------------------------------------------------------------
template struct util::noise::musgrave<float, util::noise::cellular<float>>;
template struct util::noise::musgrave<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::musgrave<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::cellular<float>>;
template struct util::noise::rmf<float, util::noise::gradient<float,util::lerp::linear>>;
template struct util::noise::rmf<float, util::noise::gradient<float,util::lerp::quintic>>;
template struct util::noise::rmf<float, util::noise::value<float,util::lerp::linear>>;
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::musgrave<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::musgrave<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::cellular<double>>;
template struct util::noise::rmf<double, util::noise::gradient<double,util::lerp::linear>>;
template struct util::noise::rmf<double, util::noise::gradient<double,util::lerp::quintic>>;
template struct util::noise::rmf<double, util::noise::value<double,util::lerp::linear>>;
template struct util::noise::rmf<double, util::noise::value<double,util::lerp::quintic>>;

View File

@ -24,21 +24,28 @@ namespace util {
/// Base noise summation
template <typename T>
struct fractal {
fractal (unsigned octaves,
T frequency,
T lacunarity);
using seed_t = uint64_t;
fractal (seed_t);
fractal ();
virtual ~fractal ();
unsigned octaves;
T frequency;
T lacunarity;
virtual T operator() (T x, T y) const = 0;
seed_t seed;
};
/// 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>
struct fbm : public fractal<T> {
using seed_t = typename basis<T>::seed_t;
@ -46,24 +53,48 @@ namespace util {
fbm (unsigned octaves,
T frequency,
T lacunarity,
T amplitude,
T gain,
seed_t seed);
fbm ();
unsigned octaves;
T frequency;
T lacunarity;
T amplitude;
T gain;
B basis;
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>
struct musgrave : public fractal<T> {
struct rmf : public fractal<T> {
using seed_t = typename basis<T>::seed_t;
musgrave (unsigned octaves,
rmf (unsigned octaves,
T frequency,
T lacunarity,
T amplitude,
T gain,
seed_t seed);
musgrave ();
rmf ();
unsigned octaves;
T frequency;
T lacunarity;
T amplitude;
T gain;
B basis;
virtual T operator() (T x, T y) const override;