Page 1 of 3

Perlin noise generation in Lua/Löve?

Posted: Sat Jun 25, 2011 2:46 am
by Jasoco
Been looking into terrain generation as an experiment, but don't know how to actually do it.

http://www.google.com/search?q=perlin+noise

Found some code on this page:
http://freespace.virgin.net/hugo.elias/ ... perlin.htm

But I can't figure out how to convert the 2D functions to Lua. There are some methods on there I don't know how to translate to Lua. My first hurdle was 7fffffff. I don't know what that is or how it applies.

I dunno. I have no idea where to begin. Or whether I should try.

Re: Perlin noise generation in Lua/Löve?

Posted: Sat Jun 25, 2011 4:12 am
by tentus
Jasoco wrote:But I can't figure out how to convert the 2D functions to Lua. There are some methods on there I don't know how to translate to Lua. My first hurdle was 7fffffff. I don't know what that is or how it applies.
That's a random function he's writing, to generate the points in the line graphs. You can use this to achieve the same thing (If I read it right):

Code: Select all

function intNoise()
    return ((math.random() * 2) - 1)   
end

Re: Perlin noise generation in Lua/Löve?

Posted: Sat Jun 25, 2011 4:22 am
by Jasoco
I dunno. His noise function receives a variable and bases the returned value on it. I'm more interested in the 2D version also. The 1D version wouldn't be useful for terrain.

Re: Perlin noise generation in Lua/Löve?

Posted: Sat Jun 25, 2011 5:21 am
by tentus
Ah, you're right. Looks like that function takes in a number and returns a random-seeming float between 1 and -1. Interesting.

I've been thinking about doing some perlin stuff recently too, thanks to Shamus Young.

Re: Perlin noise generation in Lua/Löve?

Posted: Sat Jun 25, 2011 6:32 am
by Kadoba
Jasoco wrote: My first hurdle was 7fffffff. I don't know what that is or how it applies.
That's hexadecimal (base 16). It's just a different way of writing 2147483647, a prime number. Lua has a random number generator in the math library so you shouldn't have to make your own. Also you'll want to understand the 1D function before trying to grasp 2d because it's the same but applied in two dimensions.

I don't know why you would need several random number generators though. Just alter your seed input slightly but deterministically for each function:

Code: Select all

function random1(val)
   math.randomseed(val)
  -- get random numbers
end

function random2(val)
  math.randomseed(val+1)
  -- get random numbers
end

-- etc

Re: Perlin noise generation in Lua/Löve?

Posted: Sat Jun 25, 2011 6:54 am
by slime
As seen in this post, there is a fast perlin/simplex noise generator for LuaJIT: http://staffwww.itn.liu.se/~stegu/simpl ... /Noise.lua

Re: Perlin noise generation in Lua/Löve?

Posted: Sat Jun 25, 2011 8:14 am
by vrld
I did implement that noise function for the 4KB explosion contest.
They key is that you get the same random value depending on the x- and y-coordinates you are going to write. The tutorial uses that weird noise function, which is fast in C, but not in Lua. I created an image data full of random values where the random value for given x and y can be retrieved by ImageData:getPixel.

The relevant code is in the function value_noise in loader.lua.

Re: Perlin noise generation in Lua/Löve?

Posted: Sun Jun 26, 2011 5:47 am
by middlerun
That's funny, I just sat down with the intention of experimenting with Perlin noise for a game I want to make. I have a glance at the Löve forums, and see this thread. :shock:

Re: Perlin noise generation in Lua/Löve?

Posted: Sun Jun 26, 2011 9:37 am
by Adamantos
This will do the job:

Code: Select all

function noise( x,  y,  z) 
  local X = math.floor(x % 255)
  local Y = math.floor(y % 255)
  local Z = math.floor(z % 255)
  x = x - math.floor(x)
  y = y - math.floor(y)
  z = z - math.floor(z)
  local u = fade(x)
  local v = fade(y)
  local w = fade(z) 
  
  A   = p[X  ]+Y
  AA  = p[A]+Z
  AB  = p[A+1]+Z
  B   = p[X+1]+Y
  BA  = p[B]+Z
  BB  = p[B+1]+Z

  return lerp(w, lerp(v, lerp(u, grad(p[AA  ], x  , y  , z   ), 
                                 grad(p[BA  ], x-1, y  , z   )), 
                         lerp(u, grad(p[AB  ], x  , y-1, z   ), 
                                 grad(p[BB  ], x-1, y-1, z   ))),
                 lerp(v, lerp(u, grad(p[AA+1], x  , y  , z-1 ),  
                                 grad(p[BA+1], x-1, y  , z-1 )),
                         lerp(u, grad(p[AB+1], x  , y-1, z-1 ),
                                 grad(p[BB+1], x-1, y-1, z-1 )))
  )
end


function fade (t)
  return t * t * t * (t * (t * 6 - 15) + 10)
end


function lerp(t,a,b)
  return a + t * (b - a)
end


function grad(hash,x,y,z)
  local h = hash % 16
  local u 
  local v 
  
  if (h<8) then u = x else u = y end
  if (h<4) then v = y elseif (h==12 or h==14) then v=x else v=z end
  local r
  
  if ((h%2) == 0) then r=u else r=-u end
  if ((h%4) == 0) then r=r+v else r=r-v end
  return r
end


p = {}
local permutation = { 151,160,137,91,90,15,
  131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
  190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
  88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
  77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
  102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
  135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
  5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
  223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
  129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
  251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
  49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
  138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
}

for i=0,255 do
  p[i] = permutation[i+1]
  p[256+i] = permutation[i+1]
end

For generating a 2d map you would do something like that:

Code: Select all

-- generate noise
  for x=1,map.sizeX do
    for y=1,map.sizeY do
      map.elevation[x][y] = noise(x/map.scale + map.dx, y/map.scale + map.dy,0)
    end
  end 
Where map.dx/dy is the offset and map.scale the zoom factor

Re: Perlin noise generation in Lua/Löve?

Posted: Sun Jun 26, 2011 9:42 am
by Adamantos
By the way ... here is a little island generator based on my previous code snipplet:
(Press "g" for a new random island)