diff --git a/Doc/tutorial_08.docu b/Doc/tutorial_08.docu index c7a0409e..394e81d5 100644 --- a/Doc/tutorial_08.docu +++ b/Doc/tutorial_08.docu @@ -65,7 +65,7 @@ ASCII is not a real option and will be selected, if binary was not defined. \li defined with vc (e.g. used by meshlab) \li colors encoded in a vertex line (v followed by 6 values) -\**) only ascii version and only vertex and face properties with fundamental types. Take into account, that you don't have to request these custom properties before loading. +\**) only vertex and face properties with fundamental types. Take into account, that you don't have to request these custom properties before loading. \***) no reader exists diff --git a/src/OpenMesh/Core/IO/reader/PLYReader.cc b/src/OpenMesh/Core/IO/reader/PLYReader.cc index b3b1340a..33855512 100644 --- a/src/OpenMesh/Core/IO/reader/PLYReader.cc +++ b/src/OpenMesh/Core/IO/reader/PLYReader.cc @@ -191,10 +191,11 @@ struct Handle2Prop typedef OpenMesh::FPropHandleT PropT; }; -template -void assignCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, bool isList) +//read and assign custom properties with the given type. Also creates property, if not exist +template +void _PLYReader_::readCreateCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const _PLYReader_::ValueType _valueType, const _PLYReader_::ValueType _listType) const { - if (!isList) + if (_listType == Unsupported) //no list type defined -> property is not a list { //get/add property typename Handle2Prop::PropT prop; @@ -206,7 +207,7 @@ void assignCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const //read and assign T in; - _in >> in; + read(_valueType, _in, in, OpenMesh::GenProg::Bool2Type()); _bi.kernel()->property(prop,_h) = in; } else @@ -221,57 +222,56 @@ void assignCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const //init vector int numberOfValues; - _in >> numberOfValues; + read(_listType, _in, numberOfValues, OpenMesh::GenProg::Bool2Type()); std::vector vec; vec.reserve(numberOfValues); //read and assign for (int i = 0; i < numberOfValues; ++i) { T in; - _in >> in; + read(_valueType, _in, in, OpenMesh::GenProg::Bool2Type()); vec.push_back(in); } _bi.kernel()->property(prop,_h) = vec; } } -template -void _PLYReader_::readCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const ValueType _valueType, const ValueType _listIndexType) const +template +void _PLYReader_::readCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const _PLYReader_::ValueType _valueType, const _PLYReader_::ValueType _listIndexType) const { - const bool isList = _listIndexType != Unsupported; switch (_valueType) { case ValueTypeINT8: case ValueTypeCHAR: - assignCustomProperty(_in,_bi,_h,_propName,isList); + readCreateCustomProperty(_in,_bi,_h,_propName,_valueType,_listIndexType); break; case ValueTypeUINT8: case ValueTypeUCHAR: - assignCustomProperty(_in,_bi,_h,_propName,isList); + readCreateCustomProperty(_in,_bi,_h,_propName,_valueType,_listIndexType); break; case ValueTypeINT16: case ValueTypeSHORT: - assignCustomProperty(_in,_bi,_h,_propName,isList); + readCreateCustomProperty(_in,_bi,_h,_propName,_valueType,_listIndexType); break; case ValueTypeUINT16: case ValueTypeUSHORT: - assignCustomProperty(_in,_bi,_h,_propName,isList); + readCreateCustomProperty(_in,_bi,_h,_propName,_valueType,_listIndexType); break; case ValueTypeINT32: case ValueTypeINT: - assignCustomProperty(_in,_bi,_h,_propName,isList); + readCreateCustomProperty(_in,_bi,_h,_propName,_valueType,_listIndexType); break; case ValueTypeUINT32: case ValueTypeUINT: - assignCustomProperty(_in,_bi,_h,_propName,isList); + readCreateCustomProperty(_in,_bi,_h,_propName,_valueType,_listIndexType); break; case ValueTypeFLOAT32: case ValueTypeFLOAT: - assignCustomProperty(_in,_bi,_h,_propName,isList); + readCreateCustomProperty(_in,_bi,_h,_propName,_valueType,_listIndexType); break; case ValueTypeFLOAT64: case ValueTypeDOUBLE: - assignCustomProperty(_in,_bi,_h,_propName,isList); + readCreateCustomProperty(_in,_bi,_h,_propName,_valueType,_listIndexType); break; default: std::cerr << "unsupported type" << std::endl; @@ -387,7 +387,7 @@ bool _PLYReader_::read_ascii(std::istream& _in, BaseImporter& _bi, const Options break; case CUSTOM_PROP: if (_opt.check(Options::Custom)) - readCustomProperty(_in, _bi, vh, vertexProperties_[propertyIndex].name, vertexProperties_[propertyIndex].value, vertexProperties_[propertyIndex].listIndexType); + readCustomProperty(_in, _bi, vh, vertexProperties_[propertyIndex].name, vertexProperties_[propertyIndex].value, vertexProperties_[propertyIndex].listIndexType); else _in >> trash; break; @@ -439,7 +439,7 @@ bool _PLYReader_::read_ascii(std::istream& _in, BaseImporter& _bi, const Options case CUSTOM_PROP: if (_opt.check(Options::Custom) && fh.is_valid()) - readCustomProperty(_in, _bi, fh, prop.name, prop.value, prop.listIndexType); + readCustomProperty(_in, _bi, fh, prop.name, prop.value, prop.listIndexType); else _in >> trash; break; @@ -477,6 +477,8 @@ bool _PLYReader_::read_binary(std::istream& _in, BaseImporter& _bi, bool /*_swap // read vertices: for (unsigned int i = 0; i < vertexCount_ && !_in.eof(); ++i) { + vh = _bi.add_vertex(); + v[0] = 0.0; v[1] = 0.0; v[2] = 0.0; @@ -556,6 +558,12 @@ bool _PLYReader_::read_binary(std::istream& _in, BaseImporter& _bi, bool /*_swap readInteger(vertexProperties_[propertyIndex].value, _in, c[3]); break; + case CUSTOM_PROP: + if (_opt.check(Options::Custom)) + readCustomProperty(_in, _bi, vh, vertexProperties_[propertyIndex].name, vertexProperties_[propertyIndex].value, vertexProperties_[propertyIndex].listIndexType); + else + consume_input(_in, scalar_size_[vertexProperties_[propertyIndex].value]); + break; default: // Read unsupported property consume_input(_in, scalar_size_[vertexProperties_[propertyIndex].value]); @@ -564,7 +572,7 @@ bool _PLYReader_::read_binary(std::istream& _in, BaseImporter& _bi, bool /*_swap } - vh = _bi.add_vertex(v); + _bi.set_point(vh,v); if (_opt.vertex_has_normal()) _bi.set_normal(vh, n); if (_opt.vertex_has_texcoord()) @@ -573,33 +581,51 @@ bool _PLYReader_::read_binary(std::istream& _in, BaseImporter& _bi, bool /*_swap _bi.set_color(vh, Vec4uc(c)); } - if(!faceProperties_.empty()) - { - for (unsigned int i = 0; i < faceCount_; ++i) { - // Read number of vertices for the current face - unsigned int nV; - readValue(faceProperties_[0].listIndexType, _in, nV); + for (unsigned i = 0; i < faceCount_; ++i) { + FaceHandle fh; + for (size_t propertyIndex = 0; propertyIndex < faceProperties_.size(); ++propertyIndex) + { + PropertyInfo prop = faceProperties_[propertyIndex]; + switch (prop.property) { - if (nV == 3) { - vhandles.resize(3); - unsigned int j,k,l; - readInteger(faceProperties_[0].value, _in, j); - readInteger(faceProperties_[0].value, _in, k); - readInteger(faceProperties_[0].value, _in, l); + case VERTEX_INDICES: + // nV = number of Vertices for current face + unsigned int nV; + readValue(prop.listIndexType, _in, nV); - vhandles[0] = VertexHandle(j); - vhandles[1] = VertexHandle(k); - vhandles[2] = VertexHandle(l); - } else { - vhandles.clear(); - for (unsigned int j = 0; j < nV; ++j) { - unsigned int idx; - readInteger(faceProperties_[0].value, _in, idx); - vhandles.push_back(VertexHandle(idx)); + if (nV == 3) { + vhandles.resize(3); + unsigned int j,k,l; + readInteger(prop.value, _in, j); + readInteger(prop.value, _in, k); + readInteger(prop.value, _in, l); + + vhandles[0] = VertexHandle(j); + vhandles[1] = VertexHandle(k); + vhandles[2] = VertexHandle(l); + } else { + vhandles.clear(); + for (unsigned j = 0; j < nV; ++j) { + unsigned int idx; + readInteger(prop.value, _in, idx); + vhandles.push_back(VertexHandle(idx)); + } } - } - _bi.add_face(vhandles); + fh = _bi.add_face(vhandles); + break; + + case CUSTOM_PROP: + if (_opt.check(Options::Custom) && fh.is_valid()) + readCustomProperty(_in, _bi, fh, prop.name, prop.value, prop.listIndexType); + else + consume_input(_in, scalar_size_[vertexProperties_[propertyIndex].value]); + break; + + default: + consume_input(_in, scalar_size_[vertexProperties_[propertyIndex].value]); + break; + } } } @@ -656,7 +682,38 @@ void _PLYReader_::readValue(ValueType _type, std::istream& _in, double& _value) //----------------------------------------------------------------------------- +void _PLYReader_::readValue(ValueType _type, std::istream& _in, unsigned char& _value) const{ + unsigned int tmp; + readValue(_type,_in,tmp); + _value = tmp; +} +//----------------------------------------------------------------------------- + +void _PLYReader_::readValue(ValueType _type, std::istream& _in, unsigned short& _value) const{ + unsigned int tmp; + readValue(_type,_in,tmp); + _value = tmp; +} + +//----------------------------------------------------------------------------- + +void _PLYReader_::readValue(ValueType _type, std::istream& _in, signed char& _value) const{ + int tmp; + readValue(_type,_in,tmp); + _value = tmp; +} + +//----------------------------------------------------------------------------- + +void _PLYReader_::readValue(ValueType _type, std::istream& _in, short& _value) const{ + int tmp; + readValue(_type,_in,tmp); + _value = tmp; +} + + +//----------------------------------------------------------------------------- void _PLYReader_::readValue(ValueType _type, std::istream& _in, unsigned int& _value) const { uint32_t tmp_uint32_t; @@ -1088,13 +1145,13 @@ bool _PLYReader_::can_u_read(std::istream& _is) const { property.listIndexType = indexType; // just 2 elements supported by now - if (elementName == "vertex" && !options_.is_binary()) + if (elementName == "vertex") { vertexProperties_.push_back(property); } else if (elementName == "face") { - // special case for vertex indices, also needed by the binary version + // special case for vertex indices if (propertyName == "vertex_index" || propertyName == "vertex_indices") { property.property = VERTEX_INDICES; @@ -1103,14 +1160,8 @@ bool _PLYReader_::can_u_read(std::istream& _is) const { omerr() << "Custom face Properties defined, before 'vertex_indices' property was defined. They will be skipped" << std::endl; faceProperties_.clear(); } - faceProperties_.push_back(property); - }else - { - if (!options_.is_binary()) - faceProperties_.push_back(property); - else - omerr() << "Custom list properties per face not supported with binary files" << std::endl; } + faceProperties_.push_back(property); } else @@ -1195,11 +1246,8 @@ bool _PLYReader_::can_u_read(std::istream& _is) const { //not a special property, load as custom if (entry.value == Unsupported){ - Property prop = (!options_.is_binary()) ? CUSTOM_PROP : UNSUPPORTED; // loading vertex properties is not yet supported by the binary loader - if (prop != UNSUPPORTED) - options_ += Options::Custom; - else - omerr() << "Custom Properties not supported in binary files. Skipping" << std::endl; + Property prop = CUSTOM_PROP; + options_ += Options::Custom; entry = PropertyInfo(prop, valueType, propertyName); } diff --git a/src/OpenMesh/Core/IO/reader/PLYReader.hh b/src/OpenMesh/Core/IO/reader/PLYReader.hh index 33e486f3..20958f74 100644 --- a/src/OpenMesh/Core/IO/reader/PLYReader.hh +++ b/src/OpenMesh/Core/IO/reader/PLYReader.hh @@ -70,6 +70,7 @@ #include #include #include +#include #ifndef WIN32 #include @@ -138,13 +139,15 @@ private: bool read_binary(std::istream& _in, BaseImporter& _bi, bool swap, const Options& _opt) const; float readToFloatValue(ValueType _type , std::fstream& _in) const; - template - void readCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const ValueType _valueType, const ValueType _listIndexType) const; void readValue(ValueType _type , std::istream& _in, float& _value) const; - void readValue(ValueType _type, std::istream& _in, double& _value) const; + void readValue(ValueType _type , std::istream& _in, double& _value) const; void readValue(ValueType _type , std::istream& _in, unsigned int& _value) const; + void readValue(ValueType _type , std::istream& _in, unsigned short& _value) const; + void readValue(ValueType _type , std::istream& _in, unsigned char& _value) const; void readValue(ValueType _type , std::istream& _in, int& _value) const; + void readValue(ValueType _type , std::istream& _in, short& _value) const; + void readValue(ValueType _type , std::istream& _in, signed char& _value) const; void readInteger(ValueType _type, std::istream& _in, int& _value) const; void readInteger(ValueType _type, std::istream& _in, unsigned int& _value) const; @@ -193,6 +196,24 @@ private: mutable std::vector< PropertyInfo > vertexProperties_; mutable std::vector< PropertyInfo > faceProperties_; + template + inline void read(_PLYReader_::ValueType _type, std::istream& _in, T& _value, OpenMesh::GenProg::TrueType /*_binary*/) const + { + readValue(_type, _in, _value); + } + + template + inline void read(_PLYReader_::ValueType _type, std::istream& _in, T& _value, OpenMesh::GenProg::FalseType /*_binary*/) const + { + _in >> _value; + } + + //read and assign custom properties with the given type. Also creates property, if not exist + template + void readCreateCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const ValueType _valueType, const ValueType _listType) const; + + template + void readCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const _PLYReader_::ValueType _valueType, const _PLYReader_::ValueType _listIndexType) const; }; diff --git a/src/OpenMesh/Core/IO/writer/PLYWriter.cc b/src/OpenMesh/Core/IO/writer/PLYWriter.cc index 5fbea019..d10e009a 100644 --- a/src/OpenMesh/Core/IO/writer/PLYWriter.cc +++ b/src/OpenMesh/Core/IO/writer/PLYWriter.cc @@ -242,25 +242,25 @@ std::vector<_PLYWriter_::CustomProperty> _PLYWriter_::writeCustomTypeHeader(std: //----------------------------------------------------------------------------- - -void _PLYWriter_::write_customProp_ascii(std::ostream& _out, const CustomProperty& _prop, size_t _index) const +template +void _PLYWriter_::write_customProp(std::ostream& _out, const CustomProperty& _prop, size_t _index) const { if (_prop.type == ValueTypeCHAR) - _out << " " << castProperty(_prop.property)->data()[_index]; + writeProxy(_prop.type,_out, castProperty(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type()); else if (_prop.type == ValueTypeUCHAR || _prop.type == ValueTypeUINT8) - _out << " " << castProperty(_prop.property)->data()[_index]; + writeProxy(_prop.type,_out, castProperty(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type()); else if (_prop.type == ValueTypeSHORT) - _out << " " << castProperty(_prop.property)->data()[_index]; + writeProxy(_prop.type,_out, castProperty(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type()); else if (_prop.type == ValueTypeUSHORT) - _out << " " << castProperty(_prop.property)->data()[_index]; + writeProxy(_prop.type,_out, castProperty(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type()); else if (_prop.type == ValueTypeUINT) - _out << " " << castProperty(_prop.property)->data()[_index]; + writeProxy(_prop.type,_out, castProperty(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type()); else if (_prop.type == ValueTypeINT || _prop.type == ValueTypeINT32) - _out << " " << castProperty(_prop.property)->data()[_index]; + writeProxy(_prop.type,_out, castProperty(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type()); else if (_prop.type == ValueTypeFLOAT || _prop.type == ValueTypeFLOAT32) - _out << " " << castProperty(_prop.property)->data()[_index] ; + writeProxy(_prop.type,_out, castProperty(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type()); else if (_prop.type == ValueTypeDOUBLE) - _out << " " << castProperty(_prop.property)->data()[_index]; + writeProxy(_prop.type,_out, castProperty(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type()); } @@ -317,14 +317,12 @@ void _PLYWriter_::write_header(std::ostream& _out, BaseExporter& _be, Options& _ } } - if (!_opt.is_binary()) // binary not supported yet - _ovProps = writeCustomTypeHeader(_out, _be.kernel()->vprops_begin(), _be.kernel()->vprops_end()); + _ovProps = writeCustomTypeHeader(_out, _be.kernel()->vprops_begin(), _be.kernel()->vprops_end()); _out << "element face " << _be.n_faces() << '\n'; _out << "property list uchar int vertex_indices" << '\n'; - if (!_opt.is_binary()) // binary not supported yet - _ofProps = writeCustomTypeHeader(_out, _be.kernel()->fprops_begin(), _be.kernel()->fprops_end()); + _ofProps = writeCustomTypeHeader(_out, _be.kernel()->fprops_begin(), _be.kernel()->fprops_end()); _out << "end_header" << '\n'; } @@ -403,7 +401,7 @@ write_ascii(std::ostream& _out, BaseExporter& _be, Options _opt) const // write custom properties for vertices for (std::vector::iterator iter = vProps.begin(); iter < vProps.end(); ++iter) - write_customProp_ascii(_out,*iter,i); + write_customProp(_out,*iter,i); _out << "\n"; } @@ -419,7 +417,7 @@ write_ascii(std::ostream& _out, BaseExporter& _be, Options _opt) const // write custom props for (std::vector::iterator iter = fProps.begin(); iter < fProps.end(); ++iter) - write_customProp_ascii(_out,*iter,i); + write_customProp(_out,*iter,i); _out << "\n"; } @@ -490,6 +488,78 @@ void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, float value) c } } +void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, double value) const { + + double_t tmp; + + switch (_type) { + case ValueTypeDOUBLE: + tmp = value; + store( _out , tmp, options_.check(Options::MSB) ); + break; + default : + std::cerr << "unsupported conversion type to float: " << _type << std::endl; + break; + } +} + +void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, signed char value) const{ + + int8_t tmp; + + switch (_type) { + case ValueTypeCHAR: + tmp = value; + store(_out, tmp, options_.check(Options::MSB) ); + break; + default : + std::cerr << "unsupported conversion type to int: " << _type << std::endl; + break; + } +} +void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, unsigned char value) const{ + + uint8_t tmp; + + switch (_type) { + case ValueTypeUCHAR: + tmp = value; + store(_out, tmp, options_.check(Options::MSB) ); + break; + default : + std::cerr << "unsupported conversion type to int: " << _type << std::endl; + break; + } +} +void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, short value) const{ + + int16_t tmp; + + switch (_type) { + case ValueTypeSHORT: + tmp = value; + store(_out, tmp, options_.check(Options::MSB) ); + break; + default : + std::cerr << "unsupported conversion type to int: " << _type << std::endl; + break; + } +} +void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, unsigned short value) const{ + + uint16_t tmp; + + switch (_type) { + case ValueTypeUSHORT: + tmp = value; + store(_out, tmp, options_.check(Options::MSB) ); + break; + default : + std::cerr << "unsupported conversion type to int: " << _type << std::endl; + break; + } +} + bool _PLYWriter_:: write_binary(std::ostream& _out, BaseExporter& _be, Options _opt) const @@ -555,53 +625,22 @@ write_binary(std::ostream& _out, BaseExporter& _be, Options _opt) const writeValue(ValueTypeUCHAR, _out, (int)c[3]); } } + + for (std::vector::iterator iter = vProps.begin(); iter < vProps.end(); ++iter) + write_customProp(_out,*iter,i); } - // faces (indices starting at 0) - if (_be.is_triangle_mesh()) - { - for (i=0, nF=int(_be.n_faces()); i::iterator iter = fProps.begin(); iter < fProps.end(); ++iter) + write_customProp(_out,*iter,i); } return true; diff --git a/src/OpenMesh/Core/IO/writer/PLYWriter.hh b/src/OpenMesh/Core/IO/writer/PLYWriter.hh index 324d1c7b..96d4f5c0 100644 --- a/src/OpenMesh/Core/IO/writer/PLYWriter.hh +++ b/src/OpenMesh/Core/IO/writer/PLYWriter.hh @@ -70,6 +70,7 @@ #include #include #include +#include //== NAMESPACES =============================================================== @@ -132,12 +133,28 @@ private: /// write custom persistant properties into the header for the current element, returns all properties, which were written sorted std::vector writeCustomTypeHeader(std::ostream& _out, BaseKernel::const_prop_iterator _begin, BaseKernel::const_prop_iterator _end) const; - void write_customProp_ascii(std::ostream& _our, const CustomProperty& _prop, size_t _index) const; + template + void write_customProp(std::ostream& _our, const CustomProperty& _prop, size_t _index) const; + template + void writeProxy(ValueType _type, std::ostream& _out, T _value, OpenMesh::GenProg::TrueType /*_binary*/) const + { + writeValue(_type, _out, _value); + } + template + void writeProxy(ValueType _type, std::ostream& _out, T _value, OpenMesh::GenProg::FalseType /*_binary*/) const + { + _out << " " << _value; + } protected: + void writeValue(ValueType _type, std::ostream& _out, signed char value) const; + void writeValue(ValueType _type, std::ostream& _out, unsigned char value) const; + void writeValue(ValueType _type, std::ostream& _out, short value) const; + void writeValue(ValueType _type, std::ostream& _out, unsigned short value) const; void writeValue(ValueType _type, std::ostream& _out, int value) const; void writeValue(ValueType _type, std::ostream& _out, unsigned int value) const; void writeValue(ValueType _type, std::ostream& _out, float value) const; + void writeValue(ValueType _type, std::ostream& _out, double value) const; bool write_ascii(std::ostream& _out, BaseExporter&, Options) const; bool write_binary(std::ostream& _out, BaseExporter&, Options) const; diff --git a/src/Unittests/unittests_read_write_PLY.cc b/src/Unittests/unittests_read_write_PLY.cc index d7a27fe2..60a5ad47 100644 --- a/src/Unittests/unittests_read_write_PLY.cc +++ b/src/Unittests/unittests_read_write_PLY.cc @@ -606,5 +606,90 @@ TEST_F(OpenMeshReadWritePLY, WriteReadSimplePLYWithCustomProps) { remove(outFilename); +} + +TEST_F(OpenMeshReadWritePLY, WriteReadBinaryPLYWithCustomProps) { + + PolyMesh mesh; + + OpenMesh::IO::Options options; + bool ok = OpenMesh::IO::read_mesh(mesh, "cube-minimal.ply", options); + + + OpenMesh::VPropHandleT indexProp; + OpenMesh::VPropHandleT nonPersistant; + OpenMesh::VPropHandleT qualityProp; + OpenMesh::FPropHandleT faceProp; + OpenMesh::VPropHandleT removedProp; + + const std::string indexPropName = "mySuperIndexProperty"; + const std::string qualityPropName = "quality"; + const std::string facePropName = "anotherPropForFaces"; + const std::string nonPersistantName = "nonPersistant"; + const std::string removedPropName = "willBeRemoved"; + + mesh.add_property(indexProp,indexPropName); + mesh.add_property(qualityProp,qualityPropName); + mesh.add_property(removedProp, removedPropName); + mesh.add_property(faceProp,facePropName); + mesh.add_property(nonPersistant,nonPersistantName); + + mesh.property(indexProp).set_persistent(true); + mesh.property(qualityProp).set_persistent(true); + mesh.property(faceProp).set_persistent(true); + mesh.remove_property(removedProp); + + signed char i=0; + for (Mesh::VertexIter v_iter = mesh.vertices_begin(); v_iter != mesh.vertices_end(); ++v_iter, ++i) + { + mesh.property(indexProp, *v_iter) = i; + mesh.property(qualityProp, *v_iter) = 3.5*i; + } + + i = 0; + for (Mesh::FaceIter f_iter = mesh.faces_begin(); f_iter != mesh.faces_end(); ++f_iter, ++i) + { + mesh.property(faceProp, *f_iter) = -i; + } + + const char* outFilename = "cube-minimal-customprops_openmeshOutputTestfileBinary.ply"; + options += OpenMesh::IO::Options::Binary; + ok = OpenMesh::IO::write_mesh(mesh, outFilename, options); + + ASSERT_TRUE(ok); + + PolyMesh loadedMesh; + + EXPECT_FALSE(loadedMesh.get_property_handle(indexProp,indexPropName)) << "Could access to property which was deleted"; + + options.clear(); + options += OpenMesh::IO::Options::Custom; + options += OpenMesh::IO::Options::Binary; + ok = OpenMesh::IO::read_mesh(loadedMesh, outFilename, options); + + ASSERT_TRUE(ok); + + + ASSERT_TRUE(loadedMesh.get_property_handle(indexProp,indexPropName)) << "Could not access index property"; + ASSERT_TRUE(loadedMesh.get_property_handle(qualityProp,qualityPropName)) << "Could not access quality property"; + ASSERT_TRUE(loadedMesh.get_property_handle(faceProp,facePropName)) << "Could not access face property"; + EXPECT_FALSE(loadedMesh.get_property_handle(nonPersistant,nonPersistantName)) << "Could access non persistant property"; + + i=0; + for (Mesh::VertexIter v_iter = loadedMesh.vertices_begin(); v_iter != loadedMesh.vertices_end(); ++v_iter, ++i) + { + EXPECT_EQ(loadedMesh.property(indexProp, *v_iter), static_cast(i)); + EXPECT_EQ(loadedMesh.property(qualityProp, *v_iter),3.5*i); + } + + i = 0; + for (Mesh::FaceIter f_iter = loadedMesh.faces_begin(); f_iter != loadedMesh.faces_end(); ++f_iter, ++i) + { + EXPECT_EQ(loadedMesh.property(faceProp, *f_iter),-i); + } + + + //remove(outFilename); + } }