#include "mesh_decoder.h" #include "mesh_codec.hpp" #include "third_party/static_block.hpp" #include "impl/main_impl.h" #include using namespace mesh_codec; namespace mesh_decoder_impl { using mesh_map_type = std::unordered_map; mesh_map_type mesh_pool; static_block { register_cleanup_func([] { mesh_pool.clear(); }); } using hasher_type = std::hash; hasher_type name_hasher; mesh_ptr get_no_transfer_mesh(size_t name) { assert(mesh_pool.contains(name)); return mesh_pool.at(name); } } using namespace mesh_decoder_impl; struct mesh_decoder::impl { using cache_map_type = std::unordered_map; cache_map_type cache_map; static mesh_ptr decode_mesh(const data_type &data) { auto ret = mesh_type::raw_info_type(); auto reader = network_reader(data); reader >> ret.num_triangles; auto vbo_size = reader.read_value(); ret.vbo_data = reader.read_data(vbo_size); auto ebo_size = reader.read_value(); ret.ebo_data = reader.read_data(ebo_size); assert(reader.empty()); return mesh_type::from_raw(ret); } mesh_ptr decode(const data_type &data) { auto reader = network_reader(data); auto flag = reader.read_value(); if (flag == FLAG_NO_TRANSFER) { auto name = reader.read_value(); return get_no_transfer_mesh(name); } auto id = reader.read_value(); if (cache_map.contains(id)) { return cache_map.at(id); } // assert(!reader.empty()); if (reader.empty()) return nullptr; // TODO: mesh IDR may not be handled??? auto mesh = decode_mesh(reader.read_remain()); if (flag != FLAG_NO_CACHE) { assert(!cache_map.contains(id)); cache_map.emplace(id, mesh); } return mesh; } }; mesh_decoder::mesh_decoder(create_config _) : pimpl(std::make_unique()) { } mesh_decoder::~mesh_decoder() = default; mesh_ptr mesh_decoder::decode(const data_type &data) { return pimpl->decode(data); } void register_mesh_file(const std::string &name, const std::string &path) { auto mesh = mesh_type::create({.path = path}); auto name_id = name_hasher(name); assert(!mesh_pool.contains(name_id)); mesh_pool.emplace(name_id, mesh); } void register_mesh_list(const YAML::Node &conf_list) { for (auto &conf: conf_list) { register_mesh_file(LOAD_STR("name"), LOAD_STR("path")); } }