Load vertex decl asset

This commit is contained in:
Jan 2022-04-10 19:39:26 +02:00
parent e0bcf7aff0
commit 99c7ebbe9b
9 changed files with 174 additions and 13 deletions

View File

@ -78,6 +78,23 @@ namespace IW4
"texcoord[7]",
};
static_assert(std::extent_v<decltype(materialStreamDestinationNames)> == 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<decltype(materialStreamDestinationAbbreviation)> == STREAM_DST_COUNT);
static const char* materialStreamSourceNames[]
{
@ -92,6 +109,19 @@ namespace IW4
"normalTransform[1]"
};
static_assert(std::extent_v<decltype(materialStreamSourceNames)> == STREAM_SRC_COUNT);
static const char* materialStreamSourceAbbreviation[]
{
"p",
"c",
"t0",
"n",
"t",
"t1",
"t2",
"n0",
"n1"
};
static_assert(std::extent_v<decltype(materialStreamSourceAbbreviation)> == STREAM_SRC_COUNT);
inline CodeSamplerSource s_lightmapSamplers[]
{

View File

@ -91,12 +91,14 @@ namespace IW4
std::unique_ptr<d3d9::ShaderInfo> m_pixel_shader_info;
MaterialVertexDeclaration m_vertex_decl;
XAssetInfo<MaterialVertexDeclaration>* m_vertex_decl_asset;
std::vector<MaterialShaderArgument> 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<decltype(materialStreamSourceAbbreviation)>);
assert(stream.dest < std::extent_v<decltype(materialStreamDestinationAbbreviation)>);
ss << materialStreamSourceAbbreviation[stream.source] << materialStreamDestinationAbbreviation[stream.dest];
}
pass.m_vertex_decl_asset = reinterpret_cast<XAssetInfo<MaterialVertexDeclaration>*>(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<size_t>(pass.m_vertex_decl.streamCount);
if(pass.m_vertex_decl.streamCount >= std::extent_v<decltype(MaterialVertexStreamRouting::data)>)
if (pass.m_vertex_decl.streamCount >= std::extent_v<decltype(MaterialVertexStreamRouting::data)>)
{
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<MaterialStreamDestination_e>(foundDestination - std::begin(materialStreamDestinationNames));
const auto sourceIndex = static_cast<MaterialStreamStreamSource_e>(foundSource - std::begin(materialStreamSourceNames));

View File

@ -1,9 +1,11 @@
#include "AssetLoaderVertexDecl.h"
#include <cstring>
#include <iostream>
#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<decltype(MaterialVertexStreamRouting::data)>)
{
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<MaterialStreamStreamSource_e>(foundSourceAbbreviation - std::begin(materialStreamSourceAbbreviation));
const auto destinationIndex = static_cast<MaterialStreamDestination_e>(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<MaterialVertexDeclaration>(decl);
manager->AddAsset(ASSET_TYPE_VERTEXDECL, assetName, allocatedDecl);
return true;
}

View File

@ -8,7 +8,12 @@ namespace IW4
{
class AssetLoaderVertexDecl final : public BasicAssetLoader<ASSET_TYPE_VERTEXDECL, MaterialVertexDeclaration>
{
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;
};
}

View File

@ -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();
}
};
}

View File

@ -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<SimpleParserValue>& 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;
}
};

View File

@ -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)

View File

@ -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;

View File

@ -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;