Hey everyone!
I’ve had few questions about how I store 3d shapes inside a 2d texture. Or in other words, how do I turn this :
Into this:
Let me preface this by saying that all structures are contained in a 32x32x32 voxel cube – I’ll explain the reason for this later.
So where do we start? Let’s look at a graphics file. My method of storing data uses a PNG file, and the reason for this is simple – every pixel has four channels associated with it. A red, green, blue and alpha channel. Each of these channels can contain a value from 0 to 255. Depending on these numbers, the pixel will be a different colour (or transparency). So that is already a fair chunk of data that can be held in single pixel – but how can we use these pixels to actually store 2d data?
Well, it is easy to imagine how to store 2d data in a picture :
Now one solution to this problem would be to have slices of 3d data, each one over laid onto the other. And this would look something like this :
However, I didn’t want to use that approach – it works, but seems clunky to me. So I decided to go in a different direction. There are four whole channels per pixel to play around with, so it seems like a sub-optimal solution not to use them all.
So, a tiny bit of maths. Let’s look at the number 255 in binary:
11111111
Well, that was exciting 🙂
Let us imagine the lightest pixel in the universe, where all the channels are set to 255 – pure blinding white with no transparency, it would look like this:
r(255) , g(255), b(255), a(255)
Now if we translate this into binary (and this is the most important part) we get the following:
11111111 11111111 11111111 11111111
Now lets imagine the most pathetic of all pixels, where all the channels are set to 0
r(0), g(0), b(0), a(0)
And if we convert that to binary, unsurprisingly we get four sets of zeros:
00000000 00000000 00000000 00000000
Hmmm, lets try something else, let us imagine a light grey which is kinda transparent.:
r(170), g(170), b(170), a(170)
Translating that into binary, we get the following:
10101010 10101010 10101010 10101010
Now wait a second! what if we represented empty space as a 0 and a voxel as a 1? Suddenly, BOOM, you have a data structure that can hold what voxels are occupied in a row. And this is in one pixel – so if a I have a 2D set of different colours that represent different rows of voxels, I have 3d data in a 2d image! This is why I take things in a 32x32x32 cube – everything meshes together to make a nice optimal solution!
Now this is not an old trick ( the BBC used a similar idea to hold level data in hex values – I wrote about it here many years ago ). But it does mean that you can store 3d data in a png file. There are a couple of additional things that I do. Firstly you will see that though the width of the file is a sensible number, the height is 33. This is because I use the last row (or the first row depending on your conventions – I don’t judge!) to hold material data. The very first pixel on this row is the index I use to represent an empty voxel, and the first mini image is used as a checksum – it is the empty space in and around the 32x32x32 cube. If I find any of the subsequent images trying to write in that area, I know something has gone horribly horribly wrong. The second and other pixels in that row are used to indicate what material the voxel I’m placing in each one should be (earth, copper, lavarite etc; ). Once I’ve gone through this row, I know how many images I’m going to need to process, and perform a quick check sum to make sure that I have the same number of mini images as I do last row pixels.
And that, my friends, is how you can store 3d information in a 2d picture 🙂
A quick confession however – the image at the top of this blog post actually has the alpha channel removed – because otherwise when your browser tries to display it, it will look like this :
But assuming wordpress hasn’t done anything to garble the image – you should be able to download it, open it up in a graphics editor of your choice and see the invisible pixels 🙂
If you have any questions or comments feel free to use the box below, or hit me up on twitter. Hope you have a fantastic day!
Nic Nic