Skip to content

Commit

Permalink
Support display of KTX/KTX2 cubemap mipmaps.
Browse files Browse the repository at this point in the history
  • Loading branch information
bluescan committed Aug 5, 2024
1 parent 792d412 commit f3a236c
Showing 1 changed file with 45 additions and 63 deletions.
108 changes: 45 additions & 63 deletions Src/Image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1190,30 +1190,24 @@ void Image::PopulatePicturesKTX(const tImageKTX& ktx)
{
if (ktx.IsCubemap())
{
int w = ktx.GetWidth();
int h = ktx.GetHeight();

// We want the front (+Z) to be the first image.
// Cubemaps sides use a left-hand coordinate system with +Z facing the front and +Y up. We want the front (+Z)
// to be the first image because it makes the most sense from a viewing perspective. In the tImage the sides
// are loaded in the +X,-X,+Y,-Y,+Z,-Z order. We display in +Z,-Z,+X,-X,+Y,-Y order.
const int numFaces = tFaceIndex_NumFaces;
int faceOrder[numFaces] =
{
tFaceIndex_PosZ,
tFaceIndex_NegZ,
tFaceIndex_PosX,
tFaceIndex_NegX,
tFaceIndex_PosY,
tFaceIndex_NegY
};
int faceOrder[numFaces] = { tFaceIndex_PosZ, tFaceIndex_NegZ, tFaceIndex_PosX, tFaceIndex_NegX, tFaceIndex_PosY, tFaceIndex_NegY };

tList<tLayer> layers[numFaces];
ktx.GetCubemapLayers(layers);
for (int f = 0; f < int(tFaceIndex_NumFaces); f++)
{
int face = faceOrder[f];

tLayer* topMip = layers[face].First();
tAssert(topMip->PixelFormat == tPixelFormat::R8G8B8A8);
Pictures.Append(new tPicture(w, h, (tPixel4b*)topMip->Data, true));
// Grab every mipmap of each cubemap side.
for (tLayer* sideMipLayer = layers[face].First(); sideMipLayer; sideMipLayer = sideMipLayer->Next())
{
tAssert(sideMipLayer->PixelFormat == tPixelFormat::R8G8B8A8);
Pictures.Append(new tPicture(sideMipLayer->Width, sideMipLayer->Height, (tPixel4b*)sideMipLayer->Data, true));
}

// Lets reset the list so it doesn't do anything bad when destructed.
layers[face].Reset();
Expand All @@ -1240,54 +1234,42 @@ void Image::CreateAltPicturesKTX(const tImageKTX& ktx)
{
if (ktx.IsCubemap())
{
int width = Pictures.First()->GetWidth();
int height = Pictures.First()->GetHeight();

AltPicture.Set(width*4, height*3, tPixel4b::transparent);
int originX, originY;

// PosZ
tPicture* pic = Pictures.First();
originX = width; originY = height;
for (int y = 0; y < pic->GetHeight(); y++)
for (int x = 0; x < pic->GetWidth(); x++)
AltPicture.SetPixel(originX + x, originY + y, pic->GetPixel(x, y));

// NegZ
pic = pic->Next();
originX = 3*width; originY = height;
for (int y = 0; y < pic->GetHeight(); y++)
for (int x = 0; x < pic->GetWidth(); x++)
AltPicture.SetPixel(originX + x, originY + y, pic->GetPixel(x, y));

// PosX
pic = pic->Next();
originX = 2*width; originY = height;
for (int y = 0; y < pic->GetHeight(); y++)
for (int x = 0; x < pic->GetWidth(); x++)
AltPicture.SetPixel(originX + x, originY + y, pic->GetPixel(x, y));

// NegX
pic = pic->Next();
originX = 0; originY = height;
for (int y = 0; y < pic->GetHeight(); y++)
for (int x = 0; x < pic->GetWidth(); x++)
AltPicture.SetPixel(originX + x, originY + y, pic->GetPixel(x, y));

// PosY
pic = pic->Next();
originX = width; originY = 2*height;
for (int y = 0; y < pic->GetHeight(); y++)
for (int x = 0; x < pic->GetWidth(); x++)
AltPicture.SetPixel(originX + x, originY + y, pic->GetPixel(x, y));

// NegY
pic = pic->Next();
originX = width; originY = 0;
for (int y = 0; y < pic->GetHeight(); y++)
for (int x = 0; x < pic->GetWidth(); x++)
AltPicture.SetPixel(originX + x, originY + y, pic->GetPixel(x, y));
int w = ktx.GetWidth();
int h = ktx.GetHeight();
AltPicture.Set(w*4, h*3, tPixel4b::transparent);

// Cubemaps sides use a left-hand coordinate system with +Z facing the front and +Y up. We want the front (+Z)
// to be the first image because it makes the most sense from a viewing perspective. In the tImage the sides
// are loaded in the +X,-X,+Y,-Y,+Z,-Z order. We display in +Z,-Z,+X,-X,+Y,-Y order.
const int numFaces = tFaceIndex_NumFaces;
struct FaceInfo { int Face; int OriginX; int OriginY; };
FaceInfo faceInfo[numFaces] =
{
{ tFaceIndex_PosZ, w, h },
{ tFaceIndex_NegZ, 3*w, h },
{ tFaceIndex_PosX, 2*w, h },
{ tFaceIndex_NegX, 0, h },
{ tFaceIndex_PosY, w, 2*h },
{ tFaceIndex_NegY, w, 0 }
};

tList<tLayer> layers[numFaces];
ktx.GetCubemapLayers(layers);
for (int f = 0; f < int(tFaceIndex_NumFaces); f++)
{
int face = faceInfo[f].Face;
int originX = faceInfo[f].OriginX;
int originY = faceInfo[f].OriginY;

tLayer* topMip = layers[face].First();
tAssert(topMip->PixelFormat == tPixelFormat::R8G8B8A8);
for (int y = 0; y < topMip->Height; y++)
for (int x = 0; x < topMip->Width; x++)
AltPicture.SetPixel(originX + x, originY + y, topMip->GetPixel(x, y));

// Let's reset the list so it doesn't do anything bad when destructed.
layers[face].Reset();
}
AltPictureTyp = AltPictureType::CubemapTLayout;
}
else if (ktx.IsMipmapped())
Expand Down

0 comments on commit f3a236c

Please sign in to comment.