add custom property (with pod data type) support for binary ply files
closes #2496 git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@1331 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
@@ -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 defined with vc (e.g. used by meshlab)
|
||||||
\li colors encoded in a vertex line (v followed by 6 values)
|
\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
|
\***) no reader exists
|
||||||
|
|
||||||
|
|||||||
@@ -191,10 +191,11 @@ struct Handle2Prop<T,FaceHandle>
|
|||||||
typedef OpenMesh::FPropHandleT<T> PropT;
|
typedef OpenMesh::FPropHandleT<T> PropT;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename Handle>
|
//read and assign custom properties with the given type. Also creates property, if not exist
|
||||||
void assignCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, bool isList)
|
template<bool binary, typename T, typename Handle>
|
||||||
|
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
|
//get/add property
|
||||||
typename Handle2Prop<T,Handle>::PropT prop;
|
typename Handle2Prop<T,Handle>::PropT prop;
|
||||||
@@ -206,7 +207,7 @@ void assignCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const
|
|||||||
|
|
||||||
//read and assign
|
//read and assign
|
||||||
T in;
|
T in;
|
||||||
_in >> in;
|
read(_valueType, _in, in, OpenMesh::GenProg::Bool2Type<binary>());
|
||||||
_bi.kernel()->property(prop,_h) = in;
|
_bi.kernel()->property(prop,_h) = in;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -221,57 +222,56 @@ void assignCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const
|
|||||||
|
|
||||||
//init vector
|
//init vector
|
||||||
int numberOfValues;
|
int numberOfValues;
|
||||||
_in >> numberOfValues;
|
read(_listType, _in, numberOfValues, OpenMesh::GenProg::Bool2Type<binary>());
|
||||||
std::vector<T> vec;
|
std::vector<T> vec;
|
||||||
vec.reserve(numberOfValues);
|
vec.reserve(numberOfValues);
|
||||||
//read and assign
|
//read and assign
|
||||||
for (int i = 0; i < numberOfValues; ++i)
|
for (int i = 0; i < numberOfValues; ++i)
|
||||||
{
|
{
|
||||||
T in;
|
T in;
|
||||||
_in >> in;
|
read(_valueType, _in, in, OpenMesh::GenProg::Bool2Type<binary>());
|
||||||
vec.push_back(in);
|
vec.push_back(in);
|
||||||
}
|
}
|
||||||
_bi.kernel()->property(prop,_h) = vec;
|
_bi.kernel()->property(prop,_h) = vec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Handle>
|
template<bool binary, typename Handle>
|
||||||
void _PLYReader_::readCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const ValueType _valueType, const ValueType _listIndexType) const
|
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)
|
switch (_valueType)
|
||||||
{
|
{
|
||||||
case ValueTypeINT8:
|
case ValueTypeINT8:
|
||||||
case ValueTypeCHAR:
|
case ValueTypeCHAR:
|
||||||
assignCustomProperty<signed char>(_in,_bi,_h,_propName,isList);
|
readCreateCustomProperty<binary,signed char>(_in,_bi,_h,_propName,_valueType,_listIndexType);
|
||||||
break;
|
break;
|
||||||
case ValueTypeUINT8:
|
case ValueTypeUINT8:
|
||||||
case ValueTypeUCHAR:
|
case ValueTypeUCHAR:
|
||||||
assignCustomProperty<unsigned char>(_in,_bi,_h,_propName,isList);
|
readCreateCustomProperty<binary,unsigned char>(_in,_bi,_h,_propName,_valueType,_listIndexType);
|
||||||
break;
|
break;
|
||||||
case ValueTypeINT16:
|
case ValueTypeINT16:
|
||||||
case ValueTypeSHORT:
|
case ValueTypeSHORT:
|
||||||
assignCustomProperty<short>(_in,_bi,_h,_propName,isList);
|
readCreateCustomProperty<binary,short>(_in,_bi,_h,_propName,_valueType,_listIndexType);
|
||||||
break;
|
break;
|
||||||
case ValueTypeUINT16:
|
case ValueTypeUINT16:
|
||||||
case ValueTypeUSHORT:
|
case ValueTypeUSHORT:
|
||||||
assignCustomProperty<unsigned short>(_in,_bi,_h,_propName,isList);
|
readCreateCustomProperty<binary,unsigned short>(_in,_bi,_h,_propName,_valueType,_listIndexType);
|
||||||
break;
|
break;
|
||||||
case ValueTypeINT32:
|
case ValueTypeINT32:
|
||||||
case ValueTypeINT:
|
case ValueTypeINT:
|
||||||
assignCustomProperty<int>(_in,_bi,_h,_propName,isList);
|
readCreateCustomProperty<binary,int>(_in,_bi,_h,_propName,_valueType,_listIndexType);
|
||||||
break;
|
break;
|
||||||
case ValueTypeUINT32:
|
case ValueTypeUINT32:
|
||||||
case ValueTypeUINT:
|
case ValueTypeUINT:
|
||||||
assignCustomProperty<unsigned int>(_in,_bi,_h,_propName,isList);
|
readCreateCustomProperty<binary,unsigned int>(_in,_bi,_h,_propName,_valueType,_listIndexType);
|
||||||
break;
|
break;
|
||||||
case ValueTypeFLOAT32:
|
case ValueTypeFLOAT32:
|
||||||
case ValueTypeFLOAT:
|
case ValueTypeFLOAT:
|
||||||
assignCustomProperty<float>(_in,_bi,_h,_propName,isList);
|
readCreateCustomProperty<binary,float>(_in,_bi,_h,_propName,_valueType,_listIndexType);
|
||||||
break;
|
break;
|
||||||
case ValueTypeFLOAT64:
|
case ValueTypeFLOAT64:
|
||||||
case ValueTypeDOUBLE:
|
case ValueTypeDOUBLE:
|
||||||
assignCustomProperty<double>(_in,_bi,_h,_propName,isList);
|
readCreateCustomProperty<binary,double>(_in,_bi,_h,_propName,_valueType,_listIndexType);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
std::cerr << "unsupported type" << std::endl;
|
std::cerr << "unsupported type" << std::endl;
|
||||||
@@ -387,7 +387,7 @@ bool _PLYReader_::read_ascii(std::istream& _in, BaseImporter& _bi, const Options
|
|||||||
break;
|
break;
|
||||||
case CUSTOM_PROP:
|
case CUSTOM_PROP:
|
||||||
if (_opt.check(Options::Custom))
|
if (_opt.check(Options::Custom))
|
||||||
readCustomProperty(_in, _bi, vh, vertexProperties_[propertyIndex].name, vertexProperties_[propertyIndex].value, vertexProperties_[propertyIndex].listIndexType);
|
readCustomProperty<false>(_in, _bi, vh, vertexProperties_[propertyIndex].name, vertexProperties_[propertyIndex].value, vertexProperties_[propertyIndex].listIndexType);
|
||||||
else
|
else
|
||||||
_in >> trash;
|
_in >> trash;
|
||||||
break;
|
break;
|
||||||
@@ -439,7 +439,7 @@ bool _PLYReader_::read_ascii(std::istream& _in, BaseImporter& _bi, const Options
|
|||||||
|
|
||||||
case CUSTOM_PROP:
|
case CUSTOM_PROP:
|
||||||
if (_opt.check(Options::Custom) && fh.is_valid())
|
if (_opt.check(Options::Custom) && fh.is_valid())
|
||||||
readCustomProperty(_in, _bi, fh, prop.name, prop.value, prop.listIndexType);
|
readCustomProperty<false>(_in, _bi, fh, prop.name, prop.value, prop.listIndexType);
|
||||||
else
|
else
|
||||||
_in >> trash;
|
_in >> trash;
|
||||||
break;
|
break;
|
||||||
@@ -477,6 +477,8 @@ bool _PLYReader_::read_binary(std::istream& _in, BaseImporter& _bi, bool /*_swap
|
|||||||
|
|
||||||
// read vertices:
|
// read vertices:
|
||||||
for (unsigned int i = 0; i < vertexCount_ && !_in.eof(); ++i) {
|
for (unsigned int i = 0; i < vertexCount_ && !_in.eof(); ++i) {
|
||||||
|
vh = _bi.add_vertex();
|
||||||
|
|
||||||
v[0] = 0.0;
|
v[0] = 0.0;
|
||||||
v[1] = 0.0;
|
v[1] = 0.0;
|
||||||
v[2] = 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]);
|
readInteger(vertexProperties_[propertyIndex].value, _in, c[3]);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
case CUSTOM_PROP:
|
||||||
|
if (_opt.check(Options::Custom))
|
||||||
|
readCustomProperty<true>(_in, _bi, vh, vertexProperties_[propertyIndex].name, vertexProperties_[propertyIndex].value, vertexProperties_[propertyIndex].listIndexType);
|
||||||
|
else
|
||||||
|
consume_input(_in, scalar_size_[vertexProperties_[propertyIndex].value]);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// Read unsupported property
|
// Read unsupported property
|
||||||
consume_input(_in, scalar_size_[vertexProperties_[propertyIndex].value]);
|
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())
|
if (_opt.vertex_has_normal())
|
||||||
_bi.set_normal(vh, n);
|
_bi.set_normal(vh, n);
|
||||||
if (_opt.vertex_has_texcoord())
|
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));
|
_bi.set_color(vh, Vec4uc(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!faceProperties_.empty())
|
for (unsigned i = 0; i < faceCount_; ++i) {
|
||||||
{
|
FaceHandle fh;
|
||||||
for (unsigned int i = 0; i < faceCount_; ++i) {
|
for (size_t propertyIndex = 0; propertyIndex < faceProperties_.size(); ++propertyIndex)
|
||||||
// Read number of vertices for the current face
|
{
|
||||||
unsigned int nV;
|
PropertyInfo prop = faceProperties_[propertyIndex];
|
||||||
readValue(faceProperties_[0].listIndexType, _in, nV);
|
switch (prop.property) {
|
||||||
|
|
||||||
if (nV == 3) {
|
case VERTEX_INDICES:
|
||||||
vhandles.resize(3);
|
// nV = number of Vertices for current face
|
||||||
unsigned int j,k,l;
|
unsigned int nV;
|
||||||
readInteger(faceProperties_[0].value, _in, j);
|
readValue(prop.listIndexType, _in, nV);
|
||||||
readInteger(faceProperties_[0].value, _in, k);
|
|
||||||
readInteger(faceProperties_[0].value, _in, l);
|
|
||||||
|
|
||||||
vhandles[0] = VertexHandle(j);
|
if (nV == 3) {
|
||||||
vhandles[1] = VertexHandle(k);
|
vhandles.resize(3);
|
||||||
vhandles[2] = VertexHandle(l);
|
unsigned int j,k,l;
|
||||||
} else {
|
readInteger(prop.value, _in, j);
|
||||||
vhandles.clear();
|
readInteger(prop.value, _in, k);
|
||||||
for (unsigned int j = 0; j < nV; ++j) {
|
readInteger(prop.value, _in, l);
|
||||||
unsigned int idx;
|
|
||||||
readInteger(faceProperties_[0].value, _in, idx);
|
vhandles[0] = VertexHandle(j);
|
||||||
vhandles.push_back(VertexHandle(idx));
|
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<true>(_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 {
|
void _PLYReader_::readValue(ValueType _type, std::istream& _in, unsigned int& _value) const {
|
||||||
|
|
||||||
uint32_t tmp_uint32_t;
|
uint32_t tmp_uint32_t;
|
||||||
@@ -1088,13 +1145,13 @@ bool _PLYReader_::can_u_read(std::istream& _is) const {
|
|||||||
property.listIndexType = indexType;
|
property.listIndexType = indexType;
|
||||||
|
|
||||||
// just 2 elements supported by now
|
// just 2 elements supported by now
|
||||||
if (elementName == "vertex" && !options_.is_binary())
|
if (elementName == "vertex")
|
||||||
{
|
{
|
||||||
vertexProperties_.push_back(property);
|
vertexProperties_.push_back(property);
|
||||||
}
|
}
|
||||||
else if (elementName == "face")
|
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")
|
if (propertyName == "vertex_index" || propertyName == "vertex_indices")
|
||||||
{
|
{
|
||||||
property.property = 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;
|
omerr() << "Custom face Properties defined, before 'vertex_indices' property was defined. They will be skipped" << std::endl;
|
||||||
faceProperties_.clear();
|
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
|
else
|
||||||
@@ -1195,11 +1246,8 @@ bool _PLYReader_::can_u_read(std::istream& _is) const {
|
|||||||
|
|
||||||
//not a special property, load as custom
|
//not a special property, load as custom
|
||||||
if (entry.value == Unsupported){
|
if (entry.value == Unsupported){
|
||||||
Property prop = (!options_.is_binary()) ? CUSTOM_PROP : UNSUPPORTED; // loading vertex properties is not yet supported by the binary loader
|
Property prop = CUSTOM_PROP;
|
||||||
if (prop != UNSUPPORTED)
|
options_ += Options::Custom;
|
||||||
options_ += Options::Custom;
|
|
||||||
else
|
|
||||||
omerr() << "Custom Properties not supported in binary files. Skipping" << std::endl;
|
|
||||||
entry = PropertyInfo(prop, valueType, propertyName);
|
entry = PropertyInfo(prop, valueType, propertyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,7 @@
|
|||||||
#include <OpenMesh/Core/System/config.h>
|
#include <OpenMesh/Core/System/config.h>
|
||||||
#include <OpenMesh/Core/Utils/SingletonT.hh>
|
#include <OpenMesh/Core/Utils/SingletonT.hh>
|
||||||
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
|
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
|
||||||
|
#include <OpenMesh/Core/Utils/GenProg.hh>
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -138,13 +139,15 @@ private:
|
|||||||
bool read_binary(std::istream& _in, BaseImporter& _bi, bool swap, const Options& _opt) const;
|
bool read_binary(std::istream& _in, BaseImporter& _bi, bool swap, const Options& _opt) const;
|
||||||
|
|
||||||
float readToFloatValue(ValueType _type , std::fstream& _in) const;
|
float readToFloatValue(ValueType _type , std::fstream& _in) const;
|
||||||
template<typename Handle>
|
|
||||||
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, 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 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, 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, int& _value) const;
|
||||||
void readInteger(ValueType _type, std::istream& _in, unsigned 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 > vertexProperties_;
|
||||||
mutable std::vector< PropertyInfo > faceProperties_;
|
mutable std::vector< PropertyInfo > faceProperties_;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void read(_PLYReader_::ValueType _type, std::istream& _in, T& _value, OpenMesh::GenProg::TrueType /*_binary*/) const
|
||||||
|
{
|
||||||
|
readValue(_type, _in, _value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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<bool binary, typename T, typename Handle>
|
||||||
|
void readCreateCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const ValueType _valueType, const ValueType _listType) const;
|
||||||
|
|
||||||
|
template<bool binary, typename Handle>
|
||||||
|
void readCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const _PLYReader_::ValueType _valueType, const _PLYReader_::ValueType _listIndexType) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -242,25 +242,25 @@ std::vector<_PLYWriter_::CustomProperty> _PLYWriter_::writeCustomTypeHeader(std:
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<bool binary>
|
||||||
void _PLYWriter_::write_customProp_ascii(std::ostream& _out, const CustomProperty& _prop, size_t _index) const
|
void _PLYWriter_::write_customProp(std::ostream& _out, const CustomProperty& _prop, size_t _index) const
|
||||||
{
|
{
|
||||||
if (_prop.type == ValueTypeCHAR)
|
if (_prop.type == ValueTypeCHAR)
|
||||||
_out << " " << castProperty<signed char>(_prop.property)->data()[_index];
|
writeProxy(_prop.type,_out, castProperty<signed char>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
|
||||||
else if (_prop.type == ValueTypeUCHAR || _prop.type == ValueTypeUINT8)
|
else if (_prop.type == ValueTypeUCHAR || _prop.type == ValueTypeUINT8)
|
||||||
_out << " " << castProperty<unsigned char>(_prop.property)->data()[_index];
|
writeProxy(_prop.type,_out, castProperty<unsigned char>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
|
||||||
else if (_prop.type == ValueTypeSHORT)
|
else if (_prop.type == ValueTypeSHORT)
|
||||||
_out << " " << castProperty<signed short>(_prop.property)->data()[_index];
|
writeProxy(_prop.type,_out, castProperty<signed short>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
|
||||||
else if (_prop.type == ValueTypeUSHORT)
|
else if (_prop.type == ValueTypeUSHORT)
|
||||||
_out << " " << castProperty<unsigned short>(_prop.property)->data()[_index];
|
writeProxy(_prop.type,_out, castProperty<unsigned short>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
|
||||||
else if (_prop.type == ValueTypeUINT)
|
else if (_prop.type == ValueTypeUINT)
|
||||||
_out << " " << castProperty<unsigned int>(_prop.property)->data()[_index];
|
writeProxy(_prop.type,_out, castProperty<unsigned int>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
|
||||||
else if (_prop.type == ValueTypeINT || _prop.type == ValueTypeINT32)
|
else if (_prop.type == ValueTypeINT || _prop.type == ValueTypeINT32)
|
||||||
_out << " " << castProperty<signed int>(_prop.property)->data()[_index];
|
writeProxy(_prop.type,_out, castProperty<signed int>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
|
||||||
else if (_prop.type == ValueTypeFLOAT || _prop.type == ValueTypeFLOAT32)
|
else if (_prop.type == ValueTypeFLOAT || _prop.type == ValueTypeFLOAT32)
|
||||||
_out << " " << castProperty<float>(_prop.property)->data()[_index] ;
|
writeProxy(_prop.type,_out, castProperty<float>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
|
||||||
else if (_prop.type == ValueTypeDOUBLE)
|
else if (_prop.type == ValueTypeDOUBLE)
|
||||||
_out << " " << castProperty<double>(_prop.property)->data()[_index];
|
writeProxy(_prop.type,_out, castProperty<double>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -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 << "element face " << _be.n_faces() << '\n';
|
||||||
_out << "property list uchar int vertex_indices" << '\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';
|
_out << "end_header" << '\n';
|
||||||
}
|
}
|
||||||
@@ -403,7 +401,7 @@ write_ascii(std::ostream& _out, BaseExporter& _be, Options _opt) const
|
|||||||
|
|
||||||
// write custom properties for vertices
|
// write custom properties for vertices
|
||||||
for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
|
for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
|
||||||
write_customProp_ascii(_out,*iter,i);
|
write_customProp<false>(_out,*iter,i);
|
||||||
|
|
||||||
_out << "\n";
|
_out << "\n";
|
||||||
}
|
}
|
||||||
@@ -419,7 +417,7 @@ write_ascii(std::ostream& _out, BaseExporter& _be, Options _opt) const
|
|||||||
|
|
||||||
// write custom props
|
// write custom props
|
||||||
for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
|
for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
|
||||||
write_customProp_ascii(_out,*iter,i);
|
write_customProp<false>(_out,*iter,i);
|
||||||
_out << "\n";
|
_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
|
bool
|
||||||
_PLYWriter_::
|
_PLYWriter_::
|
||||||
write_binary(std::ostream& _out, BaseExporter& _be, Options _opt) const
|
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]);
|
writeValue(ValueTypeUCHAR, _out, (int)c[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
|
||||||
|
write_customProp<true>(_out,*iter,i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// faces (indices starting at 0)
|
|
||||||
if (_be.is_triangle_mesh())
|
|
||||||
{
|
|
||||||
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
|
|
||||||
{
|
|
||||||
//face
|
|
||||||
_be.get_vhandles(FaceHandle(i), vhandles);
|
|
||||||
writeValue(ValueTypeUINT8, _out, 3);
|
|
||||||
writeValue(ValueTypeINT32, _out, vhandles[0].idx());
|
|
||||||
writeValue(ValueTypeINT32, _out, vhandles[1].idx());
|
|
||||||
writeValue(ValueTypeINT32, _out, vhandles[2].idx());
|
|
||||||
|
|
||||||
// //face color
|
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
|
||||||
// if ( _opt.face_has_color() ){
|
|
||||||
// c = _be.colorA( FaceHandle(i) );
|
|
||||||
// writeValue(_out, c[0]);
|
|
||||||
// writeValue(_out, c[1]);
|
|
||||||
// writeValue(_out, c[2]);
|
|
||||||
//
|
|
||||||
// if ( _opt.color_has_alpha() )
|
|
||||||
// writeValue(_out, c[3]);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
|
//face
|
||||||
{
|
nV = _be.get_vhandles(FaceHandle(i), vhandles);
|
||||||
//face
|
writeValue(ValueTypeUINT8, _out, nV);
|
||||||
nV = _be.get_vhandles(FaceHandle(i), vhandles);
|
for (size_t j=0; j<vhandles.size(); ++j)
|
||||||
writeValue(ValueTypeUINT8, _out, nV);
|
writeValue(ValueTypeINT32, _out, vhandles[j].idx() );
|
||||||
for (size_t j=0; j<vhandles.size(); ++j)
|
|
||||||
writeValue(ValueTypeINT32, _out, vhandles[j].idx() );
|
|
||||||
|
|
||||||
// //face color
|
for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
|
||||||
// if ( _opt.face_has_color() ){
|
write_customProp<true>(_out,*iter,i);
|
||||||
// c = _be.colorA( FaceHandle(i) );
|
|
||||||
// writeValue(_out, c[0]);
|
|
||||||
// writeValue(_out, c[1]);
|
|
||||||
// writeValue(_out, c[2]);
|
|
||||||
//
|
|
||||||
// if ( _opt.color_has_alpha() )
|
|
||||||
// writeValue(_out, c[3]);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -70,6 +70,7 @@
|
|||||||
#include <OpenMesh/Core/Utils/SingletonT.hh>
|
#include <OpenMesh/Core/Utils/SingletonT.hh>
|
||||||
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
|
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
|
||||||
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
|
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
|
||||||
|
#include <OpenMesh/Core/Utils/GenProg.hh>
|
||||||
|
|
||||||
|
|
||||||
//== NAMESPACES ===============================================================
|
//== NAMESPACES ===============================================================
|
||||||
@@ -132,12 +133,28 @@ private:
|
|||||||
|
|
||||||
/// write custom persistant properties into the header for the current element, returns all properties, which were written sorted
|
/// write custom persistant properties into the header for the current element, returns all properties, which were written sorted
|
||||||
std::vector<CustomProperty> writeCustomTypeHeader(std::ostream& _out, BaseKernel::const_prop_iterator _begin, BaseKernel::const_prop_iterator _end) const;
|
std::vector<CustomProperty> 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<bool binary>
|
||||||
|
void write_customProp(std::ostream& _our, const CustomProperty& _prop, size_t _index) const;
|
||||||
|
template<typename T>
|
||||||
|
void writeProxy(ValueType _type, std::ostream& _out, T _value, OpenMesh::GenProg::TrueType /*_binary*/) const
|
||||||
|
{
|
||||||
|
writeValue(_type, _out, _value);
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
void writeProxy(ValueType _type, std::ostream& _out, T _value, OpenMesh::GenProg::FalseType /*_binary*/) const
|
||||||
|
{
|
||||||
|
_out << " " << _value;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
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, int value) const;
|
||||||
void writeValue(ValueType _type, std::ostream& _out, unsigned 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, float value) const;
|
||||||
|
void writeValue(ValueType _type, std::ostream& _out, double value) const;
|
||||||
|
|
||||||
bool write_ascii(std::ostream& _out, BaseExporter&, Options) const;
|
bool write_ascii(std::ostream& _out, BaseExporter&, Options) const;
|
||||||
bool write_binary(std::ostream& _out, BaseExporter&, Options) const;
|
bool write_binary(std::ostream& _out, BaseExporter&, Options) const;
|
||||||
|
|||||||
@@ -606,5 +606,90 @@ TEST_F(OpenMeshReadWritePLY, WriteReadSimplePLYWithCustomProps) {
|
|||||||
|
|
||||||
remove(outFilename);
|
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<unsigned short> indexProp;
|
||||||
|
OpenMesh::VPropHandleT<unsigned int> nonPersistant;
|
||||||
|
OpenMesh::VPropHandleT<double> qualityProp;
|
||||||
|
OpenMesh::FPropHandleT<signed int> faceProp;
|
||||||
|
OpenMesh::VPropHandleT<int> 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<unsigned>(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);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user