internal static int GetCompressedSizeUpToIndex(double mipIndex, ImageEngineFormat format, int baseWidth, int baseHeight)
{
/*
Mipmapping halves both dimensions per mip down. Dimensions are then divided by 4 if block compressed as a texel is 4x4 pixels.
e.g. 4096 x 4096 block compressed texture with 8 byte blocks e.g. DXT1
Sizes of mipmaps:
4096 / 4 x 4096 / 4 x 8
(4096 / 4 / 2) x (4096 / 4 / 2) x 8
(4096 / 4 / 2 / 2) x (4096 / 4 / 2 / 2) x 8
Pattern: Each dimension divided by 2 per mip size decreased.
Thus, total is divided by 4.
Size of any mip = Sum(1/4^n) x divWidth x divHeight x blockSize,
where n is the desired mip (0 based),
divWidth and divHeight are the block compress adjusted dimensions (uncompressed textures lead to just original dimensions, block compressed are divided by 4)
Turns out the partial sum of the infinite sum: Sum(1/4^n) = 1/3 x (4 - 4^-n). Who knew right?
*/
// TODO: DDS going down past 4x4
double divisor = 1;
if (ImageFormats.IsBlockCompressed(format))
divisor = 4;
double shift = 1d / (4 << (int)(2 * (mipIndex - 1)));
if (mipIndex == 0)
shift = 1d;
else if (mipIndex == -1)
shift = 4d;
double sumPart = mipIndex == -1 ? 0 :
(1d / 3d) * (4d - shift); // Shifting represents 4^-mipIndex. Math.Pow seems slow.
double totalSize = 128 + (sumPart * ImageFormats.GetBlockSize(format) * (baseWidth / divisor) * (baseHeight / divisor));
return (int)totalSize;
}