Note: This section generally covers runtime storage, not serialization.
The simplest way to store voxels is to define a three-dimensional array of elements (be it
integers), where each element represents a single voxel:
int width = ...; int height = ...; int depth = ...; var voxels = new VOXEL[width][height][depth]; // Set a voxel: voxels[x][y][z] = voxel; // Get a voxel: var voxel = voxels[x][y][z];
However, because storing arrays within arrays often means having pointers pointing at pointers (which ain't good for various reasons we won't get into here), it is generally recommended to use a one-dimensional array with a clearly defined spatial indexing scheme.
Here's an example:
--snip-- // Spatial Indexing Scheme is: Y-height, Z-depth, X-width // The arrays size is just all axes multiplied together: var voxels = new VOXEL[height * depth * width]; // Our Indexing Formula is the indexing scheme in reverse, // with the components being multiplied subsequently: // x + z*width + y*width*depth // So let's define a function (here a lambda) for it: var idx = (int x, int y, int z) => (x + z*width + y*width*depth); // ^ NOTE: You may want to throw an error right here // if the coordinate components are out of bounds. // Set a voxel: voxels[idx(x,y,z)] = voxel; // Get a voxel: var voxel = voxels[idx(x,y,z)];
Now, storing voxels in a plain array like this is perfectly fine for small scenes...
However, for larger scenes, we'll have to use a data-structure that allows both loading and purging parts of our volume (called Chunks) from memory, nearly in realtime, without slowing down accessing our voxel data.
Note: These techniques can often be combined.