From c354cf6ed68a6c921f54df4b23a6fc1a4e7cc487 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 24 May 2012 15:04:06 +1000 Subject: [PATCH] Normalise basis values and give expected bounds --- noise/basis.cpp | 33 +++++++++++++++++++++++++++------ noise/basis.hpp | 9 +++++++++ noise/fractal.cpp | 6 ++++-- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/noise/basis.cpp b/noise/basis.cpp index de6b7f62..30255c10 100644 --- a/noise/basis.cpp +++ b/noise/basis.cpp @@ -27,6 +27,7 @@ #include using namespace util::noise; +using util::range; /////////////////////////////////////////////////////////////////////////////// // Generate a type from [-UNIT..UNIT] @@ -82,10 +83,16 @@ value::value (seed_t _seed): template - value::value () +value::value () { ; } +template +range +value::bounds (void) const + { return { -1.0, 1.0 }; } + + template double value::eval (double x, double y) const { @@ -117,11 +124,18 @@ gradient::gradient (seed_t _seed): basis (_seed) { ; } + template gradient::gradient () { ; } +template +range +gradient::bounds (void) const + { return { -sqrt(2.0) / 2.0, sqrt (2.0) / 2.0 }; } + + template double gradient::eval (double x, double y) const { @@ -130,11 +144,13 @@ gradient::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 (x_int, y_int, this->seed); - vector2 p1 = generate (x_int + 1, y_int, this->seed); - vector2 p2 = generate (x_int, y_int + 1, this->seed); - vector2 p3 = generate (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 (x_int, y_int, this->seed).normalise (); + vector2 p1 = generate (x_int + 1, y_int, this->seed).normalise (); + vector2 p2 = generate (x_int, y_int + 1, this->seed).normalise (); + vector2 p3 = generate (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 +cellular::bounds (void) const + { return { 0.0, sqrt(2) }; } + + double cellular::eval (double x, double y) const { using util::point2; diff --git a/noise/basis.hpp b/noise/basis.hpp index 3e0d1bd7..df37d976 100644 --- a/noise/basis.hpp +++ b/noise/basis.hpp @@ -22,6 +22,7 @@ #include #include "../lerp.hpp" +#include "../range.hpp" namespace util { namespace noise { @@ -35,6 +36,8 @@ namespace util { virtual ~basis (); seed_t seed; + + virtual range bounds (void) const = 0; virtual double eval (double x, double y) const = 0; }; @@ -42,18 +45,24 @@ namespace util { template struct value : public basis { value (seed_t); value (); + + virtual range bounds (void) const; virtual double eval (double x, double y) const; }; template struct gradient : public basis { gradient (seed_t); gradient (); + + virtual range bounds (void) const; virtual double eval (double x, double y) const; }; struct cellular : public basis { cellular (seed_t); cellular (); + + virtual range bounds (void) const; virtual double eval (double x, double y) const; }; } diff --git a/noise/fractal.cpp b/noise/fractal.cpp index 12ad09a2..910b7c2a 100644 --- a/noise/fractal.cpp +++ b/noise/fractal.cpp @@ -58,13 +58,15 @@ double util::noise::fbm::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; }