feat: add model / texture cooking

This commit is contained in:
2026-10-13 00:28:34 +02:00
parent 38230f5092
commit 0273340e3b
6 changed files with 249 additions and 21 deletions
+79
View File
@@ -0,0 +1,79 @@
#include "ModelCooker.h"
#include <string>
#include <utility>
#include <destrum/Assets/ModelFile.h>
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;
}