mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-09-12 19:47:27 +00:00
chore: backwards compatibility for old xmodel exports
This commit is contained in:
@@ -138,8 +138,9 @@ namespace
|
|||||||
class GltfLoaderImpl final : public Loader
|
class GltfLoaderImpl final : public Loader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit GltfLoaderImpl(const Input* input)
|
GltfLoaderImpl(const Input& input, const bool useBadRotationFormulas)
|
||||||
: m_input(input)
|
: m_input(input),
|
||||||
|
m_bad_rotation_formulas(useBadRotationFormulas)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,7 +450,7 @@ namespace
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ApplyNodeMatrixTRS(const JsonNode& node, float (&localOffsetRhc)[3], float (&localRotationRhc)[4], float (&scaleRhc)[3])
|
void ApplyNodeMatrixTRS(const JsonNode& node, float (&localOffsetRhc)[3], float (&localRotationRhc)[4], float (&scaleRhc)[3])
|
||||||
{
|
{
|
||||||
const auto matrix = Eigen::Matrix4f({
|
const auto matrix = Eigen::Matrix4f({
|
||||||
{(*node.matrix)[0], (*node.matrix)[4], (*node.matrix)[8], (*node.matrix)[12]},
|
{(*node.matrix)[0], (*node.matrix)[4], (*node.matrix)[8], (*node.matrix)[12]},
|
||||||
@@ -460,29 +461,45 @@ namespace
|
|||||||
Eigen::Affine3f transform(matrix);
|
Eigen::Affine3f transform(matrix);
|
||||||
|
|
||||||
const auto translation = transform.translation();
|
const auto translation = transform.translation();
|
||||||
|
|
||||||
localOffsetRhc[0] = translation.x();
|
localOffsetRhc[0] = translation.x();
|
||||||
localOffsetRhc[1] = translation.y();
|
localOffsetRhc[1] = translation.y();
|
||||||
localOffsetRhc[2] = translation.z();
|
localOffsetRhc[2] = translation.z();
|
||||||
|
if (m_bad_rotation_formulas)
|
||||||
|
RhcToLhcCoordinates(localOffsetRhc);
|
||||||
|
|
||||||
const auto rotation = transform.rotation();
|
const auto rotation = transform.rotation();
|
||||||
const auto rotationQuat = Eigen::Quaternionf(rotation);
|
const auto rotationQuat = Eigen::Quaternionf(rotation);
|
||||||
|
if (!m_bad_rotation_formulas)
|
||||||
|
{
|
||||||
localRotationRhc[0] = rotationQuat.x();
|
localRotationRhc[0] = rotationQuat.x();
|
||||||
localRotationRhc[1] = rotationQuat.y();
|
localRotationRhc[1] = rotationQuat.y();
|
||||||
localRotationRhc[2] = rotationQuat.z();
|
localRotationRhc[2] = rotationQuat.z();
|
||||||
localRotationRhc[3] = rotationQuat.w();
|
localRotationRhc[3] = rotationQuat.w();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Backwards compatibility
|
||||||
|
localRotationRhc[0] = rotationQuat.x();
|
||||||
|
localRotationRhc[1] = -rotationQuat.z();
|
||||||
|
localRotationRhc[2] = rotationQuat.y();
|
||||||
|
localRotationRhc[3] = rotationQuat.w();
|
||||||
|
}
|
||||||
|
|
||||||
scaleRhc[0] = matrix.block<3, 1>(0, 0).norm();
|
scaleRhc[0] = matrix.block<3, 1>(0, 0).norm();
|
||||||
scaleRhc[1] = matrix.block<3, 1>(0, 1).norm();
|
scaleRhc[1] = matrix.block<3, 1>(0, 1).norm();
|
||||||
scaleRhc[2] = matrix.block<3, 1>(0, 2).norm();
|
scaleRhc[2] = matrix.block<3, 1>(0, 2).norm();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ApplyNodeSeparateTRS(const JsonNode& node, float (&localOffsetRhc)[3], float (&localRotationRhc)[4], float (&scaleRhc)[3])
|
void ApplyNodeSeparateTRS(const JsonNode& node, float (&localOffsetRhc)[3], float (&localRotationRhc)[4], float (&scaleRhc)[3])
|
||||||
{
|
{
|
||||||
if (node.translation)
|
if (node.translation)
|
||||||
{
|
{
|
||||||
localOffsetRhc[0] = (*node.translation)[0];
|
localOffsetRhc[0] = (*node.translation)[0];
|
||||||
localOffsetRhc[1] = (*node.translation)[1];
|
localOffsetRhc[1] = (*node.translation)[1];
|
||||||
localOffsetRhc[2] = (*node.translation)[2];
|
localOffsetRhc[2] = (*node.translation)[2];
|
||||||
|
if (m_bad_rotation_formulas)
|
||||||
|
RhcToLhcCoordinates(localOffsetRhc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -492,6 +509,8 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (node.rotation)
|
if (node.rotation)
|
||||||
|
{
|
||||||
|
if (!m_bad_rotation_formulas)
|
||||||
{
|
{
|
||||||
localRotationRhc[0] = (*node.rotation)[0];
|
localRotationRhc[0] = (*node.rotation)[0];
|
||||||
localRotationRhc[1] = (*node.rotation)[1];
|
localRotationRhc[1] = (*node.rotation)[1];
|
||||||
@@ -499,6 +518,15 @@ namespace
|
|||||||
localRotationRhc[3] = (*node.rotation)[3];
|
localRotationRhc[3] = (*node.rotation)[3];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
// Backwards compatibility
|
||||||
|
localRotationRhc[0] = (*node.rotation)[0];
|
||||||
|
localRotationRhc[1] = -(*node.rotation)[2];
|
||||||
|
localRotationRhc[2] = (*node.rotation)[1];
|
||||||
|
localRotationRhc[3] = (*node.rotation)[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
localRotationRhc[0] = 0.0f;
|
localRotationRhc[0] = 0.0f;
|
||||||
localRotationRhc[1] = 0.0f;
|
localRotationRhc[1] = 0.0f;
|
||||||
@@ -520,7 +548,7 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ConvertJoint(const JsonRoot& jRoot,
|
bool ConvertJoint(const JsonRoot& jRoot,
|
||||||
const JsonSkin& skin,
|
const JsonSkin& skin,
|
||||||
XModelCommon& common,
|
XModelCommon& common,
|
||||||
const unsigned skinBoneOffset,
|
const unsigned skinBoneOffset,
|
||||||
@@ -555,6 +583,7 @@ namespace
|
|||||||
bone.scale[0] = localScaleRhc[0] * parentScale[0];
|
bone.scale[0] = localScaleRhc[0] * parentScale[0];
|
||||||
bone.scale[1] = localScaleRhc[1] * parentScale[1];
|
bone.scale[1] = localScaleRhc[1] * parentScale[1];
|
||||||
bone.scale[2] = localScaleRhc[2] * parentScale[2];
|
bone.scale[2] = localScaleRhc[2] * parentScale[2];
|
||||||
|
if (!m_bad_rotation_formulas)
|
||||||
RhcToLhcScale(bone.scale);
|
RhcToLhcScale(bone.scale);
|
||||||
|
|
||||||
const Eigen::Vector3f localTranslationEigen(localOffsetRhc[0], localOffsetRhc[1], localOffsetRhc[2]);
|
const Eigen::Vector3f localTranslationEigen(localOffsetRhc[0], localOffsetRhc[1], localOffsetRhc[2]);
|
||||||
@@ -566,12 +595,14 @@ namespace
|
|||||||
bone.globalOffset[0] = globalTranslationEigenRhc.x();
|
bone.globalOffset[0] = globalTranslationEigenRhc.x();
|
||||||
bone.globalOffset[1] = globalTranslationEigenRhc.y();
|
bone.globalOffset[1] = globalTranslationEigenRhc.y();
|
||||||
bone.globalOffset[2] = globalTranslationEigenRhc.z();
|
bone.globalOffset[2] = globalTranslationEigenRhc.z();
|
||||||
|
if (!m_bad_rotation_formulas)
|
||||||
RhcToLhcCoordinates(bone.globalOffset);
|
RhcToLhcCoordinates(bone.globalOffset);
|
||||||
|
|
||||||
bone.globalRotation.x = globalRotationEigenRhc.x();
|
bone.globalRotation.x = globalRotationEigenRhc.x();
|
||||||
bone.globalRotation.y = globalRotationEigenRhc.y();
|
bone.globalRotation.y = globalRotationEigenRhc.y();
|
||||||
bone.globalRotation.z = globalRotationEigenRhc.z();
|
bone.globalRotation.z = globalRotationEigenRhc.z();
|
||||||
bone.globalRotation.w = globalRotationEigenRhc.w();
|
bone.globalRotation.w = globalRotationEigenRhc.w();
|
||||||
|
if (!m_bad_rotation_formulas)
|
||||||
RhcToLhcQuaternion(bone.globalRotation);
|
RhcToLhcQuaternion(bone.globalRotation);
|
||||||
|
|
||||||
if (node.children)
|
if (node.children)
|
||||||
@@ -587,7 +618,7 @@ namespace
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ConvertSkin(const JsonRoot& jRoot, const JsonSkin& skin, XModelCommon& common)
|
bool ConvertSkin(const JsonRoot& jRoot, const JsonSkin& skin, XModelCommon& common)
|
||||||
{
|
{
|
||||||
if (skin.joints.empty())
|
if (skin.joints.empty())
|
||||||
return true;
|
return true;
|
||||||
@@ -683,7 +714,7 @@ namespace
|
|||||||
{
|
{
|
||||||
const void* embeddedBufferPtr = nullptr;
|
const void* embeddedBufferPtr = nullptr;
|
||||||
size_t embeddedBufferSize = 0u;
|
size_t embeddedBufferSize = 0u;
|
||||||
if (!m_input->GetEmbeddedBuffer(embeddedBufferPtr, embeddedBufferSize) || embeddedBufferSize == 0u)
|
if (!m_input.GetEmbeddedBuffer(embeddedBufferPtr, embeddedBufferSize) || embeddedBufferSize == 0u)
|
||||||
throw GltfLoadException("Buffer tried to access embedded data when there is none");
|
throw GltfLoadException("Buffer tried to access embedded data when there is none");
|
||||||
|
|
||||||
m_buffers.emplace_back(std::make_unique<EmbeddedBuffer>(embeddedBufferPtr, embeddedBufferSize));
|
m_buffers.emplace_back(std::make_unique<EmbeddedBuffer>(embeddedBufferPtr, embeddedBufferSize));
|
||||||
@@ -763,7 +794,7 @@ namespace
|
|||||||
JsonRoot jRoot;
|
JsonRoot jRoot;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
jRoot = m_input->GetJson().get<JsonRoot>();
|
jRoot = m_input.GetJson().get<JsonRoot>();
|
||||||
}
|
}
|
||||||
catch (const nlohmann::json::exception& e)
|
catch (const nlohmann::json::exception& e)
|
||||||
{
|
{
|
||||||
@@ -793,7 +824,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Input* m_input;
|
const Input& m_input;
|
||||||
std::vector<ObjectToLoad> m_load_objects;
|
std::vector<ObjectToLoad> m_load_objects;
|
||||||
std::unordered_map<AccessorsForVertex, unsigned> m_vertex_offset_for_accessors;
|
std::unordered_map<AccessorsForVertex, unsigned> m_vertex_offset_for_accessors;
|
||||||
std::vector<std::unique_ptr<Accessor>> m_accessors;
|
std::vector<std::unique_ptr<Accessor>> m_accessors;
|
||||||
@@ -804,7 +835,7 @@ namespace
|
|||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::unique_ptr<Loader> Loader::CreateLoader(const Input* input)
|
std::unique_ptr<Loader> Loader::CreateLoader(const Input& input, bool useBadRotationFormulas)
|
||||||
{
|
{
|
||||||
return std::make_unique<GltfLoaderImpl>(input, useBadRotationFormulas);
|
return std::make_unique<GltfLoaderImpl>(input, useBadRotationFormulas);
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,13 @@ namespace gltf
|
|||||||
Loader& operator=(const Loader& other) = default;
|
Loader& operator=(const Loader& other) = default;
|
||||||
Loader& operator=(Loader&& other) noexcept = default;
|
Loader& operator=(Loader&& other) noexcept = default;
|
||||||
|
|
||||||
static std::unique_ptr<Loader> CreateLoader(const Input* input);
|
/**
|
||||||
|
* \brief Creates a loader capable of loading gltf-like files
|
||||||
|
* \param input The gltf input
|
||||||
|
* \param useBadRotationFormulas Old versions used bad formulas for converting into gltf space. Set to \c true to use them for loading to preserve
|
||||||
|
* backwards compatibility.
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
static std::unique_ptr<Loader> CreateLoader(const Input& input, bool useBadRotationFormulas);
|
||||||
};
|
};
|
||||||
} // namespace gltf
|
} // namespace gltf
|
||||||
|
@@ -57,7 +57,8 @@ namespace
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
XModelLoader(MemoryManager& memory, ISearchPath& searchPath, ZoneScriptStrings& scriptStrings)
|
XModelLoader(MemoryManager& memory, ISearchPath& searchPath, ZoneScriptStrings& scriptStrings)
|
||||||
: m_memory(memory),
|
: m_gltf_bad_rotation_formulas(false),
|
||||||
|
m_memory(memory),
|
||||||
m_search_path(searchPath),
|
m_search_path(searchPath),
|
||||||
m_script_strings(scriptStrings)
|
m_script_strings(scriptStrings)
|
||||||
{
|
{
|
||||||
@@ -97,12 +98,14 @@ namespace
|
|||||||
jRoot.at("_type").get_to(type);
|
jRoot.at("_type").get_to(type);
|
||||||
jRoot.at("_version").get_to(version);
|
jRoot.at("_version").get_to(version);
|
||||||
|
|
||||||
if (type != "xmodel" || version != 1u)
|
if (type != "xmodel" || version < 1u || version > 2u)
|
||||||
{
|
{
|
||||||
std::cerr << std::format("Tried to load xmodel \"{}\" but did not find expected type material of version 1\n", xmodel.name);
|
std::cerr << std::format("Tried to load xmodel \"{}\" but did not find expected type material of version 1 or 2\n", xmodel.name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_gltf_bad_rotation_formulas = version == 1u;
|
||||||
|
|
||||||
const auto jXModel = jRoot.get<JsonXModel>();
|
const auto jXModel = jRoot.get<JsonXModel>();
|
||||||
return CreateXModelFromJson(jXModel, xmodel, context, registration);
|
return CreateXModelFromJson(jXModel, xmodel, context, registration);
|
||||||
}
|
}
|
||||||
@@ -119,7 +122,7 @@ namespace
|
|||||||
std::cerr << std::format("Cannot load xmodel \"{}\": {}\n", xmodel.name, message);
|
std::cerr << std::format("Cannot load xmodel \"{}\": {}\n", xmodel.name, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::unique_ptr<XModelCommon> LoadModelByExtension(std::istream& stream, const std::string& extension)
|
std::unique_ptr<XModelCommon> LoadModelByExtension(std::istream& stream, const std::string& extension) const
|
||||||
{
|
{
|
||||||
if (extension == ".glb")
|
if (extension == ".glb")
|
||||||
{
|
{
|
||||||
@@ -127,7 +130,7 @@ namespace
|
|||||||
if (!input.ReadGltfData(stream))
|
if (!input.ReadGltfData(stream))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
const auto loader = gltf::Loader::CreateLoader(&input);
|
const auto loader = gltf::Loader::CreateLoader(input, m_gltf_bad_rotation_formulas);
|
||||||
return loader->Load();
|
return loader->Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +140,7 @@ namespace
|
|||||||
if (!input.ReadGltfData(stream))
|
if (!input.ReadGltfData(stream))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
const auto loader = gltf::Loader::CreateLoader(&input);
|
const auto loader = gltf::Loader::CreateLoader(input, m_gltf_bad_rotation_formulas);
|
||||||
return loader->Load();
|
return loader->Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1072,6 +1075,8 @@ namespace
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool m_gltf_bad_rotation_formulas;
|
||||||
|
|
||||||
std::vector<XSurface> m_surfaces;
|
std::vector<XSurface> m_surfaces;
|
||||||
std::vector<Material*> m_materials;
|
std::vector<Material*> m_materials;
|
||||||
|
|
||||||
|
@@ -690,7 +690,7 @@ namespace
|
|||||||
|
|
||||||
jRoot["$schema"] = "http://openassettools.dev/schema/xmodel.v1.json";
|
jRoot["$schema"] = "http://openassettools.dev/schema/xmodel.v1.json";
|
||||||
jRoot["_type"] = "xmodel";
|
jRoot["_type"] = "xmodel";
|
||||||
jRoot["_version"] = 1;
|
jRoot["_version"] = 2;
|
||||||
jRoot["_game"] = GAME_LOWER;
|
jRoot["_game"] = GAME_LOWER;
|
||||||
|
|
||||||
m_stream << std::setw(4) << jRoot << "\n";
|
m_stream << std::setw(4) << jRoot << "\n";
|
||||||
|
Reference in New Issue
Block a user