From 99c7ebbe9bfb698271a104cc530c1a4c53efd5f8 Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 10 Apr 2022 19:39:26 +0200 Subject: [PATCH] Load vertex decl asset --- src/ObjCommon/Game/IW4/TechsetConstantsIW4.h | 30 +++++++ .../AssetLoaders/AssetLoaderTechniqueSet.cpp | 55 +++++++++++-- .../AssetLoaders/AssetLoaderVertexDecl.cpp | 78 +++++++++++++++++++ .../IW4/AssetLoaders/AssetLoaderVertexDecl.h | 5 ++ .../Sequence/TechniqueNoScopeSequences.cpp | 5 +- .../Sequence/TechniquePassScopeSequences.cpp | 9 ++- .../Parsing/TechniqueFileParserState.cpp | 1 - .../Parsing/TechniqueFileParserState.h | 3 +- .../Techset/TechniqueDefinitionAcceptor.h | 1 + 9 files changed, 174 insertions(+), 13 deletions(-) diff --git a/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h b/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h index 37fb745b..d341e2a6 100644 --- a/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h +++ b/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h @@ -78,6 +78,23 @@ namespace IW4 "texcoord[7]", }; static_assert(std::extent_v == STREAM_DST_COUNT); + static const char* materialStreamDestinationAbbreviation[] + { + "p", + "n", + "c0", + "c1", + "d", + "t0", + "t1", + "t2", + "t3", + "t4", + "t5", + "t6", + "t7", + }; + static_assert(std::extent_v == STREAM_DST_COUNT); static const char* materialStreamSourceNames[] { @@ -92,6 +109,19 @@ namespace IW4 "normalTransform[1]" }; static_assert(std::extent_v == STREAM_SRC_COUNT); + static const char* materialStreamSourceAbbreviation[] + { + "p", + "c", + "t0", + "n", + "t", + "t1", + "t2", + "n0", + "n1" + }; + static_assert(std::extent_v == STREAM_SRC_COUNT); inline CodeSamplerSource s_lightmapSamplers[] { diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp index 4b5b0c72..0a968651 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp @@ -91,12 +91,14 @@ namespace IW4 std::unique_ptr m_pixel_shader_info; MaterialVertexDeclaration m_vertex_decl; + XAssetInfo* m_vertex_decl_asset; std::vector m_arguments; Pass() : m_vertex_shader(nullptr), m_pixel_shader(nullptr), - m_vertex_decl{} + m_vertex_decl{}, + m_vertex_decl_asset(nullptr) { } }; @@ -109,7 +111,6 @@ namespace IW4 m_manager(manager), m_zone_state(zoneState) { - m_passes.emplace_back(); } void AcceptNextPass() override @@ -117,6 +118,50 @@ namespace IW4 m_passes.emplace_back(); } + bool AutoCreateVertexShaderArguments(std::string& string) + { + return true; + } + + bool AutoCreatePixelShaderArguments(std::string& string) + { + return true; + } + + void AllocateVertexDecl() + { + assert(!m_passes.empty()); + auto& pass = m_passes.at(m_passes.size() - 1); + + std::sort(std::begin(pass.m_vertex_decl.routing.data), std::begin(pass.m_vertex_decl.routing.data) + pass.m_vertex_decl.streamCount, + [](const MaterialStreamRouting& r1, const MaterialStreamRouting& r2) + { + return r1.source < r2.source; + }); + + std::ostringstream ss; + for(auto i = 0u; i < pass.m_vertex_decl.streamCount; i++) + { + const auto& stream = pass.m_vertex_decl.routing.data[i]; + assert(stream.source < std::extent_v); + assert(stream.dest < std::extent_v); + + ss << materialStreamSourceAbbreviation[stream.source] << materialStreamDestinationAbbreviation[stream.dest]; + } + + pass.m_vertex_decl_asset = reinterpret_cast*>(m_manager->LoadDependency(ASSET_TYPE_VERTEXDECL, ss.str())); + } + + bool AcceptEndPass(std::string& errorMessage) override + { + if (!AutoCreateVertexShaderArguments(errorMessage) || !AutoCreatePixelShaderArguments(errorMessage)) + return false; + + AllocateVertexDecl(); + + return true; + } + void AcceptStateMap(const std::string& stateMapName) override { // TODO: State maps currently are not used @@ -540,14 +585,14 @@ namespace IW4 auto& pass = m_passes.at(m_passes.size() - 1); const auto streamIndex = static_cast(pass.m_vertex_decl.streamCount); - if(pass.m_vertex_decl.streamCount >= std::extent_v) + if (pass.m_vertex_decl.streamCount >= std::extent_v) { errorMessage = "Too many stream routings"; return false; } const auto foundDestination = std::find(std::begin(materialStreamDestinationNames), std::end(materialStreamDestinationNames), destination); - if(foundDestination == std::end(materialStreamDestinationNames)) + if (foundDestination == std::end(materialStreamDestinationNames)) { errorMessage = "Unknown stream destination"; return false; @@ -559,7 +604,7 @@ namespace IW4 errorMessage = "Unknown stream source"; return false; } - + const auto destinationIndex = static_cast(foundDestination - std::begin(materialStreamDestinationNames)); const auto sourceIndex = static_cast(foundSource - std::begin(materialStreamSourceNames)); diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexDecl.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexDecl.cpp index 9588ae76..e2b0ae12 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexDecl.cpp +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexDecl.cpp @@ -1,9 +1,11 @@ #include "AssetLoaderVertexDecl.h" #include +#include #include "ObjLoading.h" #include "Game/IW4/IW4.h" +#include "Game/IW4/TechsetConstantsIW4.h" #include "Pool/GlobalAssetPool.h" using namespace IW4; @@ -15,3 +17,79 @@ void* AssetLoaderVertexDecl::CreateEmptyAsset(const std::string& assetName, Memo vertexDecl->name = memory->Dup(assetName.c_str()); return vertexDecl; } + +bool AssetLoaderVertexDecl::CanLoadFromRaw() const +{ + return true; +} + +bool AssetLoaderVertexDecl::NextAbbreviation(const std::string& assetName, std::string& abbreviation, size_t& offset) +{ + if (offset >= assetName.size()) + return false; + + if (offset + 1 < assetName.size() && isdigit(assetName[offset + 1])) + { + abbreviation = std::string(assetName, offset, 2); + offset += 2; + } + else + { + abbreviation = std::string(assetName, offset, 1); + offset += 1; + } + + return true; +} + +bool AssetLoaderVertexDecl::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const +{ + MaterialVertexDeclaration decl{}; + + size_t currentOffset = 0u; + std::string sourceAbbreviation; + while (NextAbbreviation(assetName, sourceAbbreviation, currentOffset)) + { + if(decl.streamCount >= std::extent_v) + { + std::cout << "Failed to add vertex decl stream. Too many abbreviations: " << assetName << "\n"; + return false; + } + + std::string destinationAbbreviation; + if (!NextAbbreviation(assetName, destinationAbbreviation, currentOffset)) + { + std::cout << "Failed to detect vertex decl destination abbreviation: " << assetName << "\n"; + return false; + } + + const auto foundSourceAbbreviation = std::find(std::begin(materialStreamSourceAbbreviation), std::end(materialStreamSourceAbbreviation), sourceAbbreviation); + if (foundSourceAbbreviation == std::end(materialStreamSourceAbbreviation)) + { + std::cout << "Unknown vertex decl source abbreviation: " << sourceAbbreviation << "\n"; + return false; + } + + const auto foundDestinationAbbreviation = std::find(std::begin(materialStreamDestinationAbbreviation), std::end(materialStreamDestinationAbbreviation), destinationAbbreviation); + if (foundDestinationAbbreviation == std::end(materialStreamDestinationAbbreviation)) + { + std::cout << "Unknown vertex decl destination abbreviation: " << destinationAbbreviation << "\n"; + return false; + } + + const auto sourceIndex = static_cast(foundSourceAbbreviation - std::begin(materialStreamSourceAbbreviation)); + const auto destinationIndex = static_cast(foundDestinationAbbreviation - std::begin(materialStreamDestinationAbbreviation)); + + decl.routing.data[decl.streamCount].source = sourceIndex; + decl.routing.data[decl.streamCount].dest = destinationIndex; + decl.hasOptionalSource = decl.hasOptionalSource || sourceIndex >= STREAM_SRC_OPTIONAL_BEGIN; + decl.streamCount++; + } + + decl.name = memory->Dup(assetName.c_str()); + + auto* allocatedDecl = memory->Create(decl); + + manager->AddAsset(ASSET_TYPE_VERTEXDECL, assetName, allocatedDecl); + return true; +} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexDecl.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexDecl.h index 0a568bb7..196c5295 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexDecl.h +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexDecl.h @@ -8,7 +8,12 @@ namespace IW4 { class AssetLoaderVertexDecl final : public BasicAssetLoader { + static bool NextAbbreviation(const std::string& assetName, std::string& abbreviation, size_t& offset); + public: _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; + + _NODISCARD bool CanLoadFromRaw() const override; + bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; }; } diff --git a/src/ObjLoading/Techset/Parsing/Sequence/TechniqueNoScopeSequences.cpp b/src/ObjLoading/Techset/Parsing/Sequence/TechniqueNoScopeSequences.cpp index 9abdf1c2..3d5498ca 100644 --- a/src/ObjLoading/Techset/Parsing/Sequence/TechniqueNoScopeSequences.cpp +++ b/src/ObjLoading/Techset/Parsing/Sequence/TechniqueNoScopeSequences.cpp @@ -26,10 +26,7 @@ namespace techset assert(state->m_in_pass == false); state->m_in_pass = true; - if (state->m_before_first_pass) - state->m_before_first_pass = false; - else - state->m_acceptor->AcceptNextPass(); + state->m_acceptor->AcceptNextPass(); } }; } diff --git a/src/ObjLoading/Techset/Parsing/Sequence/TechniquePassScopeSequences.cpp b/src/ObjLoading/Techset/Parsing/Sequence/TechniquePassScopeSequences.cpp index 7adaaa65..ae60f3db 100644 --- a/src/ObjLoading/Techset/Parsing/Sequence/TechniquePassScopeSequences.cpp +++ b/src/ObjLoading/Techset/Parsing/Sequence/TechniquePassScopeSequences.cpp @@ -11,13 +11,15 @@ namespace techset { class SequenceEndPass final : public TechniqueParser::sequence_t { + static constexpr auto CAPTURE_FIRST_TOKEN = 1; + public: SequenceEndPass() { const SimpleMatcherFactory create(this); AddMatchers({ - create.Char('}') + create.Char('}').Capture(CAPTURE_FIRST_TOKEN) }); } @@ -25,6 +27,11 @@ namespace techset void ProcessMatch(TechniqueParserState* state, SequenceResult& result) const override { assert(state->m_in_pass == true); + + std::string errorMessage; + if(!state->m_acceptor->AcceptEndPass(errorMessage)) + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), errorMessage); + state->m_in_pass = false; } }; diff --git a/src/ObjLoading/Techset/Parsing/TechniqueFileParserState.cpp b/src/ObjLoading/Techset/Parsing/TechniqueFileParserState.cpp index 46397e57..97cdfa52 100644 --- a/src/ObjLoading/Techset/Parsing/TechniqueFileParserState.cpp +++ b/src/ObjLoading/Techset/Parsing/TechniqueFileParserState.cpp @@ -6,7 +6,6 @@ using namespace techset; TechniqueParserState::TechniqueParserState(ITechniqueDefinitionAcceptor* acceptor) : m_acceptor(acceptor), - m_before_first_pass(true), m_in_pass(false), m_in_shader(false), m_current_shader(ShaderSelector::VERTEX_SHADER) diff --git a/src/ObjLoading/Techset/Parsing/TechniqueFileParserState.h b/src/ObjLoading/Techset/Parsing/TechniqueFileParserState.h index 9a03745e..350007e5 100644 --- a/src/ObjLoading/Techset/Parsing/TechniqueFileParserState.h +++ b/src/ObjLoading/Techset/Parsing/TechniqueFileParserState.h @@ -8,8 +8,7 @@ namespace techset { public: ITechniqueDefinitionAcceptor* const m_acceptor; - - bool m_before_first_pass; + bool m_in_pass; bool m_in_shader; ShaderSelector m_current_shader; diff --git a/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h b/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h index c0938859..160a28d7 100644 --- a/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h +++ b/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h @@ -74,6 +74,7 @@ namespace techset ITechniqueDefinitionAcceptor& operator=(ITechniqueDefinitionAcceptor&& other) noexcept = default; virtual void AcceptNextPass() = 0; + virtual bool AcceptEndPass(std::string& errorMessage) = 0; virtual void AcceptStateMap(const std::string& stateMapName) = 0;