fix: handle embedded cubemap face order correctly (#996)

* fix: handle embedded cubemap face order correctly

* chore: do not treat cubemaps as separate logic when not necessary

* chore: make sure face major image data is the default and chosen for any game other than qos

* chore: make new tests use no namespace

---------

Co-authored-by: Jan Laupetin <[email protected]>
This commit is contained in:
moandJan Laupetin authored and GitHub committed 2026-11-03 22:47:04 +01:00
1 parent 63e6d57b9c
commit cc71ec7387
10 files changed
+281 -21

No files matched your search

@@ -1,14 +1,18 @@
#include "Game/IW3/Image/ImageLoaderEmbeddedIW3.h"
#include "Game/IW3/GameIW3.h"
#include "Image/DdsWriter.h"
#include "Image/Texture.h"
#include "OatTestPaths.h"
#include "SearchPath/MockSearchPath.h"
#include "Utils/MemoryManager.h"
#include <catch2/catch_test_macros.hpp>
#include <cstring>
#include <filesystem>
#include <fstream>
#include <memory>
#include <sstream>
#include <string>
namespace fs = std::filesystem;
@@ -17,6 +21,18 @@ using namespace std::literals;
namespace
{
void FillCube(image::TextureCube& texture)
{
for (auto face = 0; face < texture.GetFaceCount(); face++)
{
for (auto mip = 0; mip < texture.GetMipMapCount(); mip++)
{
const auto value = static_cast<unsigned char>(face * 16 + mip + 1);
std::memset(texture.GetBufferForMipLevel(mip, face), value, texture.GetSizeOfMipLevel(mip));
}
}
}
TEST_CASE("ImageLoaderEmbeddedIW3: Can parse dds", "[iw3][image]")
{
MockSearchPath searchPath;
@@ -54,4 +70,46 @@ namespace
REQUIRE(image->texture.loadDef);
REQUIRE(image->texture.loadDef->resourceSize > 0);
}
TEST_CASE("ImageLoaderEmbeddedIW3: Stores cubemap mip chains face-major", "[iw3][image]")
{
image::TextureCube source(&image::format::A8, 8, 8, true);
source.Allocate();
FillCube(source);
std::stringstream ddsStream(std::ios::in | std::ios::out | std::ios::binary);
image::DdsWriter writer;
writer.DumpImage(ddsStream, &source);
MockSearchPath searchPath;
searchPath.AddFileData("images/_testcube.dds", ddsStream.str());
Zone zone("MockZone", 0, GameId::IW3, GamePlatform::PC);
MemoryManager memory;
AssetCreatorCollection creatorCollection(zone);
IgnoredAssetLookup ignoredAssetLookup;
AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup);
auto loader = image::CreateLoaderEmbeddedIW3(memory, searchPath);
const auto result = loader->CreateAsset("*testcube", context);
REQUIRE(result.HasBeenSuccessful());
const auto* assetInfo = reinterpret_cast<XAssetInfo<GfxImage>*>(result.GetAssetInfo());
const auto* loadDef = assetInfo->Asset()->texture.loadDef;
REQUIRE(loadDef);
auto offset = 0uz;
for (auto face = 0; face < source.GetFaceCount(); face++)
{
for (auto mip = 0; mip < source.GetMipMapCount(); mip++)
{
const auto mipSize = source.GetSizeOfMipLevel(mip);
REQUIRE(std::memcmp(loadDef->data + offset, source.GetBufferForMipLevel(mip, face), mipSize) == 0);
offset += mipSize;
}
}
REQUIRE(offset == loadDef->resourceSize);
}
} // namespace