java - Output range of Perlin noise -


i'm investigating few of various implementations coherent noise (i know there libraries, own edification , curiosity) , how can use it, , there's 1 problem have original perlin noise thing.

according this linked math faq, output range between -1 , 1, don't understand how value gets in range.

as understand it, algorithm this: each grid point has associated random gradient vector of length 1. then, each point, 4 surrounding grid points, calculate dot product of random gradient , vector going grid-point. use fancy ease curve , linear interpolation down 1 value.

but, here's problem: these dot-products are, occasionally, going outside range [-1, 1], , since linear interpolation between dot products, doesn't mean final value will, on occasion, outside range of [-1, 1]?

say, instance, 1 of random vectors (sqrt(2)/2, sqrt(2)/2) (which has length of 1) , (0.8, 0.8) (which in unit square), result of 1.131. if value used in linear interpolation, it's entirely possible value generated greater 1. and, indeed, straight-forward implementation, happens quite frequently.

am missing here?

for reference, here's code in java. vec simple class simple 2d vector arithmetic, fade() ease curve, lerp() linear interpolation, , gradient(x, y) gives gradient grid-point vec. gridsize variable gives size of grid in pixels (it has type double):

public double getpoint(int x, int y) {     vec p = new vec(x / gridsize, y / gridsize);     vec d = new vec(math.floor(p.x), math.floor(p.y));       int x0 = (int)d.x,         y0 = (int)d.x;       double d00 = gradient(x0    , y0    ).dot(p.sub(x0    , y0    )),            d01 = gradient(x0    , y0 + 1).dot(p.sub(x0    , y0 + 1)),            d10 = gradient(x0 + 1, y0    ).dot(p.sub(x0 + 1, y0    )),            d11 = gradient(x0 + 1, y0 + 1).dot(p.sub(x0 + 1, y0 + 1));      double fadex = fade(p.x - d.x),            fadey = fade(p.y - d.y);      double i1 = lerp(fadex, d00, d10),            i2 = lerp(fadex, d01, d11);      return lerp(fadey, i1, i2); } 

edit: here's code generating random gradients:

double theta = gen.nextdouble() * 2 * math.pi;  gradients[i] = new vec(math.cos(theta), math.sin(theta)); 

where gen java.util.random.

you have y0 = (int)d.x;, mean d.y. affect output range, , reason seeing such largely out-of-range values.


that said, output range of perlin noise not [-1, 1]. while i'm not quite sure of math myself (i must getting old), this rather lengthy discussion works out actual range [-sqrt(n)/2, sqrt(n)/2], n dimensionality (2 in case). output range of 2d perlin noise function should [-0.707, 0.707]. somehow related fact both d , interpolation parameters function of p. if read through discussion, may find precise explanation looking (particularly, post #7).

i testing implementation using following program (which hacked example, pardon weird use of gridcells , gridsize):

import java.util.random;   public class perlin {      static final int gridsize = 200;     static final int gridcells = 20;     static final vec[][] gradients = new vec[gridcells + 1][gridcells + 1];      static void initializegradient () {         random rand = new random();         (int r = 0; r < gridcells + 1; ++ r) {             (int c = 0; c < gridcells + 1; ++ c) {                 double theta = rand.nextfloat() * math.pi;                 gradients[c][r] = new vec(math.cos(theta), math.sin(theta));                             }         }     }      static class vec {         double x;         double y;         vec (double x, double y) { this.x = x; this.y = y; }         double dot (vec v) { return x * v.x + y * v.y; }         vec sub (double x, double y) { return new vec(this.x - x, this.y - y); }     }      static double fade (double v) {         // easing doesn't matter range sample test.         // v = 3 * v * v - 2 * v * v * v;         return v;     }      static double lerp (double p, double a, double b) {         return (b - a) * p + a;     }      static vec gradient (int c, int r) {         return gradients[c][r];     }      // function, y0 fixed. note gridsize not double yours.          public static double getpoint(int x, int y) {          vec p = new vec(x / (double)gridsize, y / (double)gridsize);         vec d = new vec(math.floor(p.x), math.floor(p.y));          int x0 = (int)d.x,             y0 = (int)d.y;          double d00 = gradient(x0    , y0    ).dot(p.sub(x0    , y0    )),                d01 = gradient(x0    , y0 + 1).dot(p.sub(x0    , y0 + 1)),                d10 = gradient(x0 + 1, y0    ).dot(p.sub(x0 + 1, y0    )),                d11 = gradient(x0 + 1, y0 + 1).dot(p.sub(x0 + 1, y0 + 1));          double fadex = fade(p.x - d.x),                fadey = fade(p.y - d.y);          double i1 = lerp(fadex, d00, d10),                i2 = lerp(fadex, d01, d11);          return lerp(fadey, i1, i2);      }      public static void main (string[] args) {          // loop forever, regenerating gradients , resampling range.          while (true) {              initializegradient();              double minz = 0, maxz = 0;              (int x = 0; x < gridsize * gridcells; ++ x) {                 (int y = 0; y < gridsize * gridcells; ++ y) {                     double z = getpoint(x, y);                     if (z < minz)                         minz = z;                     else if (z > maxz)                         maxz = z;                 }             }              system.out.println(minz + " " + maxz);          }      }  } 

i seeing values within theoretical range of [-0.707, 0.707], although seeing values between -0.6 , 0.6; consequence of value distribution , low sampling rate.


Comments

Popular posts from this blog

c# - Send Image in Json : 400 Bad request -

jquery - Fancybox - apply a function to several elements -

An easy way to program an Android keyboard layout app -