2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-04-21 10:58:44 +00:00

fix: properly load all root bones from gltf

This commit is contained in:
Jan Laupetin
2026-04-20 22:36:31 +01:00
parent 279ac9ee5c
commit 9aa91011a4

View File

@@ -405,13 +405,12 @@ namespace
return true; return true;
} }
static std::optional<unsigned> GetRootNodeForSkin(const JsonRoot& jRoot, const JsonSkin& skin) static std::vector<unsigned> GetRootNodesForSkin(const JsonRoot& jRoot, const JsonSkin& skin)
{ {
if (!jRoot.nodes || skin.joints.empty()) if (!jRoot.nodes || skin.joints.empty())
return std::nullopt; return {};
const auto jointCount = skin.joints.size(); const auto jointCount = skin.joints.size();
auto rootCount = jointCount;
std::vector<bool> isRoot(jointCount, true); std::vector<bool> isRoot(jointCount, true);
for (const auto joint : skin.joints) for (const auto joint : skin.joints)
@@ -431,23 +430,20 @@ namespace
if (isRoot[foundChildJointIndex]) if (isRoot[foundChildJointIndex])
{ {
isRoot[foundChildJointIndex] = false; isRoot[foundChildJointIndex] = false;
rootCount--;
} }
} }
} }
} }
} }
if (rootCount != 1) std::vector<unsigned> result;
throw GltfLoadException("Skins must have exactly one common root node");
for (auto index = 0u; index < jointCount; index++) for (auto index = 0u; index < jointCount; index++)
{ {
if (isRoot[index]) if (isRoot[index])
return skin.joints[index]; result.emplace_back(skin.joints[index]);
} }
return std::nullopt; return std::move(result);
} }
void ApplyNodeMatrixTRS(const JsonNode& node, float (&localOffsetRhc)[3], float (&localRotationRhc)[4], float (&scaleRhc)[3]) const void ApplyNodeMatrixTRS(const JsonNode& node, float (&localOffsetRhc)[3], float (&localRotationRhc)[4], float (&scaleRhc)[3]) const
@@ -611,9 +607,11 @@ namespace
{ {
if (!ConvertJoint( if (!ConvertJoint(
jRoot, skin, common, skinBoneOffset, childIndex, commonBoneOffset, globalTranslationEigenRhc, globalRotationEigenRhc, bone.scale)) jRoot, skin, common, skinBoneOffset, childIndex, commonBoneOffset, globalTranslationEigenRhc, globalRotationEigenRhc, bone.scale))
{
return false; return false;
} }
} }
}
return true; return true;
} }
@@ -625,7 +623,10 @@ namespace
if (!jRoot.nodes) if (!jRoot.nodes)
return false; return false;
const auto rootNode = GetRootNodeForSkin(jRoot, skin).value_or(skin.joints[0]); auto rootNodes = GetRootNodesForSkin(jRoot, skin);
if (rootNodes.empty())
rootNodes.emplace_back(skin.joints[0]);
const auto skinBoneOffset = static_cast<unsigned>(common.m_bones.size()); const auto skinBoneOffset = static_cast<unsigned>(common.m_bones.size());
common.m_bones.resize(skinBoneOffset + skin.joints.size()); common.m_bones.resize(skinBoneOffset + skin.joints.size());
@@ -633,10 +634,16 @@ namespace
const Eigen::Quaternionf defaultRotation(1.0f, 0.0f, 0.0f, 0.0f); const Eigen::Quaternionf defaultRotation(1.0f, 0.0f, 0.0f, 0.0f);
constexpr float defaultScale[3]{1.0f, 1.0f, 1.0f}; constexpr float defaultScale[3]{1.0f, 1.0f, 1.0f};
for (const auto rootNode : rootNodes)
{
if (!ConvertJoint(jRoot, skin, common, skinBoneOffset, rootNode, std::nullopt, defaultTranslation, defaultRotation, defaultScale)) if (!ConvertJoint(jRoot, skin, common, skinBoneOffset, rootNode, std::nullopt, defaultTranslation, defaultRotation, defaultScale))
return false; return false;
}
common.CalculateBoneLocalsFromGlobals(); common.CalculateBoneLocalsFromGlobals();
// TODO: Reorder bones if necessary and prepare lookup
return true; return true;
} }