107 lines
2.9 KiB
C++
107 lines
2.9 KiB
C++
|
#include "CTextureEncoder.h"
|
||
|
#include <iostream>
|
||
|
|
||
|
CTextureEncoder::CTextureEncoder()
|
||
|
{
|
||
|
mpTexture = nullptr;
|
||
|
}
|
||
|
|
||
|
void CTextureEncoder::WriteTXTR(COutputStream& TXTR)
|
||
|
{
|
||
|
// Only DXT1->CMPR supported at the moment
|
||
|
TXTR.WriteLong(mOutputFormat);
|
||
|
TXTR.WriteShort(mpTexture->mWidth);
|
||
|
TXTR.WriteShort(mpTexture->mHeight);
|
||
|
TXTR.WriteLong(mpTexture->mNumMipMaps);
|
||
|
|
||
|
u32 MipW = mpTexture->Width() / 4;
|
||
|
u32 MipH = mpTexture->Height() / 4;
|
||
|
CMemoryInStream Image(mpTexture->mImgDataBuffer, mpTexture->mImgDataSize, IOUtil::LittleEndian);
|
||
|
u32 MipOffset = Image.Tell();
|
||
|
|
||
|
for (u32 iMip = 0; iMip < mpTexture->mNumMipMaps; iMip++)
|
||
|
{
|
||
|
for (u32 BlockY = 0; BlockY < MipH; BlockY += 2)
|
||
|
for (u32 BlockX = 0; BlockX < MipW; BlockX += 2)
|
||
|
for (u32 ImgY = BlockY; ImgY < BlockY + 2; ImgY++)
|
||
|
for (u32 ImgX = BlockX; ImgX < BlockX + 2; ImgX++)
|
||
|
{
|
||
|
u32 SrcPos = ((ImgY * MipW) + ImgX) * 8;
|
||
|
Image.Seek(MipOffset + SrcPos, SEEK_SET);
|
||
|
|
||
|
ReadSubBlockCMPR(Image, TXTR);
|
||
|
}
|
||
|
|
||
|
MipOffset += MipW * MipH * 8;
|
||
|
MipW /= 2;
|
||
|
MipH /= 2;
|
||
|
if (MipW < 2) MipW = 2;
|
||
|
if (MipH < 2) MipH = 2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CTextureEncoder::DetermineBestOutputFormat()
|
||
|
{
|
||
|
// todo
|
||
|
}
|
||
|
|
||
|
void CTextureEncoder::ReadSubBlockCMPR(CInputStream& Source, COutputStream& Dest)
|
||
|
{
|
||
|
Dest.WriteShort(Source.ReadShort());
|
||
|
Dest.WriteShort(Source.ReadShort());
|
||
|
|
||
|
for (u32 byte = 0; byte < 4; byte++) {
|
||
|
u8 b = Source.ReadByte();
|
||
|
b = ((b & 0x3) << 6) | ((b & 0xC) << 2) | ((b & 0x30) >> 2) | ((b & 0xC0) >> 6);
|
||
|
Dest.WriteByte(b);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ************ STATIC ************
|
||
|
void CTextureEncoder::EncodeTXTR(COutputStream& TXTR, CTexture *pTex)
|
||
|
{
|
||
|
if (pTex->mTexelFormat != eDXT1)
|
||
|
{
|
||
|
std::cout << "\rError: Unsupported texel format for decoding\n";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CTextureEncoder Encoder;
|
||
|
Encoder.mpTexture = pTex;
|
||
|
Encoder.mSourceFormat = eDXT1;
|
||
|
Encoder.mOutputFormat = eGX_CMPR;
|
||
|
Encoder.WriteTXTR(TXTR);
|
||
|
}
|
||
|
|
||
|
void CTextureEncoder::EncodeTXTR(COutputStream& TXTR, CTexture *pTex, ETexelFormat OutputFormat)
|
||
|
{
|
||
|
// todo: support for encoding a specific format
|
||
|
EncodeTXTR(TXTR, pTex);
|
||
|
}
|
||
|
|
||
|
ETexelFormat CTextureEncoder::GetGXFormat(ETexelFormat Format)
|
||
|
{
|
||
|
switch (Format)
|
||
|
{
|
||
|
case eLuminance: return eGX_I8;
|
||
|
case eLuminanceAlpha: return eGX_IA8;
|
||
|
case eRGBA4: return eGX_RGB5A3;
|
||
|
case eRGB565: return eGX_RGB565;
|
||
|
case eRGBA8: return eGX_RGBA8;
|
||
|
case eDXT1: return eGX_CMPR;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ETexelFormat CTextureEncoder::GetFormat(ETexelFormat Format)
|
||
|
{
|
||
|
switch (Format)
|
||
|
{
|
||
|
case eGX_I4: return eLuminance;
|
||
|
case eGX_I8: return eLuminance;
|
||
|
case eGX_IA4: return eLuminanceAlpha;
|
||
|
case eGX_IA8: return eLuminanceAlpha;
|
||
|
// todo rest of these
|
||
|
case eGX_CMPR: return eDXT1;
|
||
|
}
|
||
|
}
|