Developer Documentation
PLYWriter.cc
1 /* ========================================================================= *
2  * *
3  * OpenMesh *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openmesh.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenMesh. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40  * ========================================================================= */
41 
42 
43 
44 
45 //== INCLUDES =================================================================
46 
47 #include <fstream>
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>
53 
54 #include <iostream>
55 
56 //=== NAMESPACES ==============================================================
57 
58 
59 namespace OpenMesh {
60 namespace IO {
61 
62 
63 //=== INSTANCIATE =============================================================
64 
65 
66 // register the PLYLoader singleton with MeshLoader
68 _PLYWriter_& PLYWriter() { return __PLYWriterInstance; }
69 
70 
71 //=== IMPLEMENTATION ==========================================================
72 
73 
74 _PLYWriter_::_PLYWriter_()
75 {
76  IOManager().register_module(this);
77 
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";
87 }
88 
89 
90 //-----------------------------------------------------------------------------
91 
92 
93 bool
95 write(const std::string& _filename, BaseExporter& _be, Options _opt, std::streamsize _precision) const
96 {
97 
98  // open file
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);
102 }
103 
104 //-----------------------------------------------------------------------------
105 
106 
107 bool
109 write(std::ostream& _os, BaseExporter& _be, Options _opt, std::streamsize _precision) const
110 {
111  // check exporter features
112  if ( !check( _be, _opt ) )
113  return false;
114 
115 
116  // check writer features
117  if ( _opt.check(Options::FaceNormal) ) {
118  // Face normals are not supported
119  // Uncheck these options and output message that
120  // they are not written out even though they were requested
122  omerr() << "[PLYWriter] : Warning: Face normals are not supported and thus not exported! " << std::endl;
123  }
124 
125  options_ = _opt;
126 
127 
128  if (!_os.good())
129  {
130  omerr() << "[PLYWriter] : cannot write to stream "
131  << std::endl;
132  return false;
133  }
134 
135  if (!_opt.check(Options::Binary))
136  _os.precision(_precision);
137 
138  // write to file
139  bool result = (_opt.check(Options::Binary) ?
140  write_binary(_os, _be, _opt) :
141  write_ascii(_os, _be, _opt));
142 
143  return result;
144 }
145 
146 //-----------------------------------------------------------------------------
147 
148 // helper function for casting a property
149 template<typename T>
150 const PropertyT<T>* castProperty(const BaseProperty* _prop)
151 {
152  return dynamic_cast< const PropertyT<T>* >(_prop);
153 }
154 
155 //-----------------------------------------------------------------------------
156 std::vector<_PLYWriter_::CustomProperty> _PLYWriter_::writeCustomTypeHeader(std::ostream& _out, BaseKernel::const_prop_iterator _begin, BaseKernel::const_prop_iterator _end) const
157 {
158  std::vector<CustomProperty> customProps;
159  for (;_begin != _end; ++_begin)
160  {
161  BaseProperty* prop = *_begin;
162 
163 
164  // check, if property is persistant
165  if (!prop || !prop->persistent())
166  continue;
167 
168 
169  // identify type of property
170  CustomProperty cProp(prop);
171  size_t propSize = prop->element_size();
172  switch (propSize)
173  {
174  case 1:
175  {
176  assert_compile(sizeof(char) == 1);
177  //check, if prop is a char or unsigned char by dynamic_cast
178  //char, unsigned char and signed char are 3 distinct types
179  if (castProperty<signed char>(prop) != 0 || castProperty<char>(prop) != 0) //treat char as signed char
180  cProp.type = ValueTypeCHAR;
181  else if (castProperty<unsigned char>(prop) != 0)
182  cProp.type = ValueTypeUCHAR;
183  break;
184  }
185  case 2:
186  {
187  assert_compile (sizeof(short) == 2);
188  if (castProperty<signed short>(prop) != 0)
189  cProp.type = ValueTypeSHORT;
190  else if (castProperty<unsigned short>(prop) != 0)
191  cProp.type = ValueTypeUSHORT;
192  break;
193  }
194  case 4:
195  {
196  assert_compile (sizeof(int) == 4);
197  assert_compile (sizeof(float) == 4);
198  if (castProperty<signed int>(prop) != 0)
199  cProp.type = ValueTypeINT;
200  else if (castProperty<unsigned int>(prop) != 0)
201  cProp.type = ValueTypeUINT;
202  else if (castProperty<float>(prop) != 0)
203  cProp.type = ValueTypeFLOAT;
204  break;
205 
206  }
207  case 8:
208  assert_compile (sizeof(double) == 8);
209  if (castProperty<double>(prop) != 0)
210  cProp.type = ValueTypeDOUBLE;
211  break;
212  default:
213  break;
214  }
215 
216  if (cProp.type != Unsupported)
217  {
218  // property type was identified and it is persistant, write into header
219  customProps.push_back(cProp);
220  _out << "property " << nameOfType_[cProp.type] << " " << cProp.property->name() << "\n";
221  }
222  }
223  return customProps;
224 }
225 
226 //-----------------------------------------------------------------------------
227 
228 template<bool binary>
229 void _PLYWriter_::write_customProp(std::ostream& _out, const CustomProperty& _prop, size_t _index) const
230 {
231  if (_prop.type == ValueTypeCHAR)
232  writeProxy(_prop.type,_out, castProperty<signed char>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
233  else if (_prop.type == ValueTypeUCHAR || _prop.type == ValueTypeUINT8)
234  writeProxy(_prop.type,_out, castProperty<unsigned char>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
235  else if (_prop.type == ValueTypeSHORT)
236  writeProxy(_prop.type,_out, castProperty<signed short>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
237  else if (_prop.type == ValueTypeUSHORT)
238  writeProxy(_prop.type,_out, castProperty<unsigned short>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
239  else if (_prop.type == ValueTypeUINT)
240  writeProxy(_prop.type,_out, castProperty<unsigned int>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
241  else if (_prop.type == ValueTypeINT || _prop.type == ValueTypeINT32)
242  writeProxy(_prop.type,_out, castProperty<signed int>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
243  else if (_prop.type == ValueTypeFLOAT || _prop.type == ValueTypeFLOAT32)
244  writeProxy(_prop.type,_out, castProperty<float>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
245  else if (_prop.type == ValueTypeDOUBLE)
246  writeProxy(_prop.type,_out, castProperty<double>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
247 }
248 
249 
250 //-----------------------------------------------------------------------------
251 
252 
253 
254 void _PLYWriter_::write_header(std::ostream& _out, BaseExporter& _be, Options& _opt, std::vector<CustomProperty>& _ovProps, std::vector<CustomProperty>& _ofProps) const {
255  //writing header
256  _out << "ply" << '\n';
257 
258  if (_opt.is_binary()) {
259  _out << "format ";
260  if ( options_.check(Options::MSB) )
261  _out << "binary_big_endian ";
262  else
263  _out << "binary_little_endian ";
264  _out << "1.0" << '\n';
265  } else
266  _out << "format ascii 1.0" << '\n';
267 
268  _out << "element vertex " << _be.n_vertices() << '\n';
269 
270  _out << "property float x" << '\n';
271  _out << "property float y" << '\n';
272  _out << "property float z" << '\n';
273 
274  if ( _opt.vertex_has_normal() ){
275  _out << "property float nx" << '\n';
276  _out << "property float ny" << '\n';
277  _out << "property float nz" << '\n';
278  }
279 
280  if ( _opt.vertex_has_texcoord() ){
281  _out << "property float u" << '\n';
282  _out << "property float v" << '\n';
283  }
284 
285  if ( _opt.vertex_has_color() ){
286  if ( _opt.color_is_float() ) {
287  _out << "property float red" << '\n';
288  _out << "property float green" << '\n';
289  _out << "property float blue" << '\n';
290 
291  if ( _opt.color_has_alpha() )
292  _out << "property float alpha" << '\n';
293  } else {
294  _out << "property uchar red" << '\n';
295  _out << "property uchar green" << '\n';
296  _out << "property uchar blue" << '\n';
297 
298  if ( _opt.color_has_alpha() )
299  _out << "property uchar alpha" << '\n';
300  }
301  }
302 
303  _ovProps = writeCustomTypeHeader(_out, _be.kernel()->vprops_begin(), _be.kernel()->vprops_end());
304 
305  _out << "element face " << _be.n_faces() << '\n';
306  _out << "property list uchar int vertex_indices" << '\n';
307 
308  if ( _opt.face_has_color() ){
309  if ( _opt.color_is_float() ) {
310  _out << "property float red" << '\n';
311  _out << "property float green" << '\n';
312  _out << "property float blue" << '\n';
313 
314  if ( _opt.color_has_alpha() )
315  _out << "property float alpha" << '\n';
316  } else {
317  _out << "property uchar red" << '\n';
318  _out << "property uchar green" << '\n';
319  _out << "property uchar blue" << '\n';
320 
321  if ( _opt.color_has_alpha() )
322  _out << "property uchar alpha" << '\n';
323  }
324  }
325 
326  _ofProps = writeCustomTypeHeader(_out, _be.kernel()->fprops_begin(), _be.kernel()->fprops_end());
327 
328  _out << "end_header" << '\n';
329 }
330 
331 
332 //-----------------------------------------------------------------------------
333 
334 
335 bool
336 _PLYWriter_::
337 write_ascii(std::ostream& _out, BaseExporter& _be, Options _opt) const
338 {
339 
340  unsigned int i, nV, nF;
341  Vec3f v, n;
343  OpenMesh::Vec4ui cA;
344  OpenMesh::Vec3f cf;
345  OpenMesh::Vec4f cAf;
346  OpenMesh::Vec2f t;
347  VertexHandle vh;
348  FaceHandle fh;
349  std::vector<VertexHandle> vhandles;
350 
351  std::vector<CustomProperty> vProps;
352  std::vector<CustomProperty> fProps;
353 
354  write_header(_out, _be, _opt, vProps, fProps);
355 
356  if (_opt.color_is_float())
357  _out << std::fixed;
358 
359  // vertex data (point, normals, colors, texcoords)
360  for (i=0, nV=int(_be.n_vertices()); i<nV; ++i)
361  {
362  vh = VertexHandle(i);
363  v = _be.point(vh);
364 
365  //Vertex
366  _out << v[0] << " " << v[1] << " " << v[2];
367 
368  // Vertex Normals
369  if ( _opt.vertex_has_normal() ){
370  n = _be.normal(vh);
371  _out << " " << n[0] << " " << n[1] << " " << n[2];
372  }
373 
374  // Vertex TexCoords
375  if ( _opt.vertex_has_texcoord() ) {
376  t = _be.texcoord(vh);
377  _out << " " << t[0] << " " << t[1];
378  }
379 
380  // VertexColor
381  if ( _opt.vertex_has_color() ) {
382  //with alpha
383  if ( _opt.color_has_alpha() ){
384  if (_opt.color_is_float()) {
385  cAf = _be.colorAf(vh);
386  _out << " " << cAf;
387  } else {
388  cA = _be.colorAi(vh);
389  _out << " " << cA;
390  }
391  }else{
392  //without alpha
393  if (_opt.color_is_float()) {
394  cf = _be.colorf(vh);
395  _out << " " << cf;
396  } else {
397  c = _be.colori(vh);
398  _out << " " << c;
399  }
400  }
401  }
402 
403 
404  // write custom properties for vertices
405  for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
406  write_customProp<false>(_out,*iter,i);
407 
408  _out << "\n";
409  }
410 
411  // faces (indices starting at 0)
412  for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
413  {
414  fh = FaceHandle(i);
415 
416  // write vertex indices per face
417  nV = _be.get_vhandles(fh, vhandles);
418  _out << nV;
419  for (size_t j=0; j<vhandles.size(); ++j)
420  _out << " " << vhandles[j].idx();
421 
422  // FaceColor
423  if ( _opt.face_has_color() ) {
424  //with alpha
425  if ( _opt.color_has_alpha() ){
426  if (_opt.color_is_float()) {
427  cAf = _be.colorAf(fh);
428  _out << " " << cAf;
429  } else {
430  cA = _be.colorAi(fh);
431  _out << " " << cA;
432  }
433  }else{
434  //without alpha
435  if (_opt.color_is_float()) {
436  cf = _be.colorf(fh);
437  _out << " " << cf;
438  } else {
439  c = _be.colori(fh);
440  _out << " " << c;
441  }
442  }
443  }
444 
445  // write custom props
446  for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
447  write_customProp<false>(_out,*iter,i);
448  _out << "\n";
449  }
450 
451 
452  return true;
453 }
454 
455 
456 //-----------------------------------------------------------------------------
457 
458 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, int value) const {
459 
460  uint32_t tmp32;
461  uint8_t tmp8;
462 
463  switch (_type) {
464  case ValueTypeINT:
465  case ValueTypeINT32:
466  tmp32 = value;
467  store(_out, tmp32, options_.check(Options::MSB) );
468  break;
469 // case ValueTypeUINT8:
470 default :
471  tmp8 = value;
472  store(_out, tmp8, options_.check(Options::MSB) );
473  break;
474 // default :
475 // std::cerr << "unsupported conversion type to int: " << _type << std::endl;
476 // break;
477  }
478 }
479 
480 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, unsigned int value) const {
481 
482  uint32_t tmp32;
483  uint8_t tmp8;
484 
485  switch (_type) {
486  case ValueTypeINT:
487  case ValueTypeINT32:
488  tmp32 = value;
489  store(_out, tmp32, options_.check(Options::MSB) );
490  break;
491 // case ValueTypeUINT8:
492 default :
493  tmp8 = value;
494  store(_out, tmp8, options_.check(Options::MSB) );
495  break;
496 // default :
497 // std::cerr << "unsupported conversion type to int: " << _type << std::endl;
498 // break;
499  }
500 }
501 
502 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, float value) const {
503 
504  float32_t tmp;
505 
506  switch (_type) {
507  case ValueTypeFLOAT32:
508  case ValueTypeFLOAT:
509  tmp = value;
510  store( _out , tmp, options_.check(Options::MSB) );
511  break;
512  default :
513  std::cerr << "unsupported conversion type to float: " << _type << std::endl;
514  break;
515  }
516 }
517 
518 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, double value) const {
519 
520  float64_t tmp;
521 
522  switch (_type) {
523  case ValueTypeDOUBLE:
524  tmp = value;
525  store( _out , tmp, options_.check(Options::MSB) );
526  break;
527  default :
528  std::cerr << "unsupported conversion type to float: " << _type << std::endl;
529  break;
530  }
531 }
532 
533 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, signed char value) const{
534 
535  int8_t tmp;
536 
537  switch (_type) {
538  case ValueTypeCHAR:
539  tmp = value;
540  store(_out, tmp, options_.check(Options::MSB) );
541  break;
542  default :
543  std::cerr << "unsupported conversion type to int: " << _type << std::endl;
544  break;
545  }
546 }
547 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, unsigned char value) const{
548 
549  uint8_t tmp;
550 
551  switch (_type) {
552  case ValueTypeUCHAR:
553  tmp = value;
554  store(_out, tmp, options_.check(Options::MSB) );
555  break;
556  default :
557  std::cerr << "unsupported conversion type to int: " << _type << std::endl;
558  break;
559  }
560 }
561 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, short value) const{
562 
563  int16_t tmp;
564 
565  switch (_type) {
566  case ValueTypeSHORT:
567  tmp = value;
568  store(_out, tmp, options_.check(Options::MSB) );
569  break;
570  default :
571  std::cerr << "unsupported conversion type to int: " << _type << std::endl;
572  break;
573  }
574 }
575 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, unsigned short value) const{
576 
577  uint16_t tmp;
578 
579  switch (_type) {
580  case ValueTypeUSHORT:
581  tmp = value;
582  store(_out, tmp, options_.check(Options::MSB) );
583  break;
584  default :
585  std::cerr << "unsupported conversion type to int: " << _type << std::endl;
586  break;
587  }
588 }
589 
590 bool
591 _PLYWriter_::
592 write_binary(std::ostream& _out, BaseExporter& _be, Options _opt) const
593 {
594 
595  unsigned int i, nV, nF;
596  Vec3f v, n;
597  Vec2f t;
599  OpenMesh::Vec4f cf;
600  VertexHandle vh;
601  FaceHandle fh;
602  std::vector<VertexHandle> vhandles;
603 
604  // vProps and fProps will be empty, until custom properties are supported by the binary writer
605  std::vector<CustomProperty> vProps;
606  std::vector<CustomProperty> fProps;
607 
608  write_header(_out, _be, _opt, vProps, fProps);
609 
610  // vertex data (point, normals, texcoords)
611  for (i=0, nV=int(_be.n_vertices()); i<nV; ++i)
612  {
613  vh = VertexHandle(i);
614  v = _be.point(vh);
615 
616  //vertex
617  writeValue(ValueTypeFLOAT, _out, v[0]);
618  writeValue(ValueTypeFLOAT, _out, v[1]);
619  writeValue(ValueTypeFLOAT, _out, v[2]);
620 
621  // Vertex Normal
622  if ( _opt.vertex_has_normal() ){
623  n = _be.normal(vh);
624  writeValue(ValueTypeFLOAT, _out, n[0]);
625  writeValue(ValueTypeFLOAT, _out, n[1]);
626  writeValue(ValueTypeFLOAT, _out, n[2]);
627  }
628 
629  // Vertex TexCoords
630  if ( _opt.vertex_has_texcoord() ) {
631  t = _be.texcoord(vh);
632  writeValue(ValueTypeFLOAT, _out, t[0]);
633  writeValue(ValueTypeFLOAT, _out, t[1]);
634  }
635 
636  // vertex color
637  if ( _opt.vertex_has_color() ) {
638  if ( _opt.color_is_float() ) {
639  cf = _be.colorAf(vh);
640  writeValue(ValueTypeFLOAT, _out, cf[0]);
641  writeValue(ValueTypeFLOAT, _out, cf[1]);
642  writeValue(ValueTypeFLOAT, _out, cf[2]);
643 
644  if ( _opt.color_has_alpha() )
645  writeValue(ValueTypeFLOAT, _out, cf[3]);
646  } else {
647  c = _be.colorA(vh);
648  writeValue(ValueTypeUCHAR, _out, (int)c[0]);
649  writeValue(ValueTypeUCHAR, _out, (int)c[1]);
650  writeValue(ValueTypeUCHAR, _out, (int)c[2]);
651 
652  if ( _opt.color_has_alpha() )
653  writeValue(ValueTypeUCHAR, _out, (int)c[3]);
654  }
655  }
656 
657  for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
658  write_customProp<true>(_out,*iter,i);
659  }
660 
661 
662  for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
663  {
664  fh = FaceHandle(i);
665 
666  //face
667  nV = _be.get_vhandles(fh, vhandles);
668  writeValue(ValueTypeUINT8, _out, nV);
669  for (size_t j=0; j<vhandles.size(); ++j)
670  writeValue(ValueTypeINT32, _out, vhandles[j].idx() );
671 
672  // face color
673  if ( _opt.face_has_color() ) {
674  if ( _opt.color_is_float() ) {
675  cf = _be.colorAf(fh);
676  writeValue(ValueTypeFLOAT, _out, cf[0]);
677  writeValue(ValueTypeFLOAT, _out, cf[1]);
678  writeValue(ValueTypeFLOAT, _out, cf[2]);
679 
680  if ( _opt.color_has_alpha() )
681  writeValue(ValueTypeFLOAT, _out, cf[3]);
682  } else {
683  c = _be.colorA(fh);
684  writeValue(ValueTypeUCHAR, _out, (int)c[0]);
685  writeValue(ValueTypeUCHAR, _out, (int)c[1]);
686  writeValue(ValueTypeUCHAR, _out, (int)c[2]);
687 
688  if ( _opt.color_has_alpha() )
689  writeValue(ValueTypeUCHAR, _out, (int)c[3]);
690  }
691  }
692 
693  for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
694  write_customProp<true>(_out,*iter,i);
695  }
696 
697  return true;
698 }
699 
700 // ----------------------------------------------------------------------------
701 
702 
703 size_t
706 {
707  size_t header(0);
708  size_t data(0);
709  size_t _3floats(3*sizeof(float));
710  size_t _3ui(3*sizeof(unsigned int));
711  size_t _4ui(4*sizeof(unsigned int));
712 
713  if ( !_opt.is_binary() )
714  return 0;
715  else
716  {
717 
718  size_t _3longs(3*sizeof(long));
719 
720  header += 11; // 'OFF BINARY\n'
721  header += _3longs; // #V #F #E
722  data += _be.n_vertices() * _3floats; // vertex data
723  }
724 
725  if ( _opt.vertex_has_normal() && _be.has_vertex_normals() )
726  {
727  header += 1; // N
728  data += _be.n_vertices() * _3floats;
729  }
730 
731  if ( _opt.vertex_has_color() && _be.has_vertex_colors() )
732  {
733  header += 1; // C
734  data += _be.n_vertices() * _3floats;
735  }
736 
737  if ( _opt.vertex_has_texcoord() && _be.has_vertex_texcoords() )
738  {
739  size_t _2floats(2*sizeof(float));
740  header += 2; // ST
741  data += _be.n_vertices() * _2floats;
742  }
743 
744  // topology
745  if (_be.is_triangle_mesh())
746  {
747  data += _be.n_faces() * _4ui;
748  }
749  else
750  {
751  unsigned int i, nF;
752  std::vector<VertexHandle> vhandles;
753 
754  for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
755  {
756  data += _be.get_vhandles(FaceHandle(i), vhandles) * sizeof(unsigned int);
757 
758  }
759  }
760 
761  // face colors
762  if ( _opt.face_has_color() && _be.has_face_colors() ){
763  if ( _opt.color_has_alpha() )
764  data += _be.n_faces() * _4ui;
765  else
766  data += _be.n_faces() * _3ui;
767  }
768 
769  return header+data;
770 }
771 
772 
773 //=============================================================================
774 } // namespace IO
775 } // namespace OpenMesh
776 //=============================================================================
Handle for a face entity.
Definition: Handles.hh:141
signed char int8_t
Definition: SR_types.hh:80
Assume big endian byte ordering.
Definition: Options.hh:101
short int16_t
Definition: SR_types.hh:81
float float32_t
Definition: SR_types.hh:92
double float64_t
Definition: SR_types.hh:93
Handle for a vertex entity.
Definition: Handles.hh:120
size_t binary_size(BaseExporter &_be, Options _opt) const override
Returns expected size of file if binary format is supported else 0.
Definition: PLYWriter.cc:705
bool register_module(BaseReader *_bl)
Definition: IOManager.hh:217
bool persistent(void) const
Returns true if the persistent flag is enabled else false.
Default property class for any type T.
Definition: Property.hh:89
unsigned short uint16_t
Definition: SR_types.hh:81
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...
Definition: PLYWriter.cc:156
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.
unsigned char uint8_t
Definition: SR_types.hh:80
bool write(const std::string &, BaseExporter &, Options, std::streamsize _precision=6) const override
Definition: PLYWriter.cc:95
unsigned int uint32_t
Definition: SR_types.hh:85
Set options for reader/writer modules.
Definition: Options.hh:90
Options & unset(const value_type _rhs)
Unset options defined in _rhs.
Definition: Options.hh:174
_IOManager_ & IOManager()
Definition: IOManager.cc:72
Has (r) / store (w) face normals.
Definition: Options.hh:108
Set binary mode for r/w.
Definition: Options.hh:100
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...
Definition: PLYWriter.cc:254
_PLYWriter_ __PLYWriterInstance
Declare the single entity of the PLY writer.
Definition: PLYWriter.cc:67