- ply writer: add custom property support for ascii version
refs #2496 closes #2480 git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@1285 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
@@ -56,6 +56,7 @@
|
||||
#include <OpenMesh/Core/IO/IOManager.hh>
|
||||
#include <OpenMesh/Core/IO/BinaryHelper.hh>
|
||||
#include <OpenMesh/Core/IO/writer/PLYWriter.hh>
|
||||
#include <OpenMesh/Core/Utils/GenProg.hh>
|
||||
|
||||
#include <OpenMesh/Core/IO/SR_store.hh>
|
||||
|
||||
@@ -79,7 +80,20 @@ _PLYWriter_& PLYWriter() { return __PLYWriterInstance; }
|
||||
//=== IMPLEMENTATION ==========================================================
|
||||
|
||||
|
||||
_PLYWriter_::_PLYWriter_() { IOManager().register_module(this); }
|
||||
_PLYWriter_::_PLYWriter_()
|
||||
{
|
||||
IOManager().register_module(this);
|
||||
|
||||
nameOfType_[Unsupported] = "";
|
||||
nameOfType_[ValueTypeCHAR] = "char";
|
||||
nameOfType_[ValueTypeUCHAR] = nameOfType_[ValueTypeUINT8] = "uchar";
|
||||
nameOfType_[ValueTypeUSHORT] = "ushort";
|
||||
nameOfType_[ValueTypeSHORT] = "short";
|
||||
nameOfType_[ValueTypeUINT] = "uint";
|
||||
nameOfType_[ValueTypeINT] = "int";
|
||||
nameOfType_[ValueTypeFLOAT32] = nameOfType_[ValueTypeFLOAT] = "float";
|
||||
nameOfType_[ValueTypeDOUBLE] = "double";
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -174,11 +188,115 @@ write(std::ostream& _os, BaseExporter& _be, Options _opt, std::streamsize _preci
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// helper function for casting a property
|
||||
template<typename T>
|
||||
const PropertyT<T>* castProperty(const BaseProperty* _prop)
|
||||
{
|
||||
return dynamic_cast< const PropertyT<T>* >(_prop);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
std::vector<_PLYWriter_::CustomProperty> _PLYWriter_::writeCustomTypeHeader(std::ostream& _out, BaseKernel::const_prop_iterator _begin, BaseKernel::const_prop_iterator _end) const
|
||||
{
|
||||
std::vector<CustomProperty> customProps;
|
||||
for (;_begin != _end; ++_begin)
|
||||
{
|
||||
BaseProperty* prop = *_begin;
|
||||
|
||||
|
||||
// check, if property is persistant
|
||||
if (!prop->persistent())
|
||||
continue;
|
||||
|
||||
|
||||
// identify type of property
|
||||
CustomProperty cProp(prop);
|
||||
size_t propSize = prop->element_size();
|
||||
switch (propSize)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
assert_compile(sizeof(char) == 1);
|
||||
//check, if prop is a char or unsigned char by dynamic_cast
|
||||
//char, unsigned char and signed char are 3 distinct types
|
||||
if (castProperty<signed char>(prop) != 0 || castProperty<char>(prop) != 0) //treat char as signed char
|
||||
cProp.type = ValueTypeCHAR;
|
||||
else if (castProperty<unsigned char>(prop) != 0)
|
||||
cProp.type = ValueTypeUCHAR;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
assert_compile (sizeof(short) == 2);
|
||||
if (castProperty<signed short>(prop) != 0)
|
||||
cProp.type = ValueTypeSHORT;
|
||||
else if (castProperty<unsigned short>(prop) != 0)
|
||||
cProp.type = ValueTypeUSHORT;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
assert_compile (sizeof(int) == 4);
|
||||
assert_compile (sizeof(float) == 4);
|
||||
if (castProperty<signed int>(prop) != 0)
|
||||
cProp.type = ValueTypeINT;
|
||||
else if (castProperty<unsigned int>(prop) != 0)
|
||||
cProp.type = ValueTypeUINT;
|
||||
else if (castProperty<float>(prop) != 0)
|
||||
cProp.type = ValueTypeFLOAT;
|
||||
break;
|
||||
|
||||
}
|
||||
case 8:
|
||||
assert_compile (sizeof(double) == 8);
|
||||
if (castProperty<double>(prop) != 0)
|
||||
cProp.type = ValueTypeDOUBLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cProp.type != Unsupported)
|
||||
{
|
||||
// property type was identified and it is persistant, write into header
|
||||
customProps.push_back(cProp);
|
||||
_out << "property " << nameOfType_[cProp.type] << " " << cProp.property->name() << "\n";
|
||||
}
|
||||
}
|
||||
return customProps;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void _PLYWriter_::write_header(std::ostream& _out, BaseExporter& _be, Options& _opt) const {
|
||||
void _PLYWriter_::write_customProp_ascii(std::ostream& _out, const CustomProperty& _prop, size_t _index) const
|
||||
{
|
||||
if (_prop.type == ValueTypeCHAR)
|
||||
_out << " " << castProperty<signed char>(_prop.property)->data()[_index];
|
||||
else if (_prop.type == ValueTypeUCHAR || _prop.type == ValueTypeUINT8)
|
||||
_out << " " << castProperty<unsigned char>(_prop.property)->data()[_index];
|
||||
else if (_prop.type == ValueTypeSHORT)
|
||||
_out << " " << castProperty<signed short>(_prop.property)->data()[_index];
|
||||
else if (_prop.type == ValueTypeUSHORT)
|
||||
_out << " " << castProperty<unsigned short>(_prop.property)->data()[_index];
|
||||
else if (_prop.type == ValueTypeUINT)
|
||||
_out << " " << castProperty<unsigned int>(_prop.property)->data()[_index];
|
||||
else if (_prop.type == ValueTypeINT || _prop.type == ValueTypeINT32)
|
||||
_out << " " << castProperty<signed int>(_prop.property)->data()[_index];
|
||||
else if (_prop.type == ValueTypeFLOAT || _prop.type == ValueTypeFLOAT32)
|
||||
_out << " " << castProperty<float>(_prop.property)->data()[_index] ;
|
||||
else if (_prop.type == ValueTypeDOUBLE)
|
||||
_out << " " << castProperty<double>(_prop.property)->data()[_index];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
void _PLYWriter_::write_header(std::ostream& _out, BaseExporter& _be, Options& _opt, std::vector<CustomProperty>& _ovProps, std::vector<CustomProperty>& _ofProps) const {
|
||||
//writing header
|
||||
_out << "ply" << '\n';
|
||||
|
||||
@@ -227,8 +345,15 @@ 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());
|
||||
|
||||
_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());
|
||||
|
||||
_out << "end_header" << '\n';
|
||||
}
|
||||
|
||||
@@ -251,7 +376,10 @@ write_ascii(std::ostream& _out, BaseExporter& _be, Options _opt) const
|
||||
VertexHandle vh;
|
||||
std::vector<VertexHandle> vhandles;
|
||||
|
||||
write_header(_out, _be, _opt);
|
||||
std::vector<CustomProperty> vProps;
|
||||
std::vector<CustomProperty> fProps;
|
||||
|
||||
write_header(_out, _be, _opt, vProps, fProps);
|
||||
|
||||
if (_opt.color_is_float())
|
||||
_out << std::fixed;
|
||||
@@ -300,59 +428,27 @@ write_ascii(std::ostream& _out, BaseExporter& _be, Options _opt) const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// write custom properties for vertices
|
||||
for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
|
||||
write_customProp_ascii(_out,*iter,i);
|
||||
|
||||
_out << "\n";
|
||||
}
|
||||
|
||||
// faces (indices starting at 0)
|
||||
if (_be.is_triangle_mesh())
|
||||
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
|
||||
{
|
||||
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
|
||||
{
|
||||
_be.get_vhandles(FaceHandle(i), vhandles);
|
||||
_out << 3 << " ";
|
||||
_out << vhandles[0].idx() << " ";
|
||||
_out << vhandles[1].idx() << " ";
|
||||
_out << vhandles[2].idx();
|
||||
// write vertex indices per face
|
||||
nV = _be.get_vhandles(FaceHandle(i), vhandles);
|
||||
_out << nV;
|
||||
for (size_t j=0; j<vhandles.size(); ++j)
|
||||
_out << " " << vhandles[j].idx();
|
||||
|
||||
// //face color
|
||||
// if ( _opt.face_has_color() ){
|
||||
// //with alpha
|
||||
// if ( _opt.color_has_alpha() ){
|
||||
// cA = _be.colorA( FaceHandle(i) );
|
||||
// _out << " " << cA[0] << " " << cA[1] << " " << cA[2] << " " << cA[3];
|
||||
// }else{
|
||||
// //without alpha
|
||||
// c = _be.color( FaceHandle(i) );
|
||||
// _out << " " << c[0] << " " << c[1] << " " << c[2];
|
||||
// }
|
||||
// }
|
||||
_out << "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
|
||||
{
|
||||
nV = _be.get_vhandles(FaceHandle(i), vhandles);
|
||||
_out << nV << " ";
|
||||
for (size_t j=0; j<vhandles.size(); ++j)
|
||||
_out << vhandles[j].idx() << " ";
|
||||
|
||||
// //face color
|
||||
// if ( _opt.face_has_color() ){
|
||||
// //with alpha
|
||||
// if ( _opt.color_has_alpha() ){
|
||||
// cA = _be.colorA( FaceHandle(i) );
|
||||
// _out << cA[0] << " " << cA[1] << " " << cA[2] << " " << cA[3];
|
||||
// }else{
|
||||
// //without alpha
|
||||
// c = _be.color( FaceHandle(i) );
|
||||
// _out << c[0] << " " << c[1] << " " << c[2];
|
||||
// }
|
||||
// }
|
||||
|
||||
_out << "\n";
|
||||
}
|
||||
// write custom props
|
||||
for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
|
||||
write_customProp_ascii(_out,*iter,i);
|
||||
_out << "\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -435,7 +531,11 @@ write_binary(std::ostream& _out, BaseExporter& _be, Options _opt) const
|
||||
VertexHandle vh;
|
||||
std::vector<VertexHandle> vhandles;
|
||||
|
||||
write_header(_out, _be, _opt);
|
||||
// vProps and fProps will be empty, until custom properties are supported by the binary writer
|
||||
std::vector<CustomProperty> vProps;
|
||||
std::vector<CustomProperty> fProps;
|
||||
|
||||
write_header(_out, _be, _opt, vProps, fProps);
|
||||
|
||||
// vertex data (point, normals, texcoords)
|
||||
for (i=0, nV=int(_be.n_vertices()); i<nV; ++i)
|
||||
|
||||
Reference in New Issue
Block a user