54 #include <OpenMesh/Core/Utils/Endian.hh>
55 #include <OpenMesh/Core/IO/IOManager.hh>
56 #include <OpenMesh/Core/IO/BinaryHelper.hh>
57 #include <OpenMesh/Core/IO/writer/PLYWriter.hh>
79 _PLYWriter_::_PLYWriter_()
83 nameOfType_[Unsupported] =
"";
84 nameOfType_[ValueTypeCHAR] =
"char";
85 nameOfType_[ValueTypeUCHAR] = nameOfType_[ValueTypeUINT8] =
"uchar";
86 nameOfType_[ValueTypeUSHORT] =
"ushort";
87 nameOfType_[ValueTypeSHORT] =
"short";
88 nameOfType_[ValueTypeUINT] =
"uint";
89 nameOfType_[ValueTypeINT] =
"int";
90 nameOfType_[ValueTypeFLOAT32] = nameOfType_[ValueTypeFLOAT] =
"float";
91 nameOfType_[ValueTypeDOUBLE] =
"double";
104 std::ofstream out(_filename.c_str(), (_opt.check(
Options::Binary) ? std::ios_base::binary | std::ios_base::out
105 : std::ios_base::out) );
106 return write(out, _be, _opt, _precision);
117 if ( !check( _be, _opt ) )
127 omerr() <<
"[PLYWriter] : Warning: Face normals are not supported and thus not exported! " << std::endl;
135 omerr() <<
"[PLYWriter] : Warning: Face colors are not supported and thus not exported! " << std::endl;
143 omerr() <<
"[PLYWriter] : cannot write to stream "
149 _os.precision(_precision);
153 write_binary(_os, _be, _opt) :
154 write_ascii(_os, _be, _opt));
171 std::vector<CustomProperty> customProps;
172 for (;_begin != _end; ++_begin)
189 assert_compile(
sizeof(
char) == 1);
192 if (castProperty<signed char>(prop) != 0 || castProperty<char>(prop) != 0)
193 cProp.type = ValueTypeCHAR;
194 else if (castProperty<unsigned char>(prop) != 0)
195 cProp.type = ValueTypeUCHAR;
200 assert_compile (
sizeof(
short) == 2);
201 if (castProperty<signed short>(prop) != 0)
202 cProp.type = ValueTypeSHORT;
203 else if (castProperty<unsigned short>(prop) != 0)
204 cProp.type = ValueTypeUSHORT;
209 assert_compile (
sizeof(
int) == 4);
210 assert_compile (
sizeof(
float) == 4);
211 if (castProperty<signed int>(prop) != 0)
212 cProp.type = ValueTypeINT;
213 else if (castProperty<unsigned int>(prop) != 0)
214 cProp.type = ValueTypeUINT;
215 else if (castProperty<float>(prop) != 0)
216 cProp.type = ValueTypeFLOAT;
221 assert_compile (
sizeof(
double) == 8);
222 if (castProperty<double>(prop) != 0)
223 cProp.type = ValueTypeDOUBLE;
229 if (cProp.type != Unsupported)
232 customProps.push_back(cProp);
233 _out <<
"property " << nameOfType_[cProp.type] <<
" " << cProp.property->
name() <<
"\n";
241 template<
bool binary>
242 void _PLYWriter_::write_customProp(std::ostream& _out,
const CustomProperty& _prop,
size_t _index)
const
244 if (_prop.type == ValueTypeCHAR)
245 writeProxy(_prop.type,_out, castProperty<signed char>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
246 else if (_prop.type == ValueTypeUCHAR || _prop.type == ValueTypeUINT8)
247 writeProxy(_prop.type,_out, castProperty<unsigned char>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
248 else if (_prop.type == ValueTypeSHORT)
249 writeProxy(_prop.type,_out, castProperty<signed short>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
250 else if (_prop.type == ValueTypeUSHORT)
251 writeProxy(_prop.type,_out, castProperty<unsigned short>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
252 else if (_prop.type == ValueTypeUINT)
253 writeProxy(_prop.type,_out, castProperty<unsigned int>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
254 else if (_prop.type == ValueTypeINT || _prop.type == ValueTypeINT32)
255 writeProxy(_prop.type,_out, castProperty<signed int>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
256 else if (_prop.type == ValueTypeFLOAT || _prop.type == ValueTypeFLOAT32)
257 writeProxy(_prop.type,_out, castProperty<float>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
258 else if (_prop.type == ValueTypeDOUBLE)
259 writeProxy(_prop.type,_out, castProperty<double>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
269 _out <<
"ply" <<
'\n';
271 if (_opt.is_binary()) {
274 _out <<
"binary_big_endian ";
276 _out <<
"binary_little_endian ";
277 _out <<
"1.0" <<
'\n';
279 _out <<
"format ascii 1.0" <<
'\n';
281 _out <<
"element vertex " << _be.n_vertices() <<
'\n';
283 _out <<
"property float x" <<
'\n';
284 _out <<
"property float y" <<
'\n';
285 _out <<
"property float z" <<
'\n';
287 if ( _opt.vertex_has_normal() ){
288 _out <<
"property float nx" <<
'\n';
289 _out <<
"property float ny" <<
'\n';
290 _out <<
"property float nz" <<
'\n';
293 if ( _opt.vertex_has_texcoord() ){
294 _out <<
"property float u" <<
'\n';
295 _out <<
"property float v" <<
'\n';
298 if ( _opt.vertex_has_color() ){
299 if ( _opt.color_is_float() ) {
300 _out <<
"property float red" <<
'\n';
301 _out <<
"property float green" <<
'\n';
302 _out <<
"property float blue" <<
'\n';
304 if ( _opt.color_has_alpha() )
305 _out <<
"property float alpha" <<
'\n';
307 _out <<
"property uchar red" <<
'\n';
308 _out <<
"property uchar green" <<
'\n';
309 _out <<
"property uchar blue" <<
'\n';
311 if ( _opt.color_has_alpha() )
312 _out <<
"property uchar alpha" <<
'\n';
318 _out <<
"element face " << _be.n_faces() <<
'\n';
319 _out <<
"property list uchar int vertex_indices" <<
'\n';
323 _out <<
"end_header" <<
'\n';
335 unsigned int i, nV, nF;
343 std::vector<VertexHandle> vhandles;
345 std::vector<CustomProperty> vProps;
346 std::vector<CustomProperty> fProps;
350 if (_opt.color_is_float())
354 for (i=0, nV=
int(_be.n_vertices()); i<nV; ++i)
360 _out << v[0] <<
" " << v[1] <<
" " << v[2];
363 if ( _opt.vertex_has_normal() ){
365 _out <<
" " << n[0] <<
" " << n[1] <<
" " << n[2];
369 if ( _opt.vertex_has_texcoord() ) {
370 t = _be.texcoord(vh);
371 _out <<
" " << t[0] <<
" " << t[1];
375 if ( _opt.vertex_has_color() ) {
377 if ( _opt.color_has_alpha() ){
378 if (_opt.color_is_float()) {
379 cAf = _be.colorAf(vh);
382 cA = _be.colorAi(vh);
387 if (_opt.color_is_float()) {
399 for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
400 write_customProp<false>(_out,*iter,i);
406 for (i=0, nF=
int(_be.n_faces()); i<nF; ++i)
409 nV = _be.get_vhandles(FaceHandle(i), vhandles);
411 for (
size_t j=0; j<vhandles.size(); ++j)
412 _out <<
" " << vhandles[j].idx();
415 for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
416 write_customProp<false>(_out,*iter,i);
427 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
int value)
const {
449 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
unsigned int value)
const {
471 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
float value)
const {
476 case ValueTypeFLOAT32:
482 std::cerr <<
"unsupported conversion type to float: " << _type << std::endl;
487 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
double value)
const {
492 case ValueTypeDOUBLE:
497 std::cerr <<
"unsupported conversion type to float: " << _type << std::endl;
502 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
signed char value)
const{
512 std::cerr <<
"unsupported conversion type to int: " << _type << std::endl;
516 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
unsigned char value)
const{
526 std::cerr <<
"unsupported conversion type to int: " << _type << std::endl;
530 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
short value)
const{
540 std::cerr <<
"unsupported conversion type to int: " << _type << std::endl;
544 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
unsigned short value)
const{
549 case ValueTypeUSHORT:
554 std::cerr <<
"unsupported conversion type to int: " << _type << std::endl;
561 write_binary(std::ostream& _out,
BaseExporter& _be, Options _opt)
const
564 unsigned int i, nV, nF;
570 std::vector<VertexHandle> vhandles;
573 std::vector<CustomProperty> vProps;
574 std::vector<CustomProperty> fProps;
579 for (i=0, nV=
int(_be.n_vertices()); i<nV; ++i)
581 vh = VertexHandle(i);
585 writeValue(ValueTypeFLOAT, _out, v[0]);
586 writeValue(ValueTypeFLOAT, _out, v[1]);
587 writeValue(ValueTypeFLOAT, _out, v[2]);
590 if ( _opt.vertex_has_normal() ){
592 writeValue(ValueTypeFLOAT, _out, n[0]);
593 writeValue(ValueTypeFLOAT, _out, n[1]);
594 writeValue(ValueTypeFLOAT, _out, n[2]);
598 if ( _opt.vertex_has_texcoord() ) {
599 t = _be.texcoord(vh);
600 writeValue(ValueTypeFLOAT, _out, t[0]);
601 writeValue(ValueTypeFLOAT, _out, t[1]);
605 if ( _opt.vertex_has_color() ) {
606 if ( _opt.color_is_float() ) {
607 cf = _be.colorAf(vh);
608 writeValue(ValueTypeFLOAT, _out, cf[0]);
609 writeValue(ValueTypeFLOAT, _out, cf[1]);
610 writeValue(ValueTypeFLOAT, _out, cf[2]);
612 if ( _opt.color_has_alpha() )
613 writeValue(ValueTypeFLOAT, _out, cf[3]);
616 writeValue(ValueTypeUCHAR, _out, (
int)c[0]);
617 writeValue(ValueTypeUCHAR, _out, (
int)c[1]);
618 writeValue(ValueTypeUCHAR, _out, (
int)c[2]);
620 if ( _opt.color_has_alpha() )
621 writeValue(ValueTypeUCHAR, _out, (
int)c[3]);
625 for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
626 write_customProp<true>(_out,*iter,i);
630 for (i=0, nF=
int(_be.n_faces()); i<nF; ++i)
633 nV = _be.get_vhandles(FaceHandle(i), vhandles);
634 writeValue(ValueTypeUINT8, _out, nV);
635 for (
size_t j=0; j<vhandles.size(); ++j)
636 writeValue(ValueTypeINT32, _out, vhandles[j].idx() );
638 for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
639 write_customProp<true>(_out,*iter,i);
654 size_t _3floats(3*
sizeof(
float));
655 size_t _3ui(3*
sizeof(
unsigned int));
656 size_t _4ui(4*
sizeof(
unsigned int));
658 if ( !_opt.is_binary() )
663 size_t _3longs(3*
sizeof(
long));
667 data += _be.n_vertices() * _3floats;
670 if ( _opt.vertex_has_normal() && _be.has_vertex_normals() )
673 data += _be.n_vertices() * _3floats;
676 if ( _opt.vertex_has_color() && _be.has_vertex_colors() )
679 data += _be.n_vertices() * _3floats;
682 if ( _opt.vertex_has_texcoord() && _be.has_vertex_texcoords() )
684 size_t _2floats(2*
sizeof(
float));
686 data += _be.n_vertices() * _2floats;
690 if (_be.is_triangle_mesh())
692 data += _be.n_faces() * _4ui;
697 std::vector<VertexHandle> vhandles;
699 for (i=0, nF=
int(_be.n_faces()); i<nF; ++i)
701 data += _be.get_vhandles(
FaceHandle(i), vhandles) *
sizeof(
unsigned int);
707 if ( _opt.face_has_color() && _be.has_face_colors() ){
708 if ( _opt.color_has_alpha() )
709 data += _be.n_faces() * _4ui;
711 data += _be.n_faces() * _3ui;
bool register_module(BaseReader *_bl)
_PLYWriter_ __PLYWriterInstance
Declare the single entity of the PLY writer.
Default property class for any type T.
Has (r) / store (w) face normals.
Assume big endian byte ordering.
Has (r) / store (w) face colors.
Options & unset(const value_type _rhs)
Unset options defined in _rhs.
Set options for reader/writer modules.
const std::string & name() const
Return the name of the property.
Handle for a vertex entity.
bool write(const std::string &, BaseExporter &, Options, std::streamsize _precision=6) const
Handle for a face entity.
void write_header(std::ostream &_out, BaseExporter &_be, Options &_opt, std::vector< CustomProperty > &_ovProps, std::vector< CustomProperty > &_ofProps) const
write header into the stream _out. Returns custom properties (vertex and face) which are written into...
bool persistent(void) const
Returns true if the persistent flag is enabled else false.
std::vector< CustomProperty > writeCustomTypeHeader(std::ostream &_out, BaseKernel::const_prop_iterator _begin, BaseKernel::const_prop_iterator _end) const
write custom persistant properties into the header for the current element, returns all properties...
virtual size_t element_size() const =0
Size of one element in bytes or UnknownSize if not known.
_IOManager_ & IOManager()
size_t binary_size(BaseExporter &_be, Options _opt) const
Returns expected size of file if binary format is supported else 0.