diff --git a/src/Common/Game/IW4/IW4_Assets.h b/src/Common/Game/IW4/IW4_Assets.h index cefa073e..399a7922 100644 --- a/src/Common/Game/IW4/IW4_Assets.h +++ b/src/Common/Game/IW4/IW4_Assets.h @@ -875,8 +875,8 @@ namespace IW4 struct MaterialStreamRouting { - char source; - char dest; + unsigned char source; + unsigned char dest; }; struct MaterialVertexStreamRouting @@ -888,7 +888,7 @@ namespace IW4 struct MaterialVertexDeclaration { const char* name; - char streamCount; + unsigned char streamCount; bool hasOptionalSource; MaterialVertexStreamRouting routing; }; diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTechniqueSet.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTechniqueSet.cpp index b3cd5cd0..5e6a702e 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTechniqueSet.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTechniqueSet.cpp @@ -75,9 +75,71 @@ namespace IW4 m_stream << "}\n"; } + const char* GetStreamDestinationString(const MaterialStreamDestination_e dst) + { + static const char* destinationNames[] + { + "position", + "normal", + "color[0]", + "color[1]", + "depth", + "texcoord[0]", + "texcoord[1]", + "texcoord[2]", + "texcoord[3]", + "texcoord[4]", + "texcoord[5]", + "texcoord[6]", + "texcoord[7]", + }; + static_assert(std::extent_v == STREAM_DST_COUNT); + + const auto dstIndex = static_cast(dst); + assert(dstIndex < std::extent_v); + if (dstIndex < std::extent_v) + return destinationNames[dstIndex]; + return ""; + } + + const char* GetStreamSourceString(const MaterialStreamStreamSource_e src) + { + static const char* sourceNames[] + { + "position", + "color", + "texcoord[0]", + "normal", + "tangent", + "texcoord[1]", + "texcoord[2]", + "normalTransform[0]", + "normalTransform[1]" + }; + static_assert(std::extent_v == STREAM_SRC_COUNT); + + const auto srcIndex = static_cast(src); + assert(srcIndex < std::extent_v); + if (srcIndex < std::extent_v) + return sourceNames[srcIndex]; + return ""; + } + void DumpVertexDecl(const MaterialPass& pass) { - // TODO + if (pass.vertexDecl == nullptr || pass.vertexDecl->streamCount <= 0) + return; + + m_stream << "\n"; + + const auto streamCount = std::min(static_cast(pass.vertexDecl->streamCount), std::extent_v); + for (auto streamIndex = 0u; streamIndex < streamCount; streamIndex++) + { + const auto& stream = pass.vertexDecl->routing.data[streamIndex]; + Indent(); + m_stream << "vertex." << GetStreamDestinationString(static_cast(stream.dest)) + << " = code." << GetStreamSourceString(static_cast(stream.source)) << ";\n"; + } } void DumpPass(const MaterialPass& pass) @@ -122,7 +184,7 @@ namespace IW4 { assert(techniqueIndex < std::extent_v); - if(m_last_write_was_value) + if (m_last_write_was_value) { m_stream << "\n"; m_last_write_was_value = false; @@ -144,18 +206,18 @@ namespace IW4 { std::vector dumpedTechniques(std::extent_v); - for(auto techniqueIndex = 0u; techniqueIndex < std::extent_v; techniqueIndex++) + for (auto techniqueIndex = 0u; techniqueIndex < std::extent_v; techniqueIndex++) { const auto* technique = techset->techniques[techniqueIndex]; - if(technique == nullptr || dumpedTechniques[techniqueIndex]) + if (technique == nullptr || dumpedTechniques[techniqueIndex]) continue; dumpedTechniques[techniqueIndex] = true; WriteTechniqueType(techniqueIndex); - for(auto nextTechniqueIndex = techniqueIndex + 1; nextTechniqueIndex < std::extent_v; nextTechniqueIndex++) + for (auto nextTechniqueIndex = techniqueIndex + 1; nextTechniqueIndex < std::extent_v; nextTechniqueIndex++) { - if(techset->techniques[nextTechniqueIndex] != technique) + if (techset->techniques[nextTechniqueIndex] != technique) continue; dumpedTechniques[nextTechniqueIndex] = true;