#include "mesh_encoder.h" #include "mesh_codec.hpp" #include #include using namespace mesh_codec; struct mesh_encoder::impl { using cache_set_type = std::unordered_set; cache_set_type cache_set; static data_type encode_mesh(const mesh_ptr &mesh) { auto raw = mesh->get_raw_info(); auto ret_size = sizeof(raw.num_triangles) + sizeof(raw.vbo_data.size) + raw.vbo_data.size + sizeof(raw.ebo_data.size) + raw.ebo_data.size; auto ret = data_type(ret_size, pre_size); auto writer = network_writer(ret); writer << raw.num_triangles << raw.vbo_data.size << raw.vbo_data << raw.ebo_data.size << raw.ebo_data; assert(writer.empty()); return ret; } data_type encode(const mesh_ptr &mesh) { // handle no transfer situation if (auto no_transfer_any = mesh->get_meta_any(META_MESH_NO_TRANSFER); boost::any_cast(no_transfer_any)) { auto name = mesh->get_meta_ext(META_SERIES_NAME); auto writer = network_writer(); writer << FLAG_NO_TRANSFER << name; return writer.current_data(); } static constexpr auto hash_seed = 0; auto ret = encode_mesh(mesh); auto id = XXH64(ret.start_ptr(), ret.size, hash_seed); auto head = ret.sub_data(-pre_size); auto writer = network_writer(head); if (cache_set.contains(id)) { writer << FLAG_CACHED << id; assert(writer.empty()); return head; } else { writer << FLAG_NEW << id; cache_set.emplace(id); assert(writer.empty()); head = head.extend(ret.size); // recover data return head; } } void clear_cache() { cache_set.clear(); } }; mesh_encoder::mesh_encoder() : pimpl(std::make_unique()) {} mesh_encoder::~mesh_encoder() = default; data_type mesh_encoder::encode(const mesh_ptr &mesh) { return pimpl->encode(mesh); } void mesh_encoder::clear_cache() { pimpl->clear_cache(); }