mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 08:05:45 +00:00
Dump iw4 materials as json for data investigation purposes
This commit is contained in:
parent
0f47e64486
commit
2114b761b0
@ -632,8 +632,8 @@ namespace IW4
|
|||||||
unsigned int nameHash;
|
unsigned int nameHash;
|
||||||
char nameStart;
|
char nameStart;
|
||||||
char nameEnd;
|
char nameEnd;
|
||||||
char samplerState;
|
unsigned char samplerState;
|
||||||
char semantic;
|
unsigned char semantic; // TextureSemantic
|
||||||
MaterialTextureDefInfo u;
|
MaterialTextureDefInfo u;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -735,10 +735,10 @@ namespace IW4
|
|||||||
struct MaterialInfo
|
struct MaterialInfo
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* name;
|
||||||
char gameFlags;
|
unsigned char gameFlags;
|
||||||
char sortKey;
|
unsigned char sortKey;
|
||||||
char textureAtlasRowCount;
|
unsigned char textureAtlasRowCount;
|
||||||
char textureAtlasColumnCount;
|
unsigned char textureAtlasColumnCount;
|
||||||
GfxDrawSurf drawSurf;
|
GfxDrawSurf drawSurf;
|
||||||
unsigned int surfaceTypeBits;
|
unsigned int surfaceTypeBits;
|
||||||
uint16_t hashIndex;
|
uint16_t hashIndex;
|
||||||
@ -747,12 +747,12 @@ namespace IW4
|
|||||||
struct Material
|
struct Material
|
||||||
{
|
{
|
||||||
MaterialInfo info;
|
MaterialInfo info;
|
||||||
char stateBitsEntry[48];
|
unsigned char stateBitsEntry[48];
|
||||||
unsigned char textureCount;
|
unsigned char textureCount;
|
||||||
unsigned char constantCount;
|
unsigned char constantCount;
|
||||||
unsigned char stateBitsCount;
|
unsigned char stateBitsCount;
|
||||||
char stateFlags;
|
unsigned char stateFlags;
|
||||||
char cameraRegion;
|
unsigned char cameraRegion;
|
||||||
MaterialTechniqueSet* techniqueSet;
|
MaterialTechniqueSet* techniqueSet;
|
||||||
MaterialTextureDef* textureTable;
|
MaterialTextureDef* textureTable;
|
||||||
MaterialConstantDef* constantTable;
|
MaterialConstantDef* constantTable;
|
||||||
|
@ -567,5 +567,9 @@ namespace IW4
|
|||||||
KnownMaterialSource("attenuationMap5"),
|
KnownMaterialSource("attenuationMap5"),
|
||||||
KnownMaterialSource("attenuationMap6"),
|
KnownMaterialSource("attenuationMap6"),
|
||||||
KnownMaterialSource("attenuationMap7"),
|
KnownMaterialSource("attenuationMap7"),
|
||||||
|
KnownMaterialSource("distortionScale"),
|
||||||
|
KnownMaterialSource("eyeOffsetParms"),
|
||||||
|
KnownMaterialSource("falloffBeginColor"),
|
||||||
|
KnownMaterialSource("falloffEndColor"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
229
src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMaterial.cpp
Normal file
229
src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMaterial.cpp
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
#include "AssetDumperMaterial.h"
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include "Game/IW4/TechsetConstantsIW4.h"
|
||||||
|
|
||||||
|
using namespace IW4;
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
namespace IW4
|
||||||
|
{
|
||||||
|
const char* AssetName(const char* name)
|
||||||
|
{
|
||||||
|
if (name && name[0] == ',')
|
||||||
|
return &name[1];
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
json BuildComplexTableJson(complex_s* complexTable, const size_t count)
|
||||||
|
{
|
||||||
|
auto jArray = json::array();
|
||||||
|
|
||||||
|
if (complexTable)
|
||||||
|
{
|
||||||
|
for (auto index = 0u; index < count; index++)
|
||||||
|
{
|
||||||
|
const auto& entry = complexTable[index];
|
||||||
|
jArray.emplace_back(json{
|
||||||
|
{"real", entry.real},
|
||||||
|
{"imag", entry.imag}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return jArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
json BuildWaterJson(water_t* water)
|
||||||
|
{
|
||||||
|
if (!water)
|
||||||
|
return json{};
|
||||||
|
|
||||||
|
return json{
|
||||||
|
{"floatTime", water->writable.floatTime},
|
||||||
|
{"H0", BuildComplexTableJson(water->H0, water->M * water->N)},
|
||||||
|
{"wTerm", water->wTerm ? std::vector(water->wTerm, water->wTerm + (water->M * water->N)) : json::array()},
|
||||||
|
{"M", water->M},
|
||||||
|
{"N", water->N},
|
||||||
|
{"Lx", water->Lx},
|
||||||
|
{"Lz", water->Lz},
|
||||||
|
{"windvel", water->windvel},
|
||||||
|
{"winddir", std::vector(std::begin(water->winddir), std::end(water->winddir))},
|
||||||
|
{"amplitude", water->amplitude},
|
||||||
|
{"codeConstant", std::vector(std::begin(water->codeConstant), std::end(water->codeConstant))},
|
||||||
|
{"image", water->image && water->image->name ? AssetName(water->image->name) : nullptr}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
json BuildTextureTableJson(MaterialTextureDef* textureTable, const size_t count)
|
||||||
|
{
|
||||||
|
auto jArray = json::array();
|
||||||
|
|
||||||
|
if (textureTable)
|
||||||
|
{
|
||||||
|
for (auto index = 0u; index < count; index++)
|
||||||
|
{
|
||||||
|
const auto& entry = textureTable[index];
|
||||||
|
json jEntry = {
|
||||||
|
{"samplerState", entry.samplerState},
|
||||||
|
{"semantic", entry.semantic}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto knownMaterialSourceName = knownMaterialSourceNames.find(entry.nameHash);
|
||||||
|
if (knownMaterialSourceName != knownMaterialSourceNames.end())
|
||||||
|
{
|
||||||
|
jEntry["name"] = knownMaterialSourceName->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jEntry.merge_patch({
|
||||||
|
{"nameHash", entry.nameHash},
|
||||||
|
{"nameStart", entry.nameStart},
|
||||||
|
{"nameEnd", entry.nameEnd},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.semantic == TS_WATER_MAP)
|
||||||
|
{
|
||||||
|
jEntry["water"] = BuildWaterJson(entry.u.water);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jEntry["image"] = entry.u.image && entry.u.image->name ? AssetName(entry.u.image->name) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
jArray.emplace_back(std::move(jEntry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return jArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
json BuildConstantTableJson(MaterialConstantDef* constantTable, const size_t count)
|
||||||
|
{
|
||||||
|
auto jArray = json::array();
|
||||||
|
|
||||||
|
if (constantTable)
|
||||||
|
{
|
||||||
|
for (auto index = 0u; index < count; index++)
|
||||||
|
{
|
||||||
|
const auto& entry = constantTable[index];
|
||||||
|
json jEntry = {
|
||||||
|
{"literal", std::vector(std::begin(entry.literal), std::end(entry.literal))}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto nameLen = strnlen(entry.name, std::extent_v<decltype(MaterialConstantDef::name)>);
|
||||||
|
if (nameLen == std::extent_v<decltype(MaterialConstantDef::name)>)
|
||||||
|
{
|
||||||
|
std::string fullLengthName(entry.name, std::extent_v<decltype(MaterialConstantDef::name)>);
|
||||||
|
const auto fullLengthHash = Common::R_HashString(fullLengthName.c_str(), 0);
|
||||||
|
|
||||||
|
if (fullLengthHash == entry.nameHash)
|
||||||
|
{
|
||||||
|
jEntry["name"] = fullLengthName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto knownMaterialSourceName = knownMaterialSourceNames.find(entry.nameHash);
|
||||||
|
if (knownMaterialSourceName != knownMaterialSourceNames.end())
|
||||||
|
{
|
||||||
|
jEntry["name"] = knownMaterialSourceName->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jEntry.merge_patch({
|
||||||
|
{"nameHash", entry.nameHash},
|
||||||
|
{"namePart", fullLengthName}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jEntry["name"] = std::string(entry.name, nameLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
jArray.emplace_back(std::move(jEntry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return jArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
json BuildStateBitsTableJson(GfxStateBits* stateBitsTable, const size_t count)
|
||||||
|
{
|
||||||
|
auto jArray = json::array();
|
||||||
|
|
||||||
|
if (stateBitsTable)
|
||||||
|
{
|
||||||
|
for (auto index = 0u; index < count; index++)
|
||||||
|
{
|
||||||
|
const auto& entry = stateBitsTable[count];
|
||||||
|
jArray.emplace_back(json::array({
|
||||||
|
entry.loadBits[0],
|
||||||
|
entry.loadBits[1]
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return jArray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AssetDumperMaterial::ShouldDump(XAssetInfo<Material>* asset)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo<Material>* asset)
|
||||||
|
{
|
||||||
|
auto* material = asset->Asset();
|
||||||
|
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "materials/" << asset->m_name << ".json";
|
||||||
|
const auto assetFile = context.OpenAssetFile(ss.str());
|
||||||
|
|
||||||
|
if (!assetFile)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto& stream = *assetFile;
|
||||||
|
|
||||||
|
const json j = {
|
||||||
|
{
|
||||||
|
"info", {
|
||||||
|
{"gameFlags", material->info.gameFlags},
|
||||||
|
{"sortKey", material->info.sortKey},
|
||||||
|
{"textureAtlasRowCount", material->info.textureAtlasRowCount},
|
||||||
|
{"textureAtlasColumnCount", material->info.textureAtlasColumnCount},
|
||||||
|
{
|
||||||
|
"drawSurf", {
|
||||||
|
{"objectId", static_cast<unsigned>(material->info.drawSurf.fields.objectId)},
|
||||||
|
{"reflectionProbeIndex", static_cast<unsigned>(material->info.drawSurf.fields.reflectionProbeIndex)},
|
||||||
|
{"hasGfxEntIndex", static_cast<unsigned>(material->info.drawSurf.fields.hasGfxEntIndex)},
|
||||||
|
{"customIndex", static_cast<unsigned>(material->info.drawSurf.fields.customIndex)},
|
||||||
|
{"materialSortedIndex", static_cast<unsigned>(material->info.drawSurf.fields.materialSortedIndex)},
|
||||||
|
{"prepass", static_cast<unsigned>(material->info.drawSurf.fields.prepass)},
|
||||||
|
{"useHeroLighting", static_cast<unsigned>(material->info.drawSurf.fields.useHeroLighting)},
|
||||||
|
{"sceneLightIndex", static_cast<unsigned>(material->info.drawSurf.fields.sceneLightIndex)},
|
||||||
|
{"surfType", static_cast<unsigned>(material->info.drawSurf.fields.surfType)},
|
||||||
|
{"primarySortKey", static_cast<unsigned>(material->info.drawSurf.fields.primarySortKey)}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{"surfaceTypeBits", material->info.surfaceTypeBits},
|
||||||
|
{"hashIndex", material->info.hashIndex}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{"stateBitsEntry", std::vector(std::begin(material->stateBitsEntry), std::end(material->stateBitsEntry))},
|
||||||
|
{"stateFlags", material->stateFlags},
|
||||||
|
{"cameraRegion", material->cameraRegion},
|
||||||
|
{"techniqueSet", material->techniqueSet && material->techniqueSet->name ? AssetName(material->techniqueSet->name) : nullptr},
|
||||||
|
{"textureTable", BuildTextureTableJson(material->textureTable, material->textureCount)},
|
||||||
|
{"constantTable", BuildConstantTableJson(material->constantTable, material->constantCount)},
|
||||||
|
{"stateBitsTable", BuildStateBitsTableJson(material->stateBitsTable, material->stateBitsCount)}
|
||||||
|
};
|
||||||
|
|
||||||
|
stream << std::setw(4) << j;
|
||||||
|
}
|
14
src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMaterial.h
Normal file
14
src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMaterial.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Dumping/AbstractAssetDumper.h"
|
||||||
|
#include "Game/IW4/IW4.h"
|
||||||
|
|
||||||
|
namespace IW4
|
||||||
|
{
|
||||||
|
class AssetDumperMaterial final : public AbstractAssetDumper<Material>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
bool ShouldDump(XAssetInfo<Material>* asset) override;
|
||||||
|
void DumpAsset(AssetDumpingContext& context, XAssetInfo<Material>* asset) override;
|
||||||
|
};
|
||||||
|
}
|
@ -9,6 +9,7 @@
|
|||||||
#include "AssetDumpers/AssetDumperGfxLightDef.h"
|
#include "AssetDumpers/AssetDumperGfxLightDef.h"
|
||||||
#include "AssetDumpers/AssetDumperLoadedSound.h"
|
#include "AssetDumpers/AssetDumperLoadedSound.h"
|
||||||
#include "AssetDumpers/AssetDumperLocalizeEntry.h"
|
#include "AssetDumpers/AssetDumperLocalizeEntry.h"
|
||||||
|
#include "AssetDumpers/AssetDumperMaterial.h"
|
||||||
#include "AssetDumpers/AssetDumperMenuDef.h"
|
#include "AssetDumpers/AssetDumperMenuDef.h"
|
||||||
#include "AssetDumpers/AssetDumperMenuList.h"
|
#include "AssetDumpers/AssetDumperMenuList.h"
|
||||||
#include "AssetDumpers/AssetDumperPhysCollmap.h"
|
#include "AssetDumpers/AssetDumperPhysCollmap.h"
|
||||||
@ -47,7 +48,7 @@ bool ZoneDumper::DumpZone(AssetDumpingContext& context) const
|
|||||||
DUMP_ASSET_POOL(AssetDumperPhysCollmap, m_phys_collmap, ASSET_TYPE_PHYSCOLLMAP)
|
DUMP_ASSET_POOL(AssetDumperPhysCollmap, m_phys_collmap, ASSET_TYPE_PHYSCOLLMAP)
|
||||||
// DUMP_ASSET_POOL(AssetDumperXAnimParts, m_xanim_parts, ASSET_TYPE_XANIMPARTS)
|
// DUMP_ASSET_POOL(AssetDumperXAnimParts, m_xanim_parts, ASSET_TYPE_XANIMPARTS)
|
||||||
DUMP_ASSET_POOL(AssetDumperXModel, m_xmodel, ASSET_TYPE_XMODEL)
|
DUMP_ASSET_POOL(AssetDumperXModel, m_xmodel, ASSET_TYPE_XMODEL)
|
||||||
// DUMP_ASSET_POOL(AssetDumperMaterial, m_material, ASSET_TYPE_MATERIAL)
|
DUMP_ASSET_POOL(AssetDumperMaterial, m_material, ASSET_TYPE_MATERIAL)
|
||||||
DUMP_ASSET_POOL(AssetDumperPixelShader, m_material_pixel_shader, ASSET_TYPE_PIXELSHADER)
|
DUMP_ASSET_POOL(AssetDumperPixelShader, m_material_pixel_shader, ASSET_TYPE_PIXELSHADER)
|
||||||
DUMP_ASSET_POOL(AssetDumperVertexShader, m_material_vertex_shader, ASSET_TYPE_VERTEXSHADER)
|
DUMP_ASSET_POOL(AssetDumperVertexShader, m_material_vertex_shader, ASSET_TYPE_VERTEXSHADER)
|
||||||
DUMP_ASSET_POOL(AssetDumperTechniqueSet, m_technique_set, ASSET_TYPE_TECHNIQUE_SET)
|
DUMP_ASSET_POOL(AssetDumperTechniqueSet, m_technique_set, ASSET_TYPE_TECHNIQUE_SET)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user