Kiyaku,
I wasn’t sure what visual range Minecraft uses…but I put a sphere at one corner of your map, and back up to the middle of the map. I felt like that was a good view distance…so maybe minecraft uses something more along the lines of 1024x1024x128, instead? Not sure, I guess I could hop on and try to estimate it.
I then measured how many blocks I could cross in Minecraft, in 5 seconds…roughtly 25. I then found a flat piece of terrain (or as close as I could, without digging one out) and picked a tree that was JUST on the edge of visibility. I then measured how much time it took to reach that tree.
It took right about 45 seconds. So 45/5 = 9, 9*25 = 225.
So, this means the the viewing distance is roughly 225 blocks forward. This is so small, I’m thinking about double checking my timing or something.
But, if this is the case, I could easily go ahead and say…maybe it is really 28 blocks for every 5 seconds of walking, easily giving you the nice round number of 255.
Meaning that the total drawing distance around the player is 512x512x128.
That’s a LOT smaller than 2048x2048x128 33mb instead of 536mb!!
I’m assuming one byte per block.
(I ran a second test, and got a forward distance of 336…but that was a bad test, I had some hilly terrain. I’m just too lazy to dig a straight path right now. But even then, that would put a map of 672x672x128.)
As far as chunks, I think that is definitely a great idea.
I noticed that when new terrain moves into view, it appears in chunks. All i had to do was find a tree that was on the edge of visibility, then move forward until the next “chunk” came into view with another landmark that was on the edge of visibility, and measure the blocks between them.
Roughly 16…so I’m going to say that as the player moves forward, new terrain is added in 16x16x16 chunks. So with 33mb of blocks to draw in total (33, 554, 432) divided into chunks of 16x16x16…that comes to only having to manage 8192 chunks of blocks in memory.
So your chunk array definition would be something like
byte[,] chunk = new byte[16,16,16]; (4096 blocks or bytes)
your “world” or display array definition would be
Chunk[,] world = new Chunk[32,32,8];
A bit more manageable, I think.
Entire chunks could be marked as drawable or not, simply based on whether or not they only contain air or have no blocks adjacent to air or water (not possible to be seen). This would be a huge time saver. It would a simple thing to calculate this whenever a new chunk becomes visible.
I’m still working on how lighting is calculated for the blocks.
So, I have some questions for you:
You mentioned only drawing faces if the face was on the surface…meaning its next to an empty block, I assume. If this is so, what is a “Cube”? Is it just a prefab with 6 planes that you can hide or show?
After looking at your screenshot, it appears that you generate a cube for each visible square on the map, possibly only drawing certain sides which are visible, but still using a cube collider.
Ok, a little more and I’m done…for now
Some thoughts on the types of blocks:
That array of bytes, for storing blocks…can hold 256 values. That’s a LOT of different block types. From looking at the wiki, Minecraft has about 64. That leaves a LOT more room in that byte for extra data.
Let’s say the remaining 64 values are for future block types. Great, that leaves half the byte for other things, like the precalculated lighting for each block.
So values 0-127 determine block type.
You could use the rest to determine the lighting amounts for the 6 block sides.
I’m not saying this is the best approach…but it might be a good way to save memory. Personally, I don’t care for this approach unless I have to, as it is somewhat inflexible for new ideas or such. Other the other hand, having 33 million “Block” classes instead of bytes, each with its own storage baggage (bloat if you will), could be pretty rough.
Maybe what is best is a hybrid approach…empty blocks get 1 byte of storage…the block type. Visible blocks get the full gamut.