perlin noise

So I was looking around, I found this site https://en.wikipedia.org/wiki/Perlin_noise
but in pseudocode i found this

 
  extern float Gradient[IYMAX][IXMAX][2];


What does it mean?
extern

extern means the following declaration will be defined elsewhere, you can use this in a header file to indicate you want the files that include that header to understand that data will be available, but is not currently defined

float

float is a data type representing a floating point number such as 3482434.4234 instead of an integer such as 42384234, in this case you are indicating the type to be contained in the array declaration

Gradient

Gradient is the variable name representing the array of floats

IYMAX

IYMAX and IXMAX are numbers representing the size of the array, they must be defined previous to this declaration and cannot be dynamic

here's an example of declaring IYMAX

static const IYMAX = 12;

the static is optional in c++, if you create this variable in a header file you may find this same extern pattern seen in your question to be better suited, this would look like this:

header file
extern const IYMAX;

implementation file (.cpp)
const IYMAX = 12;

[IYMAX][IXMAX][2]

[IYMAX][IXMAX][2] indicates the size of the array of floats, because there are three brackets in a row this tells us there are three dimensions in this array.

And what I should put in that place to get a working perlin?
I assume that you are referring to this bit of (pseudo)code in the link that you give.

1
2
3
4
5
6
7
8
9
10
11
12
13
// Computes the dot product of the distance and gradient vectors.
 function dotGridGradient(int ix, int iy, float x, float y) {
 
     // Precomputed (or otherwise) gradient vectors at each grid node
     extern float Gradient[IYMAX][IXMAX][2];
 
     // Compute the distance vector
     float dx = x - (float)ix;
     float dy = y - (float)iy;
 
     // Compute the dot-product
     return (dx*Gradient[iy][ix][0] + dy*Gradient[iy][ix][1]);
 }


You need to understand what the final line is trying to produce - just the change in some variable (say f) between the grid point (ix,iy) and some other point (x,y) - an analogy would be working out the change in height given the horizontal displacement and the slope (think of a ladder against a wall). In 2d this
is
df = dx * (df/dx) + dy * (df/dy)
which is what the line
return (dx*Gradient[iy][ix][0] + dy*Gradient[iy][ix][1]);
is doing.

In this pseudocode the gradients (df/dx) and (df/dy) are assumed to be precomputed and
df/dx is put in Gradient[iy][ix][0],
df/dy is put in Gradient[iy][ix][1]

You are under no obligation to do it via a 3-d array (personally, I wouldn't) - you just have to have some means of telling this routine what df/dx and df/dy are at that point.

As @wisebin has said,
extern float Gradient[IYMAX][IXMAX][2];
just means this particular array has been defined elsewhere (probably in a different file). If you chose to use an array then it could be a global variable (heaven forbid!) in your current file - then you wouldn't even need this line.

In your link, note that this is PSEUDOCODE - it is there as a guide, not as how you should necessarily code things. As far as this routine is concerned, it simply needs to know what the gradients are in two directions (df/dx and df/dy) - how you supply them to the routine is entirely up to you.
And what value should have df for start?
From the article:
Define an n-dimensional grid. At each point on the grid (node) assign a random gradient vector of unit length in n dimensions

So the code example provided uses a two-dimensional grid, i.e., a 2-d array of random 2-d normalized gradient vectors.

df on its own has infinitesimal value -- the array contains normalized samples from a random vector field. See https://en.wikipedia.org/wiki/Gradient
Last edited on
And what I should put in that place to get a working perlin?

If you just want something that works, you could download a complete code from somewhere. For example:
https://www.solarianprogrammer.com/2012/07/18/perlin-noise-cpp-11/

And what value should have df for start? 

df doesn't need any value at the start. It is being CALCULATED in the return statement
return (dx*Gradient[iy][ix][0] + dy*Gradient[iy][ix][1]);
f is also just a convenient name I adopted for the variable that is being made noisy.

df is not infinitesimal here because (x,y) is a finite distance from (ix,iy). If you want to write that (Delta f) instead, then fine. In full
(Delta f) = (Delta x)(df/dx) + (Delta y)(df/dy)
is the linear approximation to the exact infinitesimal statement
df = dx (df/dx) + dy (df/dy)
(Those derivatives df/dx and df/dy are actually partial derivatives, as in @mbozzi's link, but there is no way of writing that here.)

Gradient[iy][ix][0] stores the partial derivative (df/dx) at grid point [iy][ix]
Gradient[iy][ix][1] stores the partial derivative (df/dy) at grid point [iy][ix]
These are defined outside of the given pseudocode; hence the extern statement.

In multiple dimensions, the vector quantity grad f = (df/dx,df/dy), or in three dimensions (df/dx,df/dy,df/dz), is the mathematical gradient, just like in ordinary differential calculus dy/dx is the gradient or slope of the curve y(x).

If you want a random 2d vector of unit length, choose a random angle A in the range 0 to 2.pi and set the vector as (cos A, sin A).




Topic archived. No new replies allowed.