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.
 
 
 
 
 
 

315 lines
9.9 KiB

////////////////////////////////////////////////////////////////////
// PLY.h
//
// Copyright 2023 cDc@seacave
// Distributed under the Boost Software License, Version 1.0
// (See http://www.boost.org/LICENSE_1_0.txt)
//
// PLY polygon files parser.
// (originally by Greg Turk, heavily modified by cDc@seacave)
//
// A PLY file contains a single polygonal _object_.
//
// An object is composed of lists of _elements_. Typical elements are
// vertices, faces, edges and materials.
//
// Each type of element for a given object has one or more _properties_
// associated with the element type. For instance, a vertex element may
// have as properties three floating-point values x,y,z and three unsigned
// chars for red, green and blue.
#ifndef __SEACAVE_PLY_H__
#define __SEACAVE_PLY_H__
// I N C L U D E S /////////////////////////////////////////////////
// D E F I N E S ///////////////////////////////////////////////////
#define PLY_OKAY 0 // ply routine worked okay
#define PLY_ERROR -1 // error in ply routine
// S T R U C T S ///////////////////////////////////////////////////
class IO_API PLY
{
public:
// scalar data types supported by PLY format
enum FileType {
ASCII = 1, // ascii PLY file
BINARY_BE = 2, // binary PLY file, big endian
BINARY_LE = 3, // binary PLY file, little endian
};
enum DataType {
StartType = 0,
Int8 = 1,
Int16 = 2,
Int32 = 3,
Uint8 = 4,
Uint16 = 5,
Uint32 = 6,
Float32 = 7,
Float64 = 8,
EndType = 9,
};
enum ListType {
SCALAR = 0,
LIST = 1,
STRING = 2,
};
enum RuleType {
AVERAGE_RULE = 1,
MAJORITY_RULE = 2,
MINIMUM_RULE = 3,
MAXIMUM_RULE = 4,
SAME_RULE = 5,
RANDOM_RULE = 6,
};
// description of a property
struct PlyProperty {
std::string name; // property name
int external_type; // file's data type
int internal_type; // program's data type
int offset; // offset bytes of prop in a struct
int is_list; // 0 = scalar, 1 = list, 2 = char string
int count_external; // file's count type
int count_internal; // program's count type
int count_offset; // offset byte for list count
};
// description of an element
struct PlyElement {
std::string name; // element name
int num; // number of elements in this object
int size; // size of element (bytes) or -1 if variable
std::vector<PlyProperty*> props;// list of properties in the file
std::vector<char> store_prop; // flags: property wanted by user?
int other_offset; // offset to un-asked-for props, or -1 if none
int other_size; // size of other_props structure
};
// describes other properties in an element
struct PlyOtherProp {
std::string name; // element name
int size; // size of other_props
std::vector<PlyProperty*> props;// list of properties in other_props
};
// for storing other_props for an other element
struct OtherData {
void* other_props;
};
// data for one "other" element
struct OtherElem {
std::string elem_name; // names of other elements
int elem_count; // count of instances of each element
OtherData** other_data; // actual property data for the elements
PlyOtherProp* other_props; // description of the property data
};
// "other" elements, not interpreted by user
struct PlyOtherElems {
std::vector<OtherElem> other_list;// list of data for other elements
};
// rules for combining "other" properties
struct PlyPropRules {
PlyElement* elem; // element whose rules we are making
int* rule_list; // types of rules (AVERAGE_PLY, MAJORITY_PLY, etc.)
uint32_t max_props; // maximum number of properties we have room for now
std::vector<void*> props; // list of properties we're combining
std::vector<float> weights; // list of weights of the properties
};
struct PlyRuleList {
LPCSTR name; // name of the rule
char* element; // name of element that rule applies to
char* property; // name of property that rule applies to
struct PlyRuleList* next; // pointer for linked list of rules
};
// property propagation rules
struct RuleName {
int code;
std::string name;
};
protected:
struct ValueType {
union {
int8_t i8;
int16_t i16;
int32_t i32;
uint8_t u8;
uint16_t u16;
uint32_t u32;
float f;
double d;
};
};
public:
PLY();
~PLY();
bool read(LPCSTR);
bool read(SEACAVE::ISTREAM*);
bool write(LPCSTR, int, LPCSTR*, int, size_t memBufferSize=0);
bool write(SEACAVE::OSTREAM*, int, LPCSTR*, int, size_t memBufferSize=0);
void release();
void set_legacy_type_names();
void get_info(float*, int*);
void append_comment(const char*);
void append_obj_info(const char*);
void copy_comments(const PLY&);
void copy_obj_info(const PLY&);
std::vector<std::string>& get_comments();
std::vector<std::string>& get_obj_info();
void describe_property(const char*, const PlyProperty&);
void describe_property(const char*, int nprops, const PlyProperty*);
void get_property(const char*, PlyProperty*);
void get_element(void*);
PlyOtherElems* get_other_element();
int get_element_list(std::vector<std::string>&) const;
void setup_property(const PlyProperty&);
LPCSTR setup_element_read(int, int*);
PlyOtherProp* get_other_properties(int);
int get_elements_count() const { return (int)elems.size(); }
int get_current_element_count() const { return which_elem->num; }
void element_count(const char*, int);
void describe_element(const char*, int);
void describe_property(const PlyProperty&);
void describe_other_properties(PlyOtherProp*, int);
void describe_other_elements( PlyOtherElems*);
void get_element_setup(const char*, int, PlyProperty*);
int get_element_description(const char*, std::vector<PlyProperty*>&) const;
void element_layout(const char*, int, int, PlyProperty*);
bool header_complete();
void put_element_setup(const char*);
void put_element(const void*);
void put_other_elements();
PlyPropRules* init_rule(const char*);
void modify_rule(PlyPropRules*, const char*, int);
void start_props(PlyPropRules*);
void weight_props(float, void*);
void* get_new_props();
void set_prop_rules(PlyRuleList*);
PlyRuleList* append_prop_rule(PlyRuleList*, const char*, const char*);
// find an element in a ply's list
PlyElement* find_element(const char*) const;
// find a property in an element's list
int find_property(PlyElement*, const char*) const;
static inline bool equal_strings(const char* s1, const char* s2) { return _tcscmp(s1, s2) == 0; }
protected:
// write to a file the word describing a PLY file data type
void write_scalar_type(int);
// read a line from a file and break it up into separate words
typedef SEACAVE::TokenInputStream<false> STRISTREAM;
char** get_words(STRISTREAM&, int*, char**);
// write an item to a file
void write_binary_item(const ValueType&, int, int);
void write_ascii_item(const ValueType&, int, int);
// return the value of a stored item
static void get_stored_item(const void*, int, ValueType&);
// get binary or ascii item and store it according to ptr and type
void get_binary_item(int, ValueType&);
static void get_ascii_item(const char*, int, ValueType&);
// store a value into where a pointer and a type specify
static void store_item(void*, int, const ValueType&, int);
// add information to a PLY file descriptor
void add_element(const char**, int);
void add_property(const char**, int);
void add_comment(const char*);
void add_obj_info(const char*);
// get a bunch of elements from a file
void ascii_get_element(uint8_t*);
void binary_get_element(uint8_t*);
void setup_other_props(PlyElement*);
PlyOtherProp* get_other_properties(PlyElement*, int);
PlyOtherProp* get_other_properties(const char*, int);
int matches_rule_name(const char*);
int get_prop_type(const char*);
// copy a property
static void copy_property(PlyProperty&, const PlyProperty&);
// return the value as T stored in val as type
template <typename T>
static inline T ValueType2Type(const ValueType& val, int type) {
switch (type) {
case Int8:
return (T)val.i8;
case Int16:
return (T)val.i16;
case Int32:
return (T)val.i32;
case Uint8:
return (T)val.u8;
case Uint16:
return (T)val.u16;
case Uint32:
return (T)val.u32;
case Float32:
return (T)val.f;
case Float64:
return (T)val.d;
}
ASSERT("error: bad type" == NULL);
return T(0);
}
protected:
// description of PLY file
std::string filename; // file name
int file_type; // ascii or binary
float version; // version number of file
std::vector<PlyElement*> elems; // list of elements
std::vector<std::string> comments;// list of comments
std::vector<std::string> obj_info;// list of object info items
PlyElement* which_elem; // element we're currently reading or writing
PlyOtherElems* other_elems; // "other" elements from a PLY file
PlyPropRules* current_rules; // current propagation rules
PlyRuleList* rule_list; // rule list from user
std::vector<double> vals; // rule list from user
union {
SEACAVE::ISTREAM* istream; // input file pointer
SEACAVE::OSTREAM* ostream; // output file pointer
};
SEACAVE::MemFile* mfp; // mem-file pointer (optional)
const char* const* write_type_names; // names of scalar types to be used for writing (new types by default)
static const char* const type_names[9]; // names of scalar types
static const char* const old_type_names[9]; // old names of types for backward compatibility
static const int ply_type_size[9];
static const RuleName rule_name_list[7];
};
#endif // __SEACAVE_PLY_H__