mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-05-12 21:31:43 +00:00
feat: preserve root bone name when dumping xmodels with omitted default armature
This commit is contained in:
@@ -56,6 +56,7 @@ namespace GAME
|
|||||||
public:
|
public:
|
||||||
std::optional<JsonXModelType> type;
|
std::optional<JsonXModelType> type;
|
||||||
std::vector<JsonXModelLod> lods;
|
std::vector<JsonXModelLod> lods;
|
||||||
|
std::optional<std::string> rootBoneName;
|
||||||
std::optional<int> collLod;
|
std::optional<int> collLod;
|
||||||
std::optional<std::string> physPreset;
|
std::optional<std::string> physPreset;
|
||||||
#if defined(FEATURE_IW4) || defined(FEATURE_IW5)
|
#if defined(FEATURE_IW4) || defined(FEATURE_IW5)
|
||||||
@@ -74,6 +75,7 @@ namespace GAME
|
|||||||
JsonXModel,
|
JsonXModel,
|
||||||
type,
|
type,
|
||||||
lods,
|
lods,
|
||||||
|
rootBoneName,
|
||||||
collLod,
|
collLod,
|
||||||
physPreset,
|
physPreset,
|
||||||
#if defined(FEATURE_IW4) || defined(FEATURE_IW5)
|
#if defined(FEATURE_IW4) || defined(FEATURE_IW5)
|
||||||
|
|||||||
@@ -161,28 +161,28 @@ namespace
|
|||||||
return GetImageFromTextureDef(*potentialTextureDefs[0]);
|
return GetImageFromTextureDef(*potentialTextureDefs[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetSurfaces(const XModel* model, const unsigned lod, XSurface*& surfs, unsigned& surfCount)
|
bool GetSurfaces(const XModel& model, const unsigned lod, XSurface*& surfs, unsigned& surfCount)
|
||||||
{
|
{
|
||||||
#if defined(FEATURE_IW4) || defined(FEATURE_IW5)
|
#if defined(FEATURE_IW4) || defined(FEATURE_IW5)
|
||||||
if (!model->lodInfo[lod].modelSurfs || !model->lodInfo[lod].modelSurfs->surfs)
|
if (!model.lodInfo[lod].modelSurfs || !model.lodInfo[lod].modelSurfs->surfs)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
surfs = model->lodInfo[lod].modelSurfs->surfs;
|
surfs = model.lodInfo[lod].modelSurfs->surfs;
|
||||||
surfCount = model->lodInfo[lod].modelSurfs->numsurfs;
|
surfCount = model.lodInfo[lod].modelSurfs->numsurfs;
|
||||||
#else
|
#else
|
||||||
if (!model->surfs)
|
if (!model.surfs)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
surfs = &model.surfs[model.lodInfo[lod].surfIndex];
|
||||||
surfCount = model->lodInfo[lod].numsurfs;
|
surfCount = model.lodInfo[lod].numsurfs;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasDefaultArmatureForLod(const XModel* model, const unsigned lod)
|
bool HasDefaultArmatureForLod(const XModel& model, const unsigned lod)
|
||||||
{
|
{
|
||||||
if (model->numRootBones != 1 || model->numBones != 1)
|
if (model.numRootBones != 1 || model.numBones != 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
XSurface* surfs;
|
XSurface* surfs;
|
||||||
@@ -213,9 +213,9 @@ namespace
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasDefaultArmatureForAllLods(const XModel* model)
|
bool HasDefaultArmatureForAllLods(const XModel& model)
|
||||||
{
|
{
|
||||||
for (auto lod = 0u; lod < model->numLods; lod++)
|
for (auto lod = 0u; lod < model.numLods; lod++)
|
||||||
{
|
{
|
||||||
if (!HasDefaultArmatureForLod(model, lod))
|
if (!HasDefaultArmatureForLod(model, lod))
|
||||||
return false;
|
return false;
|
||||||
@@ -348,7 +348,7 @@ namespace
|
|||||||
{
|
{
|
||||||
XSurface* surfs;
|
XSurface* surfs;
|
||||||
unsigned surfCount;
|
unsigned surfCount;
|
||||||
if (!GetSurfaces(model, lod, surfs, surfCount))
|
if (!GetSurfaces(*model, lod, surfs, surfCount))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
||||||
@@ -376,7 +376,7 @@ namespace
|
|||||||
{
|
{
|
||||||
XSurface* surfs;
|
XSurface* surfs;
|
||||||
unsigned surfCount;
|
unsigned surfCount;
|
||||||
if (!GetSurfaces(model, lod, surfs, surfCount))
|
if (!GetSurfaces(*model, lod, surfs, surfCount))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto totalWeightCount = 0u;
|
auto totalWeightCount = 0u;
|
||||||
@@ -410,7 +410,7 @@ namespace
|
|||||||
{
|
{
|
||||||
XSurface* surfs;
|
XSurface* surfs;
|
||||||
unsigned surfCount;
|
unsigned surfCount;
|
||||||
if (!GetSurfaces(model, lod, surfs, surfCount))
|
if (!GetSurfaces(*model, lod, surfs, surfCount))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto& weightCollection = out.m_bone_weight_data;
|
auto& weightCollection = out.m_bone_weight_data;
|
||||||
@@ -529,7 +529,7 @@ namespace
|
|||||||
{
|
{
|
||||||
XSurface* surfs;
|
XSurface* surfs;
|
||||||
unsigned surfCount;
|
unsigned surfCount;
|
||||||
if (!GetSurfaces(model, lod, surfs, surfCount))
|
if (!GetSurfaces(*model, lod, surfs, surfCount))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
||||||
@@ -570,7 +570,7 @@ namespace
|
|||||||
|
|
||||||
// Keep armature handling consistent across all LODs so dumped GLTF/GLB round-trips
|
// Keep armature handling consistent across all LODs so dumped GLTF/GLB round-trips
|
||||||
// preserve the same bone layout when re-imported.
|
// preserve the same bone layout when re-imported.
|
||||||
if (!CanOmitDefaultArmature() || !HasDefaultArmatureForAllLods(model))
|
if (!CanOmitDefaultArmature() || !HasDefaultArmatureForAllLods(*model))
|
||||||
{
|
{
|
||||||
AddXModelBones(out, context, model);
|
AddXModelBones(out, context, model);
|
||||||
AddXModelVertexBoneWeights(out, model, lod);
|
AddXModelVertexBoneWeights(out, model, lod);
|
||||||
@@ -698,15 +698,15 @@ namespace
|
|||||||
class JsonDumper
|
class JsonDumper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
JsonDumper(AssetDumpingContext& context, std::ostream& stream)
|
explicit JsonDumper(std::ostream& stream)
|
||||||
: m_stream(stream)
|
: m_stream(stream)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dump(const XModel* xmodel) const
|
void Dump(AssetDumpingContext& context, const XModel* xmodel) const
|
||||||
{
|
{
|
||||||
JsonXModel jsonXModel;
|
JsonXModel jsonXModel;
|
||||||
CreateJsonXModel(jsonXModel, *xmodel);
|
CreateJsonXModel(context, jsonXModel, *xmodel);
|
||||||
nlohmann::json jRoot = jsonXModel;
|
nlohmann::json jRoot = jsonXModel;
|
||||||
|
|
||||||
jRoot["$schema"] = "http://openassettools.dev/schema/xmodel.v1.json";
|
jRoot["$schema"] = "http://openassettools.dev/schema/xmodel.v1.json";
|
||||||
@@ -819,13 +819,33 @@ namespace
|
|||||||
|
|
||||||
return JsonXModelType::ANIMATED;
|
return JsonXModelType::ANIMATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetJsonRootBoneName(AssetDumpingContext& context, JsonXModel& jXModel, const XModel& xmodel)
|
||||||
|
{
|
||||||
|
assert(xmodel.boneNames);
|
||||||
|
assert(xmodel.boneNames[0] < context.m_zone.m_script_strings.Count());
|
||||||
|
assert(xmodel.numRootBones <= 1);
|
||||||
|
|
||||||
|
if (!xmodel.boneNames || xmodel.boneNames[0] >= context.m_zone.m_script_strings.Count() || xmodel.numRootBones == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
jXModel.rootBoneName = context.m_zone.m_script_strings[xmodel.boneNames[0]];
|
||||||
|
}
|
||||||
|
|
||||||
static void CreateJsonXModel(JsonXModel& jXModel, const XModel& xmodel)
|
static void CreateJsonXModel(AssetDumpingContext& context, JsonXModel& jXModel, const XModel& xmodel)
|
||||||
{
|
{
|
||||||
if (xmodel.collLod >= 0)
|
if (xmodel.collLod >= 0)
|
||||||
jXModel.collLod = xmodel.collLod;
|
jXModel.collLod = xmodel.collLod;
|
||||||
|
|
||||||
jXModel.type = GetType(xmodel);
|
jXModel.type = GetType(xmodel);
|
||||||
|
|
||||||
|
if (CanOmitDefaultArmature() && HasDefaultArmatureForAllLods(xmodel))
|
||||||
|
{
|
||||||
|
// If we are going to omit the armature, we need to make sure we remember the root bone name.
|
||||||
|
// It does not follow a specific pattern, may not be identical to the xmodel name and
|
||||||
|
// may be required for attaching the xmodel.
|
||||||
|
SetJsonRootBoneName(context, jXModel, xmodel);
|
||||||
|
}
|
||||||
|
|
||||||
for (auto lodNumber = 0u; lodNumber < xmodel.numLods; lodNumber++)
|
for (auto lodNumber = 0u; lodNumber < xmodel.numLods; lodNumber++)
|
||||||
{
|
{
|
||||||
@@ -868,8 +888,8 @@ namespace
|
|||||||
if (!assetFile)
|
if (!assetFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const JsonDumper dumper(context, *assetFile);
|
const JsonDumper dumper(*assetFile);
|
||||||
dumper.Dump(asset.Asset());
|
dumper.Dump(context, asset.Asset());
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user