tinyply.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. * tinyply 2.3.2 (https://github.com/ddiakopoulos/tinyply)
  3. *
  4. * A single-header, zero-dependency (except the C++ STL) public domain implementation
  5. * of the PLY mesh file format. Requires C++11; errors are handled through exceptions.
  6. *
  7. * This software is in the public domain. Where that dedication is not
  8. * recognized, you are granted a perpetual, irrevocable license to copy,
  9. * distribute, and modify this file as you see fit.
  10. *
  11. * Authored by Dimitri Diakopoulos (http://www.dimitridiakopoulos.com)
  12. *
  13. * tinyply.h may be included in many files, however in a single compiled file,
  14. * the implementation must be created with the following defined prior to header inclusion
  15. * #define TINYPLY_IMPLEMENTATION
  16. *
  17. */
  18. ////////////////////////
  19. // tinyply header //
  20. ////////////////////////
  21. #ifndef tinyply_h
  22. #define tinyply_h
  23. #include "igl_inline.h"
  24. #include <vector>
  25. #include <string>
  26. #include <stdint.h>
  27. #include <cstddef>
  28. #include <sstream>
  29. #include <memory>
  30. #include <unordered_map>
  31. #include <map>
  32. #include <algorithm>
  33. #include <functional>
  34. namespace igl
  35. {
  36. namespace tinyply
  37. {
  38. enum class Type : uint8_t
  39. {
  40. INVALID,
  41. INT8,
  42. UINT8,
  43. INT16,
  44. UINT16,
  45. INT32,
  46. UINT32,
  47. FLOAT32,
  48. FLOAT64
  49. };
  50. struct PropertyInfo
  51. {
  52. PropertyInfo() {};
  53. PropertyInfo(int stride, std::string str)
  54. : stride(stride), str(str) {}
  55. int stride {0};
  56. std::string str;
  57. };
  58. static std::map<Type, PropertyInfo> PropertyTable
  59. {
  60. { Type::INT8, PropertyInfo(1, std::string("char")) },
  61. { Type::UINT8, PropertyInfo(1, std::string("uchar")) },
  62. { Type::INT16, PropertyInfo(2, std::string("short")) },
  63. { Type::UINT16, PropertyInfo(2, std::string("ushort")) },
  64. { Type::INT32, PropertyInfo(4, std::string("int")) },
  65. { Type::UINT32, PropertyInfo(4, std::string("uint")) },
  66. { Type::FLOAT32, PropertyInfo(4, std::string("float")) },
  67. { Type::FLOAT64, PropertyInfo(8, std::string("double")) },
  68. { Type::INVALID, PropertyInfo(0, std::string("INVALID"))}
  69. };
  70. class Buffer
  71. {
  72. uint8_t * alias{ nullptr };
  73. struct delete_array { void operator()(uint8_t * p) { delete[] p; } };
  74. std::unique_ptr<uint8_t, decltype(Buffer::delete_array())> data;
  75. size_t size {0};
  76. public:
  77. Buffer() {};
  78. Buffer(const size_t size) : data(new uint8_t[size], delete_array()), size(size) { alias = data.get(); } // allocating
  79. Buffer(uint8_t * ptr): alias(ptr) { } // non-allocating, todo: set size?
  80. uint8_t * get() { return alias; }
  81. size_t size_bytes() const { return size; }
  82. };
  83. struct PlyData
  84. {
  85. Type t;
  86. Buffer buffer;
  87. size_t count {0};
  88. bool isList {false};
  89. };
  90. struct PlyProperty
  91. {
  92. PlyProperty(std::istream & is);
  93. PlyProperty(Type type, std::string & _name) : name(_name), propertyType(type) {}
  94. PlyProperty(Type list_type, Type prop_type, std::string & _name, size_t list_count)
  95. : name(_name), propertyType(prop_type), isList(true), listType(list_type), listCount(list_count) {}
  96. std::string name;
  97. Type propertyType{ Type::INVALID };
  98. bool isList{ false };
  99. Type listType{ Type::INVALID };
  100. size_t listCount {0};
  101. };
  102. struct PlyElement
  103. {
  104. PlyElement(std::istream & istream);
  105. PlyElement(const std::string & _name, size_t count) : name(_name), size(count) {}
  106. std::string name;
  107. size_t size {0};
  108. std::vector<PlyProperty> properties;
  109. };
  110. struct PlyFile
  111. {
  112. struct PlyFileImpl;
  113. std::unique_ptr<PlyFileImpl> impl;
  114. PlyFile();
  115. ~PlyFile();
  116. /*
  117. * The ply format requires an ascii header. This can be used to determine at
  118. * runtime which properties or elements exist in the file. Limited validation of the
  119. * header is performed; it is assumed the header correctly reflects the contents of the
  120. * payload. This function may throw. Returns true on success, false on failure.
  121. */
  122. bool parse_header(std::istream & is);
  123. /*
  124. * Execute a read operation. Data must be requested via `request_properties_from_element(...)`
  125. * prior to calling this function.
  126. */
  127. void read(std::istream & is);
  128. /*
  129. * `write` performs no validation and assumes that the data passed into
  130. * `add_properties_to_element` is well-formed.
  131. */
  132. void write(std::ostream & os, bool isBinary);
  133. /*
  134. * These functions are valid after a call to `parse_header(...)`. In the case of
  135. * writing, get_comments() reference may also be used to add new comments to the ply header.
  136. */
  137. std::vector<PlyElement> get_elements() const;
  138. std::vector<std::string> get_info() const;
  139. std::vector<std::string> & get_comments();
  140. bool is_binary_file() const;
  141. /*
  142. * In the general case where |list_size_hint| is zero, `read` performs a two-pass
  143. * parse to support variable length lists. The most general use of the
  144. * ply format is storing triangle meshes. When this fact is known a-priori, we can pass
  145. * an expected list length that will apply to this element. Doing so results in an up-front
  146. * memory allocation and a single-pass import, a 2x performance optimization.
  147. */
  148. std::shared_ptr<PlyData> request_properties_from_element(const std::string & elementKey,
  149. const std::vector<std::string> propertyKeys, const uint32_t list_size_hint = 0);
  150. void add_properties_to_element(const std::string & elementKey,
  151. const std::vector<std::string> propertyKeys,
  152. const Type type,
  153. const size_t count,
  154. uint8_t * data,
  155. const Type listType,
  156. const size_t listCount);
  157. };
  158. } // end namespace tinyply
  159. } // end namespace igl
  160. #ifndef IGL_STATIC_LIBRARY
  161. // implementation moved to tinyply.cpp
  162. # include "tinyply.cpp"
  163. #endif
  164. #endif // end tinyply_h