feat: add model / texture cooking
This commit is contained in:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user