1. We've introduced thread tags, search within a thread and similar thread search. Read more here.
    Dismiss Notice
  2. Learn how you'll soon be able to publish your games to China in four simple steps with Xiaomi. Sign up now for early access.
    Dismiss Notice
  3. Get further faster with the Unity Plus Accelerator Pack, free for new Unity Plus subscribers for a limited time. Click here for more details.
    Dismiss Notice
  4. We've released our first Timeline Experimental Preview, our new tool for creating cutscenes and more! To check it out click here.
    Dismiss Notice
  5. Unity 5.5 is now released.
    Dismiss Notice
  6. Check out all the fixes for 5.5 in patch releases 1 & 2.
    Dismiss Notice
  7. Unity 5.6 beta is now available for download.
    Dismiss Notice

After playing minecraft...

Discussion in 'General Discussion' started by jc_lvngstn, Oct 8, 2010.

  1. CaptainKiyaku

    CaptainKiyaku

    Joined:
    Feb 8, 2009
    Posts:
    323
  2. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    You might try this:

    private static bool EndProcessingThreads;

    void ProcessChunks()
    {
    ...
    While (!EndProcessingThreads)
    {
    ... do stuff
    }
    }

    public void EndThreadProcessing()
    {
    EndProcessingThreads = true;
    }
     
  3. CaptainKiyaku

    CaptainKiyaku

    Joined:
    Feb 8, 2009
    Posts:
    323
    Thanks i will try that out! I used "Application.isRunning" before but totally forgot that i'm not allowed to call Unity API stuff.

    Currently i am working on the light system. I just have to find a good way to spread the illumination. Right now i start at the top position and just scan downwards and set every zero blocks to full-lit in the lightdata field until i hit a block, then i move onto the next field.

    That is fast, but now i want to spread the light around a lightsource. I tried using a 6 field sphere around each light source but that takes way too long, then i would have to scan 12*12*12 more for every lightsource. Especially for the sky above the blocks this sucks because the neighbour light sources are full lit anyway.

    So yeah still trying to find a good way to fill the scene with light values.
     
  4. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    I've been thinking that over also, Kiyaku. I tried some googling, and didn't find anyone talking about how they think it works.

    To me, the tricky thing isn't lighting a scene to begin. Dropping a torch just adds lighting, which is easy.
    But...how do you handle REMOVING lighting? Let's say I have three blocks, each with a torch. you remove the middle torch. You can't just remove light from the adjacent blocks...you also have to take into account other light sources which still exist!

    So this tells me that Notch's algorithm had to actually mark blocks as light sources or not. By light source, I mean sunlit blocks, torches, lava. Each square can be considered a light source.

    At this point, I'm not sure if he uses some sort of scan tracing around the light source to set the light amounts on visible blocks near the light source, or what. The initial terrain generation for a chunk would be the most expensive. I'm not worried about new terrain generated when the player moves, because that takes a while to reach and threading can handle that.

    One thing I may do, just for curiosity's sake, is for each light source added to a chunk, find all blocks in a 16x16x16 area, cast a ray to the light source for visibility, and see how long it takes. that's up to 4096 rays, per light source. Talk about a test of Unity's performance there.

    Unfortunately, that brings up the issue of...having lighting the side of a block next to a torch, but leaving the other side dark.
     
  5. CaptainKiyaku

    CaptainKiyaku

    Joined:
    Feb 8, 2009
    Posts:
    323
    Hm removing light is a hard thing too. You might have to recalculate the chunk again when you remove it.

    About the light itself, that's basically what i do. I have a second dictionary that is the same size as the voxel dictionary.
    I just go through every block starting at the top and only scanning downwards and set every empty block to a light factor of 1 (highest) until i touch a block. Then i can stop and go on to the next XY position, because everything below won't be lit by sunlight.

    This is fast and works good.

    Now imagine you have a cavern with an open entry on the side. The sunlight touches the blocks outside, so i want them to illuminate into the cave too. That's why i did the 12x12x12 scan (or in your case 16x16x16, doesnt matter) but this takes way too long, cause you will have to do it with every field. It's not a matter of Unity's performance, cause i calculate that in the second thread, but the loop is just too huge for that cause you need to calculate the light 4096 times more than without the illumination.

    In my 16x16x16 scan i already consider if the light on that field is higher than mine (then i can ignore it), and if the block is solid, which solves the issue with having the left face bright but keep the right face dark. Cause the voxel doesn't check it's own light information, it asks for the neighbours light.
     
  6. Scott M

    Scott M

    Joined:
    Jul 13, 2005
    Posts:
    23
    The only information I've seen with regards to lighting is what I can glean from the .NBT file format which at least details what pre-computed values are stored in the save files:

    From http://www.minecraftwiki.net/wiki/Alpha_Level_Format

    Chunk File Format:

    -- TAG_Byte_Array("SkyLight"): 16384 bytes recording the amount of sun or moonlight hitting each block. 4 bits per block. Makes day/night transitions smoother compared to recomputing per level change.

    -- TAG_Byte_Array("BlockLight"): 16384 bytes recording the amount of block-emitted light in each block. 4 bits per block. Makes load times faster compared to recomputing at load time.

    -- TAG_Byte_Array("HeightMap"): 256 bytes of heightmap data. 16 x 16. Each byte records the lowest level in each column where the light from the sky is at full strength. Speeds computing of the SkyLight. Note: This array's indexes are ordered Z,X whereas the other array indexes are ordered X,Z,Y.

    I haven't gotten to implementing lighting yet (i'm a bit behind you guys!), but this was going to be my starting place. Hope it helps.
     
    Last edited: Oct 26, 2010
  7. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    I played around in game...first, I don't think it's a cubic 16x16x16 area centered on the player. It's more of a diamond shape.

    I drew out a diamond shape of blocks around the player, extending 8 blocks in each north/south and east/west direction. The lighting at 45 degrees only appears to extend about 4 blocks.
    So the next layer of blocks up (and down) only extends for 7 blocks in north/south/east/west

    Adding this up...it only totals up 823 blocks out of a 16x16x16 cube. A LOT less then 4096 for a 16x16x16x square. That seems a little low...but I think I figured it up right.
     
  8. CaptainKiyaku

    CaptainKiyaku

    Joined:
    Feb 8, 2009
    Posts:
    323
    Hm you could be right, i just read this: http://www.minecraftwiki.net/wiki/Light

    It sounds like it only goes from neighbour to neighbour, i guess diagonal blocks don't count as neighbour so it only goes up/down/left/right/back/forth and tells that block to be 20% less brighter than the current one, IF this one is darker.

    When the neighbor block receives it's new lightvalue, it will spread it's informations to it's own neighbors. This will fill the diagonal blocks as well from the starter block.

    I think i will try this out and see how it goes.
     
  9. CaptainKiyaku

    CaptainKiyaku

    Joined:
    Feb 8, 2009
    Posts:
    323
    Okay this approach was much faster than the first one and it looks awesome!

    However it still takes 32 seconds to calculate for a 16x16 world made out of 16x16x128 chunks.
    EDIT: Forgot to say how many steps i do! In this example i start at 1 and go down by 20% till it's below 0.2f, so that should be 8 steps in total into each direction.

    I will check if i can optimize it a bit better.
    $shadow_02.png
    $shadow_03.png
     
    Last edited: Oct 27, 2010
  10. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    That looks awesome, Kiyaku! Do you recursively alter the lighting of each block and its neighbor?
     
  11. CaptainKiyaku

    CaptainKiyaku

    Joined:
    Feb 8, 2009
    Posts:
    323
    Thanks!

    Yes that's exactly what i do. I actually apply light 2 times right now, the first time i just check where to place sunlight sources, this is superfast (1-2 seconds) and then i go through all sunlight blocks and call a recursive method that applies light, reduces the next light value, checks it's neighbours if that stone is free (if not we dont need light there), and if the light there is darker than the next lightvalue, if yes, call the same function with the new light value for that stones (so it will go through it's neighbours as well), until the lightvalue is < 0.2f.

    But like i said, it's not the fastest method yet. And i am thinking if i can reduce it to the chunk itself, so the chunks will chck for it's light instead of having a method that goes through all chunks, but that wouldn't really increase the process by a lot, so i guess i have to find a better way to spread the illumination.
     
  12. TwiiK

    TwiiK

    Joined:
    Oct 23, 2007
    Posts:
    1,531
    I'm curious about the move world VS move player issue.

    This can't possibly be how Minecraft does it, can it? I mean, he supports multiplayer. How would moving the world work in multiplayer?

    Other than that you've got some great results in this thread. :)
     
  13. beezir

    beezir

    Joined:
    Apr 3, 2009
    Posts:
    128
    World vs. Player movement is entirely a client issue. It's just used to reset a "base" origin so that floating point inaccuracy doesn't start to have an effect on terrain generation, etc. Each client in multiplayer would have their own world offset and render based on that. If another player was in range to render, it would be a simple matter for the server to provide an offset from the current player.

    That said, is anyone actually running into this problem? I would think it wouldn't hit for a significantly huge distance (max int or so) and I have yet for it to be a problem in Minecraft.
     
  14. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    I'm going ahead and putting in stuff to handle this situation, but more than once the thought occurred to me...maybe I should just restrict the world area you can explore.
    But I couldn't shake the feeling that I could do it now, and pay less, or do it later and pay more. Even though it's costing me time that I would rather be spent working on caves and lighting and such.
     
  15. Nikolay116

    Nikolay116

    Joined:
    Mar 21, 2010
    Posts:
    421
  16. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    Beezir...I noticed you use an X pattern for your uvs and vertices.
    Like this:
    32
    14

    And follow the same convention when adding your UV vectors. why is this?

    In mine, I do this:
    23
    14

    And follow the same with my UV vectors.

    The reason I'm asking this is: I'm getting weird lines between my blocks, at the edges...which tells me it has something to do with either my UV mapping, or SOMETHING being off.
    Here's my code that adds the UV coordinates:

    Rect worldTextureAtlasUv = m_World.WorldTextureAtlasUvs[0];
    chunk.Uvs.Add(new Vector2(worldTextureAtlasUv.x + epsilon, worldTextureAtlasUv.y + epsilon));

    chunk.Uvs.Add(new Vector2(worldTextureAtlasUv.x + epsilon, worldTextureAtlasUv.y + worldTextureAtlasUv.height - epsilon));

    chunk.Uvs.Add(new Vector2(worldTextureAtlasUv.x + worldTextureAtlasUv.width - epsilon, worldTextureAtlasUv.y + worldTextureAtlasUv.height - epsilon));

    chunk.Uvs.Add(new Vector2(worldTextureAtlasUv.x + worldTextureAtlasUv.width - epsilon,
    worldTextureAtlasUv.y + epsilon));

    Any idea what is going on here?

    Here's a screenshot:

    [​IMG]
     
    Last edited: Oct 27, 2010
  17. CaptainKiyaku

    CaptainKiyaku

    Joined:
    Feb 8, 2009
    Posts:
    323
    Yes his UV mapping was wrong, i had to change it too so it fits for every side.

    I'm on my mac right now but the project is on my windows PC. If you have problems getting the right UV, i will switch and show you how i do it.

    EDIT: I had white lines on the edges before too, i had to change the filter for my texture to Point to get rid of them (and it actually looks nicer with this pixel style lol), maybe that's your problem too?
     
  18. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    Well...I'm somewhat new to uvs and such...you know, the basics of 3d graphics :)
    As long as the UV coordinates always match my texture location in the atlas...how can they be wrong?
    Or, is it important that your uv coordinates "match" your vertices? Since all of my vertices follow this pattern

    23
    14

    if you are facing each side, then it seems like...my uvs should always be the same.
    Kiyaku, I switched to point, and still am seeing the brown bands.
     
  19. CaptainKiyaku

    CaptainKiyaku

    Joined:
    Feb 8, 2009
    Posts:
    323
    Could you post a screenshot of the lines and of your atlas map?
    Maybe trying Loop/Clamp can work too. Your UV order looks right, so i doubt that's the problem. Maybe your position on the texture itself is a bit off and it cuts off a few pixel from a neighbor texture.
     
  20. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    Ok, I didn't realize at the time that I needed to set the filter type on my atlas...sorry :)
    While that took care of the strips...now I still have this issue:

    [​IMG]

    I get this layer of brown...but it only shows up on blocks that are at roughly the same height as my player. A little hard to see in this picture, unless you zoom in or look close.
     
  21. CaptainKiyaku

    CaptainKiyaku

    Joined:
    Feb 8, 2009
    Posts:
    323
    That's caused by mipmapping, if you turn it off it should stay green but will get more "crispy" in the background.
     
  22. beezir

    beezir

    Joined:
    Apr 3, 2009
    Posts:
    128
    Yeah, I'm a bit late, but that's the result of mipmaps and texture atlasing. As textures get farther from the camera, the use different levels of detail to improve performance. Because the textures are on an atlas, sometimes the blurred pixels at the edge of a texture have color bleed from whatever is nearby. You can minimize it in various ways, most of which tend to involve manually creating the atlas and adding properly colored borders of several pixels between tiles. I believe there are ways to create a DDS format atlas that has pre-calculated mipmaps. As a last resort you can do what I did - turn off the mipmapping entirely and use fog to hide the shimmery result. :)
     
    Last edited: Oct 28, 2010
  23. beezir

    beezir

    Joined:
    Apr 3, 2009
    Posts:
    128
    This was entirely arbitrary. I sometimes have a weird picture of things in my head, so my numbering probably doesn't make much sense. As long as the vertices are indexed in the correct order it shouldn't matter. I did it pretty quickly and there were probably incorrect texture rotations and such.
     
    Last edited: Oct 28, 2010
  24. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    So, I'm starting to get back out of the weeds on this, thanks to some hair pulling and help from you guys.

    Something I'm going to be looking at soon is some better landscape generation...specifically, caves.
    While I could move on to other elements, to me a good cave system is key.

    Before, I simply retrieved a different set of noise values (scaled), and set results below a certain range to air. For some reason, all I got was big holes like cottage cheese in my terrain...but now that I've thought more about it, I may know why.
    Regardless, I'll try that tonight. If anyone has some pointers or suggestions, it would be greatly appreciated :)

    On the side...I have a little more work to do with the infinite terrains, but it's almost there. Also put the block digging stuff back in. I hope to have something better to post soon.
    Thanks,
    JC
     
  25. Robotails

    Robotails

    Joined:
    Oct 24, 2010
    Posts:
    8
    Hey

    ok does anyone know how to make voxels just appear in pre set places
     
  26. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    Can you give a little more description on this?
     
  27. Robotails

    Robotails

    Joined:
    Oct 24, 2010
    Posts:
    8
    like minecraft but when you start up game the blocks are in pre set places and you can build etc
     
  28. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    Basically, what I did was use a perlin noise function (see code samples in this post) to generate a heightmap, and then fill everything below that height with blocks.
    The perlin noise gives you a decent terrain, there are ways to tweak it to make look better. I'm still a bit of a noob here.
     
    Last edited: Oct 29, 2010
  29. Andrew Greenwood

    Andrew Greenwood

    Joined:
    Oct 13, 2010
    Posts:
    6
    My sister is always wear a minecraft at the playing time...
     
  30. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    So, I got a "better" cave system going...just by doing another pass on my chunk terrain, getting a scaled simplex noise value and setting anything that fell below a certain amount to air.
    It slowed down my terrain generation a bit. My first pass gets the 2d height of a column of blocks and sets everything below that height to dirt/rock/etc, I figure I can make this faster by combining the two passes.

    So...it gives me ok caves, nothing to write home about. Certainly not as nice as Notch's. For one thing...they are very "smooth" along the walls. I'd like caves with a little more jaggy interiors, mine look like long bubbles. I'll experiment some more with this.
     
  31. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    I've been reading this article:
    http://http.developer.nvidia.com/GPUGems3/gpugems3_ch01.html

    I love the results they show. I'm not interested in using their marching cubes algorithm to generate a terrain mesh, personally I'm fine with blocks. However, the means they use to generate terrain density seems VERY nice.

    I think images 1-13, 1-14, and 1-15 are very interesting, as is the discussion on ambient occlusion.
    Anyone else think they might with to investigate this more?
     
  32. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,595
    you better are not interested in the tech as it can not be replicated at all with Unity, thats DX10+ Geometry shader code as well as 3d textures ...
    thats exactly where we will fall short.
    That being said, working marching cube algos etc and voxel theory are maaany years old and for that side you can find articles.

    Also the other aspects aside of the actual generation and effects of it still apply (AO should too)
     
  33. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    So, from what I recall in that article...they use a pregenerated cube of noise, and create the density stuff from that.

    density += noiseVol1.Sample(TrilinearRepeat, ws*4.03).x*0.25;
    density += noiseVol2.Sample(TrilinearRepeat, ws*1.96).x*0.50;
    density += noiseVol3.Sample(TrilinearRepeat, ws*1.01).x*1.00;

    So, this got me wondering if Notch isn't doing something similar. When you first start a game, there is a blank screen with a progress bar, could this be pregenerating the initial world noise?

    regardless, whether we use that method, or just use the existing stuff...the BIG thing that interested me are the terrain results they get. The terrain densities they get doesn't appear to depend on anything other than standard noise octaves.
    I want to understand that more. So, even if it were slower for now, if I could generate terrain that followed that I'd be fine. I think the answer is probably simple, but I'm supposed to be doing other stuff right now :)

    Like...figure 1-11, on the right. Or 1-15.

    I guess what I would need to do is figure out how to change my existing noise generating stuff to match what they are doing.
     
    Last edited: Oct 29, 2010
  34. Taintspore

    Taintspore

    Joined:
    Sep 29, 2009
    Posts:
    185
    @JC: How many octaves of noise are you using for your caves? I was using six and it seemed to create nice cave boundaries.

    The method in GPU Gems 3 was the first one I tried. It didn't turn out so well. It created either very boxy caves (few octaves) or caves with tonnes of floating voxels. I don't think I have the code anymore but I might have a player lying around somewhere, if I can find it I'll post it.

    I got results fairly similar to Notch's first attempt. There might be a way to tame it but I couldn't find it. The biggest problem is that if you do it CPU side you can't use nearly the same amount of voxels to make it look like it does if done GPU side.

    I tried running dilation and erosion operations on it to with different masks and got some 'weird' results.
     
    Last edited: Oct 29, 2010
  35. unityandyou

    unityandyou

    Joined:
    Jun 25, 2010
    Posts:
    50
    Idk i tried to make it on unity3d and epicly failed.


    Happy Programming!
     
  36. Robotails

    Robotails

    Joined:
    Oct 24, 2010
    Posts:
    8
    Can someone please give me a hand on making blocks appear and be able to remove and add them
     
  37. beezir

    beezir

    Joined:
    Apr 3, 2009
    Posts:
    128
    Probably the easiest way to get detailed help on this is to check earlier in the thread and download the basic package I posted. It comes complete with code and generates simple terrain and everything. Read through and understand the basics, improve on it, come up with better ways to do things if you think of them, etc. It doesn't include calls to add blocks, only remove them, but it should be a pretty easy addition once you see how the rest is done.

    EDIT: Here's a link to the post with the code to save yourself some skimming.
     
    Last edited: Oct 30, 2010
  38. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    Here's my terrain and cave generation code:
    /// <summary>
    /// Generate terrain for a chunk.
    /// </summary>
    /// <param name="chunk"></param>
    public static void GenerateChunkTerrain(ChunkData chunk)
    {
    for (int x = 0; x < ChunkData.WidthInBlocks; x++)
    {
    int blockX = chunk.X*ChunkData.WidthInBlocks + x + (int) (World.NoiseBlockXOffset);

    for (int y = 0; y < ChunkData.HeightInBlocks; y++)
    {
    int blockY = chunk.Y*ChunkData.HeightInBlocks + y;
    // our intitial terrain height
    int noise = (int)GetBlockNoise(blockX, blockY);
    chunk.Blocks[x,y,noise].Type = BlockType.TopSoil;
    // from here down, we set the actual terrain type
    for (int z = 0; z < noise - 1; z++)
    {
    //{
    float caveNoise = (PerlinSimplexNoise.noise(blockX/420.0f, blockY/420.0f, z/420.0f) + 1.0f)*0.5f;
    caveNoise += (PerlinSimplexNoise.noise(blockX/160.0f, blockY/160.0f, z/160.0f) + 1.5f)*0.5f;
    caveNoise += (PerlinSimplexNoise.noise(blockX/20.0f, blockY/20.0f, z/20.0f) + 1.0f)*0.5f;

    BlockType typeToSet;
    if (caveNoise/3.0f < 0.3f)
    {
    typeToSet = BlockType.Air;
    }
    else
    {
    typeToSet = BlockType.Dirt;
    }

    chunk.Blocks[x, y, z].Type = typeToSet;
    }
    }
    }
    }

    Here's a screenshot of my caves. Notice they tend to be in clumps...but they still look like smooth blobs, connected by accident.
    [​IMG]

    I understand (I think) how the first octave works. But I don't feel I have a complete enough understanding of using octaves and such to really control my output..I'm just adding octaves, with various numbers, trying to see what results I get.
    The initial noise value I get from the PerlinSimplesNoise.noise function returns a value from -1 to 1. I add 1 to make it range from 0 to 2, then multiply by .5 to get it to be from 0 to 1.

    Anyone shed some light on this, for me?
     
    Last edited: Oct 30, 2010
  39. Taintspore

    Taintspore

    Joined:
    Sep 29, 2009
    Posts:
    185
    I'll see if I can help.

    I'll use the function Noise(x) = amplitude * f(frequency * x) for a single octave. (add more inputs for more dimensions :p)

    (the order doesn't matter because everything is summed but I'll start at the big shapes)

    The first octave gives you your basic shapes: hills here and valleys there. It has the highest amplitude and the lowest frequency. Say amp=freq=1.

    The next octave adds some details to the original. It has a higher frequency (narrower peaks and valleys) and lower amplitude (shorter hills, shallower valleys).

    You keep creating octaves and summing them together, and each successive octave adds a little more detail to the output. Eventually creating mounds and ditches.

    The increase in frequency and decrease in amplitude are controlled by lacunarity and persistence respectively (been a while, might have those backwards). It's usually a good idea to have them related, say lacunarity = 1/persistence = 2 (ie if you halve the amplitude you double the frequency) and IIRC the 2 is a nice constant. So on octave one if amplitude=frequency = 1, then on octave two you have new_amp = 1/2 old_amp and new_freq = 2 old_freq.

    Octaves are summed as you go.

    Something you might want to read up on is self similarity. Each octave is similar to the previous one only zoomed in or out and made to be not as tall. This is because you're using the same noise function, you're just zooming in or out and making it taller or shorter before adding it to the total noise.

    I hope that helps a bit, if you really want to get deeper into procedurally creating content pick up Texturing and Modelling: a Procedural Approach. It was written by the masters eg Perlin, Musgrave and Worley. Tonnes of code, math, and explanations. It gets a little heavy at times but it's a fantastic resource.


    Oh, by looking at your pictures, start with a larger amplitude and frequency, I had to over do it a bit to get the caverns i got. For my cave noise i take the absolute value and set anything > .9 to air.

    Not sure if you. Need this or not, but if you take the peaks and troughs (say >.9 and <-.9) you get big blobby Swiss cheese holes, if you were to set anything between .7 and .8 to air you'd end up with a cave that's like the skin of the blob (ie a hollow with a floating rock shaped like the hollow inside it). If you set number near zero to air you get something akin to stacked objects (where the surface of the objects are caves), that one is bad for the fps and creates massive 'terrain scarring' that is generally weird.

    I hope that helped somewhat, it's getting late so I might be a bit fried.

    It might be easier to understand if you see it in action. Start with one octave, take a look at what it made, then run it again with a second octave (using the same seed) to see the smaller details added. Do it for a few octaves and it should make a more sense.
     
    Last edited: Oct 30, 2010
  40. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    @Taintpose...that was very helpful. It opened up my eyes a bit. Regarding my landscape (only 10x10 chunks square):

    Here's a smaller piece of my code:
    float noise = PerlinSimplexNoise.noise(blockX * 0.01f, blockY * 0.01f, z * 0.01f) * 80;

    noise += PerlinSimplexNoise.noise(blockX*0.1f, blockY*0.1f, z*0.1f)*10;
    if (noise < 0f)
    {
    chunk.Blocks[x,y,z].Type = BlockType.TopSoil;
    }

    Here is what it generates:
    [​IMG]

    I can definitely see how this can be used to generate caves. But, regarding this terrain...


    Effectively, it's a slice of 3d noise. But before, I used 2d noise (x,y) to supply a height. Which was great for my previous terrain, for mountains, hills valleys etc. But I can't get overhangs and such with that, because it's a 2d heightmap.
    So this new method...is great, but it's a 3d noise ...sponge thing. I don't see how I can have a semi realistic looking landscape with mountains and such, the 'top' of the terrain is flat and cut off because of the chunk boundaries.
    Does that make sense? If I were making a Cavecraft clone, yeah it would be perfect.

    So, should I use a 2d method to create a heightmap, and leave the 3d one for caves?

    Specifically, like this:
    [​IMG]

    I don't see how the method I'm using has limits that provide for mountains, instead of just 3d sponge world :)
     
    Last edited: Oct 30, 2010
  41. Lab013

    Lab013

    Joined:
    Oct 22, 2008
    Posts:
    405
    Just thinking out loud here, but it seems that all of you are trying to produce blocks directly. Why not create a mesh and then fill that mesh with cubes? It seems there may be some advantages to generating a mesh instead of cubes directly.
     
  42. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    18,520
    Using C++ style vectors you could in theory only store changes. Just grow the vectors outwards from the first block. You could use 0-128 range to store the block type, and 64 to store the multiplier offset and direction, then another 64 for the amount.

    Unsigned bytes would mean you could fit a whole level in a couple of k. Given sanity is a requirement I would just stick with an array or use voxels :)
     
  43. Taintspore

    Taintspore

    Joined:
    Sep 29, 2009
    Posts:
    185
    @JC That's pretty much exactly what I did. I create a 2D height map inside two nested loops (x and z). Then I had a third loop for y that would start at the height value and work towards the bottom of the chunk filling it in with the 3d noise values. That way you get you mountains and valleys and caves with overhangs.

    Code (csharp):
    1. Loop over x
    2. [INDENT]Loop over z
    3. [INDENT]Height = Noise(x,z) * c
    4. //c is your noise to height
    5. //constant or formula, I use 50
    6.  
    7. Loop over y from height to bottom of chunk
    8. [INDENT]Density = Noise(x,y,z)
    9. // techincally should be x,z,y but I rotate
    10. //the noise space to avoid similarity with the height map
    11. If(density fits your criteria for air)
    12. [INDENT]Set voxel at x,y,z to air[/INDENT]
    13. Else
    14. [INDENT]Set to something else dependent on density value[/INDENT][/INDENT][/INDENT][/INDENT]
     
    Last edited: Oct 30, 2010
  44. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    @Lab013 and Hippocoder...this seems like the only way that I see to get overhands while generating, as opposed to using 3d noise/caves to get them. I'm not sure I'm ready to go down that road just yet...there's still the requirement of being able to dig into the terrain (which, nothing says I couldn't add/remove verts and recreate the mesh).
    Yeah...it definitely is an interesting idea.

    @Taintspore...ok, that sounds good. It's something I can wrap my mind around right now. I'll tinker with it some more.
     
  45. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453

    I think I have a slightly different approach...if it works, I'll post it.
     
  46. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    Ok...I think I've found an excellent way. It doesn't seem to slow down my normal process much at all.
    Summary:
    When you generate the terrain (not the mesh, just the data) for blocks, mark all SUNLIT air blocks as having your highest light value. Not terrain blocks, AIR blocks.

    The lighting pass does this:
    for each sunlit block in a chunk, it checks its neighbors. If any of THEM have a lower value, it sets their light value to 80% of sunlit.
    So, air blocks under a ledge that weren't sunlit had 0 lighting. If they are next to a sunlit air block, it sets their lighting to 80%.
    So now...all empty air blocks that were not light but are right next to a sunlit block...gets 80% lighting.

    Repeat this for the next lower light value...80%.
    For all 80% lit blocks, check their neighbor...if the neighbor value is less than 60%, set its light value to 60%


    So, if you have 8 shades of light...you do 8 passes on the chunk.
    But, it's not THAT bad...because you can ignore any blocks that don't match the shade of light you are checking. So if you are doing the 60% light pass...ignore your current block if its lighting does not match.

    I combined this with my mesh creation thread. When I loop through all blocks in my chunk, I look AROUND the empty air block I am on and use its lighting to light adjacent block sides. Since the air blocks know their lighting, (100%, 80%, etc), they use that shade value to color solid block sides next to them.

    Beezir's code generated a mesh by looking at the current TERRAIN block, and checking if air was around it.
    This process HAS to look at the current AIR block, and check if solid blocks are around it.

    This might be a little abstract, I know I got confused a couple of times. Here is how it works, looking at a 2d slice of terrain:
    [​IMG]

    The thing is...it's pretty darn fast, because in my case it's just code looping through an array of blocks.

    I've got a few small issues to iron out (for some reason, lighting around chunks is wonky) and I need to do some cleanup. After that, I'll post my source.


    Here's a screenshot:
    [​IMG]
     
    Last edited: Oct 31, 2010
  47. CaptainKiyaku

    CaptainKiyaku

    Joined:
    Feb 8, 2009
    Posts:
    323
    Well that's quite simliar to my method. If i get you right, you go through your chunk array 8 times and checks for the current lightvalue and change its neighbours lighting if they are lower, right?

    I just go through every voxel ones and call the same method on neighbors. I think there isn't a big difference.

    Before i had only one method that would calculate light, this took too long so ive included it into the mesh generator too which was fast enough (chunks get created a little bit slower but its hard to notice). I just had some bugs left that sometimes a blocks shadow was too hard and it didnt get illuminated by neighbors, still have to figure that out.

    EDIT: Cool screenshot btw, have to get a decend noise generator too, i dont like that my hills are so tiny currently (like its almost one hill per chunk, but i want big mountains splitted onto many chunks so i have to play with the noise a bit)
     
  48. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    Yes, sounds pretty much the same, I thought you were using a recursive solution that took a while! I also need to handle the situation where, say I'm on the surface and dig a block out, and directly beneath is a very large cavern. I have to relight the sunlit blocks all the way down, and regenerate those chunks. No big deal, I just want to do it without a big slowdown.
    My digging can also be a little bit sluggish at times. I think it's because, if you remove a block that is on the corner of two chunks, it has to regenerate them which causes a slight hiccup. Some optimization should be able to fix this.
     
  49. CaptainKiyaku

    CaptainKiyaku

    Joined:
    Feb 8, 2009
    Posts:
    323
    I do use a recursive function but only on the air blocks and only if their current light value is sunlight. So i doubt this slows down much, it will stop if something is blogging. And when it's lighting the neighbor fields with 20% less light, it will ignore them the next time i check for the sunlight blocks.

    I also get the sluggish feeling when digging. So what i want to do is first create the mesh for the chunk, and then recolor it. I will see how that changes the performance. But this way mining will feel more responding and light can just be a bit late if worst comes worst.

    Got a weird bug now that my terrain loading breaks sometimes and stops replacing/regenerating chunks, like the thread just dies. Will check this out.

    Also i was wondering about some slowdowns in my code when i realized i called Debug.Log in my thread loop, that slows the process quite a lot lol.
     
  50. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,453
    Yes...the Debug.log is horribly slow. I wish real-time debugging were possible.
    My cave stuff looks good sometimes...but it often takes up too many vertices in a chunk, which I suspect is causing issues. In fact, I'm considering changing my world to be made up of 16x16x16 chunks, several deep, instead of 128 blocks deep.

    I'd really like to have better caves...but that has eluded me so far :( I'd appreciate anyone being able to lend a hand with this.

    Here's my latest code, with lighting. It still has some bugs, but should be ok to run so far. It still only adds terrain as you move east or west. Kinda got sidetracked on the lighting stuff :D

    http://www.filefactory.com/file/b412403/n/MineClone.unitypackage

    Oh, also...something that might speed up lighting is this:
    The terrain generation has to identify sunlit blocks...not sure how I can speed this up.

    The first pass in mesh generation handles the sunlit blocks...but, instead of for each shade of light having a full pass, the previous pass could just generate a list of blocks for that pass.

    So, sunlit mesh identifies 80% shaded blocks, adds those to list.
    Next pass only processes those blocks, instead of scanning the entire chunk. It puts 60% blocks in the list now.
    And so on...until the absolute darkness pass, which has to scan the entire chunk. But, instead of having 8 full chunk scans for 8 shades of light, you only have two full scans, the others only process the blocks with those shades.
    Could save some time.
     
    Last edited: Oct 31, 2010