# What alternatives to large arrays do I have for level data?

So I'm going to store my levels in int[] arrays.

Most levels are going to be 300*300*300. However, there will be about 24 levels and so that is 24 int arrays of size 300*300*300. However, that would mean I need about 2.5GB just to hold the information. Was wondering is there ways around this.

It just the nature of the game I need this many things. I can possible go down to 100*100*100 levels, but then I would still need about 17 at minimum.

I just can't get around using large arrays.

• Time to google sparse octrees. Oct 9, 2013 at 0:03
• You don't need to hold all levels in memory at once, for persisting on the hard-drive you can compress them with anything you like, from simple RLE to LZMA. Oct 9, 2013 at 0:09
• May math came out at under 20MB. 300*300*300 (3D voxel terrain?) * 24 * sizeof(int) / 1048576. I don't claim to be a mathematician, and I won't claim I'm free of making mistakes, but 2.5GB seems pretty out of the ballpark. Oct 9, 2013 at 0:17
• @SeanMiddleditch 2.414 GB to be exact Oct 9, 2013 at 0:30
• @MooseBoys: Hmm, yeah, I'm definitely not a mathematician. :) Oct 9, 2013 at 0:38

As mentioned in PeterT's comment, you don't need to load all of your levels at once; instead you just load the current level and when the player transitions from that to a new one, you unload the current and load the new.

That gets you down to about 100mb (the raw per-level cost), but we can go lower still.

Consider a cube; right now you're defining each cube as 8 vertices with 3 ints in each - that's 24 ints total. Instead of that, look at the data you actually need to define a cube. You need the midpoint, and you need the size of the cube; since it's a cube the size is going to be the same in all 6 directions, so that's down from 24 ints to 4.

You'll probably also want rotation, so let's add either an axis/angle or quaternion representation, which is 4 floats (you could alternatively use Euler angles for 3 floats), and - assuming on the platforms that you're interested in - a float is the same size as an int, you're looking at the equivalent of 8 ints.

And what if it's not a cube? Simple enough; you still just need the midpoint, but this time you need 3 sizes; that's 2 extra so our final cost is going to be the equivalent of either 4, 6, 8 or 10 ints - worst case of less than half what you currently have. I'm going to assume cubes for the rest of this, for simplicity, but the same principles will apply if you don't have cubes.

So, we're now at 33mb per level, or 16mb if you don't need rotation. That's quite comfortable, even for 6 or 7 year-old hardware.

So you want to draw it efficiently? You can still do so, even without storing the full vertex data. The midpoint and size is perfectly sufficient to store in a VBO (I'm assuming OpenGL here), and you can use either instancing or a geometry shader to expand that to a full cube. If you need to rotate it, you can convert your axis/angle or quaternion to a matrix in the same shader code and just perform an additional matrix multiply.

And that should resolve your memory problems and yet still get you pretty decent performance (just make sure that you've a reasonably good culling algorithm in place), without even needing to go near any kind of funky compression (or streaming, for that matter) scheme that doesn't translate well to graphics hardware.

If you truly have 300^3*24 unique uncorrelated integer values representing your game, there's no way around the storage requirements. If, however, there are correlations between values (e.g. large volumes of the same value, gradients, or repeating patterns), you can use compression to store the level data, decompressing each level as it is needed. For a typical minecraft-ey volume data set, you should be able to compress 2.4GB down to around 100MB [citation needed].