Files
Z3D/source/assets/file_parsers/threedtk_pose_loader.cpp
2025-04-02 17:45:41 +02:00

112 lines
2.4 KiB
C++

#include "assets/file_parsers/threedtk_pose_loader.hpp"
#include <fstream>
#include <execution>
#include <glm/ext/matrix_transform.hpp>
#include <glm/gtx/euler_angles.hpp>
#include "util/logger.hpp"
std::error_code assets::threedtk_pose_loader::prefetch(
path_id_lookups& lookups
) {
return {};
}
std::error_code assets::threedtk_pose_loader::load(
path_id_lookups& lookups,
data_stores& stores,
bool pedantic
) {
m_path_buffer.clear();
lookups.poses.by_extension(".pose", m_path_buffer);
std::for_each(
std::execution::parallel_unsequenced_policy{},
m_path_buffer.begin(),
m_path_buffer.end(),
parser_context{
lookups,
stores
}
);
return {};
}
assets::threedtk_pose_loader::parser_context::parser_context(
path_id_lookups& m_id_lookups,
data_stores& m_stores
) :
m_id_lookups{ &m_id_lookups },
m_stores{ &m_stores }
{
m_line_buffer.reserve(64);
}
void assets::threedtk_pose_loader::parser_context::operator()(lookup_type::const_pointer entry) noexcept
{
const auto& [ filename, id ] = *entry;
if (const auto res = parse_file(filename, m_line_buffer))
{
m_stores->poses.insert(id, res.value());
}
else
{
const auto error = res.error();
ztu::logger::error(
"Error while parsing 3dtk pose file %: [%] %",
filename,
error.category().name(),
error.message()
);
}
}
ztu::result<assets::pose_data> assets::threedtk_pose_loader::parse_file(
const std::filesystem::path& filename,
std::string& line_buffer
) {
auto in = std::ifstream{ filename };
if (not in.is_open())
{
return std::unexpected{ std::make_error_code(std::errc::no_such_file_or_directory) };
}
std::array<glm::vec3, 2> transform_vecs{};
for (std::size_t row{}; row != 2; ++row) {
std::getline(in, line_buffer);
auto it = line_buffer.cbegin().base();
auto end = line_buffer.cend().base();
for (glm::vec3::length_type col{}; col != 3; ++col) {
const auto [ ptr, ec ] = std::from_chars(
it, end,
transform_vecs[row][col],
std::chars_format::general
);
if (ec != std::errc{}) {
return std::unexpected{ std::make_error_code(ec) };
}
it = ptr + 1; // skip space in between components
}
}
const auto& translation = transform_vecs[0];
auto& angles = transform_vecs[1];
angles *= static_cast<float>(M_PI / 180.0);
return (
glm::translate(glm::identity<glm::mat4>(), translation) *
glm::eulerAngleXYZ(angles[0], angles[1], angles[2])
);
}