49#include <OpenMesh/Core/Utils/Endian.hh>
50#include <OpenMesh/Core/IO/IOManager.hh>
51#include <OpenMesh/Core/IO/BinaryHelper.hh>
52#include <OpenMesh/Core/IO/writer/PLYWriter.hh>
74_PLYWriter_::_PLYWriter_()
78 nameOfType_[Unsupported] =
"";
79 nameOfType_[ValueTypeCHAR] =
"char";
80 nameOfType_[ValueTypeUCHAR] = nameOfType_[ValueTypeUINT8] =
"uchar";
81 nameOfType_[ValueTypeUSHORT] =
"ushort";
82 nameOfType_[ValueTypeSHORT] =
"short";
83 nameOfType_[ValueTypeUINT] =
"uint";
84 nameOfType_[ValueTypeINT] =
"int";
85 nameOfType_[ValueTypeFLOAT32] = nameOfType_[ValueTypeFLOAT] =
"float";
86 nameOfType_[ValueTypeDOUBLE] =
"double";
99 std::ofstream out(_filename.c_str(), (_opt.check(
Options::Binary) ? std::ios_base::binary | std::ios_base::out
100 : std::ios_base::out) );
101 return write(out, _be, _opt, _precision);
112 options_ = _writeOptions;
115 if ( !check( _be, options_ ) )
124 omerr() <<
"[PLYWriter] : Warning: Face normals are not supported and thus not exported! " << std::endl;
131 omerr() <<
"[PLYWriter] : cannot write to stream "
137 _os.precision(_precision);
141 write_binary(_os, _be, options_) :
142 write_ascii(_os, _be, options_));
159 std::vector<CustomProperty> customProps;
160 for (;_begin != _end; ++_begin)
177 assert_compile(
sizeof(
char) == 1);
180 if (castProperty<signed char>(prop) != 0 || castProperty<char>(prop) != 0)
181 cProp.type = ValueTypeCHAR;
182 else if (castProperty<unsigned char>(prop) != 0)
183 cProp.type = ValueTypeUCHAR;
188 assert_compile (
sizeof(
short) == 2);
189 if (castProperty<signed short>(prop) != 0)
190 cProp.type = ValueTypeSHORT;
191 else if (castProperty<unsigned short>(prop) != 0)
192 cProp.type = ValueTypeUSHORT;
197 assert_compile (
sizeof(
int) == 4);
198 assert_compile (
sizeof(
float) == 4);
199 if (castProperty<signed int>(prop) != 0)
200 cProp.type = ValueTypeINT;
201 else if (castProperty<unsigned int>(prop) != 0)
202 cProp.type = ValueTypeUINT;
203 else if (castProperty<float>(prop) != 0)
204 cProp.type = ValueTypeFLOAT;
209 assert_compile (
sizeof(
double) == 8);
210 if (castProperty<double>(prop) != 0)
211 cProp.type = ValueTypeDOUBLE;
217 if (cProp.type != Unsupported)
220 customProps.push_back(cProp);
221 _out <<
"property " << nameOfType_[cProp.type] <<
" " << cProp.property->
name() <<
"\n";
230void _PLYWriter_::write_customProp(std::ostream& _out,
const CustomProperty& _prop,
size_t _index)
const
232 if (_prop.type == ValueTypeCHAR)
233 writeProxy(_prop.type,_out, castProperty<signed char>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
234 else if (_prop.type == ValueTypeUCHAR || _prop.type == ValueTypeUINT8)
235 writeProxy(_prop.type,_out, castProperty<unsigned char>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
236 else if (_prop.type == ValueTypeSHORT)
237 writeProxy(_prop.type,_out, castProperty<signed short>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
238 else if (_prop.type == ValueTypeUSHORT)
239 writeProxy(_prop.type,_out, castProperty<unsigned short>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
240 else if (_prop.type == ValueTypeUINT)
241 writeProxy(_prop.type,_out, castProperty<unsigned int>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
242 else if (_prop.type == ValueTypeINT || _prop.type == ValueTypeINT32)
243 writeProxy(_prop.type,_out, castProperty<signed int>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
244 else if (_prop.type == ValueTypeFLOAT || _prop.type == ValueTypeFLOAT32)
245 writeProxy(_prop.type,_out, castProperty<float>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
246 else if (_prop.type == ValueTypeDOUBLE)
247 writeProxy(_prop.type,_out, castProperty<double>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
257 _out <<
"ply" <<
'\n';
259 if (_opt.is_binary()) {
262 _out <<
"binary_big_endian ";
264 _out <<
"binary_little_endian ";
265 _out <<
"1.0" <<
'\n';
267 _out <<
"format ascii 1.0" <<
'\n';
269 _out <<
"element vertex " << _be.n_vertices() <<
'\n';
271 _out <<
"property float x" <<
'\n';
272 _out <<
"property float y" <<
'\n';
273 _out <<
"property float z" <<
'\n';
275 if ( _opt.vertex_has_normal() ){
276 _out <<
"property float nx" <<
'\n';
277 _out <<
"property float ny" <<
'\n';
278 _out <<
"property float nz" <<
'\n';
281 if ( _opt.vertex_has_texcoord() ){
282 if ( _opt.use_st_coordinates() ){
283 _out <<
"property float s" <<
'\n';
284 _out <<
"property float t" <<
'\n';
286 _out <<
"property float u" <<
'\n';
287 _out <<
"property float v" <<
'\n';
291 if ( _opt.vertex_has_color() ){
292 if ( _opt.color_is_float() ) {
293 _out <<
"property float red" <<
'\n';
294 _out <<
"property float green" <<
'\n';
295 _out <<
"property float blue" <<
'\n';
297 if ( _opt.color_has_alpha() )
298 _out <<
"property float alpha" <<
'\n';
300 _out <<
"property uchar red" <<
'\n';
301 _out <<
"property uchar green" <<
'\n';
302 _out <<
"property uchar blue" <<
'\n';
304 if ( _opt.color_has_alpha() )
305 _out <<
"property uchar alpha" <<
'\n';
311 _out <<
"element face " << _be.n_faces() <<
'\n';
312 _out <<
"property list uchar int vertex_indices" <<
'\n';
314 if ( _opt.face_has_color() ){
315 if ( _opt.color_is_float() ) {
316 _out <<
"property float red" <<
'\n';
317 _out <<
"property float green" <<
'\n';
318 _out <<
"property float blue" <<
'\n';
320 if ( _opt.color_has_alpha() )
321 _out <<
"property float alpha" <<
'\n';
323 _out <<
"property uchar red" <<
'\n';
324 _out <<
"property uchar green" <<
'\n';
325 _out <<
"property uchar blue" <<
'\n';
327 if ( _opt.color_has_alpha() )
328 _out <<
"property uchar alpha" <<
'\n';
334 _out <<
"end_header" <<
'\n';
346 unsigned int i, nV, nF;
355 std::vector<VertexHandle> vhandles;
357 std::vector<CustomProperty> vProps;
358 std::vector<CustomProperty> fProps;
362 if (_opt.color_is_float())
366 for (i=0, nV=
int(_be.n_vertices()); i<nV; ++i)
372 _out << v[0] <<
" " << v[1] <<
" " << v[2];
375 if ( _opt.vertex_has_normal() ){
377 _out <<
" " << n[0] <<
" " << n[1] <<
" " << n[2];
381 if ( _opt.vertex_has_texcoord() ) {
382 t = _be.texcoord(vh);
383 _out <<
" " << t[0] <<
" " << t[1];
387 if ( _opt.vertex_has_color() ) {
389 if ( _opt.color_has_alpha() ){
390 if (_opt.color_is_float()) {
391 cAf = _be.colorAf(vh);
394 cA = _be.colorAi(vh);
399 if (_opt.color_is_float()) {
411 for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
412 write_customProp<false>(_out,*iter,i);
418 for (i=0, nF=
int(_be.n_faces()); i<nF; ++i)
423 nV = _be.get_vhandles(fh, vhandles);
425 for (
size_t j=0; j<vhandles.size(); ++j)
426 _out <<
" " << vhandles[j].idx();
429 if ( _opt.face_has_color() ) {
431 if ( _opt.color_has_alpha() ){
432 if (_opt.color_is_float()) {
433 cAf = _be.colorAf(fh);
436 cA = _be.colorAi(fh);
441 if (_opt.color_is_float()) {
452 for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
453 write_customProp<false>(_out,*iter,i);
464void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
int value)
const {
486void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
unsigned int value)
const {
508void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
float value)
const {
513 case ValueTypeFLOAT32:
519 std::cerr <<
"unsupported conversion type to float: " << _type << std::endl;
524void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
double value)
const {
529 case ValueTypeDOUBLE:
534 std::cerr <<
"unsupported conversion type to float: " << _type << std::endl;
539void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
signed char value)
const{
549 std::cerr <<
"unsupported conversion type to int: " << _type << std::endl;
553void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
unsigned char value)
const{
563 std::cerr <<
"unsupported conversion type to int: " << _type << std::endl;
567void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
short value)
const{
577 std::cerr <<
"unsupported conversion type to int: " << _type << std::endl;
581void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
unsigned short value)
const{
586 case ValueTypeUSHORT:
591 std::cerr <<
"unsupported conversion type to int: " << _type << std::endl;
598write_binary(std::ostream& _out,
BaseExporter& _be, Options _opt)
const
601 unsigned int i, nV, nF;
608 std::vector<VertexHandle> vhandles;
611 std::vector<CustomProperty> vProps;
612 std::vector<CustomProperty> fProps;
617 for (i=0, nV=
int(_be.n_vertices()); i<nV; ++i)
619 vh = VertexHandle(i);
623 writeValue(ValueTypeFLOAT, _out, v[0]);
624 writeValue(ValueTypeFLOAT, _out, v[1]);
625 writeValue(ValueTypeFLOAT, _out, v[2]);
628 if ( _opt.vertex_has_normal() ){
630 writeValue(ValueTypeFLOAT, _out, n[0]);
631 writeValue(ValueTypeFLOAT, _out, n[1]);
632 writeValue(ValueTypeFLOAT, _out, n[2]);
636 if ( _opt.vertex_has_texcoord() ) {
637 t = _be.texcoord(vh);
638 writeValue(ValueTypeFLOAT, _out, t[0]);
639 writeValue(ValueTypeFLOAT, _out, t[1]);
643 if ( _opt.vertex_has_color() ) {
644 if ( _opt.color_is_float() ) {
645 cf = _be.colorAf(vh);
646 writeValue(ValueTypeFLOAT, _out, cf[0]);
647 writeValue(ValueTypeFLOAT, _out, cf[1]);
648 writeValue(ValueTypeFLOAT, _out, cf[2]);
650 if ( _opt.color_has_alpha() )
651 writeValue(ValueTypeFLOAT, _out, cf[3]);
654 writeValue(ValueTypeUCHAR, _out, (
int)c[0]);
655 writeValue(ValueTypeUCHAR, _out, (
int)c[1]);
656 writeValue(ValueTypeUCHAR, _out, (
int)c[2]);
658 if ( _opt.color_has_alpha() )
659 writeValue(ValueTypeUCHAR, _out, (
int)c[3]);
663 for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
664 write_customProp<true>(_out,*iter,i);
668 for (i=0, nF=
int(_be.n_faces()); i<nF; ++i)
673 nV = _be.get_vhandles(fh, vhandles);
674 writeValue(ValueTypeUINT8, _out, nV);
675 for (
size_t j=0; j<vhandles.size(); ++j)
676 writeValue(ValueTypeINT32, _out, vhandles[j].idx() );
679 if ( _opt.face_has_color() ) {
680 if ( _opt.color_is_float() ) {
681 cf = _be.colorAf(fh);
682 writeValue(ValueTypeFLOAT, _out, cf[0]);
683 writeValue(ValueTypeFLOAT, _out, cf[1]);
684 writeValue(ValueTypeFLOAT, _out, cf[2]);
686 if ( _opt.color_has_alpha() )
687 writeValue(ValueTypeFLOAT, _out, cf[3]);
690 writeValue(ValueTypeUCHAR, _out, (
int)c[0]);
691 writeValue(ValueTypeUCHAR, _out, (
int)c[1]);
692 writeValue(ValueTypeUCHAR, _out, (
int)c[2]);
694 if ( _opt.color_has_alpha() )
695 writeValue(ValueTypeUCHAR, _out, (
int)c[3]);
699 for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
700 write_customProp<true>(_out,*iter,i);
715 size_t _3floats(3*
sizeof(
float));
716 size_t _3ui(3*
sizeof(
unsigned int));
717 size_t _4ui(4*
sizeof(
unsigned int));
719 if ( !_writeOptions.is_binary() )
724 size_t _3longs(3*
sizeof(
long));
728 data += _be.n_vertices() * _3floats;
731 if ( _writeOptions.vertex_has_normal() && _be.has_vertex_normals() )
734 data += _be.n_vertices() * _3floats;
737 if ( _writeOptions.vertex_has_color() && _be.has_vertex_colors() )
740 data += _be.n_vertices() * _3floats;
743 if ( _writeOptions.vertex_has_texcoord() && _be.has_vertex_texcoords() )
745 size_t _2floats(2*
sizeof(
float));
747 data += _be.n_vertices() * _2floats;
751 if (_be.is_triangle_mesh())
753 data += _be.n_faces() * _4ui;
758 std::vector<VertexHandle> vhandles;
760 for (i=0, nF=
int(_be.n_faces()); i<nF; ++i)
762 data += _be.get_vhandles(
FaceHandle(i), vhandles) *
sizeof(
unsigned int);
768 if ( _writeOptions.face_has_color() && _be.has_face_colors() ){
769 if ( _writeOptions.color_has_alpha() )
770 data += _be.n_faces() * _4ui;
772 data += _be.n_faces() * _3ui;
prop_iterator vprops_end()
prop_iterator vprops_begin()
prop_iterator fprops_begin()
PropertyContainer::const_iterator const_prop_iterator
prop_iterator fprops_end()
bool persistent(void) const
Returns true if the persistent flag is enabled else false.
virtual size_t element_size() const =0
Size of one element in bytes or UnknownSize if not known.
const std::string & name() const
Return the name of the property.
Set options for reader/writer modules.
@ FaceNormal
Has (r) / store (w) face normals.
@ MSB
Assume big endian byte ordering.
@ Binary
Set binary mode for r/w.
bool register_module(BaseReader *_bl)
size_t binary_size(BaseExporter &_be, const Options &_opt) const override
Returns expected size of file if binary format is supported else 0.
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,...
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 write(const std::string &, BaseExporter &, const Options &_writeOptions, std::streamsize _precision=6) const override
Default property class for any type T.
_IOManager_ & IOManager()
_PLYWriter_ __PLYWriterInstance
Declare the single entity of the PLY writer.
Handle for a face entity.
Handle for a vertex entity.