diff --git a/src/polymesh/formats.cc b/src/polymesh/formats.cc index bb50e52fc69c7c1f412107ededb630f6caf9d526..039af918fd18a7cb5ce78da3a6d96272608fe98e 100644 --- a/src/polymesh/formats.cc +++ b/src/polymesh/formats.cc @@ -7,7 +7,6 @@ #include "formats/obj.hh" #include "formats/off.hh" -#include "formats/pm.hh" #include "formats/stl.hh" template <class ScalarT> diff --git a/src/polymesh/formats/pm.cc b/src/polymesh/formats/pm.cc deleted file mode 100644 index 53ca43953942da735a85ff60f5d2ee60f7aa39bb..0000000000000000000000000000000000000000 --- a/src/polymesh/formats/pm.cc +++ /dev/null @@ -1,274 +0,0 @@ -#include "pm.hh" - -#include <polymesh/ext/attribute_collection.hh> -#include <polymesh/low_level_api.hh> - -#include <fstream> -#include <iostream> -#include <mutex> -#include <typeindex> -#include <unordered_map> - -#ifdef POLYMESH_SUPPORT_GLM -#include <glm/ext.hpp> -#include <glm/glm.hpp> -#endif - -namespace polymesh -{ -namespace -{ -std::unordered_map<std::string, unique_ptr<detail::GenericAttributeSerializer>> sSerializers; -const std::string unregistered_type_name = "UNREGISTERED_TYPE"; -} // namespace - -void detail::register_attribute_serializer(const std::string& identifier, unique_ptr<detail::GenericAttributeSerializer> ptr) -{ - sSerializers[identifier] = std::move(ptr); -} - -template <class Tag> -std::pair<std::string, detail::GenericAttributeSerializer*> find_serializer_for(primitive_attribute_base<Tag> const& attr) -{ - for (auto const& pair : sSerializers) - { - if (pair.second->is_compatible_to(attr)) - return {pair.first, pair.second.get()}; - } - return {{}, nullptr}; -} - -struct pm_header -{ - char pm[4] = {'P', 'M', 0, 0}; - int32_t num_vertices; - int32_t num_halfedges; - int32_t num_faces; - - int32_t num_vertex_attributes; - int32_t num_halfedge_attributes; - int32_t num_edge_attributes; - int32_t num_face_attributes; - - bool valid() const { return pm[0] == 'P' && pm[1] == 'M' && pm[2] == 0 && pm[3] == 0; } -}; - -template <class tag> -static std::istream& read_index(std::istream& in, primitive_index<tag>& idx) -{ - int32_t val; - in.read(reinterpret_cast<char*>(&val), sizeof(int32_t)); - idx.value = val; - return in; -} - -template <class tag> -static std::ostream& write_index(std::ostream& out, primitive_index<tag> const& idx) -{ - const int32_t val = idx.value; - return out.write(reinterpret_cast<char const*>(&val), sizeof(int32_t)); -} - -static std::ostream& write_string(std::ostream& out, std::string const& text) { return out.write(text.c_str(), text.size() + 1); } -static std::istream& read_string(std::istream& in, std::string& text) { return std::getline(in, text, '\0'); } - -template <class tag> -static std::ostream& storeAttributes(std::ostream& out, std::map<std::string, unique_ptr<primitive_attribute_base<tag>>> const& attrs) -{ - for (auto const& attr : attrs) - { - write_string(out, attr.first); // Attribute Name - - auto const& ser = find_serializer_for(*attr.second); - if (ser.second) - { - write_string(out, ser.first); // Attribute Type - ser.second->serialize(out, *attr.second); // Attribute Data - } - else - { - write_string(out, unregistered_type_name); - std::cout << "polymesh::write_pm: " << attr.first << " has unregistered type and is not going to be written." << std::endl; - } - } - return out; -} - -template <class tag> -static bool restoreAttributes(std::istream& in, Mesh const& mesh, attribute_collection& attrs, uint32_t count) -{ - using tag_ptr = tag*; - - for (uint32_t i = 0; i < count; i++) - { - std::string attrName, attrType; - read_string(in, attrName); - read_string(in, attrType); - - if (attrType == unregistered_type_name) - continue; - - auto it = sSerializers.find(attrType); - if (it != sSerializers.end()) - { - it->second->deserialize(in, mesh, attrs, attrName, tag_ptr{}); - } - else - { - std::cout << "polymesh::read_pm: " << attrName << " has unregistered type " << attrType << ", unable to restore remaining attributes." << std::endl; - return false; - } - } - - return true; -} - -void write_pm(std::ostream& out, const Mesh& mesh, const attribute_collection& attributes) -{ - auto ll = low_level_api(mesh); - - if (!mesh.is_compact()) - std::cout << "polymesh::write_pm: saving a non-compact mesh." << std::endl; - - pm_header header; - header.num_vertices = int(mesh.all_vertices().size()); - header.num_halfedges = int(mesh.all_halfedges().size()); - header.num_faces = int(mesh.all_faces().size()); - header.num_vertex_attributes = int(attributes.vertex_attributes().size()); - header.num_halfedge_attributes = int(attributes.halfedge_attributes().size()); - header.num_edge_attributes = int(attributes.edge_attributes().size()); - header.num_face_attributes = int(attributes.face_attributes().size()); - out.write(reinterpret_cast<char*>(&header), sizeof(header)); - - // Store mesh topology - for (int i = 0; i < header.num_faces; ++i) - write_index(out, ll.halfedge_of(face_index(i))); - for (int i = 0; i < header.num_vertices; i++) - write_index(out, ll.outgoing_halfedge_of(vertex_index(i))); - - for (int i = 0; i < header.num_halfedges; ++i) - write_index(out, ll.to_vertex_of(halfedge_index(i))); - for (int i = 0; i < header.num_halfedges; ++i) - write_index(out, ll.face_of(halfedge_index(i))); - for (int i = 0; i < header.num_halfedges; ++i) - write_index(out, ll.next_halfedge_of(halfedge_index(i))); - for (int i = 0; i < header.num_halfedges; ++i) - write_index(out, ll.prev_halfedge_of(halfedge_index(i))); - - // Store attributes - storeAttributes(out, attributes.vertex_attributes()); - storeAttributes(out, attributes.halfedge_attributes()); - storeAttributes(out, attributes.edge_attributes()); - storeAttributes(out, attributes.face_attributes()); -} - -bool read_pm(std::istream& input, Mesh& mesh, attribute_collection& attributes) -{ - pm_header header; - input.read(reinterpret_cast<char*>(&header), sizeof(header)); - POLYMESH_ASSERT(header.valid() && "PM-File contains the wrong magic number!"); - - mesh.clear(); - auto ll = low_level_api(mesh); - ll.alloc_primitives(header.num_vertices, header.num_faces, header.num_halfedges); - - for (int i = 0; i < header.num_faces; ++i) - read_index(input, ll.halfedge_of(face_index(i))); - for (int i = 0; i < header.num_vertices; i++) - read_index(input, ll.outgoing_halfedge_of(vertex_index(i))); - - for (int i = 0; i < header.num_halfedges; ++i) - read_index(input, ll.to_vertex_of(halfedge_index(i))); - for (int i = 0; i < header.num_halfedges; ++i) - read_index(input, ll.face_of(halfedge_index(i))); - for (int i = 0; i < header.num_halfedges; ++i) - read_index(input, ll.next_halfedge_of(halfedge_index(i))); - for (int i = 0; i < header.num_halfedges; ++i) - read_index(input, ll.prev_halfedge_of(halfedge_index(i))); - - // Restore attributes - return restoreAttributes<vertex_tag>(input, mesh, attributes, header.num_vertex_attributes) - && restoreAttributes<halfedge_tag>(input, mesh, attributes, header.num_halfedge_attributes) - && restoreAttributes<edge_tag>(input, mesh, attributes, header.num_edge_attributes) - && restoreAttributes<face_tag>(input, mesh, attributes, header.num_face_attributes) // - && !input.fail(); -} - -void write_pm(const std::string& filename, const Mesh& mesh, const attribute_collection& attributes) -{ - std::ofstream out(filename, std::ios::binary | std::ios::trunc); - write_pm(out, mesh, attributes); -} - -bool read_pm(const std::string& filename, Mesh& mesh, attribute_collection& attributes) -{ - std::ifstream in(filename, std::ios::binary); - return read_pm(in, mesh, attributes); -} - - -#define REGISTER_TYPE(type) register_type<type>(#type) -static bool registered_default_types = []() { - REGISTER_TYPE(bool); - REGISTER_TYPE(float); - REGISTER_TYPE(double); - - REGISTER_TYPE(int8_t); - REGISTER_TYPE(int16_t); - REGISTER_TYPE(int32_t); - REGISTER_TYPE(int64_t); - REGISTER_TYPE(uint8_t); - REGISTER_TYPE(uint16_t); - REGISTER_TYPE(uint32_t); - REGISTER_TYPE(uint64_t); - -#ifdef POLYMESH_SUPPORT_GLM - REGISTER_TYPE(glm::vec2); - REGISTER_TYPE(glm::vec3); - REGISTER_TYPE(glm::vec4); - REGISTER_TYPE(glm::bvec2); - REGISTER_TYPE(glm::bvec3); - REGISTER_TYPE(glm::bvec4); - REGISTER_TYPE(glm::dvec2); - REGISTER_TYPE(glm::dvec3); - REGISTER_TYPE(glm::dvec4); - REGISTER_TYPE(glm::ivec2); - REGISTER_TYPE(glm::ivec3); - REGISTER_TYPE(glm::ivec4); - REGISTER_TYPE(glm::uvec2); - REGISTER_TYPE(glm::uvec3); - REGISTER_TYPE(glm::uvec4); - - REGISTER_TYPE(glm::mat2x2); - REGISTER_TYPE(glm::mat2x3); - REGISTER_TYPE(glm::mat2x4); - REGISTER_TYPE(glm::mat3x2); - REGISTER_TYPE(glm::mat3x3); - REGISTER_TYPE(glm::mat3x4); - REGISTER_TYPE(glm::mat4x2); - REGISTER_TYPE(glm::mat4x3); - REGISTER_TYPE(glm::mat4x4); - - REGISTER_TYPE(glm::dmat2x2); - REGISTER_TYPE(glm::dmat2x3); - REGISTER_TYPE(glm::dmat2x4); - REGISTER_TYPE(glm::dmat3x2); - REGISTER_TYPE(glm::dmat3x3); - REGISTER_TYPE(glm::dmat3x4); - REGISTER_TYPE(glm::dmat4x2); - REGISTER_TYPE(glm::dmat4x3); - REGISTER_TYPE(glm::dmat4x4); - - REGISTER_TYPE(glm::quat); -#endif - - register_type<std::string>("std::string", detail::string_serdes{}); - - return true; -}(); - -void detail::ostream_write(std::ostream& out, const char* data, size_t size) { out.write(data, size); } - -void detail::ostream_read(std::istream& in, char* data, size_t size) { in.read(data, size); } - -} // namespace polymesh diff --git a/src/polymesh/formats/pm.hh b/src/polymesh/formats/pm.hh deleted file mode 100644 index 287c742a24870722b41f72338868b9ae220f5a3f..0000000000000000000000000000000000000000 --- a/src/polymesh/formats/pm.hh +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -#include <iosfwd> -#include <string> - -#include "../Mesh.hh" -#include "../attributes.hh" - -#include "../detail/AttributeSerializer.hh" - -namespace polymesh -{ -void write_pm(std::string const& filename, Mesh const& mesh, attribute_collection const& attributes); -void write_pm(std::ostream& out, Mesh const& mesh, attribute_collection const& attributes); - -bool read_pm(std::string const& filename, Mesh& mesh, attribute_collection& attributes); -bool read_pm(std::istream& input, Mesh& mesh, attribute_collection& attributes); - -namespace detail -{ -void ostream_write(std::ostream& out, char const* data, size_t size); -void ostream_read(std::istream& in, char* data, size_t size); - -template <typename T> -struct bytewise_serdes -{ - void serialize(std::ostream& out, T const* data, size_t num_items) const - { - ostream_write(out, reinterpret_cast<char const*>(data), num_items * sizeof(T)); - } - void deserialize(std::istream& in, T* data, size_t num_items) const { ostream_read(in, reinterpret_cast<char*>(data), num_items * sizeof(T)); } -}; - -struct string_serdes -{ - void serialize(std::ostream& out, std::string const* strings, size_t num_items) const - { - for (size_t i = 0; i < num_items; i++) - ostream_write(out, strings[i].c_str(), strings[i].size() + 1); - } - void deserialize(std::istream& in, std::string* strings, size_t num_items) const - { - for (size_t i = 0; i < num_items; i++) - std::getline(in, strings[i], '\0'); - } -}; - -void register_attribute_serializer(std::string const& identifier, unique_ptr<detail::GenericAttributeSerializer> ptr); -} - -template <typename T, typename serdes = detail::bytewise_serdes<T>> -void register_type(std::string const& identifier, serdes&& serializer = detail::bytewise_serdes<T>{}) -{ - unique_ptr<detail::GenericAttributeSerializer> ptr; - ptr.reset(new detail::AttributeSerializer<T, serdes>(serializer)); - detail::register_attribute_serializer(identifier, std::move(ptr)); -} -}