mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 00:02:55 +00:00
Merge pull request #128 from Laupetin/feature/json-material-loading
feat: load t6 materials from json
This commit is contained in:
commit
3ebea76685
@ -2913,9 +2913,7 @@ namespace T6
|
|||||||
GFXS_POLYGON_OFFSET_0 = 0,
|
GFXS_POLYGON_OFFSET_0 = 0,
|
||||||
GFXS_POLYGON_OFFSET_1 = 1,
|
GFXS_POLYGON_OFFSET_1 = 1,
|
||||||
GFXS_POLYGON_OFFSET_2 = 2,
|
GFXS_POLYGON_OFFSET_2 = 2,
|
||||||
GFXS_POLYGON_OFFSET_SHADOWMAP = 3,
|
GFXS_POLYGON_OFFSET_SHADOWMAP = 3
|
||||||
|
|
||||||
GFXS_POLYGON_OFFSET_COUNT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GfxStencilOp
|
enum GfxStencilOp
|
||||||
@ -2927,9 +2925,7 @@ namespace T6
|
|||||||
GFXS_STENCILOP_DECRSAT = 0x4,
|
GFXS_STENCILOP_DECRSAT = 0x4,
|
||||||
GFXS_STENCILOP_INVERT = 0x5,
|
GFXS_STENCILOP_INVERT = 0x5,
|
||||||
GFXS_STENCILOP_INCR = 0x6,
|
GFXS_STENCILOP_INCR = 0x6,
|
||||||
GFXS_STENCILOP_DECR = 0x7,
|
GFXS_STENCILOP_DECR = 0x7
|
||||||
|
|
||||||
GFXS_STENCILOP_COUNT,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GfxStencilFunc
|
enum GfxStencilFunc
|
||||||
@ -2941,9 +2937,7 @@ namespace T6
|
|||||||
GFXS_STENCILFUNC_GREATER = 0x4,
|
GFXS_STENCILFUNC_GREATER = 0x4,
|
||||||
GFXS_STENCILFUNC_NOTEQUAL = 0x5,
|
GFXS_STENCILFUNC_NOTEQUAL = 0x5,
|
||||||
GFXS_STENCILFUNC_GREATEREQUAL = 0x6,
|
GFXS_STENCILFUNC_GREATEREQUAL = 0x6,
|
||||||
GFXS_STENCILFUNC_ALWAYS = 0x7,
|
GFXS_STENCILFUNC_ALWAYS = 0x7
|
||||||
|
|
||||||
GFXS_STENCILFUNC_COUNT,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GfxStateBitsLoadBitsStructured
|
struct GfxStateBitsLoadBitsStructured
|
||||||
|
@ -3,6 +3,7 @@ ObjCommon = {}
|
|||||||
function ObjCommon:include(includes)
|
function ObjCommon:include(includes)
|
||||||
if includes:handle(self:name()) then
|
if includes:handle(self:name()) then
|
||||||
Common:include(includes)
|
Common:include(includes)
|
||||||
|
json:include(includes)
|
||||||
minizip:include(includes)
|
minizip:include(includes)
|
||||||
includedirs {
|
includedirs {
|
||||||
path.join(ProjectFolder(), "ObjCommon")
|
path.join(ProjectFolder(), "ObjCommon")
|
||||||
|
0
src/ObjCommon/Game/T6/Material/JsonMaterial.cpp
Normal file
0
src/ObjCommon/Game/T6/Material/JsonMaterial.cpp
Normal file
397
src/ObjCommon/Game/T6/Material/JsonMaterial.h
Normal file
397
src/ObjCommon/Game/T6/Material/JsonMaterial.h
Normal file
@ -0,0 +1,397 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Game/T6/T6.h"
|
||||||
|
#include "Utils/JsonOptional.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace T6
|
||||||
|
{
|
||||||
|
NLOHMANN_JSON_SERIALIZE_ENUM(GfxStencilOp,
|
||||||
|
{
|
||||||
|
{GFXS_STENCILOP_KEEP, "keep" },
|
||||||
|
{GFXS_STENCILOP_ZERO, "zero" },
|
||||||
|
{GFXS_STENCILOP_REPLACE, "replace"},
|
||||||
|
{GFXS_STENCILOP_INCRSAT, "incrsat"},
|
||||||
|
{GFXS_STENCILOP_DECRSAT, "decrsat"},
|
||||||
|
{GFXS_STENCILOP_INVERT, "invert" },
|
||||||
|
{GFXS_STENCILOP_INCR, "incr" },
|
||||||
|
{GFXS_STENCILOP_DECR, "decr" },
|
||||||
|
});
|
||||||
|
|
||||||
|
NLOHMANN_JSON_SERIALIZE_ENUM(GfxStencilFunc,
|
||||||
|
{
|
||||||
|
{GFXS_STENCILFUNC_NEVER, "never" },
|
||||||
|
{GFXS_STENCILFUNC_LESS, "less" },
|
||||||
|
{GFXS_STENCILFUNC_EQUAL, "equal" },
|
||||||
|
{GFXS_STENCILFUNC_LESSEQUAL, "lessequal" },
|
||||||
|
{GFXS_STENCILFUNC_GREATER, "greater" },
|
||||||
|
{GFXS_STENCILFUNC_NOTEQUAL, "notequal" },
|
||||||
|
{GFXS_STENCILFUNC_GREATEREQUAL, "greaterequal"},
|
||||||
|
{GFXS_STENCILFUNC_ALWAYS, "always" },
|
||||||
|
});
|
||||||
|
|
||||||
|
class JsonStencil
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GfxStencilOp pass;
|
||||||
|
GfxStencilOp fail;
|
||||||
|
GfxStencilOp zfail;
|
||||||
|
GfxStencilFunc func;
|
||||||
|
};
|
||||||
|
|
||||||
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonStencil, pass, fail, zfail, func);
|
||||||
|
|
||||||
|
enum class JsonAlphaTest
|
||||||
|
{
|
||||||
|
INVALID,
|
||||||
|
DISABLED,
|
||||||
|
GT0,
|
||||||
|
GE128
|
||||||
|
};
|
||||||
|
|
||||||
|
NLOHMANN_JSON_SERIALIZE_ENUM(
|
||||||
|
JsonAlphaTest,
|
||||||
|
{
|
||||||
|
{JsonAlphaTest::INVALID, nullptr },
|
||||||
|
{JsonAlphaTest::DISABLED, "disabled"},
|
||||||
|
{JsonAlphaTest::GT0, "gt0" },
|
||||||
|
{JsonAlphaTest::GE128, "ge128" }
|
||||||
|
});
|
||||||
|
|
||||||
|
enum class JsonCullFace
|
||||||
|
{
|
||||||
|
INVALID,
|
||||||
|
NONE,
|
||||||
|
BACK,
|
||||||
|
FRONT
|
||||||
|
};
|
||||||
|
|
||||||
|
NLOHMANN_JSON_SERIALIZE_ENUM(
|
||||||
|
JsonCullFace,
|
||||||
|
{
|
||||||
|
{JsonCullFace::INVALID, nullptr},
|
||||||
|
{JsonCullFace::NONE, "none" },
|
||||||
|
{JsonCullFace::BACK, "back" },
|
||||||
|
{JsonCullFace::FRONT, "front"}
|
||||||
|
});
|
||||||
|
|
||||||
|
enum class JsonDepthTest
|
||||||
|
{
|
||||||
|
INVALID,
|
||||||
|
DISABLED,
|
||||||
|
ALWAYS,
|
||||||
|
LESS,
|
||||||
|
EQUAL,
|
||||||
|
LESS_EQUAL
|
||||||
|
};
|
||||||
|
|
||||||
|
NLOHMANN_JSON_SERIALIZE_ENUM(JsonDepthTest,
|
||||||
|
{
|
||||||
|
{JsonDepthTest::INVALID, nullptr },
|
||||||
|
{JsonDepthTest::DISABLED, "disabled" },
|
||||||
|
{JsonDepthTest::ALWAYS, "always" },
|
||||||
|
{JsonDepthTest::LESS, "less" },
|
||||||
|
{JsonDepthTest::EQUAL, "equal" },
|
||||||
|
{JsonDepthTest::LESS_EQUAL, "less_equal"}
|
||||||
|
});
|
||||||
|
|
||||||
|
NLOHMANN_JSON_SERIALIZE_ENUM(GfxBlend,
|
||||||
|
{
|
||||||
|
{GFXS_BLEND_DISABLED, "disabled" },
|
||||||
|
{GFXS_BLEND_ZERO, "zero" },
|
||||||
|
{GFXS_BLEND_ONE, "one" },
|
||||||
|
{GFXS_BLEND_SRCCOLOR, "srccolor" },
|
||||||
|
{GFXS_BLEND_INVSRCCOLOR, "invsrccolor" },
|
||||||
|
{GFXS_BLEND_SRCALPHA, "srcalpha" },
|
||||||
|
{GFXS_BLEND_INVSRCALPHA, "invsrcalpha" },
|
||||||
|
{GFXS_BLEND_DESTALPHA, "destalpha" },
|
||||||
|
{GFXS_BLEND_INVDESTALPHA, "invdestalpha"},
|
||||||
|
{GFXS_BLEND_DESTCOLOR, "destcolor" },
|
||||||
|
{GFXS_BLEND_INVDESTCOLOR, "invdestcolor"},
|
||||||
|
});
|
||||||
|
|
||||||
|
NLOHMANN_JSON_SERIALIZE_ENUM(GfxBlendOp,
|
||||||
|
{
|
||||||
|
{GFXS_BLENDOP_DISABLED, "disabled" },
|
||||||
|
{GFXS_BLENDOP_ADD, "add" },
|
||||||
|
{GFXS_BLENDOP_SUBTRACT, "subtract" },
|
||||||
|
{GFXS_BLENDOP_REVSUBTRACT, "revsubtract"},
|
||||||
|
{GFXS_BLENDOP_MIN, "min" },
|
||||||
|
{GFXS_BLENDOP_MAX, "max" },
|
||||||
|
});
|
||||||
|
|
||||||
|
NLOHMANN_JSON_SERIALIZE_ENUM(GfxPolygonOffset_e,
|
||||||
|
{
|
||||||
|
{GFXS_POLYGON_OFFSET_0, "offset0" },
|
||||||
|
{GFXS_POLYGON_OFFSET_1, "offset1" },
|
||||||
|
{GFXS_POLYGON_OFFSET_2, "offset2" },
|
||||||
|
{GFXS_POLYGON_OFFSET_SHADOWMAP, "offsetShadowmap"},
|
||||||
|
});
|
||||||
|
|
||||||
|
class JsonStateBitsTableEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GfxBlend srcBlendRgb;
|
||||||
|
GfxBlend dstBlendRgb;
|
||||||
|
GfxBlendOp blendOpRgb;
|
||||||
|
JsonAlphaTest alphaTest;
|
||||||
|
JsonCullFace cullFace;
|
||||||
|
GfxBlend srcBlendAlpha;
|
||||||
|
GfxBlend dstBlendAlpha;
|
||||||
|
GfxBlendOp blendOpAlpha;
|
||||||
|
bool colorWriteRgb;
|
||||||
|
bool colorWriteAlpha;
|
||||||
|
bool polymodeLine;
|
||||||
|
bool depthWrite;
|
||||||
|
JsonDepthTest depthTest;
|
||||||
|
GfxPolygonOffset_e polygonOffset;
|
||||||
|
std::optional<JsonStencil> stencilFront;
|
||||||
|
std::optional<JsonStencil> stencilBack;
|
||||||
|
};
|
||||||
|
|
||||||
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonStateBitsTableEntry,
|
||||||
|
srcBlendRgb,
|
||||||
|
dstBlendRgb,
|
||||||
|
blendOpRgb,
|
||||||
|
alphaTest,
|
||||||
|
cullFace,
|
||||||
|
srcBlendAlpha,
|
||||||
|
dstBlendAlpha,
|
||||||
|
blendOpAlpha,
|
||||||
|
colorWriteRgb,
|
||||||
|
colorWriteAlpha,
|
||||||
|
polymodeLine,
|
||||||
|
depthWrite,
|
||||||
|
depthWrite,
|
||||||
|
depthTest,
|
||||||
|
polygonOffset,
|
||||||
|
stencilFront,
|
||||||
|
stencilBack);
|
||||||
|
|
||||||
|
class JsonConstant
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::optional<std::string> name;
|
||||||
|
std::optional<std::string> nameFragment;
|
||||||
|
std::optional<unsigned> nameHash;
|
||||||
|
std::vector<float> literal;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void to_json(nlohmann::json& out, const JsonConstant& in)
|
||||||
|
{
|
||||||
|
if (in.name.has_value())
|
||||||
|
{
|
||||||
|
out["name"] = in.name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out["nameFragment"] = in.nameFragment;
|
||||||
|
out["nameHash"] = in.nameHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
out["literal"] = in.literal;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void from_json(const nlohmann::json& in, JsonConstant& out)
|
||||||
|
{
|
||||||
|
in.value("name", nlohmann::json()).get_to(out.name);
|
||||||
|
in.value("nameFragment", nlohmann::json()).get_to(out.nameFragment);
|
||||||
|
in.value("nameHash", nlohmann::json()).get_to(out.nameHash);
|
||||||
|
in.at("literal").get_to(out.literal);
|
||||||
|
};
|
||||||
|
|
||||||
|
NLOHMANN_JSON_SERIALIZE_ENUM(TextureFilter,
|
||||||
|
{
|
||||||
|
{TEXTURE_FILTER_DISABLED, "disabled"},
|
||||||
|
{TEXTURE_FILTER_NEAREST, "nearest" },
|
||||||
|
{TEXTURE_FILTER_LINEAR, "linear" },
|
||||||
|
{TEXTURE_FILTER_ANISO2X, "aniso2x" },
|
||||||
|
{TEXTURE_FILTER_ANISO4X, "aniso4x" },
|
||||||
|
{TEXTURE_FILTER_COMPARE, "compare" },
|
||||||
|
});
|
||||||
|
|
||||||
|
NLOHMANN_JSON_SERIALIZE_ENUM(SamplerStateBitsMipMap_e,
|
||||||
|
{
|
||||||
|
{SAMPLER_MIPMAP_ENUM_DISABLED, "disabled"},
|
||||||
|
{SAMPLER_MIPMAP_ENUM_NEAREST, "nearest" },
|
||||||
|
{SAMPLER_MIPMAP_ENUM_LINEAR, "linear" },
|
||||||
|
});
|
||||||
|
|
||||||
|
class JsonSamplerState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextureFilter filter;
|
||||||
|
SamplerStateBitsMipMap_e mipMap;
|
||||||
|
bool clampU;
|
||||||
|
bool clampV;
|
||||||
|
bool clampW;
|
||||||
|
};
|
||||||
|
|
||||||
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonSamplerState, filter, mipMap, clampU, clampV, clampW);
|
||||||
|
|
||||||
|
NLOHMANN_JSON_SERIALIZE_ENUM(TextureSemantic,
|
||||||
|
{
|
||||||
|
{TS_2D, "2D" },
|
||||||
|
{TS_FUNCTION, "function" },
|
||||||
|
{TS_COLOR_MAP, "colorMap" },
|
||||||
|
{TS_UNUSED_1, "unused1" },
|
||||||
|
{TS_UNUSED_2, "unused2" },
|
||||||
|
{TS_NORMAL_MAP, "normalMap" },
|
||||||
|
{TS_UNUSED_3, "unused3" },
|
||||||
|
{TS_UNUSED_4, "unused4" },
|
||||||
|
{TS_SPECULAR_MAP, "specularMap" },
|
||||||
|
{TS_UNUSED_5, "unused5" },
|
||||||
|
{TS_OCCLUSION_MAP, "occlusionMap"},
|
||||||
|
{TS_UNUSED_6, "unused6" },
|
||||||
|
{TS_COLOR0_MAP, "color0Map" },
|
||||||
|
{TS_COLOR1_MAP, "color1Map" },
|
||||||
|
{TS_COLOR2_MAP, "color2Map" },
|
||||||
|
{TS_COLOR3_MAP, "color3Map" },
|
||||||
|
{TS_COLOR4_MAP, "color4Map" },
|
||||||
|
{TS_COLOR5_MAP, "color5Map" },
|
||||||
|
{TS_COLOR6_MAP, "color6Map" },
|
||||||
|
{TS_COLOR7_MAP, "color7Map" },
|
||||||
|
{TS_COLOR8_MAP, "color8Map" },
|
||||||
|
{TS_COLOR9_MAP, "color9Map" },
|
||||||
|
{TS_COLOR10_MAP, "color10Map" },
|
||||||
|
{TS_COLOR11_MAP, "color11Map" },
|
||||||
|
{TS_COLOR12_MAP, "color12Map" },
|
||||||
|
{TS_COLOR13_MAP, "color13Map" },
|
||||||
|
{TS_COLOR14_MAP, "color14Map" },
|
||||||
|
{TS_COLOR15_MAP, "color15Map" },
|
||||||
|
{TS_THROW_MAP, "throwMap" },
|
||||||
|
});
|
||||||
|
|
||||||
|
class JsonTexture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::optional<std::string> name;
|
||||||
|
std::optional<unsigned> nameHash;
|
||||||
|
std::optional<std::string> nameStart;
|
||||||
|
std::optional<std::string> nameEnd;
|
||||||
|
TextureSemantic semantic;
|
||||||
|
bool isMatureContent;
|
||||||
|
JsonSamplerState samplerState;
|
||||||
|
std::string image;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void to_json(nlohmann::json& out, const JsonTexture& in)
|
||||||
|
{
|
||||||
|
if (in.name.has_value())
|
||||||
|
{
|
||||||
|
out["name"] = in.name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out["nameHash"] = in.nameHash;
|
||||||
|
out["nameStart"] = in.nameStart;
|
||||||
|
out["nameEnd"] = in.nameEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
out["semantic"] = in.semantic;
|
||||||
|
out["isMatureContent"] = in.isMatureContent;
|
||||||
|
out["samplerState"] = in.samplerState;
|
||||||
|
out["image"] = in.image;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void from_json(const nlohmann::json& in, JsonTexture& out)
|
||||||
|
{
|
||||||
|
in.value("name", nlohmann::json()).get_to(out.name);
|
||||||
|
in.value("nameHash", nlohmann::json()).get_to(out.nameHash);
|
||||||
|
in.value("nameStart", nlohmann::json()).get_to(out.nameStart);
|
||||||
|
in.value("nameEnd", nlohmann::json()).get_to(out.nameEnd);
|
||||||
|
in.at("semantic").get_to(out.semantic);
|
||||||
|
in.at("isMatureContent").get_to(out.isMatureContent);
|
||||||
|
in.at("samplerState").get_to(out.samplerState);
|
||||||
|
in.at("image").get_to(out.image);
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonTextureAtlas
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uint8_t rows;
|
||||||
|
uint8_t columns;
|
||||||
|
};
|
||||||
|
|
||||||
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonTextureAtlas, rows, columns);
|
||||||
|
|
||||||
|
NLOHMANN_JSON_SERIALIZE_ENUM(MaterialGameFlags,
|
||||||
|
{
|
||||||
|
{MTL_GAMEFLAG_1, "1" },
|
||||||
|
{MTL_GAMEFLAG_2, "2" },
|
||||||
|
{MTL_GAMEFLAG_NO_MARKS, "NO_MARKS" },
|
||||||
|
{MTL_GAMEFLAG_NO_MARKS, "4" },
|
||||||
|
{MTL_GAMEFLAG_8, "8" },
|
||||||
|
{MTL_GAMEFLAG_10, "10" },
|
||||||
|
{MTL_GAMEFLAG_20, "20" },
|
||||||
|
{MTL_GAMEFLAG_CASTS_SHADOW, "CASTS_SHADOW"},
|
||||||
|
{MTL_GAMEFLAG_CASTS_SHADOW, "40" },
|
||||||
|
{MTL_GAMEFLAG_80, "80" },
|
||||||
|
{MTL_GAMEFLAG_100, "100" },
|
||||||
|
{MTL_GAMEFLAG_200, "200" },
|
||||||
|
{MTL_GAMEFLAG_400, "400" },
|
||||||
|
{MTL_GAMEFLAG_800, "800" },
|
||||||
|
{MTL_GAMEFLAG_1000, "1000" },
|
||||||
|
});
|
||||||
|
|
||||||
|
NLOHMANN_JSON_SERIALIZE_ENUM(GfxCameraRegionType,
|
||||||
|
{
|
||||||
|
{CAMERA_REGION_LIT_OPAQUE, "litOpaque" },
|
||||||
|
{CAMERA_REGION_LIT_TRANS, "litTrans" },
|
||||||
|
{CAMERA_REGION_LIT_QUASI_OPAQUE, "litQuasiOpaque"},
|
||||||
|
{CAMERA_REGION_EMISSIVE_OPAQUE, "emissiveOpaque"},
|
||||||
|
{CAMERA_REGION_EMISSIVE_TRANS, "emissiveTrans" },
|
||||||
|
{CAMERA_REGION_EMISSIVE_FX, "emissiveFx" },
|
||||||
|
{CAMERA_REGION_LIGHT_MAP_OPAQUE, "lightMapOpaque"},
|
||||||
|
{CAMERA_REGION_DEPTH_HACK, "depthHack" },
|
||||||
|
{CAMERA_REGION_UNUSED, "unused" },
|
||||||
|
{CAMERA_REGION_SONAR, "sonar" },
|
||||||
|
{CAMERA_REGION_NONE, "none" },
|
||||||
|
});
|
||||||
|
|
||||||
|
class JsonMaterial
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector<MaterialGameFlags> gameFlags;
|
||||||
|
unsigned sortKey;
|
||||||
|
std::optional<JsonTextureAtlas> textureAtlas;
|
||||||
|
unsigned surfaceTypeBits;
|
||||||
|
unsigned layeredSurfaceTypes;
|
||||||
|
unsigned hashIndex;
|
||||||
|
unsigned surfaceFlags;
|
||||||
|
unsigned contents;
|
||||||
|
std::vector<int8_t> stateBitsEntry;
|
||||||
|
unsigned stateFlags;
|
||||||
|
GfxCameraRegionType cameraRegion;
|
||||||
|
uint8_t probeMipBits;
|
||||||
|
std::string techniqueSet;
|
||||||
|
std::vector<JsonTexture> textures;
|
||||||
|
std::vector<JsonConstant> constants;
|
||||||
|
std::vector<JsonStateBitsTableEntry> stateBits;
|
||||||
|
std::optional<std::string> thermalMaterial;
|
||||||
|
};
|
||||||
|
|
||||||
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonMaterial,
|
||||||
|
gameFlags,
|
||||||
|
sortKey,
|
||||||
|
textureAtlas,
|
||||||
|
surfaceTypeBits,
|
||||||
|
layeredSurfaceTypes,
|
||||||
|
hashIndex,
|
||||||
|
surfaceFlags,
|
||||||
|
contents,
|
||||||
|
stateBitsEntry,
|
||||||
|
stateFlags,
|
||||||
|
cameraRegion,
|
||||||
|
probeMipBits,
|
||||||
|
techniqueSet,
|
||||||
|
textures,
|
||||||
|
constants,
|
||||||
|
stateBits,
|
||||||
|
thermalMaterial);
|
||||||
|
} // namespace T6
|
@ -1,119 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Game/T6/CommonT6.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
inline const char* textureSemanticNames[]{
|
|
||||||
"2D", "function", "colorMap", "unused1", "unused2", "normalMap", "unused3", "unused4", "specularMap", "unused5",
|
|
||||||
"occlusionMap", "unused6", "color0Map", "color1Map", "color2Map", "color3Map", "color4Map", "color5Map", "color6Map", "color7Map",
|
|
||||||
"color8Map", "color9Map", "color10Map", "color11Map", "color12Map", "color13Map", "color14Map", "color15Map", "throwMap",
|
|
||||||
};
|
|
||||||
static_assert(std::extent_v<decltype(textureSemanticNames)> == TS_COUNT);
|
|
||||||
|
|
||||||
inline const char* cameraRegionNames[]{
|
|
||||||
"litOpaque",
|
|
||||||
"litTrans",
|
|
||||||
"litQuasiOpaque",
|
|
||||||
"emissiveOpaque",
|
|
||||||
"emissiveTrans",
|
|
||||||
"emissiveFx",
|
|
||||||
"lightMapOpaque",
|
|
||||||
"depthHack",
|
|
||||||
"unused",
|
|
||||||
"sonar",
|
|
||||||
"none",
|
|
||||||
};
|
|
||||||
static_assert(std::extent_v<decltype(cameraRegionNames)> == CAMERA_REGION_NONE + 1);
|
|
||||||
|
|
||||||
static const char* textureFilterNames[]{
|
|
||||||
"disabled",
|
|
||||||
"nearest",
|
|
||||||
"linear",
|
|
||||||
"aniso2x",
|
|
||||||
"aniso4x",
|
|
||||||
"compare",
|
|
||||||
};
|
|
||||||
static_assert(std::extent_v<decltype(textureFilterNames)> == TEXTURE_FILTER_COUNT);
|
|
||||||
|
|
||||||
static const char* samplerStateMipMapNames[]{
|
|
||||||
"disabled",
|
|
||||||
"nearest",
|
|
||||||
"linear",
|
|
||||||
};
|
|
||||||
static_assert(std::extent_v<decltype(samplerStateMipMapNames)> == SAMPLER_MIPMAP_ENUM_COUNT);
|
|
||||||
|
|
||||||
static const char* gameFlagNames[]{
|
|
||||||
"1",
|
|
||||||
"2",
|
|
||||||
"NO_MARKS",
|
|
||||||
"8",
|
|
||||||
"10",
|
|
||||||
"20",
|
|
||||||
"CASTS_SHADOW",
|
|
||||||
"80",
|
|
||||||
"100",
|
|
||||||
"200",
|
|
||||||
"400",
|
|
||||||
"800",
|
|
||||||
"1000",
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const char* blendNames[]{
|
|
||||||
"disabled",
|
|
||||||
"zero",
|
|
||||||
"one",
|
|
||||||
"srccolor",
|
|
||||||
"invsrccolor",
|
|
||||||
"srcalpha",
|
|
||||||
"invsrcalpha",
|
|
||||||
"destalpha",
|
|
||||||
"invdestalpha",
|
|
||||||
"destcolor",
|
|
||||||
"invdestcolor",
|
|
||||||
};
|
|
||||||
static_assert(std::extent_v<decltype(blendNames)> == GFXS_BLEND_COUNT);
|
|
||||||
|
|
||||||
inline const char* blendOpNames[]{
|
|
||||||
"disabled",
|
|
||||||
"add",
|
|
||||||
"subtract",
|
|
||||||
"revsubtract",
|
|
||||||
"min",
|
|
||||||
"max",
|
|
||||||
};
|
|
||||||
static_assert(std::extent_v<decltype(blendOpNames)> == GFXS_BLENDOP_COUNT);
|
|
||||||
|
|
||||||
inline const char* polygonOffsetNames[]{
|
|
||||||
"offset0",
|
|
||||||
"offset1",
|
|
||||||
"offset2",
|
|
||||||
"offsetShadowmap",
|
|
||||||
};
|
|
||||||
static_assert(std::extent_v<decltype(polygonOffsetNames)> == GFXS_POLYGON_OFFSET_COUNT);
|
|
||||||
|
|
||||||
inline const char* stencilOpNames[]{
|
|
||||||
"keep",
|
|
||||||
"zero",
|
|
||||||
"replace",
|
|
||||||
"incrsat",
|
|
||||||
"decrsat",
|
|
||||||
"invert",
|
|
||||||
"incr",
|
|
||||||
"decr",
|
|
||||||
};
|
|
||||||
static_assert(std::extent_v<decltype(stencilOpNames)> == GFXS_STENCILOP_COUNT);
|
|
||||||
|
|
||||||
inline const char* stencilFuncNames[]{
|
|
||||||
"never",
|
|
||||||
"less",
|
|
||||||
"equal",
|
|
||||||
"lessequal",
|
|
||||||
"greater",
|
|
||||||
"notequal",
|
|
||||||
"greaterequal",
|
|
||||||
"always",
|
|
||||||
};
|
|
||||||
static_assert(std::extent_v<decltype(stencilFuncNames)> == GFXS_STENCILFUNC_COUNT);
|
|
||||||
} // namespace T6
|
|
37
src/ObjCommon/Utils/JsonOptional.h
Normal file
37
src/ObjCommon/Utils/JsonOptional.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
// partial specialization (full specialization works too)
|
||||||
|
namespace nlohmann
|
||||||
|
{
|
||||||
|
template<typename T> struct adl_serializer<std::optional<T>>
|
||||||
|
{
|
||||||
|
static void to_json(json& j, const std::optional<T>& opt)
|
||||||
|
{
|
||||||
|
if (!opt.has_value())
|
||||||
|
{
|
||||||
|
j = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
j = *opt; // this will call adl_serializer<T>::to_json which will
|
||||||
|
// find the free function to_json in T's namespace!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json& j, std::optional<T>& opt)
|
||||||
|
{
|
||||||
|
if (j.is_null())
|
||||||
|
{
|
||||||
|
opt = std::nullopt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opt = j.template get<T>(); // same as above, but with
|
||||||
|
// adl_serializer<T>::from_json
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace nlohmann
|
@ -36,6 +36,11 @@ public:
|
|||||||
return AddAsset(assetType, assetName, asset, std::vector<XAssetInfoGeneric*>(), std::vector<scr_string_t>());
|
return AddAsset(assetType, assetName, asset, std::vector<XAssetInfoGeneric*>(), std::vector<scr_string_t>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XAssetInfoGeneric* AddAsset(const asset_type_t assetType, const std::string& assetName, void* asset, std::vector<XAssetInfoGeneric*> dependencies)
|
||||||
|
{
|
||||||
|
return AddAsset(assetType, assetName, asset, std::move(dependencies), std::vector<scr_string_t>());
|
||||||
|
}
|
||||||
|
|
||||||
virtual XAssetInfoGeneric* LoadDependency(asset_type_t assetType, const std::string& assetName) = 0;
|
virtual XAssetInfoGeneric* LoadDependency(asset_type_t assetType, const std::string& assetName) = 0;
|
||||||
virtual IndirectAssetReference LoadIndirectAssetReference(asset_type_t assetType, const std::string& assetName) = 0;
|
virtual IndirectAssetReference LoadIndirectAssetReference(asset_type_t assetType, const std::string& assetName) = 0;
|
||||||
};
|
};
|
||||||
|
60
src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMaterial.cpp
Normal file
60
src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMaterial.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include "AssetLoaderMaterial.h"
|
||||||
|
|
||||||
|
#include "Game/T6/Material/JsonMaterialLoader.h"
|
||||||
|
#include "Game/T6/T6.h"
|
||||||
|
#include "Pool/GlobalAssetPool.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <format>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace T6;
|
||||||
|
|
||||||
|
void* AssetLoaderMaterial::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
||||||
|
{
|
||||||
|
auto* material = memory->Create<Material>();
|
||||||
|
memset(material, 0, sizeof(Material));
|
||||||
|
material->info.name = memory->Dup(assetName.c_str());
|
||||||
|
|
||||||
|
return material;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AssetLoaderMaterial::CanLoadFromRaw() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AssetLoaderMaterial::GetFileNameForAsset(const std::string& assetName)
|
||||||
|
{
|
||||||
|
std::string sanitizedFileName(assetName);
|
||||||
|
if (sanitizedFileName[0] == '*')
|
||||||
|
{
|
||||||
|
std::ranges::replace(sanitizedFileName, '*', '_');
|
||||||
|
const auto parenthesisPos = sanitizedFileName.find('(');
|
||||||
|
if (parenthesisPos != std::string::npos)
|
||||||
|
sanitizedFileName.erase(parenthesisPos);
|
||||||
|
sanitizedFileName = "generated/" + sanitizedFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::format("materials/{}.json", sanitizedFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AssetLoaderMaterial::LoadFromRaw(
|
||||||
|
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
||||||
|
{
|
||||||
|
const auto file = searchPath->Open(GetFileNameForAsset(assetName));
|
||||||
|
if (!file.IsOpen())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto* material = static_cast<Material*>(memory->Alloc(sizeof(Material)));
|
||||||
|
memset(material, 0, sizeof(Material));
|
||||||
|
material->info.name = memory->Dup(assetName.c_str());
|
||||||
|
|
||||||
|
std::vector<XAssetInfoGeneric*> dependencies;
|
||||||
|
if (LoadMaterialAsJson(*file.m_stream, *material, memory, manager, dependencies))
|
||||||
|
manager->AddAsset(ASSET_TYPE_MATERIAL, assetName, material, std::move(dependencies));
|
||||||
|
else
|
||||||
|
std::cerr << "Failed to load material \"" << assetName << "\"\n";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
19
src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMaterial.h
Normal file
19
src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMaterial.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "AssetLoading/BasicAssetLoader.h"
|
||||||
|
#include "AssetLoading/IAssetLoadingManager.h"
|
||||||
|
#include "Game/T6/T6.h"
|
||||||
|
#include "SearchPath/ISearchPath.h"
|
||||||
|
|
||||||
|
namespace T6
|
||||||
|
{
|
||||||
|
class AssetLoaderMaterial final : public BasicAssetLoader<ASSET_TYPE_MATERIAL, Material>
|
||||||
|
{
|
||||||
|
static std::string GetFileNameForAsset(const std::string& assetName);
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
} // namespace T6
|
373
src/ObjLoading/Game/T6/Material/JsonMaterialLoader.cpp
Normal file
373
src/ObjLoading/Game/T6/Material/JsonMaterialLoader.cpp
Normal file
@ -0,0 +1,373 @@
|
|||||||
|
#include "JsonMaterialLoader.h"
|
||||||
|
|
||||||
|
#include "Game/T6/CommonT6.h"
|
||||||
|
#include "Game/T6/Material/JsonMaterial.h"
|
||||||
|
|
||||||
|
#include <format>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
using namespace nlohmann;
|
||||||
|
|
||||||
|
namespace T6
|
||||||
|
{
|
||||||
|
class JsonLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
JsonLoader(std::istream& stream, MemoryManager& memory, IAssetLoadingManager& manager, std::vector<XAssetInfoGeneric*>& dependencies)
|
||||||
|
: m_stream(stream),
|
||||||
|
m_memory(memory),
|
||||||
|
m_manager(manager),
|
||||||
|
m_dependencies(dependencies)
|
||||||
|
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Load(Material& material) const
|
||||||
|
{
|
||||||
|
const auto jRoot = json::parse(m_stream);
|
||||||
|
std::string type;
|
||||||
|
unsigned version;
|
||||||
|
|
||||||
|
jRoot.at("_type").get_to(type);
|
||||||
|
jRoot.at("_version").get_to(version);
|
||||||
|
|
||||||
|
if (type != "material" || version != 1u)
|
||||||
|
{
|
||||||
|
std::cerr << "Tried to load material \"" << material.info.name << "\" but did not find expected type material of version 1\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto jMaterial = jRoot.get<JsonMaterial>();
|
||||||
|
return CreateMaterialFromJson(jMaterial, material);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void PrintError(const Material& material, const std::string& message)
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot load material \"" << material.info.name << "\": " << message << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CreateGameFlagsFromJson(const JsonMaterial& jMaterial, unsigned& gameFlags)
|
||||||
|
{
|
||||||
|
for (const auto gameFlag : jMaterial.gameFlags)
|
||||||
|
gameFlags |= gameFlag;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateTextureDefFromJson(const JsonTexture& jTexture, MaterialTextureDef& textureDef, const Material& material) const
|
||||||
|
{
|
||||||
|
if (jTexture.name)
|
||||||
|
{
|
||||||
|
if (jTexture.name->empty())
|
||||||
|
{
|
||||||
|
PrintError(material, "textureDef name cannot be empty");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
textureDef.nameStart = jTexture.name.value()[0];
|
||||||
|
textureDef.nameEnd = jTexture.name.value()[jTexture.name->size() - 1];
|
||||||
|
textureDef.nameHash = Common::R_HashString(jTexture.name.value().c_str(), 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!jTexture.nameStart || !jTexture.nameEnd || !jTexture.nameHash)
|
||||||
|
{
|
||||||
|
PrintError(material, "textureDefs without name must have nameStart, nameEnd and nameHash");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jTexture.nameStart->size() != 1 || jTexture.nameEnd->size() != 1)
|
||||||
|
{
|
||||||
|
PrintError(material, "nameStart and nameEnd must be a string of exactly one character");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
textureDef.nameStart = jTexture.nameStart.value()[0];
|
||||||
|
textureDef.nameEnd = jTexture.nameEnd.value()[0];
|
||||||
|
textureDef.nameHash = jTexture.nameHash.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
textureDef.samplerState.filter = jTexture.samplerState.filter;
|
||||||
|
textureDef.samplerState.mipMap = jTexture.samplerState.mipMap;
|
||||||
|
textureDef.samplerState.clampU = jTexture.samplerState.clampU;
|
||||||
|
textureDef.samplerState.clampV = jTexture.samplerState.clampV;
|
||||||
|
textureDef.samplerState.clampW = jTexture.samplerState.clampW;
|
||||||
|
|
||||||
|
textureDef.semantic = jTexture.semantic;
|
||||||
|
textureDef.isMatureContent = jTexture.isMatureContent;
|
||||||
|
|
||||||
|
auto* image = static_cast<XAssetInfo<GfxImage>*>(m_manager.LoadDependency(ASSET_TYPE_IMAGE, jTexture.image));
|
||||||
|
if (!image)
|
||||||
|
{
|
||||||
|
PrintError(material, std::format("Could not find textureDef image: {}", jTexture.image));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_dependencies.push_back(image);
|
||||||
|
textureDef.image = image->Asset();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CreateConstantDefFromJson(const JsonConstant& jConstant, MaterialConstantDef& constantDef, const Material& material)
|
||||||
|
{
|
||||||
|
if (jConstant.name)
|
||||||
|
{
|
||||||
|
const auto copyCount = std::min(jConstant.name->size() + 1, std::extent_v<decltype(MaterialConstantDef::name)>);
|
||||||
|
strncpy(constantDef.name, jConstant.name->c_str(), copyCount);
|
||||||
|
if (copyCount < std::extent_v<decltype(MaterialConstantDef::name)>)
|
||||||
|
memset(&constantDef.name[copyCount], 0, std::extent_v<decltype(MaterialConstantDef::name)> - copyCount);
|
||||||
|
constantDef.nameHash = Common::R_HashString(jConstant.name->c_str(), 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!jConstant.nameFragment || !jConstant.nameHash)
|
||||||
|
{
|
||||||
|
PrintError(material, "constantDefs without name must have nameFragment and nameHash");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto copyCount = std::min(jConstant.nameFragment->size() + 1, std::extent_v<decltype(MaterialConstantDef::name)>);
|
||||||
|
strncpy(constantDef.name, jConstant.nameFragment->c_str(), copyCount);
|
||||||
|
if (copyCount < std::extent_v<decltype(MaterialConstantDef::name)>)
|
||||||
|
memset(&constantDef.name[copyCount], 0, std::extent_v<decltype(MaterialConstantDef::name)> - copyCount);
|
||||||
|
constantDef.nameHash = jConstant.nameHash.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jConstant.literal.size() != 4)
|
||||||
|
{
|
||||||
|
PrintError(material, "constantDef literal must be array of size 4");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
constantDef.literal.x = jConstant.literal[0];
|
||||||
|
constantDef.literal.y = jConstant.literal[1];
|
||||||
|
constantDef.literal.z = jConstant.literal[2];
|
||||||
|
constantDef.literal.w = jConstant.literal[3];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CreateStateBitsTableEntryFromJson(const JsonStateBitsTableEntry& jStateBitsTableEntry, GfxStateBits& stateBitsTableEntry, const Material& material)
|
||||||
|
{
|
||||||
|
auto& structured = stateBitsTableEntry.loadBits.structured;
|
||||||
|
|
||||||
|
structured.srcBlendRgb = jStateBitsTableEntry.srcBlendRgb;
|
||||||
|
structured.dstBlendRgb = jStateBitsTableEntry.dstBlendRgb;
|
||||||
|
structured.blendOpRgb = jStateBitsTableEntry.blendOpRgb;
|
||||||
|
|
||||||
|
if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::DISABLED)
|
||||||
|
{
|
||||||
|
structured.alphaTestDisabled = 1;
|
||||||
|
structured.alphaTest = 0;
|
||||||
|
}
|
||||||
|
else if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::GT0)
|
||||||
|
{
|
||||||
|
structured.alphaTestDisabled = 0;
|
||||||
|
structured.alphaTest = GFXS_ALPHA_TEST_GT_0;
|
||||||
|
}
|
||||||
|
else if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::GE128)
|
||||||
|
{
|
||||||
|
structured.alphaTestDisabled = 0;
|
||||||
|
structured.alphaTest = GFXS_ALPHA_TEST_GE_128;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrintError(material, "Invalid value for alphaTest");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jStateBitsTableEntry.cullFace == JsonCullFace::NONE)
|
||||||
|
structured.cullFace = GFXS0_CULL_NONE;
|
||||||
|
else if (jStateBitsTableEntry.cullFace == JsonCullFace::BACK)
|
||||||
|
structured.cullFace = GFXS0_CULL_BACK;
|
||||||
|
else if (jStateBitsTableEntry.cullFace == JsonCullFace::FRONT)
|
||||||
|
structured.cullFace = GFXS0_CULL_FRONT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrintError(material, "Invalid value for cull face");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
structured.srcBlendAlpha = jStateBitsTableEntry.srcBlendAlpha;
|
||||||
|
structured.dstBlendAlpha = jStateBitsTableEntry.dstBlendAlpha;
|
||||||
|
structured.blendOpAlpha = jStateBitsTableEntry.blendOpAlpha;
|
||||||
|
structured.colorWriteRgb = jStateBitsTableEntry.colorWriteRgb;
|
||||||
|
structured.colorWriteAlpha = jStateBitsTableEntry.colorWriteAlpha;
|
||||||
|
structured.polymodeLine = jStateBitsTableEntry.polymodeLine;
|
||||||
|
structured.depthWrite = jStateBitsTableEntry.depthWrite;
|
||||||
|
|
||||||
|
if (jStateBitsTableEntry.depthTest == JsonDepthTest::DISABLED)
|
||||||
|
structured.depthTestDisabled = 1;
|
||||||
|
else if (jStateBitsTableEntry.depthTest == JsonDepthTest::ALWAYS)
|
||||||
|
structured.depthTest = GFXS_DEPTHTEST_ALWAYS;
|
||||||
|
else if (jStateBitsTableEntry.depthTest == JsonDepthTest::LESS)
|
||||||
|
structured.depthTest = GFXS_DEPTHTEST_LESS;
|
||||||
|
else if (jStateBitsTableEntry.depthTest == JsonDepthTest::EQUAL)
|
||||||
|
structured.depthTest = GFXS_DEPTHTEST_EQUAL;
|
||||||
|
else if (jStateBitsTableEntry.depthTest == JsonDepthTest::LESS_EQUAL)
|
||||||
|
structured.depthTest = GFXS_DEPTHTEST_LESSEQUAL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrintError(material, "Invalid value for depth test");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
structured.polygonOffset = jStateBitsTableEntry.polygonOffset;
|
||||||
|
|
||||||
|
if (jStateBitsTableEntry.stencilFront)
|
||||||
|
{
|
||||||
|
structured.stencilFrontEnabled = 1;
|
||||||
|
structured.stencilFrontPass = jStateBitsTableEntry.stencilFront->pass;
|
||||||
|
structured.stencilFrontFail = jStateBitsTableEntry.stencilFront->fail;
|
||||||
|
structured.stencilFrontZFail = jStateBitsTableEntry.stencilFront->zfail;
|
||||||
|
structured.stencilFrontFunc = jStateBitsTableEntry.stencilFront->func;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jStateBitsTableEntry.stencilBack)
|
||||||
|
{
|
||||||
|
structured.stencilBackEnabled = 1;
|
||||||
|
structured.stencilBackPass = jStateBitsTableEntry.stencilBack->pass;
|
||||||
|
structured.stencilBackFail = jStateBitsTableEntry.stencilBack->fail;
|
||||||
|
structured.stencilBackZFail = jStateBitsTableEntry.stencilBack->zfail;
|
||||||
|
structured.stencilBackFunc = jStateBitsTableEntry.stencilBack->func;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateMaterialFromJson(const JsonMaterial& jMaterial, Material& material) const
|
||||||
|
{
|
||||||
|
if (!CreateGameFlagsFromJson(jMaterial, material.info.gameFlags))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
material.info.sortKey = static_cast<unsigned char>(jMaterial.sortKey);
|
||||||
|
|
||||||
|
if (jMaterial.textureAtlas)
|
||||||
|
{
|
||||||
|
material.info.textureAtlasRowCount = jMaterial.textureAtlas->rows;
|
||||||
|
material.info.textureAtlasColumnCount = jMaterial.textureAtlas->columns;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
material.info.textureAtlasRowCount = 0;
|
||||||
|
material.info.textureAtlasColumnCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
material.info.surfaceTypeBits = jMaterial.surfaceTypeBits;
|
||||||
|
material.info.layeredSurfaceTypes = jMaterial.layeredSurfaceTypes;
|
||||||
|
material.info.hashIndex = static_cast<uint16_t>(jMaterial.hashIndex);
|
||||||
|
material.info.surfaceFlags = jMaterial.surfaceFlags;
|
||||||
|
material.info.contents = jMaterial.contents;
|
||||||
|
|
||||||
|
if (jMaterial.stateBitsEntry.size() != std::extent_v<decltype(Material::stateBitsEntry)>)
|
||||||
|
{
|
||||||
|
PrintError(material, std::format("StateBitsEntry size is not {}", jMaterial.stateBitsEntry.size()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (auto i = 0u; i < std::extent_v<decltype(Material::stateBitsEntry)>; i++)
|
||||||
|
material.stateBitsEntry[i] = jMaterial.stateBitsEntry[i];
|
||||||
|
|
||||||
|
material.stateFlags = static_cast<unsigned char>(jMaterial.stateFlags);
|
||||||
|
material.cameraRegion = jMaterial.cameraRegion;
|
||||||
|
material.probeMipBits = jMaterial.probeMipBits;
|
||||||
|
|
||||||
|
auto* techniqueSet = static_cast<XAssetInfo<MaterialTechniqueSet>*>(m_manager.LoadDependency(ASSET_TYPE_TECHNIQUE_SET, jMaterial.techniqueSet));
|
||||||
|
if (!techniqueSet)
|
||||||
|
{
|
||||||
|
PrintError(material, "Could not find technique set");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_dependencies.push_back(techniqueSet);
|
||||||
|
material.techniqueSet = techniqueSet->Asset();
|
||||||
|
|
||||||
|
if (!jMaterial.textures.empty())
|
||||||
|
{
|
||||||
|
material.textureCount = static_cast<unsigned char>(jMaterial.textures.size());
|
||||||
|
material.textureTable = static_cast<MaterialTextureDef*>(m_memory.Alloc(sizeof(MaterialTextureDef) * material.textureCount));
|
||||||
|
memset(material.textureTable, 0, sizeof(MaterialTextureDef) * material.textureCount);
|
||||||
|
|
||||||
|
for (auto i = 0u; i < material.textureCount; i++)
|
||||||
|
{
|
||||||
|
if (!CreateTextureDefFromJson(jMaterial.textures[i], material.textureTable[i], material))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
material.textureCount = 0;
|
||||||
|
material.textureTable = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!jMaterial.constants.empty())
|
||||||
|
{
|
||||||
|
material.constantCount = static_cast<unsigned char>(jMaterial.constants.size());
|
||||||
|
material.constantTable = static_cast<MaterialConstantDef*>(m_memory.Alloc(sizeof(MaterialConstantDef) * material.constantCount));
|
||||||
|
memset(material.constantTable, 0, sizeof(MaterialConstantDef) * material.constantCount);
|
||||||
|
|
||||||
|
for (auto i = 0u; i < material.constantCount; i++)
|
||||||
|
{
|
||||||
|
if (!CreateConstantDefFromJson(jMaterial.constants[i], material.constantTable[i], material))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
material.constantCount = 0;
|
||||||
|
material.constantTable = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!jMaterial.stateBits.empty())
|
||||||
|
{
|
||||||
|
material.stateBitsCount = static_cast<unsigned char>(jMaterial.stateBits.size());
|
||||||
|
material.stateBitsTable = static_cast<GfxStateBitsTable*>(m_memory.Alloc(sizeof(GfxStateBitsTable) * material.stateBitsCount));
|
||||||
|
memset(material.stateBitsTable, 0, sizeof(GfxStateBitsTable) * material.stateBitsCount);
|
||||||
|
|
||||||
|
for (auto i = 0u; i < material.stateBitsCount; i++)
|
||||||
|
{
|
||||||
|
if (!CreateStateBitsTableEntryFromJson(jMaterial.stateBits[i], material.stateBitsTable[i], material))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
material.stateBitsCount = 0;
|
||||||
|
material.stateBitsTable = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jMaterial.thermalMaterial)
|
||||||
|
{
|
||||||
|
auto* thermalMaterial = static_cast<XAssetInfo<Material>*>(m_manager.LoadDependency(ASSET_TYPE_MATERIAL, jMaterial.thermalMaterial.value()));
|
||||||
|
if (!thermalMaterial)
|
||||||
|
{
|
||||||
|
PrintError(material, "Could not find thermal material");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_dependencies.push_back(thermalMaterial);
|
||||||
|
material.thermalMaterial = thermalMaterial->Asset();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
material.thermalMaterial = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream& m_stream;
|
||||||
|
MemoryManager& m_memory;
|
||||||
|
IAssetLoadingManager& m_manager;
|
||||||
|
std::vector<XAssetInfoGeneric*>& m_dependencies;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool LoadMaterialAsJson(
|
||||||
|
std::istream& stream, Material& material, MemoryManager* memory, IAssetLoadingManager* manager, std::vector<XAssetInfoGeneric*>& dependencies)
|
||||||
|
{
|
||||||
|
const JsonLoader loader(stream, *memory, *manager, dependencies);
|
||||||
|
|
||||||
|
return loader.Load(material);
|
||||||
|
}
|
||||||
|
} // namespace T6
|
13
src/ObjLoading/Game/T6/Material/JsonMaterialLoader.h
Normal file
13
src/ObjLoading/Game/T6/Material/JsonMaterialLoader.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AssetLoading/IAssetLoadingManager.h"
|
||||||
|
#include "Game/T6/T6.h"
|
||||||
|
#include "Utils/MemoryManager.h"
|
||||||
|
|
||||||
|
#include <istream>
|
||||||
|
|
||||||
|
namespace T6
|
||||||
|
{
|
||||||
|
bool LoadMaterialAsJson(
|
||||||
|
std::istream& stream, Material& material, MemoryManager* memory, IAssetLoadingManager* manager, std::vector<XAssetInfoGeneric*>& dependencies);
|
||||||
|
} // namespace T6
|
@ -3,6 +3,7 @@
|
|||||||
#include "AssetLoaders/AssetLoaderFontIcon.h"
|
#include "AssetLoaders/AssetLoaderFontIcon.h"
|
||||||
#include "AssetLoaders/AssetLoaderGfxImage.h"
|
#include "AssetLoaders/AssetLoaderGfxImage.h"
|
||||||
#include "AssetLoaders/AssetLoaderLocalizeEntry.h"
|
#include "AssetLoaders/AssetLoaderLocalizeEntry.h"
|
||||||
|
#include "AssetLoaders/AssetLoaderMaterial.h"
|
||||||
#include "AssetLoaders/AssetLoaderPhysConstraints.h"
|
#include "AssetLoaders/AssetLoaderPhysConstraints.h"
|
||||||
#include "AssetLoaders/AssetLoaderPhysPreset.h"
|
#include "AssetLoaders/AssetLoaderPhysPreset.h"
|
||||||
#include "AssetLoaders/AssetLoaderQdb.h"
|
#include "AssetLoaders/AssetLoaderQdb.h"
|
||||||
@ -49,7 +50,8 @@ namespace T6
|
|||||||
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_DESTRUCTIBLEDEF, DestructibleDef))
|
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_DESTRUCTIBLEDEF, DestructibleDef))
|
||||||
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XANIMPARTS, XAnimParts))
|
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XANIMPARTS, XAnimParts))
|
||||||
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XMODEL, XModel))
|
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XMODEL, XModel))
|
||||||
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MATERIAL, Material))
|
// REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MATERIAL, Material))
|
||||||
|
REGISTER_ASSET_LOADER(AssetLoaderMaterial)
|
||||||
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_TECHNIQUE_SET, MaterialTechniqueSet))
|
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_TECHNIQUE_SET, MaterialTechniqueSet))
|
||||||
REGISTER_ASSET_LOADER(AssetLoaderGfxImage)
|
REGISTER_ASSET_LOADER(AssetLoaderGfxImage)
|
||||||
REGISTER_ASSET_LOADER(AssetLoaderSoundBank)
|
REGISTER_ASSET_LOADER(AssetLoaderSoundBank)
|
||||||
|
File diff suppressed because it is too large
Load Diff
245
src/ObjWriting/Game/T6/Material/JsonMaterialWriter.cpp
Normal file
245
src/ObjWriting/Game/T6/Material/JsonMaterialWriter.cpp
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
#include "JsonMaterialWriter.h"
|
||||||
|
|
||||||
|
#include "Game/T6/CommonT6.h"
|
||||||
|
#include "Game/T6/Material/JsonMaterial.h"
|
||||||
|
#include "MaterialConstantZoneState.h"
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
using namespace nlohmann;
|
||||||
|
|
||||||
|
namespace T6
|
||||||
|
{
|
||||||
|
class JsonDumper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
JsonDumper(AssetDumpingContext& context, std::ostream& stream)
|
||||||
|
: m_stream(stream),
|
||||||
|
m_material_constants(*context.GetZoneAssetDumperState<MaterialConstantZoneState>())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dump(const Material* material) const
|
||||||
|
{
|
||||||
|
JsonMaterial jsonMaterial;
|
||||||
|
CreateJsonMaterial(jsonMaterial, *material);
|
||||||
|
json jRoot = jsonMaterial;
|
||||||
|
|
||||||
|
jRoot["_type"] = "material";
|
||||||
|
jRoot["_version"] = 1;
|
||||||
|
|
||||||
|
m_stream << std::setw(4) << jRoot << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const char* AssetName(const char* input)
|
||||||
|
{
|
||||||
|
if (input && input[0] == ',')
|
||||||
|
return &input[1];
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CreateJsonGameFlags(JsonMaterial& jMaterial, const unsigned gameFlags)
|
||||||
|
{
|
||||||
|
jMaterial.gameFlags.clear();
|
||||||
|
for (auto i = 0u; i < sizeof(gameFlags) * 8u; i++)
|
||||||
|
{
|
||||||
|
const auto flag = static_cast<MaterialGameFlags>(1 << i);
|
||||||
|
|
||||||
|
if (gameFlags & flag)
|
||||||
|
jMaterial.gameFlags.emplace_back(flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CreateJsonSamplerState(JsonSamplerState& jSamplerState, const MaterialTextureDefSamplerState& samplerState)
|
||||||
|
{
|
||||||
|
jSamplerState.filter = static_cast<TextureFilter>(samplerState.filter);
|
||||||
|
jSamplerState.mipMap = static_cast<SamplerStateBitsMipMap_e>(samplerState.mipMap);
|
||||||
|
jSamplerState.clampU = samplerState.clampU;
|
||||||
|
jSamplerState.clampV = samplerState.clampV;
|
||||||
|
jSamplerState.clampW = samplerState.clampW;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateJsonTexture(JsonTexture& jTextureDef, const MaterialTextureDef& textureDef) const
|
||||||
|
{
|
||||||
|
std::string textureDefName;
|
||||||
|
if (m_material_constants.GetTextureDefName(textureDef.nameHash, textureDefName))
|
||||||
|
{
|
||||||
|
jTextureDef.name = textureDefName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jTextureDef.nameHash = textureDef.nameHash;
|
||||||
|
jTextureDef.nameStart = std::string(1u, textureDef.nameStart);
|
||||||
|
jTextureDef.nameEnd = std::string(1u, textureDef.nameEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
jTextureDef.semantic = static_cast<TextureSemantic>(textureDef.semantic);
|
||||||
|
jTextureDef.isMatureContent = textureDef.isMatureContent;
|
||||||
|
|
||||||
|
CreateJsonSamplerState(jTextureDef.samplerState, textureDef.samplerState);
|
||||||
|
|
||||||
|
if (textureDef.image && textureDef.image->name)
|
||||||
|
jTextureDef.image = AssetName(textureDef.image->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateJsonConstant(JsonConstant& jConstantDef, const MaterialConstantDef& constantDef) const
|
||||||
|
{
|
||||||
|
const auto fragmentLength = strnlen(constantDef.name, std::extent_v<decltype(MaterialConstantDef::name)>);
|
||||||
|
const std::string nameFragment(constantDef.name, fragmentLength);
|
||||||
|
std::string knownConstantName;
|
||||||
|
|
||||||
|
if (fragmentLength < std::extent_v<decltype(MaterialConstantDef::name)> || Common::R_HashString(nameFragment.c_str(), 0) == constantDef.nameHash)
|
||||||
|
{
|
||||||
|
jConstantDef.name = nameFragment;
|
||||||
|
}
|
||||||
|
else if (m_material_constants.GetConstantName(constantDef.nameHash, knownConstantName))
|
||||||
|
{
|
||||||
|
jConstantDef.name = knownConstantName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jConstantDef.nameHash = constantDef.nameHash;
|
||||||
|
jConstantDef.nameFragment = nameFragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
jConstantDef.literal = std::vector({
|
||||||
|
constantDef.literal.x,
|
||||||
|
constantDef.literal.y,
|
||||||
|
constantDef.literal.z,
|
||||||
|
constantDef.literal.w,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CreateJsonStencil(JsonStencil& jStencil, const unsigned pass, const unsigned fail, const unsigned zFail, const unsigned func)
|
||||||
|
{
|
||||||
|
jStencil.pass = static_cast<GfxStencilOp>(pass);
|
||||||
|
jStencil.fail = static_cast<GfxStencilOp>(fail);
|
||||||
|
jStencil.zfail = static_cast<GfxStencilOp>(zFail);
|
||||||
|
jStencil.func = static_cast<GfxStencilFunc>(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CreateJsonStateBitsTableEntry(JsonStateBitsTableEntry& jStateBitsTableEntry, const GfxStateBitsTable& stateBitsTableEntry)
|
||||||
|
{
|
||||||
|
const auto& structured = stateBitsTableEntry.loadBits.structured;
|
||||||
|
|
||||||
|
jStateBitsTableEntry.srcBlendRgb = static_cast<GfxBlend>(structured.srcBlendRgb);
|
||||||
|
jStateBitsTableEntry.dstBlendRgb = static_cast<GfxBlend>(structured.dstBlendRgb);
|
||||||
|
jStateBitsTableEntry.blendOpRgb = static_cast<GfxBlendOp>(structured.blendOpRgb);
|
||||||
|
|
||||||
|
assert(structured.alphaTestDisabled || structured.alphaTest == GFXS_ALPHA_TEST_GT_0 || structured.alphaTest == GFXS_ALPHA_TEST_GE_128);
|
||||||
|
if (structured.alphaTestDisabled)
|
||||||
|
jStateBitsTableEntry.alphaTest = JsonAlphaTest::DISABLED;
|
||||||
|
else if (structured.alphaTest == GFXS_ALPHA_TEST_GT_0)
|
||||||
|
jStateBitsTableEntry.alphaTest = JsonAlphaTest::GT0;
|
||||||
|
else if (structured.alphaTest == GFXS_ALPHA_TEST_GE_128)
|
||||||
|
jStateBitsTableEntry.alphaTest = JsonAlphaTest::GE128;
|
||||||
|
else
|
||||||
|
jStateBitsTableEntry.alphaTest = JsonAlphaTest::INVALID;
|
||||||
|
|
||||||
|
assert(structured.cullFace == GFXS0_CULL_NONE || structured.cullFace == GFXS0_CULL_BACK || structured.cullFace == GFXS0_CULL_FRONT);
|
||||||
|
if (structured.cullFace == GFXS0_CULL_NONE)
|
||||||
|
jStateBitsTableEntry.cullFace = JsonCullFace::NONE;
|
||||||
|
else if (structured.cullFace == GFXS0_CULL_BACK)
|
||||||
|
jStateBitsTableEntry.cullFace = JsonCullFace::BACK;
|
||||||
|
else if (structured.cullFace == GFXS0_CULL_FRONT)
|
||||||
|
jStateBitsTableEntry.cullFace = JsonCullFace::FRONT;
|
||||||
|
else
|
||||||
|
jStateBitsTableEntry.cullFace = JsonCullFace::INVALID;
|
||||||
|
|
||||||
|
jStateBitsTableEntry.srcBlendAlpha = static_cast<GfxBlend>(structured.srcBlendAlpha);
|
||||||
|
jStateBitsTableEntry.dstBlendAlpha = static_cast<GfxBlend>(structured.dstBlendAlpha);
|
||||||
|
jStateBitsTableEntry.blendOpAlpha = static_cast<GfxBlendOp>(structured.blendOpAlpha);
|
||||||
|
jStateBitsTableEntry.colorWriteRgb = structured.colorWriteRgb;
|
||||||
|
jStateBitsTableEntry.colorWriteAlpha = structured.colorWriteAlpha;
|
||||||
|
jStateBitsTableEntry.polymodeLine = structured.polymodeLine;
|
||||||
|
jStateBitsTableEntry.depthWrite = structured.depthWrite;
|
||||||
|
|
||||||
|
assert(structured.depthTestDisabled || structured.depthTest == GFXS_DEPTHTEST_ALWAYS || structured.depthTest == GFXS_DEPTHTEST_LESS
|
||||||
|
|| structured.depthTest == GFXS_DEPTHTEST_EQUAL || structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL);
|
||||||
|
if (structured.depthTestDisabled)
|
||||||
|
jStateBitsTableEntry.depthTest = JsonDepthTest::DISABLED;
|
||||||
|
else if (structured.depthTest == GFXS_DEPTHTEST_ALWAYS)
|
||||||
|
jStateBitsTableEntry.depthTest = JsonDepthTest::ALWAYS;
|
||||||
|
else if (structured.depthTest == GFXS_DEPTHTEST_LESS)
|
||||||
|
jStateBitsTableEntry.depthTest = JsonDepthTest::LESS;
|
||||||
|
else if (structured.depthTest == GFXS_DEPTHTEST_EQUAL)
|
||||||
|
jStateBitsTableEntry.depthTest = JsonDepthTest::EQUAL;
|
||||||
|
else if (structured.depthTest == GFXS_DEPTHTEST_LESSEQUAL)
|
||||||
|
jStateBitsTableEntry.depthTest = JsonDepthTest::LESS_EQUAL;
|
||||||
|
else
|
||||||
|
jStateBitsTableEntry.depthTest = JsonDepthTest::INVALID;
|
||||||
|
|
||||||
|
jStateBitsTableEntry.polygonOffset = static_cast<GfxPolygonOffset_e>(structured.polygonOffset);
|
||||||
|
|
||||||
|
if (structured.stencilFrontEnabled)
|
||||||
|
{
|
||||||
|
JsonStencil jStencilFront;
|
||||||
|
CreateJsonStencil(
|
||||||
|
jStencilFront, structured.stencilFrontPass, structured.stencilFrontFail, structured.stencilFrontZFail, structured.stencilFrontFunc);
|
||||||
|
jStateBitsTableEntry.stencilFront = jStencilFront;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (structured.stencilBackEnabled)
|
||||||
|
{
|
||||||
|
JsonStencil jStencilBack;
|
||||||
|
CreateJsonStencil(
|
||||||
|
jStencilBack, structured.stencilBackPass, structured.stencilBackFail, structured.stencilBackZFail, structured.stencilBackFunc);
|
||||||
|
jStateBitsTableEntry.stencilBack = jStencilBack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateJsonMaterial(JsonMaterial& jMaterial, const Material& material) const
|
||||||
|
{
|
||||||
|
CreateJsonGameFlags(jMaterial, material.info.gameFlags);
|
||||||
|
jMaterial.sortKey = material.info.sortKey;
|
||||||
|
|
||||||
|
jMaterial.textureAtlas = JsonTextureAtlas();
|
||||||
|
jMaterial.textureAtlas->rows = material.info.textureAtlasRowCount;
|
||||||
|
jMaterial.textureAtlas->columns = material.info.textureAtlasColumnCount;
|
||||||
|
|
||||||
|
jMaterial.surfaceTypeBits = material.info.surfaceTypeBits;
|
||||||
|
jMaterial.layeredSurfaceTypes = material.info.layeredSurfaceTypes;
|
||||||
|
jMaterial.hashIndex = material.info.hashIndex;
|
||||||
|
jMaterial.surfaceFlags = material.info.surfaceFlags;
|
||||||
|
jMaterial.contents = material.info.contents;
|
||||||
|
|
||||||
|
jMaterial.stateBitsEntry.resize(std::extent_v<decltype(Material::stateBitsEntry)>);
|
||||||
|
for (auto i = 0u; i < std::extent_v<decltype(Material::stateBitsEntry)>; i++)
|
||||||
|
jMaterial.stateBitsEntry[i] = material.stateBitsEntry[i];
|
||||||
|
|
||||||
|
jMaterial.stateFlags = material.stateFlags;
|
||||||
|
jMaterial.cameraRegion = static_cast<GfxCameraRegionType>(material.cameraRegion);
|
||||||
|
jMaterial.probeMipBits = material.probeMipBits;
|
||||||
|
|
||||||
|
if (material.techniqueSet && material.techniqueSet->name)
|
||||||
|
jMaterial.techniqueSet = AssetName(material.techniqueSet->name);
|
||||||
|
|
||||||
|
jMaterial.textures.resize(material.textureCount);
|
||||||
|
for (auto i = 0u; i < material.textureCount; i++)
|
||||||
|
CreateJsonTexture(jMaterial.textures[i], material.textureTable[i]);
|
||||||
|
|
||||||
|
jMaterial.constants.resize(material.constantCount);
|
||||||
|
for (auto i = 0u; i < material.constantCount; i++)
|
||||||
|
CreateJsonConstant(jMaterial.constants[i], material.constantTable[i]);
|
||||||
|
|
||||||
|
jMaterial.stateBits.resize(material.stateBitsCount);
|
||||||
|
for (auto i = 0u; i < material.stateBitsCount; i++)
|
||||||
|
CreateJsonStateBitsTableEntry(jMaterial.stateBits[i], material.stateBitsTable[i]);
|
||||||
|
|
||||||
|
if (material.thermalMaterial && material.thermalMaterial->info.name)
|
||||||
|
jMaterial.thermalMaterial = AssetName(material.thermalMaterial->info.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& m_stream;
|
||||||
|
const MaterialConstantZoneState& m_material_constants;
|
||||||
|
};
|
||||||
|
|
||||||
|
void DumpMaterialAsJson(std::ostream& stream, const Material* material, AssetDumpingContext& context)
|
||||||
|
{
|
||||||
|
const JsonDumper dumper(context, stream);
|
||||||
|
dumper.Dump(material);
|
||||||
|
}
|
||||||
|
} // namespace T6
|
11
src/ObjWriting/Game/T6/Material/JsonMaterialWriter.h
Normal file
11
src/ObjWriting/Game/T6/Material/JsonMaterialWriter.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Dumping/AssetDumpingContext.h"
|
||||||
|
#include "Game/T6/T6.h"
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
namespace T6
|
||||||
|
{
|
||||||
|
void DumpMaterialAsJson(std::ostream& stream, const Material* material, AssetDumpingContext& context);
|
||||||
|
} // namespace T6
|
636
src/ObjWriting/Game/T6/Material/MaterialConstantZoneState.cpp
Normal file
636
src/ObjWriting/Game/T6/Material/MaterialConstantZoneState.cpp
Normal file
@ -0,0 +1,636 @@
|
|||||||
|
#include "MaterialConstantZoneState.h"
|
||||||
|
|
||||||
|
#include "Game/T6/CommonT6.h"
|
||||||
|
#include "Game/T6/GameAssetPoolT6.h"
|
||||||
|
#include "Game/T6/GameT6.h"
|
||||||
|
#include "ObjWriting.h"
|
||||||
|
#include "Shader/D3D11ShaderAnalyser.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
namespace T6
|
||||||
|
{
|
||||||
|
static constexpr const char* SAMPLER_STR = "Sampler";
|
||||||
|
static constexpr const char* GLOBALS_CBUFFER_NAME = "$Globals";
|
||||||
|
static constexpr const char* PER_OBJECT_CONSTS_CBUFFER_NAME = "PerObjectConsts";
|
||||||
|
|
||||||
|
const char* KNOWN_CONSTANT_NAMES[]{
|
||||||
|
"AngularVelocityScale",
|
||||||
|
"AnimSpeed",
|
||||||
|
"Background",
|
||||||
|
"BackgroundColor",
|
||||||
|
"BackgroundNoise",
|
||||||
|
"BakedLightingIntensity",
|
||||||
|
"BloodBrightness",
|
||||||
|
"BloodIntensity",
|
||||||
|
"BlurAmount",
|
||||||
|
"CapWidth",
|
||||||
|
"Char_Size",
|
||||||
|
"Char_Width",
|
||||||
|
"Coarseness",
|
||||||
|
"Color",
|
||||||
|
"ColorAmount",
|
||||||
|
"ColorBias",
|
||||||
|
"Color_Map_Noise",
|
||||||
|
"Color_Map_Scale",
|
||||||
|
"Color_Map_Size_Scale",
|
||||||
|
"DDXScale",
|
||||||
|
"DDYScale",
|
||||||
|
"DarkenAmount",
|
||||||
|
"DarkenPower",
|
||||||
|
"Detail_Amount",
|
||||||
|
"Detail_Normal_Tile",
|
||||||
|
"Diffuse_Normal_Height_Facing",
|
||||||
|
"Dimensions",
|
||||||
|
"DispersionAmount",
|
||||||
|
"Dolly",
|
||||||
|
"EdgeColor",
|
||||||
|
"EdgeHarshness",
|
||||||
|
"EdgeIntensity",
|
||||||
|
"EdgeMaxDist",
|
||||||
|
"EdgeMinDist",
|
||||||
|
"EdgeSize",
|
||||||
|
"Edge_Color_Multiplier",
|
||||||
|
"Emissive_Amount",
|
||||||
|
"EnemiesColor",
|
||||||
|
"Exposure",
|
||||||
|
"FPS",
|
||||||
|
"Fade_Distance",
|
||||||
|
"Fill_Direction",
|
||||||
|
"Fill_Direction2",
|
||||||
|
"FirstFrame",
|
||||||
|
"FlareIntensity",
|
||||||
|
"FlareScale",
|
||||||
|
"FlattenEdges",
|
||||||
|
"Flicker_Max",
|
||||||
|
"Flicker_Min",
|
||||||
|
"Flicker_Seed",
|
||||||
|
"Flicker_Speed",
|
||||||
|
"Font_Color",
|
||||||
|
"Gamma",
|
||||||
|
"GlossAmount",
|
||||||
|
"Gloss_Amount",
|
||||||
|
"Glow_Alt_Color",
|
||||||
|
"Glow_Color",
|
||||||
|
"Glow_Falloff",
|
||||||
|
"GradientColor",
|
||||||
|
"GradientMax",
|
||||||
|
"GradientMin",
|
||||||
|
"Grain_Amount",
|
||||||
|
"Grain_Color",
|
||||||
|
"Grid",
|
||||||
|
"Hardness",
|
||||||
|
"Heart_Rate_Offset",
|
||||||
|
"Heart_Rate_Scale",
|
||||||
|
"Highlight_1_Brightness",
|
||||||
|
"Highlight_1_Sharpness",
|
||||||
|
"Highlight_2_Brightness",
|
||||||
|
"Highlight_2_Sharpness",
|
||||||
|
"Highlight_2_Size",
|
||||||
|
"Hightlight_1_Size",
|
||||||
|
"Holo_Scale",
|
||||||
|
"LastFrame",
|
||||||
|
"Layer1Alpha",
|
||||||
|
"Layer1Depth",
|
||||||
|
"Layer1Offset",
|
||||||
|
"Layer1OffsetBobbleDelay",
|
||||||
|
"Layer1OffsetBobbleSpeedAndSize",
|
||||||
|
"Layer1Origin",
|
||||||
|
"Layer1Rotation",
|
||||||
|
"Layer1Scale",
|
||||||
|
"Layer1ScaleBobbleDelay",
|
||||||
|
"Layer1ScaleBobbleSpeedAndSize",
|
||||||
|
"Layer1Scroll",
|
||||||
|
"Layer2Alpha",
|
||||||
|
"Layer2Depth",
|
||||||
|
"Layer2Offset",
|
||||||
|
"Layer2OffsetBobbleDelay",
|
||||||
|
"Layer2OffsetBobbleSpeedAndSize",
|
||||||
|
"Layer2Origin",
|
||||||
|
"Layer2Rotation",
|
||||||
|
"Layer2Scale",
|
||||||
|
"Layer2ScaleBobbleDelay",
|
||||||
|
"Layer2ScaleBobbleSpeedAndSize",
|
||||||
|
"Layer2Scroll",
|
||||||
|
"Layer3Alpha",
|
||||||
|
"Layer3Depth",
|
||||||
|
"Layer3Offset",
|
||||||
|
"Layer3Origin",
|
||||||
|
"Layer3Rotation",
|
||||||
|
"Layer3Scale",
|
||||||
|
"Layer3Scroll",
|
||||||
|
"Layer4Alpha",
|
||||||
|
"Layer4Depth",
|
||||||
|
"Layer4Offset",
|
||||||
|
"Layer4Origin",
|
||||||
|
"Layer4Rotation",
|
||||||
|
"Layer4Scale",
|
||||||
|
"Layer4Scroll",
|
||||||
|
"LineColor",
|
||||||
|
"LineNoise",
|
||||||
|
"LineWidth",
|
||||||
|
"MaxDepth",
|
||||||
|
"MaxFlickerColor",
|
||||||
|
"MaxPulseDepth",
|
||||||
|
"MaxResolution",
|
||||||
|
"Max_Color",
|
||||||
|
"Maximum_Distance",
|
||||||
|
"Midlayer_Depth",
|
||||||
|
"MinDepth",
|
||||||
|
"MinFlickerColor",
|
||||||
|
"MinResolution",
|
||||||
|
"MinStatic",
|
||||||
|
"MinVelocityFraction",
|
||||||
|
"Min_Color",
|
||||||
|
"Min_Player_Intensity",
|
||||||
|
"MomentumColor",
|
||||||
|
"NegativeColor",
|
||||||
|
"NoisePower",
|
||||||
|
"Noise_Scale",
|
||||||
|
"NormalHeightMultiplier",
|
||||||
|
"Normal_Detail_Height",
|
||||||
|
"Normal_Detail_Scale",
|
||||||
|
"Normal_Map_Size_Scale",
|
||||||
|
"Normal_Variance_Scale",
|
||||||
|
"NumFrames",
|
||||||
|
"Outline_Lookup_Scale",
|
||||||
|
"OverallAmount",
|
||||||
|
"OverallBrightness",
|
||||||
|
"Overlay_Color",
|
||||||
|
"P1",
|
||||||
|
"P2",
|
||||||
|
"Padding",
|
||||||
|
"Player_Color_Multiplier",
|
||||||
|
"Player_Lookup_Scale",
|
||||||
|
"PositiveColor",
|
||||||
|
"Power",
|
||||||
|
"PulseColor",
|
||||||
|
"PulseInterval",
|
||||||
|
"PulseTime",
|
||||||
|
"Pulse_Color_Multiplier",
|
||||||
|
"Pulse_Lookup_Scale",
|
||||||
|
"Radius",
|
||||||
|
"ReflectionAmount",
|
||||||
|
"Reflection_Amount",
|
||||||
|
"Reflection_Blur",
|
||||||
|
"Reticle_Alt_Color",
|
||||||
|
"Reticle_Color",
|
||||||
|
"Row_Chars_",
|
||||||
|
"Scale",
|
||||||
|
"ScanlineColor",
|
||||||
|
"ScanlineIntensity",
|
||||||
|
"ScanlineOffset",
|
||||||
|
"ScanlinePower",
|
||||||
|
"ScanlineSpeed",
|
||||||
|
"ScatterAmount",
|
||||||
|
"ScatterSize",
|
||||||
|
"SceneNoise",
|
||||||
|
"SparkleBrightness",
|
||||||
|
"SparkleDensity",
|
||||||
|
"SparklePower",
|
||||||
|
"SparkleProbeAmount",
|
||||||
|
"SparkleScale",
|
||||||
|
"SparkleSpecAmount",
|
||||||
|
"SparkleWash",
|
||||||
|
"SpecGloss_Map_Size_Scale",
|
||||||
|
"SpecularAmount",
|
||||||
|
"SpecularColor",
|
||||||
|
"Specular_Amount",
|
||||||
|
"Specular_Decay_Threshold",
|
||||||
|
"Speed",
|
||||||
|
"StaticAmount",
|
||||||
|
"StaticLookupSpeed",
|
||||||
|
"StaticLookupX",
|
||||||
|
"StaticScale",
|
||||||
|
"Static_Size",
|
||||||
|
"Static_amount",
|
||||||
|
"TearLookupMaxX",
|
||||||
|
"TearLookupMinX",
|
||||||
|
"TearLookupSpeed",
|
||||||
|
"TearMultiplier",
|
||||||
|
"TearPower",
|
||||||
|
"Thickness",
|
||||||
|
"TickMarkColorAndHarshness",
|
||||||
|
"Tint",
|
||||||
|
"VelocityScale",
|
||||||
|
"VignetteMultiplier",
|
||||||
|
"VignettePower",
|
||||||
|
"WarpAmount",
|
||||||
|
"WarpHeight",
|
||||||
|
"WarpScale",
|
||||||
|
"WarpSpeed",
|
||||||
|
"WashOut",
|
||||||
|
"WashoutMultiply",
|
||||||
|
"WaterDirection",
|
||||||
|
"WaterHeight",
|
||||||
|
"WaterRefraction",
|
||||||
|
"WaterScale1",
|
||||||
|
"WaterScale2",
|
||||||
|
"WaterSpeed1",
|
||||||
|
"WaterSpeed2",
|
||||||
|
"Zoom",
|
||||||
|
"alphaDissolveParms",
|
||||||
|
"alphaRevealParms",
|
||||||
|
"alphaRevealParms1",
|
||||||
|
"alphaRevealParms2",
|
||||||
|
"alphaRevealParms3",
|
||||||
|
"alphaRevealParms4",
|
||||||
|
"clipSpaceLookupOffset",
|
||||||
|
"clipSpaceLookupScale",
|
||||||
|
"cloudsFeather",
|
||||||
|
"cloudsHeights",
|
||||||
|
"cloudsUVMad1",
|
||||||
|
"cloudsUVMad2",
|
||||||
|
"cloudsUVMul1",
|
||||||
|
"cloudsUVMul2",
|
||||||
|
"codeMeshArg",
|
||||||
|
"colorDetailScale",
|
||||||
|
"colorObjMax",
|
||||||
|
"colorObjMaxBaseBlend",
|
||||||
|
"colorObjMin",
|
||||||
|
"colorObjMinBaseBlend",
|
||||||
|
"colorTint",
|
||||||
|
"debugBumpmap",
|
||||||
|
"debugPerformance",
|
||||||
|
"detailScale",
|
||||||
|
"detailScale1",
|
||||||
|
"detailScale2",
|
||||||
|
"detailScale3",
|
||||||
|
"detailScale4",
|
||||||
|
"distortionScale",
|
||||||
|
"dofEquationScene",
|
||||||
|
"dofEquationViewModelAndFarBlur",
|
||||||
|
"dofLerpBias",
|
||||||
|
"dofLerpDownBias",
|
||||||
|
"dofLerpDownScale",
|
||||||
|
"dofLerpScale",
|
||||||
|
"dofLerpUpBias",
|
||||||
|
"dofLerpUpScale",
|
||||||
|
"dofRowDelta",
|
||||||
|
"eyeOffsetParms",
|
||||||
|
"falloffBeginColor",
|
||||||
|
"falloffEndColor",
|
||||||
|
"falloffParms",
|
||||||
|
"featherParms",
|
||||||
|
"flagParams",
|
||||||
|
"framebufferRead",
|
||||||
|
"gameTime",
|
||||||
|
"hdrAmount",
|
||||||
|
"inverseTransposeWorldMatrix",
|
||||||
|
"inverseTransposeWorldViewMatrix",
|
||||||
|
"inverseWorldMatrix",
|
||||||
|
"inverseWorldViewMatrix",
|
||||||
|
"motionblurDirectionAndMagnitude",
|
||||||
|
"occlusionAmount",
|
||||||
|
"occlusionAmount1",
|
||||||
|
"occlusionAmount2",
|
||||||
|
"occlusionAmount3",
|
||||||
|
"occlusionAmount4",
|
||||||
|
"particleCloudColor",
|
||||||
|
"particleCloudMatrix",
|
||||||
|
"particleCloudVelWorld",
|
||||||
|
"resizeParams1",
|
||||||
|
"resizeParams2",
|
||||||
|
"scaleRGB",
|
||||||
|
"scriptVector0",
|
||||||
|
"scriptVector1",
|
||||||
|
"scriptVector2",
|
||||||
|
"scriptVector3",
|
||||||
|
"scriptVector4",
|
||||||
|
"scriptVector5",
|
||||||
|
"scriptVector6",
|
||||||
|
"scriptVector7",
|
||||||
|
"skyBoxCloudWeights",
|
||||||
|
"skyBoxRotationSize",
|
||||||
|
"skyColorParms",
|
||||||
|
"spotLightWeight",
|
||||||
|
"treeCanopyLightingParms",
|
||||||
|
"treeCanopyScatterColor",
|
||||||
|
"treeCanopySwayParms",
|
||||||
|
"ui3dUVSetup0",
|
||||||
|
"ui3dUVSetup1",
|
||||||
|
"ui3dUVSetup2",
|
||||||
|
"ui3dUVSetup3",
|
||||||
|
"ui3dUVSetup4",
|
||||||
|
"ui3dUVSetup5",
|
||||||
|
"uvAnimParms",
|
||||||
|
"uvScroll",
|
||||||
|
"viewMatrix",
|
||||||
|
"weaponParam0",
|
||||||
|
"weaponParam1",
|
||||||
|
"weaponParam2",
|
||||||
|
"weaponParam3",
|
||||||
|
"weaponParam4",
|
||||||
|
"weaponParam5",
|
||||||
|
"weaponParam6",
|
||||||
|
"weaponParam7",
|
||||||
|
"weaponParam8",
|
||||||
|
"weaponParam9",
|
||||||
|
"worldViewMatrix",
|
||||||
|
"worldViewProjectionMatrix",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* KNOWN_TEXTURE_DEF_NAMES[]{
|
||||||
|
"AddMap",
|
||||||
|
"Blip_Mask",
|
||||||
|
"BlockNoise",
|
||||||
|
"CS_Z_buffer",
|
||||||
|
"Camo_Detail_Map",
|
||||||
|
"Color_Map",
|
||||||
|
"CompassMap",
|
||||||
|
"Detail_Map",
|
||||||
|
"Diffuse",
|
||||||
|
"Diffuse_Map",
|
||||||
|
"DpadTexture",
|
||||||
|
"FontTextutre",
|
||||||
|
"Grain_Map",
|
||||||
|
"GridTexture",
|
||||||
|
"GrimeMap",
|
||||||
|
"Heart_Rate_Image",
|
||||||
|
"Hologram_Diffuse",
|
||||||
|
"Image",
|
||||||
|
"Layer1Map",
|
||||||
|
"Layer2Map",
|
||||||
|
"Layer3Map",
|
||||||
|
"Layer4Map",
|
||||||
|
"Lookup",
|
||||||
|
"Lookup2",
|
||||||
|
"LookupMap",
|
||||||
|
"Mask",
|
||||||
|
"Noise",
|
||||||
|
"Noise_Texture",
|
||||||
|
"NormalDetailMap",
|
||||||
|
"Normal_Detail_Map",
|
||||||
|
"Normal_Map",
|
||||||
|
"Overlay_Map",
|
||||||
|
"Reflection_Mask",
|
||||||
|
"Reveal_Map",
|
||||||
|
"Rim_Color_Mask",
|
||||||
|
"Rim_Specular_Mask",
|
||||||
|
"Rim_Occlusion_Mask",
|
||||||
|
"Scanline",
|
||||||
|
"SparkleMap",
|
||||||
|
"SpecularAndGloss",
|
||||||
|
"SpecularAndGloss2",
|
||||||
|
"Specular_Color_Map",
|
||||||
|
"Specular_Gloss_Map",
|
||||||
|
"Specular_Map",
|
||||||
|
"SpotShadowSamplerState",
|
||||||
|
"SpotShadowState",
|
||||||
|
"SpriteMap",
|
||||||
|
"Static",
|
||||||
|
"StaticMap",
|
||||||
|
"Static_Noise_Map",
|
||||||
|
"SunShadowSamplerState",
|
||||||
|
"SunShadowState",
|
||||||
|
"Surface_Normal_Map",
|
||||||
|
"ThermalMapMask",
|
||||||
|
"Thermal_Gradient",
|
||||||
|
"Thermal_Map",
|
||||||
|
"TickMarkMaterial",
|
||||||
|
"Tile",
|
||||||
|
"WarpMap",
|
||||||
|
"WaterNormalMap",
|
||||||
|
"Weapon_Normal_Map",
|
||||||
|
"Weapon_Specular_Map",
|
||||||
|
"Wireframe",
|
||||||
|
"ZBuffer_Map",
|
||||||
|
"attenuation",
|
||||||
|
"attenuationSampler",
|
||||||
|
"baseLut2D",
|
||||||
|
"baseLut2DSampler",
|
||||||
|
"cinematicA",
|
||||||
|
"cinematicASampler",
|
||||||
|
"cinematicCb",
|
||||||
|
"cinematicCbSampler",
|
||||||
|
"cinematicCr",
|
||||||
|
"cinematicCrSampler",
|
||||||
|
"cinematicY",
|
||||||
|
"cinematicYSampler",
|
||||||
|
"codeTexture0",
|
||||||
|
"codeTexture1",
|
||||||
|
"codeTexture2",
|
||||||
|
"color",
|
||||||
|
"colorDetailMap",
|
||||||
|
"colorDetailMapSampler",
|
||||||
|
"colorMap",
|
||||||
|
"colorMap1",
|
||||||
|
"colorMap2",
|
||||||
|
"colorMap2D",
|
||||||
|
"colorMapPostSun",
|
||||||
|
"colorMapPostSunSampler",
|
||||||
|
"colorMapSampler",
|
||||||
|
"colorMapSampler1",
|
||||||
|
"colorMapSampler2",
|
||||||
|
"colorSampler",
|
||||||
|
"detailMap",
|
||||||
|
"detailMapSampler",
|
||||||
|
"dlightAttenuation",
|
||||||
|
"dlightAttenuationSampler",
|
||||||
|
"floatZ",
|
||||||
|
"floatZSampler",
|
||||||
|
"imageSampler",
|
||||||
|
"lightmapSamplerSecondary",
|
||||||
|
"lightmapSecondary",
|
||||||
|
"lut2D",
|
||||||
|
"lut2DSampler",
|
||||||
|
"lut3D",
|
||||||
|
"lut3DSampler",
|
||||||
|
"missileCam",
|
||||||
|
"missileCamSampler",
|
||||||
|
"modelLighting",
|
||||||
|
"modelLightingSampler",
|
||||||
|
"normalMap",
|
||||||
|
"normalMap1",
|
||||||
|
"normalMap2",
|
||||||
|
"normalMapSampler",
|
||||||
|
"normalMapSampler1",
|
||||||
|
"normalMapSampler2",
|
||||||
|
"occlusionMap",
|
||||||
|
"occlusionMapSampler",
|
||||||
|
"occMap",
|
||||||
|
"occMapSampler",
|
||||||
|
"outdoorMap",
|
||||||
|
"outdoorMapSampler",
|
||||||
|
"radiantDiffuseMap",
|
||||||
|
"rawFloatZ",
|
||||||
|
"rawFloatZSampler",
|
||||||
|
"reflectionProbe",
|
||||||
|
"reflectionProbeSampler",
|
||||||
|
"shadowmapSamplerSpot",
|
||||||
|
"shadowmapSamplerSun",
|
||||||
|
"shadowmapSpot",
|
||||||
|
"shadowmapSun",
|
||||||
|
"sonarColor",
|
||||||
|
"sonarColorSampler",
|
||||||
|
"sonarDepth",
|
||||||
|
"sonarDepthSampler",
|
||||||
|
"source",
|
||||||
|
"specularMap",
|
||||||
|
"specularMap1",
|
||||||
|
"specularMap2",
|
||||||
|
"specularMapSampler",
|
||||||
|
"specularMapSampler1",
|
||||||
|
"specularMapSampler2",
|
||||||
|
"stencil",
|
||||||
|
"stencilSampler",
|
||||||
|
"ui3d",
|
||||||
|
"ui3dSampler",
|
||||||
|
};
|
||||||
|
|
||||||
|
void MaterialConstantZoneState::ExtractNamesFromZone()
|
||||||
|
{
|
||||||
|
if (ObjWriting::Configuration.Verbose)
|
||||||
|
std::cout << "Building material constant name lookup...\n";
|
||||||
|
|
||||||
|
const auto begin = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
AddStaticKnownNames();
|
||||||
|
|
||||||
|
for (const auto* zone : g_GameT6.GetZones())
|
||||||
|
{
|
||||||
|
const auto* t6AssetPools = dynamic_cast<const GameAssetPoolT6*>(zone->m_pools.get());
|
||||||
|
if (!t6AssetPools)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (const auto* techniqueSetInfo : *t6AssetPools->m_technique_set)
|
||||||
|
{
|
||||||
|
const auto* techniqueSet = techniqueSetInfo->Asset();
|
||||||
|
|
||||||
|
for (const auto* technique : techniqueSet->techniques)
|
||||||
|
{
|
||||||
|
if (technique)
|
||||||
|
ExtractNamesFromTechnique(technique);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto end = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
if (ObjWriting::Configuration.Verbose)
|
||||||
|
{
|
||||||
|
const auto durationInMs = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin);
|
||||||
|
std::cout << "Built material constant name lookup in " << durationInMs.count() << "ms: " << m_constant_names_from_shaders.size()
|
||||||
|
<< " constant names; " << m_texture_def_names_from_shaders.size() << " texture def names\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MaterialConstantZoneState::GetConstantName(const unsigned hash, std::string& constantName) const
|
||||||
|
{
|
||||||
|
const auto existingConstantName = m_constant_names_from_shaders.find(hash);
|
||||||
|
if (existingConstantName != m_constant_names_from_shaders.end())
|
||||||
|
{
|
||||||
|
constantName = existingConstantName->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MaterialConstantZoneState::GetTextureDefName(const unsigned hash, std::string& textureDefName) const
|
||||||
|
{
|
||||||
|
const auto existingTextureDefName = m_texture_def_names_from_shaders.find(hash);
|
||||||
|
if (existingTextureDefName != m_texture_def_names_from_shaders.end())
|
||||||
|
{
|
||||||
|
textureDefName = existingTextureDefName->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialConstantZoneState::ExtractNamesFromTechnique(const MaterialTechnique* technique)
|
||||||
|
{
|
||||||
|
const auto existingTechnique = m_dumped_techniques.find(technique);
|
||||||
|
if (existingTechnique != m_dumped_techniques.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_dumped_techniques.emplace(technique);
|
||||||
|
|
||||||
|
for (auto passIndex = 0u; passIndex < technique->passCount; passIndex++)
|
||||||
|
{
|
||||||
|
const auto& pass = technique->passArray[passIndex];
|
||||||
|
|
||||||
|
if (pass.vertexShader && pass.vertexShader->prog.loadDef.program)
|
||||||
|
ExtractNamesFromShader(pass.vertexShader->prog.loadDef.program, pass.vertexShader->prog.loadDef.programSize);
|
||||||
|
|
||||||
|
if (pass.pixelShader && pass.pixelShader->prog.loadDef.program)
|
||||||
|
ExtractNamesFromShader(pass.pixelShader->prog.loadDef.program, pass.pixelShader->prog.loadDef.programSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialConstantZoneState::ExtractNamesFromShader(const char* shader, const size_t shaderSize)
|
||||||
|
{
|
||||||
|
const auto shaderInfo = d3d11::ShaderAnalyser::GetShaderInfo(reinterpret_cast<const uint8_t*>(shader), shaderSize);
|
||||||
|
if (!shaderInfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto globalsConstantBuffer = std::ranges::find_if(std::as_const(shaderInfo->m_constant_buffers),
|
||||||
|
[](const d3d11::ConstantBuffer& constantBuffer)
|
||||||
|
{
|
||||||
|
return constantBuffer.m_name == GLOBALS_CBUFFER_NAME;
|
||||||
|
});
|
||||||
|
|
||||||
|
const auto perObjectConsts = std::ranges::find_if(std::as_const(shaderInfo->m_constant_buffers),
|
||||||
|
[](const d3d11::ConstantBuffer& constantBuffer)
|
||||||
|
{
|
||||||
|
return constantBuffer.m_name == PER_OBJECT_CONSTS_CBUFFER_NAME;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (globalsConstantBuffer != shaderInfo->m_constant_buffers.end())
|
||||||
|
{
|
||||||
|
for (const auto& variable : globalsConstantBuffer->m_variables)
|
||||||
|
AddConstantName(variable.m_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (perObjectConsts != shaderInfo->m_constant_buffers.end())
|
||||||
|
{
|
||||||
|
for (const auto& variable : perObjectConsts->m_variables)
|
||||||
|
AddConstantName(variable.m_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& boundResource : shaderInfo->m_bound_resources)
|
||||||
|
{
|
||||||
|
if (boundResource.m_type == d3d11::BoundResourceType::SAMPLER || boundResource.m_type == d3d11::BoundResourceType::TEXTURE)
|
||||||
|
{
|
||||||
|
if (AddTextureDefName(boundResource.m_name))
|
||||||
|
{
|
||||||
|
const auto samplerPos = boundResource.m_name.rfind(SAMPLER_STR);
|
||||||
|
if (samplerPos != std::string::npos)
|
||||||
|
{
|
||||||
|
auto nameWithoutSamplerStr = boundResource.m_name;
|
||||||
|
nameWithoutSamplerStr.erase(samplerPos, std::char_traits<char>::length(SAMPLER_STR));
|
||||||
|
AddTextureDefName(std::move(nameWithoutSamplerStr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialConstantZoneState::AddStaticKnownNames()
|
||||||
|
{
|
||||||
|
for (const auto* knownConstantName : KNOWN_CONSTANT_NAMES)
|
||||||
|
AddConstantName(knownConstantName);
|
||||||
|
for (const auto* knownTextureDefName : KNOWN_TEXTURE_DEF_NAMES)
|
||||||
|
AddTextureDefName(knownTextureDefName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialConstantZoneState::AddConstantName(std::string constantName)
|
||||||
|
{
|
||||||
|
const auto hash = Common::R_HashString(constantName.c_str(), 0);
|
||||||
|
if (m_constant_names_from_shaders.contains(hash))
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_constant_names_from_shaders.emplace(hash, std::move(constantName));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MaterialConstantZoneState::AddTextureDefName(std::string textureDefName)
|
||||||
|
{
|
||||||
|
const auto hash = Common::R_HashString(textureDefName.c_str(), 0);
|
||||||
|
if (m_texture_def_names_from_shaders.contains(hash))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_texture_def_names_from_shaders.emplace(hash, std::move(textureDefName));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // namespace T6
|
30
src/ObjWriting/Game/T6/Material/MaterialConstantZoneState.h
Normal file
30
src/ObjWriting/Game/T6/Material/MaterialConstantZoneState.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Dumping/IZoneAssetDumperState.h"
|
||||||
|
#include "Game/T6/T6.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace T6
|
||||||
|
{
|
||||||
|
class MaterialConstantZoneState final : public IZoneAssetDumperState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void ExtractNamesFromZone();
|
||||||
|
bool GetConstantName(unsigned hash, std::string& constantName) const;
|
||||||
|
bool GetTextureDefName(unsigned hash, std::string& textureDefName) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ExtractNamesFromTechnique(const MaterialTechnique* technique);
|
||||||
|
void ExtractNamesFromShader(const char* shader, size_t shaderSize);
|
||||||
|
void AddStaticKnownNames();
|
||||||
|
void AddConstantName(std::string constantName);
|
||||||
|
bool AddTextureDefName(std::string textureDefName);
|
||||||
|
|
||||||
|
std::unordered_set<const MaterialTechnique*> m_dumped_techniques;
|
||||||
|
std::unordered_map<unsigned, std::string> m_constant_names_from_shaders;
|
||||||
|
std::unordered_map<unsigned, std::string> m_texture_def_names_from_shaders;
|
||||||
|
};
|
||||||
|
} // namespace T6
|
Loading…
x
Reference in New Issue
Block a user