Search Unity

How do I correctly "layer" the generation of a voxel world?

Discussion in 'World Building' started by Deleted User, Sep 14, 2018.

  1. Deleted User

    Deleted User

    Guest

    So basically how I'm currently generating my voxel world is I use Perlin Noise to generate random levels of elevation, making a somewhat mountainous terrain that is made mostly of stone with the few last top blocks being dirt; I then go over that several times with methods that I'm calling "layers" which are named things like GenerateWater or GenerateGrass and likewise loop through all the blocks in a chunk and replace certain blocks with water or grass. So, for instance, my GenerwateWater method checks to see if a block is an air block and if it is below sea level, and if it is, the block gets changed to water. So there is an obvious problem with this as it is it is definitely not very resource friendly as if I was using a hundred layers to generate things like structures or plants and each layer potentially looped through tens of thousands of blocks to check if they can be changed.

    How would Terraria, Minecraft, Starbound, or one of the billions of other blocky games handle inserting finer details like trees and dungeons?
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Well most of those generators will do stuff relative to ground level. So along with the other data in your chunk, you should keep track of what is ground level (or the lowest air block) for each column of blocks.

    Then your water generator, for example, skips any column where that level is above sea level. Your plant generator starts there and only looks a few blocks up (and maybe down) from there. Etc.
     
  3. Deleted User

    Deleted User

    Guest

    I am indeed keeping track of elevation, but I'm trying not to rely on that too much because I'd like to have plants be generated in illuminated caves and stuff like that at some point. The biggest thing that I'm concerned about is just managing all the layers in a better way than storing them all in methods unless that's the best way to tack on more features.
     
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    You could always define a class (or better yet, a class interface) for any generation pass, and then implement that for each type of generator you want. Then your world-generator can simply have a list of those, and call each one.

    But on the other hand, that may be more work than it deserves to be. Do whatever seems simplest to you.
     
  5. Deleted User

    Deleted User

    Guest

    Making a class for each overlap of generation seems like a neater way to do it. Although the messiest yet most performance efficient method would simply be to combine everything into one ugly massive method, which I don't think is worth the performance gain.
     
    JoeStrout likes this.
  6. TauCraft

    TauCraft

    Joined:
    Nov 1, 2016
    Posts:
    1
    Assuming the iteration over all blocks comes with some overhead, you could group these 'layers' into single loops that check each block only once and then call only the necessary methods. You will also have to accept that manipulating large scale voxel worlds is quite an expensive operation, so you may want to divide your world into 'chunks', if you haven't done that already.