Normalise basis values and give expected bounds

This commit is contained in:
Danny Robson 2012-05-24 15:04:06 +10:00
parent aabbf231c5
commit c354cf6ed6
3 changed files with 40 additions and 8 deletions

View File

@ -27,6 +27,7 @@
#include <algorithm>
using namespace util::noise;
using util::range;
///////////////////////////////////////////////////////////////////////////////
// Generate a type from [-UNIT..UNIT]
@ -86,6 +87,12 @@ template <lerp_function L>
{ ; }
template <lerp_function L>
range<double>
value<L>::bounds (void) const
{ return { -1.0, 1.0 }; }
template <lerp_function L>
double
value<L>::eval (double x, double y) const {
@ -117,11 +124,18 @@ gradient<L>::gradient (seed_t _seed):
basis (_seed)
{ ; }
template <lerp_function L>
gradient<L>::gradient ()
{ ; }
template <lerp_function L>
range<double>
gradient<L>::bounds (void) const
{ return { -sqrt(2.0) / 2.0, sqrt (2.0) / 2.0 }; }
template <lerp_function L>
double
gradient<L>::eval (double x, double y) const {
@ -130,11 +144,13 @@ gradient<L>::eval (double x, double y) const {
double x_fac = x - x_int;
double y_fac = y - y_int;
// Generate the four corner values
vector2 p0 = generate<vector2> (x_int, y_int, this->seed);
vector2 p1 = generate<vector2> (x_int + 1, y_int, this->seed);
vector2 p2 = generate<vector2> (x_int, y_int + 1, this->seed);
vector2 p3 = generate<vector2> (x_int + 1, y_int + 1, this->seed);
// Generate the four corner values. It's not strictly necessary to
// normalise the values, but we get a more consistent and visually
// appealing range of outputs with normalised values.
vector2 p0 = generate<vector2> (x_int, y_int, this->seed).normalise ();
vector2 p1 = generate<vector2> (x_int + 1, y_int, this->seed).normalise ();
vector2 p2 = generate<vector2> (x_int, y_int + 1, this->seed).normalise ();
vector2 p3 = generate<vector2> (x_int + 1, y_int + 1, this->seed).normalise ();
double v0 = p0.x * x_fac + p0.y * y_fac;
double v1 = p1.x * (x_fac - 1.0) + p1.y * y_fac;
@ -161,6 +177,11 @@ cellular::cellular ()
{ ; }
range<double>
cellular::bounds (void) const
{ return { 0.0, sqrt(2) }; }
double
cellular::eval (double x, double y) const {
using util::point2;

View File

@ -22,6 +22,7 @@
#include <cstdlib>
#include "../lerp.hpp"
#include "../range.hpp"
namespace util {
namespace noise {
@ -35,6 +36,8 @@ namespace util {
virtual ~basis ();
seed_t seed;
virtual range<double> bounds (void) const = 0;
virtual double eval (double x, double y) const = 0;
};
@ -42,18 +45,24 @@ namespace util {
template <lerp_function L> struct value : public basis {
value (seed_t);
value ();
virtual range<double> bounds (void) const;
virtual double eval (double x, double y) const;
};
template <lerp_function L> struct gradient : public basis {
gradient (seed_t);
gradient ();
virtual range<double> bounds (void) const;
virtual double eval (double x, double y) const;
};
struct cellular : public basis {
cellular (seed_t);
cellular ();
virtual range<double> bounds (void) const;
virtual double eval (double x, double y) const;
};
}

View File

@ -58,13 +58,15 @@ double
util::noise::fbm<B>::eval (double x, double y) const {
double total = 0.0;
double f = this->frequency;
double a = this->lacunarity;
double a = 1.0;
double a_sum = 0.0;
for (size_t i = 0; i < this->octaves; ++i) {
total += basis.eval (x * f, y * f) * a;
total = max (-1.0, min (1.0, total));
f *= 2.0;
a_sum += a;
a *= this->lacunarity;
}