#include "ModelCooker.h" #include #include #include ModelCooker::ModelCooker(Options opt) : m_opt(std::move(opt)) { } bool ModelCooker::CookFileIfNeeded(const fs::path& source, const fs::path& output) const { if (!NeedsRebuild(source, output)) return false; ModelDoc::ModelAsset model = ModelDoc::LoadModel(source.generic_string(), ModelFile::CookOptions); MakePathsPortable(model, source); fs::create_directories(output.parent_path()); ModelFile::WriteToFile(model, output); return true; } fs::path ModelCooker::MakeOutputPath(const fs::path& dstLikeSrc) { fs::path out = dstLikeSrc; out.replace_extension(dstLikeSrc.extension().string() + std::string(ModelFile::Extension)); return out; } bool ModelCooker::NeedsRebuild(const fs::path& source, const fs::path& output) { if (!fs::exists(output)) return true; if (fs::last_write_time(source) > fs::last_write_time(output)) return true; return ModelFile::ReadVersionFromFile(output) != ModelFile::Version; } void ModelCooker::MakePathsPortable(ModelDoc::ModelAsset& model, const fs::path& source) const { const fs::path inputRoot = fs::absolute(m_opt.inputRoot).lexically_normal(); const fs::path modelPath = fs::absolute(source).lexically_normal(); const fs::path modelDir = modelPath.parent_path(); const std::string reference = modelPath.lexically_relative(inputRoot).generic_string(); model.sourcePath = reference; model.skeleton.assetReference.path = reference; for (ModelDoc::MeshPrimitive& primitive : model.primitives) { primitive.mesh.assetReference.path = reference; if (primitive.mesh.skeleton) primitive.mesh.skeleton->assetReference.path = reference; } for (ModelDoc::MaterialInfo& material : model.materials) { material.assetReference.path = reference; for (ModelDoc::TextureInfo& texture : material.textures) { if (texture.embedded || texture.path.empty()) continue; const fs::path texturePath = fs::path(texture.path).lexically_normal(); const fs::path fromRoot = texturePath.lexically_relative(inputRoot); if (fromRoot.empty() || *fromRoot.begin() == "..") continue; texture.path = texturePath.lexically_relative(modelDir).generic_string(); } } for (SkeletalAnimation& animation : model.animations) animation.assetReference.path = reference; }