80 lines
2.5 KiB
C++
80 lines
2.5 KiB
C++
#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;
|
|
}
|