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

View File

@ -22,6 +22,7 @@
#include <cstdlib> #include <cstdlib>
#include "../lerp.hpp" #include "../lerp.hpp"
#include "../range.hpp"
namespace util { namespace util {
namespace noise { namespace noise {
@ -35,6 +36,8 @@ namespace util {
virtual ~basis (); virtual ~basis ();
seed_t seed; seed_t seed;
virtual range<double> bounds (void) const = 0;
virtual double eval (double x, double y) 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 { template <lerp_function L> struct value : public basis {
value (seed_t); value (seed_t);
value (); value ();
virtual range<double> bounds (void) const;
virtual double eval (double x, double y) const; virtual double eval (double x, double y) const;
}; };
template <lerp_function L> struct gradient : public basis { template <lerp_function L> struct gradient : public basis {
gradient (seed_t); gradient (seed_t);
gradient (); gradient ();
virtual range<double> bounds (void) const;
virtual double eval (double x, double y) const; virtual double eval (double x, double y) const;
}; };
struct cellular : public basis { struct cellular : public basis {
cellular (seed_t); cellular (seed_t);
cellular (); cellular ();
virtual range<double> bounds (void) const;
virtual double eval (double x, double y) 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 { util::noise::fbm<B>::eval (double x, double y) const {
double total = 0.0; double total = 0.0;
double f = this->frequency; 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) { for (size_t i = 0; i < this->octaves; ++i) {
total += basis.eval (x * f, y * f) * a; total += basis.eval (x * f, y * f) * a;
total = max (-1.0, min (1.0, total));
f *= 2.0; f *= 2.0;
a_sum += a;
a *= this->lacunarity; a *= this->lacunarity;
} }