From d4a95d046e19e6aa48237166e96e88c997d554dc Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Thu, 22 Jan 2026 21:43:06 +0000 Subject: [PATCH] chore: make sure TechsetCompilerT6 sets proper worldVertFormat --- src/Common/Game/IW3/IW3_Assets.h | 18 ++++- src/Common/Game/IW4/IW4_Assets.h | 18 ++++- src/Common/Game/IW5/IW5_Assets.h | 18 ++++- src/Common/Game/T5/T5_Assets.h | 15 +++- src/Common/Game/T6/T6_Assets.h | 15 +++- src/ObjCommon/Techset/CommonTechset.cpp | 6 ++ src/ObjCommon/Techset/CommonTechset.h | 1 + src/ObjCommon/Techset/TechsetCommon.cpp | 24 +++++++ src/ObjCommon/Techset/TechsetCommon.h | 2 + .../Game/T6/Techset/TechsetCompilerT6.cpp | 71 ++++++++++++++++++- .../Techset/CommonTechsetLoader.cpp | 4 +- .../Techset/Parsing/TechsetFileParser.cpp | 4 +- .../Techset/Parsing/TechsetFileParser.h | 4 +- .../Parsing/TechsetFileParserState.cpp | 4 +- .../Techset/Parsing/TechsetFileParserState.h | 3 +- .../Game/T6/Techset/TechsetCompilerT6Test.cpp | 65 +++++++++++++++++ 16 files changed, 255 insertions(+), 17 deletions(-) create mode 100644 test/ObjCompilingTests/Game/T6/Techset/TechsetCompilerT6Test.cpp diff --git a/src/Common/Game/IW3/IW3_Assets.h b/src/Common/Game/IW3/IW3_Assets.h index e9bcb463..7d0d0aed 100644 --- a/src/Common/Game/IW3/IW3_Assets.h +++ b/src/Common/Game/IW3/IW3_Assets.h @@ -1468,10 +1468,26 @@ namespace IW3 TECHNIQUE_NONE = 0x24, }; + enum MaterialWorldVertexFormat : unsigned char + { + MTL_WORLDVERT_TEX_1_NRM_1 = 0x0, + MTL_WORLDVERT_TEX_2_NRM_1 = 0x1, + MTL_WORLDVERT_TEX_2_NRM_2 = 0x2, + MTL_WORLDVERT_TEX_3_NRM_1 = 0x3, + MTL_WORLDVERT_TEX_3_NRM_2 = 0x4, + MTL_WORLDVERT_TEX_3_NRM_3 = 0x5, + MTL_WORLDVERT_TEX_4_NRM_1 = 0x6, + MTL_WORLDVERT_TEX_4_NRM_2 = 0x7, + MTL_WORLDVERT_TEX_4_NRM_3 = 0x8, + MTL_WORLDVERT_TEX_5_NRM_1 = 0x9, + MTL_WORLDVERT_TEX_5_NRM_2 = 0xA, + MTL_WORLDVERT_TEX_5_NRM_3 = 0xB, + }; + struct MaterialTechniqueSet { const char* name; - char worldVertFormat; + MaterialWorldVertexFormat worldVertFormat; bool hasBeenUploaded; char unused[1]; MaterialTechniqueSet* remappedTechniqueSet; diff --git a/src/Common/Game/IW4/IW4_Assets.h b/src/Common/Game/IW4/IW4_Assets.h index 1e3437e1..f752380b 100644 --- a/src/Common/Game/IW4/IW4_Assets.h +++ b/src/Common/Game/IW4/IW4_Assets.h @@ -1721,10 +1721,26 @@ namespace IW4 TECHNIQUE_COUNT }; + enum MaterialWorldVertexFormat : unsigned char + { + MTL_WORLDVERT_TEX_1_NRM_1 = 0x0, + MTL_WORLDVERT_TEX_2_NRM_1 = 0x1, + MTL_WORLDVERT_TEX_2_NRM_2 = 0x2, + MTL_WORLDVERT_TEX_3_NRM_1 = 0x3, + MTL_WORLDVERT_TEX_3_NRM_2 = 0x4, + MTL_WORLDVERT_TEX_3_NRM_3 = 0x5, + MTL_WORLDVERT_TEX_4_NRM_1 = 0x6, + MTL_WORLDVERT_TEX_4_NRM_2 = 0x7, + MTL_WORLDVERT_TEX_4_NRM_3 = 0x8, + MTL_WORLDVERT_TEX_5_NRM_1 = 0x9, + MTL_WORLDVERT_TEX_5_NRM_2 = 0xA, + MTL_WORLDVERT_TEX_5_NRM_3 = 0xB, + }; + struct MaterialTechniqueSet { const char* name; - unsigned char worldVertFormat; + MaterialWorldVertexFormat worldVertFormat; bool hasBeenUploaded; unsigned char unused[1]; MaterialTechniqueSet* remappedTechniqueSet; diff --git a/src/Common/Game/IW5/IW5_Assets.h b/src/Common/Game/IW5/IW5_Assets.h index 4613e8b0..c4156cd5 100644 --- a/src/Common/Game/IW5/IW5_Assets.h +++ b/src/Common/Game/IW5/IW5_Assets.h @@ -1102,10 +1102,26 @@ namespace IW5 MaterialPass passArray[1]; }; + enum MaterialWorldVertexFormat : unsigned char + { + MTL_WORLDVERT_TEX_1_NRM_1 = 0x0, + MTL_WORLDVERT_TEX_2_NRM_1 = 0x1, + MTL_WORLDVERT_TEX_2_NRM_2 = 0x2, + MTL_WORLDVERT_TEX_3_NRM_1 = 0x3, + MTL_WORLDVERT_TEX_3_NRM_2 = 0x4, + MTL_WORLDVERT_TEX_3_NRM_3 = 0x5, + MTL_WORLDVERT_TEX_4_NRM_1 = 0x6, + MTL_WORLDVERT_TEX_4_NRM_2 = 0x7, + MTL_WORLDVERT_TEX_4_NRM_3 = 0x8, + MTL_WORLDVERT_TEX_5_NRM_1 = 0x9, + MTL_WORLDVERT_TEX_5_NRM_2 = 0xA, + MTL_WORLDVERT_TEX_5_NRM_3 = 0xB, + }; + struct MaterialTechniqueSet { const char* name; - unsigned char worldVertFormat; + MaterialWorldVertexFormat worldVertFormat; unsigned char unused[2]; MaterialTechniqueSet* remappedTechniqueSet; MaterialTechnique* techniques[54]; diff --git a/src/Common/Game/T5/T5_Assets.h b/src/Common/Game/T5/T5_Assets.h index db716247..96537b83 100644 --- a/src/Common/Game/T5/T5_Assets.h +++ b/src/Common/Game/T5/T5_Assets.h @@ -1720,10 +1720,23 @@ namespace T5 TECHNIQUE_COUNT }; + enum MaterialWorldVertexFormat : unsigned char + { + MTL_WORLDVERT_TEX_1_NRM_1 = 0x0, + MTL_WORLDVERT_TEX_2_NRM_1 = 0x1, + MTL_WORLDVERT_TEX_2_NRM_2 = 0x2, + MTL_WORLDVERT_TEX_3_NRM_1 = 0x3, + MTL_WORLDVERT_TEX_3_NRM_2 = 0x4, + MTL_WORLDVERT_TEX_3_NRM_3 = 0x5, + MTL_WORLDVERT_TEX_4_NRM_1 = 0x6, + MTL_WORLDVERT_TEX_4_NRM_2 = 0x7, + MTL_WORLDVERT_TEX_4_NRM_3 = 0x8, + }; + struct MaterialTechniqueSet { const char* name; - char worldVertFormat; + MaterialWorldVertexFormat worldVertFormat; char unused[1]; uint16_t techsetFlags; MaterialTechnique* techniques[130]; diff --git a/src/Common/Game/T6/T6_Assets.h b/src/Common/Game/T6/T6_Assets.h index 9b0a102d..659ba508 100644 --- a/src/Common/Game/T6/T6_Assets.h +++ b/src/Common/Game/T6/T6_Assets.h @@ -840,10 +840,23 @@ namespace T6 TECHNIQUE_COUNT }; + enum MaterialWorldVertexFormat : unsigned char + { + MTL_WORLDVERT_TEX_1_NRM_1 = 0x0, + MTL_WORLDVERT_TEX_2_NRM_1 = 0x1, + MTL_WORLDVERT_TEX_2_NRM_2 = 0x2, + MTL_WORLDVERT_TEX_3_NRM_1 = 0x3, + MTL_WORLDVERT_TEX_3_NRM_2 = 0x4, + MTL_WORLDVERT_TEX_3_NRM_3 = 0x5, + MTL_WORLDVERT_TEX_4_NRM_1 = 0x6, + MTL_WORLDVERT_TEX_4_NRM_2 = 0x7, + MTL_WORLDVERT_TEX_4_NRM_3 = 0x8, + }; + struct MaterialTechniqueSet { const char* name; - char worldVertFormat; + MaterialWorldVertexFormat worldVertFormat; MaterialTechnique* techniques[36]; }; diff --git a/src/ObjCommon/Techset/CommonTechset.cpp b/src/ObjCommon/Techset/CommonTechset.cpp index 3d6ae765..a96daa07 100644 --- a/src/ObjCommon/Techset/CommonTechset.cpp +++ b/src/ObjCommon/Techset/CommonTechset.cpp @@ -46,4 +46,10 @@ namespace techset m_technique_names(std::move(techniqueNames)) { } + + CommonTechset::CommonTechset(std::string name, const size_t techniqueTypeCount) + : m_name(std::move(name)), + m_technique_names(techniqueTypeCount) + { + } } // namespace techset diff --git a/src/ObjCommon/Techset/CommonTechset.h b/src/ObjCommon/Techset/CommonTechset.h index e80d873d..9ba15e57 100644 --- a/src/ObjCommon/Techset/CommonTechset.h +++ b/src/ObjCommon/Techset/CommonTechset.h @@ -28,6 +28,7 @@ namespace techset CommonTechset() = default; explicit CommonTechset(size_t techniqueTypeCount); CommonTechset(std::string name, std::vector techniqueNames); + CommonTechset(std::string name, size_t techniqueTypeCount); std::string m_name; std::vector m_technique_names; diff --git a/src/ObjCommon/Techset/TechsetCommon.cpp b/src/ObjCommon/Techset/TechsetCommon.cpp index f21097bd..e6455f01 100644 --- a/src/ObjCommon/Techset/TechsetCommon.cpp +++ b/src/ObjCommon/Techset/TechsetCommon.cpp @@ -18,4 +18,28 @@ namespace techset { return std::format("techsets/{}.techset", assetName); } + + void CountWorldVertFormatParameters(const std::string& assetName, size_t& texCount, size_t& normalCount) + { + texCount = 0; + normalCount = 0; + + if (assetName.empty()) + return; + + const auto nameLen = assetName.size(); + for (auto pos = 1u; pos < nameLen - 1u; pos++) + { + if (assetName[pos - 1] != '_' && !isdigit(assetName[pos - 1])) + continue; + if (!isdigit(assetName[pos + 1])) + continue; + + const auto c = tolower(assetName[pos]); + if (c == 'c') + texCount++; + else if (c == 'n') + normalCount++; + } + } } // namespace techset diff --git a/src/ObjCommon/Techset/TechsetCommon.h b/src/ObjCommon/Techset/TechsetCommon.h index ad65b5df..25cd3fc3 100644 --- a/src/ObjCommon/Techset/TechsetCommon.h +++ b/src/ObjCommon/Techset/TechsetCommon.h @@ -7,4 +7,6 @@ namespace techset std::string GetFileNameForStateMapName(const std::string& stateMapName); std::string GetFileNameForTechniqueName(const std::string& assetName); std::string GetFileNameForTechsetName(const std::string& assetName); + + void CountWorldVertFormatParameters(const std::string& assetName, size_t& texCount, size_t& normalCount); } // namespace techset diff --git a/src/ObjCompiling/Game/T6/Techset/TechsetCompilerT6.cpp b/src/ObjCompiling/Game/T6/Techset/TechsetCompilerT6.cpp index 68882385..9a672a30 100644 --- a/src/ObjCompiling/Game/T6/Techset/TechsetCompilerT6.cpp +++ b/src/ObjCompiling/Game/T6/Techset/TechsetCompilerT6.cpp @@ -1,16 +1,81 @@ #include "TechsetCompilerT6.h" #include "Game/T6/T6.h" +#include "Game/T6/Techset/TechsetConstantsT6.h" +#include "Techset/CommonTechsetLoader.h" +#include "Techset/TechsetCommon.h" + +using namespace T6; namespace { - class TechsetCompilerT6 final : public AssetCreator + MaterialWorldVertexFormat GetWorldVertexFormat(const std::string& name) + { + if (name.contains("lit_")) + { + size_t texCount = 0u, normalCount = 0u; + techset::CountWorldVertFormatParameters(name, texCount, normalCount); + + // 0 and 1 seem to be treated equally + texCount = std::max(texCount, 1u); + normalCount = std::max(normalCount, 1u); + + if (texCount == 1 && normalCount == 1) + return MTL_WORLDVERT_TEX_1_NRM_1; + if (texCount == 2 && normalCount == 1) + return MTL_WORLDVERT_TEX_2_NRM_1; + if (texCount == 2 && normalCount == 2) + return MTL_WORLDVERT_TEX_2_NRM_2; + if (texCount == 3 && normalCount == 1) + return MTL_WORLDVERT_TEX_3_NRM_1; + if (texCount == 3 && normalCount == 2) + return MTL_WORLDVERT_TEX_3_NRM_2; + if (texCount == 3 && normalCount == 3) + return MTL_WORLDVERT_TEX_3_NRM_3; + if (texCount == 4 && normalCount == 1) + return MTL_WORLDVERT_TEX_4_NRM_1; + if (texCount == 4 && normalCount == 2) + return MTL_WORLDVERT_TEX_4_NRM_2; + if (texCount == 4 && normalCount == 3) + return MTL_WORLDVERT_TEX_4_NRM_3; + } + + return static_cast(0); + } + + MaterialTechniqueSet* ConvertTechniqueSet(const techset::CommonTechset& commonTechset, MemoryManager& memory) + { + auto* techset = memory.Alloc(); + techset->name = memory.Dup(commonTechset.m_name.c_str()); + techset->worldVertFormat = GetWorldVertexFormat(commonTechset.m_name); + + return techset; + } + + class TechsetCompilerT6 final : public AssetCreator { public: + TechsetCompilerT6(ISearchPath& searchPath, MemoryManager& memory) + : m_search_path(searchPath), + m_memory(memory) + { + } + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - return AssetCreationResult::NoAction(); + bool failure = false; + const auto commonTechset = techset::LoadCommonTechset(assetName, commonTechniqueTypeNames, m_search_path, failure); + if (!commonTechset) + return failure ? AssetCreationResult::Failure() : AssetCreationResult::NoAction(); + + auto* techset = ConvertTechniqueSet(*commonTechset, m_memory); + + return AssetCreationResult::Success(context.AddAsset(AssetRegistration(assetName, techset))); } + + private: + ISearchPath& m_search_path; + MemoryManager& m_memory; }; } // namespace @@ -18,6 +83,6 @@ namespace techset { std::unique_ptr CreateCompilerT6(MemoryManager& memory, ISearchPath& searchPath) { - return std::make_unique(); + return std::make_unique(searchPath, memory); } } // namespace techset diff --git a/src/ObjCompiling/Techset/CommonTechsetLoader.cpp b/src/ObjCompiling/Techset/CommonTechsetLoader.cpp index 34d54e11..407f8f80 100644 --- a/src/ObjCompiling/Techset/CommonTechsetLoader.cpp +++ b/src/ObjCompiling/Techset/CommonTechsetLoader.cpp @@ -20,7 +20,7 @@ namespace techset { failure = false; - const auto fileName = GetFileNameForTechniqueName(assetName); + const auto fileName = GetFileNameForTechsetName(assetName); const auto techniqueFile = searchPath.Open(fileName); if (!techniqueFile.IsOpen()) return nullptr; @@ -36,7 +36,7 @@ namespace techset CommentRemovingStreamProxy commentProxy(&baseStream); const auto lexer = std::make_unique(&commentProxy, std::move(lexerConfig)); - const auto parser = std::make_unique(*lexer, techniqueTypeNames); + const auto parser = std::make_unique(*lexer, assetName, techniqueTypeNames); const auto success = parser->Parse(); if (success) diff --git a/src/ObjCompiling/Techset/Parsing/TechsetFileParser.cpp b/src/ObjCompiling/Techset/Parsing/TechsetFileParser.cpp index 5bd6bfc3..4025ad29 100644 --- a/src/ObjCompiling/Techset/Parsing/TechsetFileParser.cpp +++ b/src/ObjCompiling/Techset/Parsing/TechsetFileParser.cpp @@ -72,8 +72,8 @@ namespace namespace techset { - TechsetParser::TechsetParser(SimpleLexer& lexer, const CommonTechniqueTypeNames& techniqueTypeNames) - : AbstractParser(&lexer, std::make_unique(techniqueTypeNames)) + TechsetParser::TechsetParser(SimpleLexer& lexer, std::string techsetName, const CommonTechniqueTypeNames& techniqueTypeNames) + : AbstractParser(&lexer, std::make_unique(std::move(techsetName), techniqueTypeNames)) { } diff --git a/src/ObjCompiling/Techset/Parsing/TechsetFileParser.h b/src/ObjCompiling/Techset/Parsing/TechsetFileParser.h index d10b718e..0bcab1a9 100644 --- a/src/ObjCompiling/Techset/Parsing/TechsetFileParser.h +++ b/src/ObjCompiling/Techset/Parsing/TechsetFileParser.h @@ -10,9 +10,9 @@ namespace techset class TechsetParser final : public AbstractParser { public: - TechsetParser(SimpleLexer& lexer, const CommonTechniqueTypeNames& techniqueTypeNames); + TechsetParser(SimpleLexer& lexer, std::string techsetName, const CommonTechniqueTypeNames& techniqueTypeNames); [[nodiscard]] std::unique_ptr GetParsingResult() const; - + protected: const std::vector& GetTestsForState() override; }; diff --git a/src/ObjCompiling/Techset/Parsing/TechsetFileParserState.cpp b/src/ObjCompiling/Techset/Parsing/TechsetFileParserState.cpp index 5fb2a9fe..46bbabc7 100644 --- a/src/ObjCompiling/Techset/Parsing/TechsetFileParserState.cpp +++ b/src/ObjCompiling/Techset/Parsing/TechsetFileParserState.cpp @@ -2,9 +2,9 @@ namespace techset { - TechsetParserState::TechsetParserState(const CommonTechniqueTypeNames& techniqueTypeNames) + TechsetParserState::TechsetParserState(std::string techsetName, const CommonTechniqueTypeNames& techniqueTypeNames) : m_technique_type_names(techniqueTypeNames), - m_definition(std::make_unique(techniqueTypeNames.GetTechniqueTypeCount())) + m_definition(std::make_unique(std::move(techsetName), techniqueTypeNames.GetTechniqueTypeCount())) { } } // namespace techset diff --git a/src/ObjCompiling/Techset/Parsing/TechsetFileParserState.h b/src/ObjCompiling/Techset/Parsing/TechsetFileParserState.h index fb0154c5..67a74b3f 100644 --- a/src/ObjCompiling/Techset/Parsing/TechsetFileParserState.h +++ b/src/ObjCompiling/Techset/Parsing/TechsetFileParserState.h @@ -4,6 +4,7 @@ #include #include +#include #include namespace techset @@ -11,7 +12,7 @@ namespace techset class TechsetParserState { public: - explicit TechsetParserState(const CommonTechniqueTypeNames& techniqueTypeNames); + TechsetParserState(std::string techsetName, const CommonTechniqueTypeNames& techniqueTypeNames); const CommonTechniqueTypeNames& m_technique_type_names; std::unique_ptr m_definition; diff --git a/test/ObjCompilingTests/Game/T6/Techset/TechsetCompilerT6Test.cpp b/test/ObjCompilingTests/Game/T6/Techset/TechsetCompilerT6Test.cpp new file mode 100644 index 00000000..d9c36ba5 --- /dev/null +++ b/test/ObjCompilingTests/Game/T6/Techset/TechsetCompilerT6Test.cpp @@ -0,0 +1,65 @@ +#include "Game/T6/Techset/TechsetCompilerT6.h" + +#include "Game/T6/GameAssetPoolT6.h" +#include "SearchPath/MockSearchPath.h" +#include "Utils/TestMemoryManager.h" + +#include +#include +#include +#include + +using namespace T6; +using namespace std::string_literals; + +TEST_CASE("Game::T6::Techset::TechsetCompilerT6", "[techset][t6]") +{ + Zone zone("test", 0, GameId::T6, GamePlatform::PC); + AssetCreatorCollection creators(zone); + IgnoredAssetLookup ignoredAssets; + AssetCreationContext context(zone, &creators, &ignoredAssets); + MockSearchPath searchPath; + TestMemoryManager memory; + const auto sut = ::techset::CreateCompilerT6(memory, searchPath); + + SECTION("Sets correct worldVertFormat") + { + const auto [techsetName, expectedWorldVertFormat] = GENERATE(Catch::Generators::table({ + {"default", MTL_WORLDVERT_TEX_1_NRM_1}, + {"effect_zeqqz943", MTL_WORLDVERT_TEX_1_NRM_1}, + {"lit_r0c0_t1c1n1", MTL_WORLDVERT_TEX_2_NRM_1}, + {"lit_r0c0n0x0_b1c1n1s1v1", MTL_WORLDVERT_TEX_2_NRM_2}, + {"lit_r0c0n0x0_b1c1n1s1v1_b2c2n2x2", MTL_WORLDVERT_TEX_3_NRM_3}, + {"lit_sm_b0c0_b1c1_b2c2", MTL_WORLDVERT_TEX_3_NRM_1}, + {"lit_sm_b0c0_b1c1n1x1_b2c2n2v2", MTL_WORLDVERT_TEX_3_NRM_2}, + {"lit_sm_r0c0_b1c1_b2c2_b3c3", MTL_WORLDVERT_TEX_4_NRM_1}, + {"lit_sm_r0c0n0_b1c1_b2c2n2v2_m3c3", MTL_WORLDVERT_TEX_4_NRM_2}, + {"lit_sm_r0c0n0_b1c1n1s1", MTL_WORLDVERT_TEX_2_NRM_2}, + {"lit_sm_r0c0n0s0_b1c1n1s1_b2c2n2", MTL_WORLDVERT_TEX_3_NRM_3}, + {"lit_sm_r0c0n0x0_b1c1_b2c2n2s2", MTL_WORLDVERT_TEX_3_NRM_2}, + {"lit_sm_r0c0n0x0_b1c1n1_b2c2n2s2v2", MTL_WORLDVERT_TEX_3_NRM_3}, + {"lit_sm_r0c0n0x0_b1c1s1v1_m2c2_m3c3", MTL_WORLDVERT_TEX_4_NRM_1}, + {"lit_sm_r0c0n0x0_b1c1v1_b2c2n2s2_m3c3", MTL_WORLDVERT_TEX_4_NRM_2}, + {"lit_sm_r0c0s0_b1c1n1s1_m2c2", MTL_WORLDVERT_TEX_3_NRM_1}, + {"lit_sm_r0c0x0_b1c1", MTL_WORLDVERT_TEX_2_NRM_1}, + {"lit_sm_r0c0x0_b1c1n1s1_b2c2n2s2", MTL_WORLDVERT_TEX_3_NRM_2}, + {"lit_sm_r0c0x0_m1c1_m2c2_m3c3", MTL_WORLDVERT_TEX_4_NRM_1}, + {"lit_sm_t0c0n0_b1c1n1v1", MTL_WORLDVERT_TEX_2_NRM_2}, + {"lit_sm_t0c0n0s0_b1c1n1_b2c2n2s2v2", MTL_WORLDVERT_TEX_3_NRM_3}, + {"mc_lit_sm_r0c0d0_2213939z", MTL_WORLDVERT_TEX_1_NRM_1}, + {"wpc_lit_sm_b0c0s0_3f3q946z", MTL_WORLDVERT_TEX_1_NRM_1}, + {"wpc_lit_sm_r0c0n0s0o0_qj92q1f8", MTL_WORLDVERT_TEX_1_NRM_1}, + {"wpc_sw4_3d_burning_embers_nuketown_74j6971w", MTL_WORLDVERT_TEX_1_NRM_1}, + {"wpc_unlitdecalblend_add_j26wq580", MTL_WORLDVERT_TEX_1_NRM_1}, + })); + + CAPTURE(techsetName); + searchPath.AddFileData(std::format("techsets/{}.techset", techsetName), ""); + + const auto result = sut->CreateAsset(techsetName, context); + REQUIRE(result.HasBeenSuccessful()); + + const auto* techset = static_cast(result.GetAssetInfo()->m_ptr); + CHECK(techset->worldVertFormat == expectedWorldVertFormat); + } +}