58 lines
1.7 KiB
C++
58 lines
1.7 KiB
C++
#include "TextureCooker.h"
|
|
|
|
#include <cstdlib>
|
|
#include <memory>
|
|
#include <span>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
#include <tinyexr.h>
|
|
|
|
#include <destrum/Assets/TextureFile.h>
|
|
|
|
bool TextureCooker::CookFileIfNeeded(const fs::path& source, const fs::path& output) const
|
|
{
|
|
if (!NeedsRebuild(source, output))
|
|
return false;
|
|
|
|
float* rgba = nullptr;
|
|
int width = 0;
|
|
int height = 0;
|
|
const char* error = nullptr;
|
|
|
|
if (LoadEXR(&rgba, &width, &height, source.string().c_str(), &error) != TINYEXR_SUCCESS)
|
|
{
|
|
const std::string message = error ? error : "unknown error";
|
|
FreeEXRErrorMessage(error);
|
|
throw std::runtime_error("TinyEXR failed to load '" + source.string() + "': " + message);
|
|
}
|
|
|
|
const std::unique_ptr<float, decltype(&std::free)> pixels(rgba, &std::free);
|
|
const std::size_t floatCount = static_cast<std::size_t>(width) * static_cast<std::size_t>(height) * 4;
|
|
|
|
const TextureFile::Texture texture = TextureFile::FromRGBA32Float(
|
|
static_cast<std::uint32_t>(width),
|
|
static_cast<std::uint32_t>(height),
|
|
std::span<const float>(pixels.get(), floatCount));
|
|
|
|
fs::create_directories(output.parent_path());
|
|
TextureFile::WriteToFile(texture, output);
|
|
return true;
|
|
}
|
|
|
|
fs::path TextureCooker::MakeOutputPath(const fs::path& dstLikeSrc)
|
|
{
|
|
fs::path out = dstLikeSrc;
|
|
out.replace_extension(dstLikeSrc.extension().string() + std::string(TextureFile::Extension));
|
|
return out;
|
|
}
|
|
|
|
bool TextureCooker::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 TextureFile::ReadVersionFromFile(output) != TextureFile::Version;
|
|
}
|