49 #include <OpenMesh/Core/IO/reader/PLYReader.hh> 50 #include <OpenMesh/Core/IO/IOManager.hh> 51 #include <OpenMesh/Core/Utils/color_cast.hh> 80 _PLYReader_::_PLYReader_() {
108 std::fstream in(_filename.c_str(), (std::ios_base::binary | std::ios_base::in) );
110 if (!in.is_open() || !in.good()) {
111 omerr() <<
"[PLYReader] : cannot not open file " << _filename << std::endl;
115 bool result =
read(in, _bi, _opt);
127 omerr() <<
"[PLYReader] : cannot not use stream" << std::endl;
133 omerr() <<
"[PLYReader] : Unable to parse header\n";
173 return (
options_.is_binary() ? read_binary(_in, _bi, swap, _opt) : read_ascii(_in, _bi, _opt));
177 template<
typename T,
typename Handle>
193 template<
bool binary,
typename T,
typename Handle>
194 void _PLYReader_::readCreateCustomProperty(std::istream& _in,
BaseImporter& _bi, Handle _h,
const std::string& _propName,
const _PLYReader_::ValueType _valueType,
const _PLYReader_::ValueType _listType)
const 196 if (_listType == Unsupported)
203 _bi.kernel()->
property(prop).set_persistent(
true);
208 read(_valueType, _in, in, OpenMesh::GenProg::Bool2Type<binary>());
209 _bi.kernel()->
property(prop,_h) = in;
218 _bi.kernel()->
property(prop).set_persistent(
true);
222 unsigned int numberOfValues;
223 readInteger(_listType, _in, numberOfValues, OpenMesh::GenProg::Bool2Type<binary>());
224 std::vector<T> vec(numberOfValues);
226 for (
unsigned int i = 0; i < numberOfValues; ++i)
228 read(_valueType, _in, vec[i], OpenMesh::GenProg::Bool2Type<binary>());
230 _bi.kernel()->
property(prop,_h) = vec;
234 template<
bool binary,
typename Handle>
235 void _PLYReader_::readCustomProperty(std::istream& _in,
BaseImporter& _bi, Handle _h,
const std::string& _propName,
const _PLYReader_::ValueType _valueType,
const _PLYReader_::ValueType _listIndexType)
const 241 readCreateCustomProperty<binary,signed char>(_in,_bi,_h,_propName,_valueType,_listIndexType);
245 readCreateCustomProperty<binary,unsigned char>(_in,_bi,_h,_propName,_valueType,_listIndexType);
249 readCreateCustomProperty<binary,short>(_in,_bi,_h,_propName,_valueType,_listIndexType);
251 case ValueTypeUINT16:
252 case ValueTypeUSHORT:
253 readCreateCustomProperty<binary,unsigned short>(_in,_bi,_h,_propName,_valueType,_listIndexType);
257 readCreateCustomProperty<binary,int>(_in,_bi,_h,_propName,_valueType,_listIndexType);
259 case ValueTypeUINT32:
261 readCreateCustomProperty<binary,unsigned int>(_in,_bi,_h,_propName,_valueType,_listIndexType);
263 case ValueTypeFLOAT32:
265 readCreateCustomProperty<binary,float>(_in,_bi,_h,_propName,_valueType,_listIndexType);
267 case ValueTypeFLOAT64:
268 case ValueTypeDOUBLE:
269 readCreateCustomProperty<binary,double>(_in,_bi,_h,_propName,_valueType,_listIndexType);
272 std::cerr <<
"unsupported type" << std::endl;
280 bool _PLYReader_::read_ascii(std::istream& _in,
BaseImporter& _bi,
const Options& _opt)
const {
282 unsigned int i, j, k, l, idx;
289 BaseImporter::VHandles vhandles;
292 _bi.reserve(vertexCount_, 3* vertexCount_ , faceCount_);
294 if (vertexDimension_ != 3) {
295 omerr() <<
"[PLYReader] : Only vertex dimension 3 is supported." << std::endl;
299 const bool err_enabled = omerr().is_enabled();
300 size_t complex_faces = 0;
304 for (std::vector<ElementInfo>::iterator e_it = elements_.begin(); e_it != elements_.end(); ++e_it)
310 omerr() <<
"Unexpected end of file while reading." << std::endl;
314 if (e_it->element_== VERTEX)
317 for (i = 0; i < e_it->count_ && !_in.eof(); ++i) {
318 vh = _bi.add_vertex();
336 for (
size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex) {
338 switch (prop.property) {
364 if (prop.value == ValueTypeFLOAT32 ||
365 prop.value == ValueTypeFLOAT) {
373 if (prop.value == ValueTypeFLOAT32 ||
374 prop.value == ValueTypeFLOAT) {
382 if (prop.value == ValueTypeFLOAT32 ||
383 prop.value == ValueTypeFLOAT) {
391 if (prop.value == ValueTypeFLOAT32 ||
392 prop.value == ValueTypeFLOAT) {
401 readCustomProperty<false>(_in, _bi, vh, prop.name, prop.value, prop.listIndexType);
411 _bi.set_point(vh, v);
412 if (_opt.vertex_has_normal())
413 _bi.set_normal(vh, n);
414 if (_opt.vertex_has_texcoord())
415 _bi.set_texcoord(vh, t);
416 if (_opt.vertex_has_color())
417 _bi.set_color(vh,
Vec4uc(c));
420 else if (e_it->element_ == FACE)
423 for (i = 0; i < faceCount_ && !_in.eof(); ++i) {
431 for (
size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex) {
433 switch (prop.property) {
451 for (j = 0; j < nV; ++j) {
457 fh = _bi.add_face(vhandles);
463 if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
471 if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
479 if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
487 if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
496 readCustomProperty<false>(_in, _bi, fh, prop.name, prop.value, prop.listIndexType);
506 if (_opt.face_has_color())
507 _bi.set_color(fh,
Vec4uc(c));
513 for (i = 0; i < e_it->count_ && !_in.eof(); ++i) {
514 for (
size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex)
522 if(e_it->element_== FACE)
531 omerr() << complex_faces <<
"The reader encountered invalid faces, that could not be added.\n";
539 bool _PLYReader_::read_binary(std::istream& _in,
BaseImporter& _bi,
bool ,
const Options& _opt)
const {
543 BaseImporter::VHandles vhandles;
548 _bi.reserve(vertexCount_, 3* vertexCount_ , faceCount_);
550 const bool err_enabled = omerr().is_enabled();
551 size_t complex_faces = 0;
555 for (std::vector<ElementInfo>::iterator e_it = elements_.begin(); e_it != elements_.end(); ++e_it)
557 if (e_it->element_ == VERTEX)
560 for (
unsigned int i = 0; i < e_it->count_ && !_in.eof(); ++i) {
561 vh = _bi.add_vertex();
579 for (
size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex) {
581 switch (prop.property) {
583 readValue(prop.value, _in, v[0]);
586 readValue(prop.value, _in, v[1]);
589 readValue(prop.value, _in, v[2]);
592 readValue(prop.value, _in, n[0]);
595 readValue(prop.value, _in, n[1]);
598 readValue(prop.value, _in, n[2]);
601 readValue(prop.value, _in, t[0]);
604 readValue(prop.value, _in, t[1]);
607 if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
608 readValue(prop.value, _in, tmp);
613 readInteger(prop.value, _in, c[0]);
617 if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
618 readValue(prop.value, _in, tmp);
622 readInteger(prop.value, _in, c[1]);
626 if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
627 readValue(prop.value, _in, tmp);
631 readInteger(prop.value, _in, c[2]);
635 if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
636 readValue(prop.value, _in, tmp);
640 readInteger(prop.value, _in, c[3]);
645 readCustomProperty<true>(_in, _bi, vh, prop.name, prop.value, prop.listIndexType);
657 _bi.set_point(vh, v);
658 if (_opt.vertex_has_normal())
659 _bi.set_normal(vh, n);
660 if (_opt.vertex_has_texcoord())
661 _bi.set_texcoord(vh, t);
662 if (_opt.vertex_has_color())
663 _bi.set_color(vh,
Vec4uc(c));
666 else if (e_it->element_ == FACE) {
667 for (
unsigned i = 0; i < e_it->count_ && !_in.eof(); ++i) {
675 for (
size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex)
678 switch (prop.property) {
683 readInteger(prop.listIndexType, _in, nV);
687 unsigned int j, k, l;
688 readInteger(prop.value, _in, j);
689 readInteger(prop.value, _in, k);
690 readInteger(prop.value, _in, l);
698 for (
unsigned j = 0; j < nV; ++j) {
700 readInteger(prop.value, _in, idx);
705 fh = _bi.add_face(vhandles);
710 if (prop.value == ValueTypeFLOAT32 ||
711 prop.value == ValueTypeFLOAT) {
712 readValue(prop.value, _in, tmp);
715 readInteger(prop.value, _in, c[0]);
718 if (prop.value == ValueTypeFLOAT32 ||
719 prop.value == ValueTypeFLOAT) {
720 readValue(prop.value, _in, tmp);
723 readInteger(prop.value, _in, c[1]);
726 if (prop.value == ValueTypeFLOAT32 ||
727 prop.value == ValueTypeFLOAT) {
728 readValue(prop.value, _in, tmp);
731 readInteger(prop.value, _in, c[2]);
734 if (prop.value == ValueTypeFLOAT32 ||
735 prop.value == ValueTypeFLOAT) {
736 readValue(prop.value, _in, tmp);
739 readInteger(prop.value, _in, c[3]);
743 readCustomProperty<true>(_in, _bi, fh, prop.name, prop.value, prop.listIndexType);
753 if (_opt.face_has_color())
754 _bi.set_color(fh,
Vec4uc(c));
758 for (
unsigned int i = 0; i < e_it->count_ && !_in.eof(); ++i)
760 for (
size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex)
773 omerr() <<
"Unexpected end of file while reading." << std::endl;
777 if (e_it->element_ == FACE)
785 omerr() << complex_faces <<
"The reader encountered invalid faces, that could not be added.\n";
795 void _PLYReader_::readValue(ValueType _type, std::istream& _in,
float& _value)
const {
798 case ValueTypeFLOAT32:
804 case ValueTypeDOUBLE:
805 case ValueTypeFLOAT64:
807 readValue(_type, _in, dtmp);
808 _value =
static_cast<float>(dtmp);
812 std::cerr <<
"unsupported conversion type to float: " << _type << std::endl;
821 void _PLYReader_::readValue(ValueType _type, std::istream& _in,
double& _value)
const {
825 case ValueTypeFLOAT64:
827 case ValueTypeDOUBLE:
838 std::cerr <<
"unsupported conversion type to double: " << _type << std::endl;
847 void _PLYReader_::readValue(ValueType _type, std::istream& _in,
unsigned char& _value)
const{
849 readValue(_type,_in,tmp);
855 void _PLYReader_::readValue(ValueType _type, std::istream& _in,
unsigned short& _value)
const{
857 readValue(_type,_in,tmp);
863 void _PLYReader_::readValue(ValueType _type, std::istream& _in,
signed char& _value)
const{
865 readValue(_type,_in,tmp);
871 void _PLYReader_::readValue(ValueType _type, std::istream& _in,
short& _value)
const{
873 readValue(_type,_in,tmp);
879 void _PLYReader_::readValue(ValueType _type, std::istream& _in,
unsigned int& _value)
const {
889 case ValueTypeUINT32:
892 _value = tmp_uint32_t;
896 case ValueTypeUSHORT:
898 case ValueTypeUINT16:
901 _value = tmp_uint16_t;
917 std::cerr <<
"unsupported conversion type to unsigned int: " << _type << std::endl;
927 void _PLYReader_::readValue(ValueType _type, std::istream& _in,
int& _value)
const {
940 _value = tmp_int32_t;
949 _value = tmp_int16_t;
965 std::cerr <<
"unsupported conversion type to int: " << _type << std::endl;
975 void _PLYReader_::readInteger(ValueType _type, std::istream& _in, T& _value)
const {
977 static_assert(std::is_integral<T>::value,
"Integral required.");
992 _value = tmp_int16_t;
996 case ValueTypeUINT16:
998 case ValueTypeUSHORT:
1000 _value = tmp_uint16_t;
1006 case ValueTypeINT32:
1009 _value = tmp_int32_t;
1015 case ValueTypeUINT32:
1018 _value = tmp_uint32_t;
1031 case ValueTypeUCHAR:
1033 case ValueTypeUINT8:
1043 std::cerr <<
"unsupported conversion type to integral: " << _type << std::endl;
1058 std::ifstream ifs(_filename.c_str());
1071 std::string get_property_name(std::string _string1, std::string _string2) {
1073 if (_string1 ==
"float32" || _string1 ==
"float64" || _string1 ==
"float" || _string1 ==
"double" ||
1074 _string1 ==
"int8" || _string1 ==
"uint8" || _string1 ==
"char" || _string1 ==
"uchar" ||
1075 _string1 ==
"int32" || _string1 ==
"uint32" || _string1 ==
"int" || _string1 ==
"uint" ||
1076 _string1 ==
"int16" || _string1 ==
"uint16" || _string1 ==
"short" || _string1 ==
"ushort")
1079 if (_string2 ==
"float32" || _string2 ==
"float64" || _string2 ==
"float" || _string2 ==
"double" ||
1080 _string2 ==
"int8" || _string2 ==
"uint8" || _string2 ==
"char" || _string2 ==
"uchar" ||
1081 _string2 ==
"int32" || _string2 ==
"uint32" || _string2 ==
"int" || _string2 ==
"uint" ||
1082 _string2 ==
"int16" || _string2 ==
"uint16" || _string2 ==
"short" || _string2 ==
"ushort")
1086 std::cerr <<
"Unsupported entry type" << std::endl;
1087 return "Unsupported";
1092 _PLYReader_::ValueType get_property_type(std::string& _string1, std::string& _string2) {
1094 if (_string1 ==
"float32" || _string2 ==
"float32")
1096 return _PLYReader_::ValueTypeFLOAT32;
1098 else if (_string1 ==
"float64" || _string2 ==
"float64")
1100 return _PLYReader_::ValueTypeFLOAT64;
1102 else if (_string1 ==
"float" || _string2 ==
"float")
1104 return _PLYReader_::ValueTypeFLOAT;
1106 else if (_string1 ==
"double" || _string2 ==
"double")
1108 return _PLYReader_::ValueTypeDOUBLE;
1110 else if (_string1 ==
"int8" || _string2 ==
"int8")
1112 return _PLYReader_::ValueTypeINT8;
1114 else if (_string1 ==
"uint8" || _string2 ==
"uint8")
1116 return _PLYReader_::ValueTypeUINT8;
1118 else if (_string1 ==
"char" || _string2 ==
"char")
1120 return _PLYReader_::ValueTypeCHAR;
1122 else if (_string1 ==
"uchar" || _string2 ==
"uchar")
1124 return _PLYReader_::ValueTypeUCHAR;
1126 else if (_string1 ==
"int32" || _string2 ==
"int32")
1128 return _PLYReader_::ValueTypeINT32;
1130 else if (_string1 ==
"uint32" || _string2 ==
"uint32")
1132 return _PLYReader_::ValueTypeUINT32;
1134 else if (_string1 ==
"int" || _string2 ==
"int")
1136 return _PLYReader_::ValueTypeINT;
1138 else if (_string1 ==
"uint" || _string2 ==
"uint")
1140 return _PLYReader_::ValueTypeUINT;
1142 else if (_string1 ==
"int16" || _string2 ==
"int16")
1144 return _PLYReader_::ValueTypeINT16;
1146 else if (_string1 ==
"uint16" || _string2 ==
"uint16")
1148 return _PLYReader_::ValueTypeUINT16;
1150 else if (_string1 ==
"short" || _string2 ==
"short")
1152 return _PLYReader_::ValueTypeSHORT;
1154 else if (_string1 ==
"ushort" || _string2 ==
"ushort")
1156 return _PLYReader_::ValueTypeUSHORT;
1158 return _PLYReader_::Unsupported;
1174 std::getline(_is, line);
1178 const size_t s = line.size();
1179 if( s > 0 && line[s - 1] ==
'\r') line.resize(s - 1);
1182 if (line !=
"PLY" && line !=
"ply")
1187 vertexDimension_ = 0;
1189 unsigned int elementCount = 0;
1191 std::string keyword;
1192 std::string fileType;
1193 std::string elementName =
"";
1194 std::string propertyName;
1195 std::string listIndexType;
1196 std::string listEntryType;
1204 omerr() <<
"Defect PLY header detected" << std::endl;
1208 if (fileType ==
"ascii") {
1210 }
else if (fileType ==
"binary_little_endian") {
1216 }
else if (fileType ==
"binary_big_endian") {
1223 omerr() <<
"Unsupported PLY format: " << fileType << std::endl;
1227 std::streamoff streamPos = _is.tellg();
1229 while (keyword !=
"end_header") {
1231 if (keyword ==
"comment") {
1232 std::getline(_is, line);
1233 }
else if (keyword ==
"element") {
1235 _is >> elementCount;
1238 element.name_ = elementName;
1239 element.count_ = elementCount;
1241 if (elementName ==
"vertex") {
1242 vertexCount_ = elementCount;
1243 element.element_ = VERTEX;
1244 }
else if (elementName ==
"face") {
1245 faceCount_ = elementCount;
1246 element.element_ = FACE;
1248 omerr() <<
"PLY header unsupported element type: " << elementName << std::endl;
1249 element.element_ = UNKNOWN;
1252 elements_.push_back(element);
1253 }
else if (keyword ==
"property") {
1260 if (tmp1 ==
"list") {
1261 _is >> listIndexType;
1262 _is >> listEntryType;
1263 _is >> propertyName;
1265 ValueType indexType = Unsupported;
1266 ValueType entryType = Unsupported;
1268 if (listIndexType ==
"uint8") {
1269 indexType = ValueTypeUINT8;
1270 }
else if (listIndexType ==
"uint16") {
1271 indexType = ValueTypeUINT16;
1272 }
else if (listIndexType ==
"uchar") {
1273 indexType = ValueTypeUCHAR;
1274 }
else if (listIndexType ==
"int") {
1275 indexType = ValueTypeINT;
1277 omerr() <<
"Unsupported Index type for property list: " << listIndexType << std::endl;
1281 entryType = get_property_type(listEntryType, listEntryType);
1283 if (entryType == Unsupported) {
1284 omerr() <<
"Unsupported Entry type for property list: " << listEntryType << std::endl;
1287 PropertyInfo property(CUSTOM_PROP, entryType, propertyName);
1288 property.listIndexType = indexType;
1290 if (elementName ==
"face")
1293 if (propertyName ==
"vertex_index" || propertyName ==
"vertex_indices")
1295 property.property = VERTEX_INDICES;
1297 if (!elements_.back().properties_.empty())
1299 omerr() <<
"Custom face Properties defined, before 'vertex_indices' property was defined. They will be skipped" << std::endl;
1300 elements_.back().properties_.clear();
1308 omerr() <<
"property " << propertyName <<
" belongs to unsupported element " << elementName << std::endl;
1310 elements_.back().properties_.push_back(property);
1319 ValueType valueType = get_property_type(tmp1, tmp2);
1320 propertyName = get_property_name(tmp1, tmp2);
1325 if (elementName ==
"vertex") {
1326 if (propertyName ==
"x") {
1329 }
else if (propertyName ==
"y") {
1332 }
else if (propertyName ==
"z") {
1335 }
else if (propertyName ==
"nx") {
1338 }
else if (propertyName ==
"ny") {
1341 }
else if (propertyName ==
"nz") {
1344 }
else if (propertyName ==
"u" || propertyName ==
"s") {
1347 }
else if (propertyName ==
"v" || propertyName ==
"t") {
1350 }
else if (propertyName ==
"red") {
1353 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1355 }
else if (propertyName ==
"green") {
1358 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1360 }
else if (propertyName ==
"blue") {
1363 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1365 }
else if (propertyName ==
"diffuse_red") {
1368 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1370 }
else if (propertyName ==
"diffuse_green") {
1373 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1375 }
else if (propertyName ==
"diffuse_blue") {
1378 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1380 }
else if (propertyName ==
"alpha") {
1384 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1388 else if (elementName ==
"face") {
1389 if (propertyName ==
"red") {
1392 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1394 }
else if (propertyName ==
"green") {
1397 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1399 }
else if (propertyName ==
"blue") {
1402 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1404 }
else if (propertyName ==
"alpha") {
1408 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1414 if (entry.value == Unsupported){
1415 Property prop = CUSTOM_PROP;
1420 if (entry.property != UNSUPPORTED)
1422 elements_.back().properties_.push_back(entry);
1427 omlog() <<
"Unsupported keyword : " << keyword << std::endl;
1430 streamPos = _is.tellg();
1433 omerr() <<
"Error while reading PLY file header" << std::endl;
1441 _is.seekg(streamPos);
1448 if (c1 == 0x0D && c2 == 0x0A) {
1449 _is.seekg(streamPos + 14);
1452 _is.seekg(streamPos + 12);
Swap byte order in binary mode.
virtual bool can_u_read(const std::string &_filename) const
Returns true if writer can parse _filename (checks extension). _filename can also provide an extensio...
Handle for a face entity.
Assume big endian byte ordering.
Has (r) / store (w) vertex colors.
void clear(void)
Clear all bits.
Has (r) / store (w) face colors.
Has (r) / store (w) float values for colors (currently only implemented for PLY and OFF files) ...
Handle for a vertex entity.
Scalar value_type
the type of the scalar used in this template
bool read(const std::string &_filename, BaseImporter &_bi, Options &_opt) override
bool get_property_handle(VPropHandleT< T > &_ph, const std::string &_name) const
bool is_valid() const
The handle is valid iff the index is not negative.
Options userOptions_
Options that the user wants to read.
Has (r) / store (w) alpha values for colors.
bool can_u_read(const std::string &_filename) const override
Returns true if writer can parse _filename (checks extension). _filename can also provide an extensio...
bool register_module(BaseReader *_bl)
Has (r) custom properties (currently only implemented in PLY Reader ASCII version) ...
Cellection of information about a property.
void consume_input(std::istream &_in, int _count) const
Read unsupported properties in PLY file.
void cleanup(void)
Restore state after default constructor.
Set options for reader/writer modules.
PropertyT< T > & property(VPropHandleT< T > _ph)
Has (r) / store (w) vertex normals.
_IOManager_ & IOManager()
Options options_
Available per file options for reading.
_PLYReader_ __PLYReaderInstance
Declare the single entity of the PLY reader.
Assume little endian byte ordering.
void add_property(VPropHandleT< T > &_ph, const std::string &_name="<vprop>")
Has (r) / store (w) texture coordinates.
std::map< ValueType, int > scalar_size_
Stores sizes of property types.