tinyply.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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. #include <stdint.h>
  35. namespace igl
  36. {
  37. namespace tinyply
  38. {
  39. enum class Type : uint8_t
  40. {
  41. INVALID,
  42. INT8,
  43. UINT8,
  44. INT16,
  45. UINT16,
  46. INT32,
  47. UINT32,
  48. FLOAT32,
  49. FLOAT64
  50. };
  51. struct PropertyInfo
  52. {
  53. PropertyInfo() {};
  54. PropertyInfo(int stride, std::string str)
  55. : stride(stride), str(str) {}
  56. int stride {0};
  57. std::string str;
  58. };
  59. static std::map<Type, PropertyInfo> PropertyTable
  60. {
  61. { Type::INT8, PropertyInfo(1, std::string("char")) },
  62. { Type::UINT8, PropertyInfo(1, std::string("uchar")) },
  63. { Type::INT16, PropertyInfo(2, std::string("short")) },
  64. { Type::UINT16, PropertyInfo(2, std::string("ushort")) },
  65. { Type::INT32, PropertyInfo(4, std::string("int")) },
  66. { Type::UINT32, PropertyInfo(4, std::string("uint")) },
  67. { Type::FLOAT32, PropertyInfo(4, std::string("float")) },
  68. { Type::FLOAT64, PropertyInfo(8, std::string("double")) },
  69. { Type::INVALID, PropertyInfo(0, std::string("INVALID"))}
  70. };
  71. class Buffer
  72. {
  73. uint8_t * alias{ nullptr };
  74. struct delete_array { void operator()(uint8_t * p) { delete[] p; } };
  75. std::unique_ptr<uint8_t, decltype(Buffer::delete_array())> data;
  76. size_t size {0};
  77. public:
  78. Buffer() {};
  79. Buffer(const size_t size) : data(new uint8_t[size], delete_array()), size(size) { alias = data.get(); } // allocating
  80. Buffer(uint8_t * ptr): alias(ptr) { } // non-allocating, todo: set size?
  81. uint8_t * get() { return alias; }
  82. size_t size_bytes() const { return size; }
  83. };
  84. struct PlyData
  85. {
  86. Type t;
  87. Buffer buffer;
  88. size_t count {0};
  89. bool isList {false};
  90. };
  91. struct PlyProperty
  92. {
  93. PlyProperty(std::istream & is);
  94. PlyProperty(Type type, std::string & _name) : name(_name), propertyType(type) {}
  95. PlyProperty(Type list_type, Type prop_type, std::string & _name, size_t list_count)
  96. : name(_name), propertyType(prop_type), isList(true), listType(list_type), listCount(list_count) {}
  97. std::string name;
  98. Type propertyType{ Type::INVALID };
  99. bool isList{ false };
  100. Type listType{ Type::INVALID };
  101. size_t listCount {0};
  102. };
  103. struct PlyElement
  104. {
  105. PlyElement(std::istream & istream);
  106. PlyElement(const std::string & _name, size_t count) : name(_name), size(count) {}
  107. std::string name;
  108. size_t size {0};
  109. std::vector<PlyProperty> properties;
  110. };
  111. struct PlyFile
  112. {
  113. struct PlyFileImpl;
  114. std::unique_ptr<PlyFileImpl> impl;
  115. PlyFile();
  116. ~PlyFile();
  117. /*
  118. * The ply format requires an ascii header. This can be used to determine at
  119. * runtime which properties or elements exist in the file. Limited validation of the
  120. * header is performed; it is assumed the header correctly reflects the contents of the
  121. * payload. This function may throw. Returns true on success, false on failure.
  122. */
  123. bool parse_header(std::istream & is);
  124. /*
  125. * Execute a read operation. Data must be requested via `request_properties_from_element(...)`
  126. * prior to calling this function.
  127. */
  128. void read(std::istream & is);
  129. /*
  130. * `write` performs no validation and assumes that the data passed into
  131. * `add_properties_to_element` is well-formed.
  132. */
  133. void write(std::ostream & os, bool isBinary);
  134. /*
  135. * These functions are valid after a call to `parse_header(...)`. In the case of
  136. * writing, get_comments() reference may also be used to add new comments to the ply header.
  137. */
  138. std::vector<PlyElement> get_elements() const;
  139. std::vector<std::string> get_info() const;
  140. std::vector<std::string> & get_comments();
  141. bool is_binary_file() const;
  142. /*
  143. * In the general case where |list_size_hint| is zero, `read` performs a two-pass
  144. * parse to support variable length lists. The most general use of the
  145. * ply format is storing triangle meshes. When this fact is known a-priori, we can pass
  146. * an expected list length that will apply to this element. Doing so results in an up-front
  147. * memory allocation and a single-pass import, a 2x performance optimization.
  148. */
  149. std::shared_ptr<PlyData> request_properties_from_element(const std::string & elementKey,
  150. const std::vector<std::string> propertyKeys, const uint32_t list_size_hint = 0);
  151. void add_properties_to_element(const std::string & elementKey,
  152. const std::vector<std::string> propertyKeys,
  153. const Type type,
  154. const size_t count,
  155. uint8_t * data,
  156. const Type listType,
  157. const size_t listCount);
  158. };
  159. } // end namespace tinyply
  160. } // end namespace igl
  161. #ifndef IGL_STATIC_LIBRARY
  162. // implementation moved to tinyply.cpp
  163. # include "tinyply.cpp"
  164. #endif
  165. #endif // end tinyply_h