As I mentioned in my last entry, DXT4/5 flipping was being a bit of a pain, so I thought about it for a while and decided 'screw loops!' and did the flipping the direct way.
Honestly, I should have probably done this before, but was so focused on 'loops' and 'elegance' that I missed it somewhere along the line.
So, I present, the DXT4/5 flipping code aka Bit Shifting madness!
GTLUtils::dxt4 fullFlip(GTLUtils::dxt4 &src) { GTLUtils::dxt4 dest; dest = yFlip(src); dest = xFlip(dest); return dest; } GTLUtils::dxt4 yFlip(GTLUtils::dxt4 &src) { GTLUtils::dxt4 dest; dest.alpha0 = src.alpha0; dest.alpha1 = src.alpha1; // Dest = lower half | lower half dest.lookup6 = ((0xF & src.lookup1) << 4) | ((0xF0 & src.lookup2) >> 4); dest.lookup5 = ((0xF & src.lookup3) << 4) | ((0xF0 & src.lookup1) >> 4); dest.lookup4 = ((0xF & src.lookup2) << 4) | ((0xF0 & src.lookup3) >> 4); dest.lookup3 = ((0xF & src.lookup4) << 4) | ((0xF0 & src.lookup5) >> 4); dest.lookup2 = ((0xF & src.lookup6) << 4) | ((0xF0 & src.lookup4) >> 4); dest.lookup1 = ((0xF & src.lookup5) << 4) | ((0xF0 & src.lookup6) >> 4); dest.colourdata = yFlip(src.colourdata); return dest; } GTLUtils::dxt4 xFlip(GTLUtils::dxt4 &src) { GTLUtils::dxt4 dest; dest.alpha0 = src.alpha0; dest.alpha1 = src.alpha1; // row 0 dest.lookup1 = (0x70 & src.lookup2) << 1; // pixel 4 dest.lookup1 |= ( 0x80 & src.lookup2) >> 5; // pixel 3 dest.lookup1 |= ( 0x3 & src.lookup1) << 3; // and again dest.lookup1 |= (0x1c & src.lookup1) >> 3; // pixel 2 dest.lookup2 = (0x1c & src.lookup1) << 5; // and again dest.lookup2 |= (0xE0 & src.lookup1) >> 1; // pixel 1 // row 1 dest.lookup2 |= (0x7 & src.lookup3) << 1; // pixel 4 dest.lookup2 |= (0x38 & src.lookup3) >> 5; // pixel 3 dest.lookup3 = (0x38 & src.lookup3) << 3; // and again dest.lookup3 |= (0x1 & src.lookup2) << 5; // pixel 2 dest.lookup3 |= (0xC0 & src.lookup3) >> 3; // and again dest.lookup3 |= (0xE & src.lookup2) >> 1; // pixel 4 // row 2 dest.lookup4 = (0x70 & src.lookup5) << 1; // pixel 4 dest.lookup4 |= ( 0x80 & src.lookup5) >> 5; // pixel 3 dest.lookup4 |= ( 0x3 & src.lookup4) << 3; // and again dest.lookup4 |= (0x1c & src.lookup4) >> 3; // pixel 2 dest.lookup5 = (0x1c & src.lookup4) << 5; // and again dest.lookup5 |= (0xE0 & src.lookup4) >> 1; // pixel 1 // row 3 dest.lookup5 |= (0x7 & src.lookup6) << 1; // pixel 4 dest.lookup5 |= (0x38 & src.lookup6) >> 5; // pixel 3 dest.lookup6 = (0x38 & src.lookup6) << 3; // and again dest.lookup6 |= (0x1 & src.lookup5) << 5; // pixel 2 dest.lookup6 |= (0xC0 & src.lookup6) >> 3; // and again dest.lookup6 |= (0xE & src.lookup5) >> 1; // pixel 4 dest.colourdata = xFlip(src.colourdata); return dest; }
This works perfectly and allows the flipping of a DXT5 texture just fine.
With that done I think I'm wandering towards 'feature complete', a quick look back into this journal shows the last 'todo' list consisting of;
- non-compressed DXTn formats flipping
- decompression routine
- visually check the images are sanely rotated.
All I need to deal with now are 16bit per channel floating point images for DDS files and we should be done with basic loading, at least on a big endian system, I'm not sure how well the above bit fiddling will work on little endian systems (I admit I tend to be endian blind [sad]).
A Network loader still needs to be intergated, but as I'm using libcurl for that it shouldn't be too hard to do... I should probably get on that now [grin]