Perlin noise planet generator.

Showcase your libraries, tools and other projects that help your fellow love users.
Post Reply
pedrosgali
Party member
Posts: 107
Joined: Wed Oct 15, 2014 5:00 pm
Location: Yorkshire, England

Perlin noise planet generator.

Post by pedrosgali »

Here's a little library I wrote yesterday to make 2d Perlin noise, I'm using it to make procedurally generated planets for a space game I'm making. I thought others might find it useful.
You can pass the draw function a texture table to set the colours drawn so planet types can all be different colours etc.

Usage:

Code: Select all

--call your lib
local mg = require "/Lib/mapgen"

--Make a texture:
--The texture table is a numbered table with two values;
--cutoff: all values below the cutoff will be set to the colour.
--col: a table of 3 RGB percentages, the height is multiplied by these to get an RGB colour
--     and makes a nice gradient

local earthTexture = {
 --the numbers in the col table are percentages of the height value so enter numbers 0-1
--Colours should be ordered lowest to highest, sea floor to mountain peaks.
  [1] = {cutoff = 130, col = {0, .1, 1}},--Deep Blue
  [2] = {cutoff = 150, col = {0, .3, .9}},--Lighter Blue
  [3] = {cutoff = 155, col = {0, .5, .8}},--Cyan
  [4] = {cutoff = 160, col = {1, 1, 0}},--Yellow
  [5] = {cutoff = 200, col = {0, .5, 0}},--Green
  [6] = {cutoff = 220, col = {0, .3, 0}},--Dark Green
  [7] = {cutoff = 240, col = {.5, .5, .5}},--Grey
  [8] = {cutoff = 260, col = {1, 1, 1}},--White
  }

function love.load()
  local seed = math.random(1, 1000000)--or any number you want.
  local amp = math.random(50, 2000) --or any number you want
  local freq = math.random(100, 400) --or any number you want
  local oct = math.random(14, 20) --or any number you want High numbers here make it take longer to generate.
  map = mapgen.generate(seed, mapWidth, mapHeight, amp, freq, oct) --Make a new map.
  canvas = mapgen.drawCanvas(map, earthTexture) --to draw the planet to a canvas pass it
--                                                the planet map and a texture table.
end

function love.draw()
  love.graphics.draw(canvas, 1, 1)
end
Here's a .love that will just make random planet maps. The library is inside if you want to use it.
mapgen.love
(13.6 KiB) Downloaded 310 times
Let me know what you think. :)
User avatar
ivan
Party member
Posts: 1912
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Perlin noise planet generator.

Post by ivan »

Looks good. A bit slow on my 2009 laptop but it looks good.

Running the demo takes up about 125 mb of ram which is a bit excessive.
Going over the code I have a few suggestions:

1.use a one dimensional table instead of map[x][y] - it will reduce your memory consumption by 1/height
you can later transform the [x][y] coordinates using the modulus operator (%)

2.don't use a table for each item in the map (example: map[x][y] = {}; map[x][y].height)
use parallel table instead that will reduce memory by 1/(width*height)
for example:

Code: Select all

altitudeMap = {} -- one dimensional numerically indexed table
couldsMap = {} -- second one dimensional numerically indexed table
...
and so on
3.check out the benefit of locals in critical code:

Code: Select all

    for y = 0, h - 1 do
      m[x][y] = {}
      m[x][y].height = 0
      for i = 1, oct do
        m[x][y].height = m[x][y].height + map.getNoiseValue(m, x, y, i)
      end
      mapMin = math.min(mapMin, m[x][y].height)
      mapMax = math.max(mapMax, m[x][y].height)
    end
This code will run a lot of times, so you can benefit from locals here.
Each time you use the "." or "[]" operators - that's a table lookup which is a little bit slower than locals.
Not only that but it makes you code longer (horizontally).
pedrosgali
Party member
Posts: 107
Joined: Wed Oct 15, 2014 5:00 pm
Location: Yorkshire, England

Re: Perlin noise planet generator.

Post by pedrosgali »

Thanks for the input, I know it's a bit ram intensive at the minute. How would I use the modulus operator transform? I'm not sure what you mean.

Code: Select all

if not wearTheseGlasses() then
  chewing_on_trashcan = true
end
User avatar
ivan
Party member
Posts: 1912
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Perlin noise planet generator.

Post by ivan »

Oh, I just meant converting from x,y to a single index:

Code: Select all

-- converts an index to x, y
function toXY ( n )
  local x = n % mapWidth
  local y = ( n - x ) / mapWidth
  return x + 1, y + 1
end

-- converts x, y to an index
function toIndex ( x, y )
  return ( y - 1 ) * mapWidth + ( x - 1 )
end
This will allow you store the map in a one-dimensional table:

Code: Select all

map =
{
  1,2,3,4,5,
  6,7,8,9,10,
  11,12,13,14,15
}
versus:

Code: Select all

map = {}
map[1] = { 1,2,3,4,5 }
map[2] = { 6,7,8,9,10 }
map[3] = { 11,12,13,14,15 }
pedrosgali
Party member
Posts: 107
Joined: Wed Oct 15, 2014 5:00 pm
Location: Yorkshire, England

Re: Perlin noise planet generator.

Post by pedrosgali »

That sir is genius! I'll do that as soon as I get home. Thanks. :)

Code: Select all

if not wearTheseGlasses() then
  chewing_on_trashcan = true
end
Germanunkol
Party member
Posts: 712
Joined: Fri Jun 22, 2012 4:54 pm
Contact:

Re: Perlin noise planet generator.

Post by Germanunkol »

Hi,

This is cool!
I once made something very similar, which uses a shader to mimic a 3D-effect.
Maybe you can rip some parts from it?
trAInsported - Write AI to control your trains
Bandana (Dev blog) - Platformer featuring an awesome little ninja by Micha and me
GridCars - Our jam entry for LD31
Germanunkol.de
pedrosgali
Party member
Posts: 107
Joined: Wed Oct 15, 2014 5:00 pm
Location: Yorkshire, England

Re: Perlin noise planet generator.

Post by pedrosgali »

Hey Germanunkol, that shader was exactly what I was looking for. Thank you so much for pointing me to it, had to make a few modifications as I'm going for a top down view but the fisheye lens effect is amazing!
I'm currently working on a texture editor for these heightmaps, I'll post it here when I'm further along.
Thank you again. :)

Code: Select all

if not wearTheseGlasses() then
  chewing_on_trashcan = true
end
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest