You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
6.1 KiB

/*
* tinyply 2.3.2 (https://github.com/ddiakopoulos/tinyply)
*
* A single-header, zero-dependency (except the C++ STL) public domain implementation
* of the PLY mesh file format. Requires C++11; errors are handled through exceptions.
*
* This software is in the public domain. Where that dedication is not
* recognized, you are granted a perpetual, irrevocable license to copy,
* distribute, and modify this file as you see fit.
*
* Authored by Dimitri Diakopoulos (http://www.dimitridiakopoulos.com)
*
* tinyply.h may be included in many files, however in a single compiled file,
* the implementation must be created with the following defined prior to header inclusion
* #define TINYPLY_IMPLEMENTATION
*
*/
////////////////////////
// tinyply header //
////////////////////////
#ifndef tinyply_h
#define tinyply_h
#include "igl_inline.h"
#include <vector>
#include <string>
#include <stdint.h>
#include <cstddef>
#include <sstream>
#include <memory>
#include <unordered_map>
#include <map>
#include <algorithm>
#include <functional>
#include <stdint.h>
namespace igl
{
namespace tinyply
{
enum class Type : uint8_t
{
INVALID,
INT8,
UINT8,
INT16,
UINT16,
INT32,
UINT32,
FLOAT32,
FLOAT64
};
struct PropertyInfo
{
PropertyInfo() {};
PropertyInfo(int stride, std::string str)
: stride(stride), str(str) {}
int stride {0};
std::string str;
};
static std::map<Type, PropertyInfo> PropertyTable
{
{ Type::INT8, PropertyInfo(1, std::string("char")) },
{ Type::UINT8, PropertyInfo(1, std::string("uchar")) },
{ Type::INT16, PropertyInfo(2, std::string("short")) },
{ Type::UINT16, PropertyInfo(2, std::string("ushort")) },
{ Type::INT32, PropertyInfo(4, std::string("int")) },
{ Type::UINT32, PropertyInfo(4, std::string("uint")) },
{ Type::FLOAT32, PropertyInfo(4, std::string("float")) },
{ Type::FLOAT64, PropertyInfo(8, std::string("double")) },
{ Type::INVALID, PropertyInfo(0, std::string("INVALID"))}
};
class Buffer
{
uint8_t * alias{ nullptr };
struct delete_array { void operator()(uint8_t * p) { delete[] p; } };
std::unique_ptr<uint8_t, decltype(Buffer::delete_array())> data;
size_t size {0};
public:
Buffer() {};
Buffer(const size_t size) : data(new uint8_t[size], delete_array()), size(size) { alias = data.get(); } // allocating
Buffer(uint8_t * ptr): alias(ptr) { } // non-allocating, todo: set size?
uint8_t * get() { return alias; }
size_t size_bytes() const { return size; }
};
struct PlyData
{
Type t;
Buffer buffer;
size_t count {0};
bool isList {false};
};
struct PlyProperty
{
PlyProperty(std::istream & is);
PlyProperty(Type type, std::string & _name) : name(_name), propertyType(type) {}
PlyProperty(Type list_type, Type prop_type, std::string & _name, size_t list_count)
: name(_name), propertyType(prop_type), isList(true), listType(list_type), listCount(list_count) {}
std::string name;
Type propertyType{ Type::INVALID };
bool isList{ false };
Type listType{ Type::INVALID };
size_t listCount {0};
};
struct PlyElement
{
PlyElement(std::istream & istream);
PlyElement(const std::string & _name, size_t count) : name(_name), size(count) {}
std::string name;
size_t size {0};
std::vector<PlyProperty> properties;
};
struct PlyFile
{
struct PlyFileImpl;
std::unique_ptr<PlyFileImpl> impl;
PlyFile();
~PlyFile();
/*
* The ply format requires an ascii header. This can be used to determine at
* runtime which properties or elements exist in the file. Limited validation of the
* header is performed; it is assumed the header correctly reflects the contents of the
* payload. This function may throw. Returns true on success, false on failure.
*/
bool parse_header(std::istream & is);
/*
* Execute a read operation. Data must be requested via `request_properties_from_element(...)`
* prior to calling this function.
*/
void read(std::istream & is);
/*
* `write` performs no validation and assumes that the data passed into
* `add_properties_to_element` is well-formed.
*/
void write(std::ostream & os, bool isBinary);
/*
* These functions are valid after a call to `parse_header(...)`. In the case of
* writing, get_comments() reference may also be used to add new comments to the ply header.
*/
std::vector<PlyElement> get_elements() const;
std::vector<std::string> get_info() const;
std::vector<std::string> & get_comments();
bool is_binary_file() const;
/*
* In the general case where |list_size_hint| is zero, `read` performs a two-pass
* parse to support variable length lists. The most general use of the
* ply format is storing triangle meshes. When this fact is known a-priori, we can pass
* an expected list length that will apply to this element. Doing so results in an up-front
* memory allocation and a single-pass import, a 2x performance optimization.
*/
std::shared_ptr<PlyData> request_properties_from_element(const std::string & elementKey,
const std::vector<std::string> propertyKeys, const uint32_t list_size_hint = 0);
void add_properties_to_element(const std::string & elementKey,
const std::vector<std::string> propertyKeys,
const Type type,
const size_t count,
uint8_t * data,
const Type listType,
const size_t listCount);
};
} // end namespace tinyply
} // end namespace igl
#ifndef IGL_STATIC_LIBRARY
// implementation moved to tinyply.cpp
# include "tinyply.cpp"
#endif
#endif // end tinyply_h