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  * $Revision$ *
45  * $Date$ *
46  * *
47 \*===========================================================================*/
48 
49 
50 //== INCLUDES =================================================================
51 
52 #include <fstream>
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>
58 
59 #include <iostream>
60 
61 //=== NAMESPACES ==============================================================
62 
63 
64 namespace OpenMesh {
65 namespace IO {
66 
67 
68 //=== INSTANCIATE =============================================================
69 
70 
71 // register the PLYLoader singleton with MeshLoader
73 _PLYWriter_& PLYWriter() { return __PLYWriterInstance; }
74 
75 
76 //=== IMPLEMENTATION ==========================================================
77 
78 
79 _PLYWriter_::_PLYWriter_()
80 {
81  IOManager().register_module(this);
82 
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";
92 }
93 
94 
95 //-----------------------------------------------------------------------------
96 
97 
98 bool
100 write(const std::string& _filename, BaseExporter& _be, Options _opt, std::streamsize _precision) const
101 {
102 
103  // open file
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);
107 }
108 
109 //-----------------------------------------------------------------------------
110 
111 
112 bool
114 write(std::ostream& _os, BaseExporter& _be, Options _opt, std::streamsize _precision) const
115 {
116  // check exporter features
117  if ( !check( _be, _opt ) )
118  return false;
119 
120 
121  // check writer features
122  if ( _opt.check(Options::FaceNormal) ) {
123  // Face normals are not supported
124  // Uncheck these options and output message that
125  // they are not written out even though they were requested
127  omerr() << "[PLYWriter] : Warning: Face normals are not supported and thus not exported! " << std::endl;
128  }
129 
130  if ( _opt.check(Options::FaceColor) ) {
131  // Face normals are not supported
132  // Uncheck these options and output message that
133  // they are not written out even though they were requested
135  omerr() << "[PLYWriter] : Warning: Face colors are not supported and thus not exported! " << std::endl;
136  }
137 
138  options_ = _opt;
139 
140 
141  if (!_os.good())
142  {
143  omerr() << "[PLYWriter] : cannot write to stream "
144  << std::endl;
145  return false;
146  }
147 
148  if (!_opt.check(Options::Binary))
149  _os.precision(_precision);
150 
151  // write to file
152  bool result = (_opt.check(Options::Binary) ?
153  write_binary(_os, _be, _opt) :
154  write_ascii(_os, _be, _opt));
155 
156  return result;
157 }
158 
159 //-----------------------------------------------------------------------------
160 
161 // helper function for casting a property
162 template<typename T>
163 const PropertyT<T>* castProperty(const BaseProperty* _prop)
164 {
165  return dynamic_cast< const PropertyT<T>* >(_prop);
166 }
167 
168 //-----------------------------------------------------------------------------
169 std::vector<_PLYWriter_::CustomProperty> _PLYWriter_::writeCustomTypeHeader(std::ostream& _out, BaseKernel::const_prop_iterator _begin, BaseKernel::const_prop_iterator _end) const
170 {
171  std::vector<CustomProperty> customProps;
172  for (;_begin != _end; ++_begin)
173  {
174  BaseProperty* prop = *_begin;
175 
176 
177  // check, if property is persistant
178  if (!prop || !prop->persistent())
179  continue;
180 
181 
182  // identify type of property
183  CustomProperty cProp(prop);
184  size_t propSize = prop->element_size();
185  switch (propSize)
186  {
187  case 1:
188  {
189  assert_compile(sizeof(char) == 1);
190  //check, if prop is a char or unsigned char by dynamic_cast
191  //char, unsigned char and signed char are 3 distinct types
192  if (castProperty<signed char>(prop) != 0 || castProperty<char>(prop) != 0) //treat char as signed char
193  cProp.type = ValueTypeCHAR;
194  else if (castProperty<unsigned char>(prop) != 0)
195  cProp.type = ValueTypeUCHAR;
196  break;
197  }
198  case 2:
199  {
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;
205  break;
206  }
207  case 4:
208  {
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;
217  break;
218 
219  }
220  case 8:
221  assert_compile (sizeof(double) == 8);
222  if (castProperty<double>(prop) != 0)
223  cProp.type = ValueTypeDOUBLE;
224  break;
225  default:
226  break;
227  }
228 
229  if (cProp.type != Unsupported)
230  {
231  // property type was identified and it is persistant, write into header
232  customProps.push_back(cProp);
233  _out << "property " << nameOfType_[cProp.type] << " " << cProp.property->name() << "\n";
234  }
235  }
236  return customProps;
237 }
238 
239 //-----------------------------------------------------------------------------
240 
241 template<bool binary>
242 void _PLYWriter_::write_customProp(std::ostream& _out, const CustomProperty& _prop, size_t _index) const
243 {
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>());
260 }
261 
262 
263 //-----------------------------------------------------------------------------
264 
265 
266 
267 void _PLYWriter_::write_header(std::ostream& _out, BaseExporter& _be, Options& _opt, std::vector<CustomProperty>& _ovProps, std::vector<CustomProperty>& _ofProps) const {
268  //writing header
269  _out << "ply" << '\n';
270 
271  if (_opt.is_binary()) {
272  _out << "format ";
273  if ( options_.check(Options::MSB) )
274  _out << "binary_big_endian ";
275  else
276  _out << "binary_little_endian ";
277  _out << "1.0" << '\n';
278  } else
279  _out << "format ascii 1.0" << '\n';
280 
281  _out << "element vertex " << _be.n_vertices() << '\n';
282 
283  _out << "property float x" << '\n';
284  _out << "property float y" << '\n';
285  _out << "property float z" << '\n';
286 
287  if ( _opt.vertex_has_normal() ){
288  _out << "property float nx" << '\n';
289  _out << "property float ny" << '\n';
290  _out << "property float nz" << '\n';
291  }
292 
293  if ( _opt.vertex_has_texcoord() ){
294  _out << "property float u" << '\n';
295  _out << "property float v" << '\n';
296  }
297 
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';
303 
304  if ( _opt.color_has_alpha() )
305  _out << "property float alpha" << '\n';
306  } else {
307  _out << "property uchar red" << '\n';
308  _out << "property uchar green" << '\n';
309  _out << "property uchar blue" << '\n';
310 
311  if ( _opt.color_has_alpha() )
312  _out << "property uchar alpha" << '\n';
313  }
314  }
315 
316  _ovProps = writeCustomTypeHeader(_out, _be.kernel()->vprops_begin(), _be.kernel()->vprops_end());
317 
318  _out << "element face " << _be.n_faces() << '\n';
319  _out << "property list uchar int vertex_indices" << '\n';
320 
321  _ofProps = writeCustomTypeHeader(_out, _be.kernel()->fprops_begin(), _be.kernel()->fprops_end());
322 
323  _out << "end_header" << '\n';
324 }
325 
326 
327 //-----------------------------------------------------------------------------
328 
329 
330 bool
331 _PLYWriter_::
332 write_ascii(std::ostream& _out, BaseExporter& _be, Options _opt) const
333 {
334 
335  unsigned int i, nV, nF;
336  Vec3f v, n;
338  OpenMesh::Vec4ui cA;
339  OpenMesh::Vec3f cf;
340  OpenMesh::Vec4f cAf;
341  OpenMesh::Vec2f t;
342  VertexHandle vh;
343  std::vector<VertexHandle> vhandles;
344 
345  std::vector<CustomProperty> vProps;
346  std::vector<CustomProperty> fProps;
347 
348  write_header(_out, _be, _opt, vProps, fProps);
349 
350  if (_opt.color_is_float())
351  _out << std::fixed;
352 
353  // vertex data (point, normals, colors, texcoords)
354  for (i=0, nV=int(_be.n_vertices()); i<nV; ++i)
355  {
356  vh = VertexHandle(i);
357  v = _be.point(vh);
358 
359  //Vertex
360  _out << v[0] << " " << v[1] << " " << v[2];
361 
362  // Vertex Normals
363  if ( _opt.vertex_has_normal() ){
364  n = _be.normal(vh);
365  _out << " " << n[0] << " " << n[1] << " " << n[2];
366  }
367 
368  // Vertex TexCoords
369  if ( _opt.vertex_has_texcoord() ) {
370  t = _be.texcoord(vh);
371  _out << " " << t[0] << " " << t[1];
372  }
373 
374  // VertexColor
375  if ( _opt.vertex_has_color() ) {
376  //with alpha
377  if ( _opt.color_has_alpha() ){
378  if (_opt.color_is_float()) {
379  cAf = _be.colorAf(vh);
380  _out << " " << cAf;
381  } else {
382  cA = _be.colorAi(vh);
383  _out << " " << cA;
384  }
385  }else{
386  //without alpha
387  if (_opt.color_is_float()) {
388  cf = _be.colorf(vh);
389  _out << " " << cf;
390  } else {
391  c = _be.colori(vh);
392  _out << " " << c;
393  }
394  }
395  }
396 
397 
398  // write custom properties for vertices
399  for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
400  write_customProp<false>(_out,*iter,i);
401 
402  _out << "\n";
403  }
404 
405  // faces (indices starting at 0)
406  for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
407  {
408  // write vertex indices per face
409  nV = _be.get_vhandles(FaceHandle(i), vhandles);
410  _out << nV;
411  for (size_t j=0; j<vhandles.size(); ++j)
412  _out << " " << vhandles[j].idx();
413 
414  // write custom props
415  for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
416  write_customProp<false>(_out,*iter,i);
417  _out << "\n";
418  }
419 
420 
421  return true;
422 }
423 
424 
425 //-----------------------------------------------------------------------------
426 
427 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, int value) const {
428 
429  uint32_t tmp32;
430  uint8_t tmp8;
431 
432  switch (_type) {
433  case ValueTypeINT:
434  case ValueTypeINT32:
435  tmp32 = value;
436  store(_out, tmp32, options_.check(Options::MSB) );
437  break;
438 // case ValueTypeUINT8:
439 default :
440  tmp8 = value;
441  store(_out, tmp8, options_.check(Options::MSB) );
442  break;
443 // default :
444 // std::cerr << "unsupported conversion type to int: " << _type << std::endl;
445 // break;
446  }
447 }
448 
449 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, unsigned int value) const {
450 
451  uint32_t tmp32;
452  uint8_t tmp8;
453 
454  switch (_type) {
455  case ValueTypeINT:
456  case ValueTypeINT32:
457  tmp32 = value;
458  store(_out, tmp32, options_.check(Options::MSB) );
459  break;
460 // case ValueTypeUINT8:
461 default :
462  tmp8 = value;
463  store(_out, tmp8, options_.check(Options::MSB) );
464  break;
465 // default :
466 // std::cerr << "unsupported conversion type to int: " << _type << std::endl;
467 // break;
468  }
469 }
470 
471 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, float value) const {
472 
473  float32_t tmp;
474 
475  switch (_type) {
476  case ValueTypeFLOAT32:
477  case ValueTypeFLOAT:
478  tmp = value;
479  store( _out , tmp, options_.check(Options::MSB) );
480  break;
481  default :
482  std::cerr << "unsupported conversion type to float: " << _type << std::endl;
483  break;
484  }
485 }
486 
487 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, double value) const {
488 
489  float64_t tmp;
490 
491  switch (_type) {
492  case ValueTypeDOUBLE:
493  tmp = value;
494  store( _out , tmp, options_.check(Options::MSB) );
495  break;
496  default :
497  std::cerr << "unsupported conversion type to float: " << _type << std::endl;
498  break;
499  }
500 }
501 
502 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, signed char value) const{
503 
504  int8_t tmp;
505 
506  switch (_type) {
507  case ValueTypeCHAR:
508  tmp = value;
509  store(_out, tmp, options_.check(Options::MSB) );
510  break;
511  default :
512  std::cerr << "unsupported conversion type to int: " << _type << std::endl;
513  break;
514  }
515 }
516 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, unsigned char value) const{
517 
518  uint8_t tmp;
519 
520  switch (_type) {
521  case ValueTypeUCHAR:
522  tmp = value;
523  store(_out, tmp, options_.check(Options::MSB) );
524  break;
525  default :
526  std::cerr << "unsupported conversion type to int: " << _type << std::endl;
527  break;
528  }
529 }
530 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, short value) const{
531 
532  int16_t tmp;
533 
534  switch (_type) {
535  case ValueTypeSHORT:
536  tmp = value;
537  store(_out, tmp, options_.check(Options::MSB) );
538  break;
539  default :
540  std::cerr << "unsupported conversion type to int: " << _type << std::endl;
541  break;
542  }
543 }
544 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, unsigned short value) const{
545 
546  uint16_t tmp;
547 
548  switch (_type) {
549  case ValueTypeUSHORT:
550  tmp = value;
551  store(_out, tmp, options_.check(Options::MSB) );
552  break;
553  default :
554  std::cerr << "unsupported conversion type to int: " << _type << std::endl;
555  break;
556  }
557 }
558 
559 bool
560 _PLYWriter_::
561 write_binary(std::ostream& _out, BaseExporter& _be, Options _opt) const
562 {
563 
564  unsigned int i, nV, nF;
565  Vec3f v, n;
566  Vec2f t;
568  OpenMesh::Vec4f cf;
569  VertexHandle vh;
570  std::vector<VertexHandle> vhandles;
571 
572  // vProps and fProps will be empty, until custom properties are supported by the binary writer
573  std::vector<CustomProperty> vProps;
574  std::vector<CustomProperty> fProps;
575 
576  write_header(_out, _be, _opt, vProps, fProps);
577 
578  // vertex data (point, normals, texcoords)
579  for (i=0, nV=int(_be.n_vertices()); i<nV; ++i)
580  {
581  vh = VertexHandle(i);
582  v = _be.point(vh);
583 
584  //vertex
585  writeValue(ValueTypeFLOAT, _out, v[0]);
586  writeValue(ValueTypeFLOAT, _out, v[1]);
587  writeValue(ValueTypeFLOAT, _out, v[2]);
588 
589  // Vertex Normal
590  if ( _opt.vertex_has_normal() ){
591  n = _be.normal(vh);
592  writeValue(ValueTypeFLOAT, _out, n[0]);
593  writeValue(ValueTypeFLOAT, _out, n[1]);
594  writeValue(ValueTypeFLOAT, _out, n[2]);
595  }
596 
597  // Vertex TexCoords
598  if ( _opt.vertex_has_texcoord() ) {
599  t = _be.texcoord(vh);
600  writeValue(ValueTypeFLOAT, _out, t[0]);
601  writeValue(ValueTypeFLOAT, _out, t[1]);
602  }
603 
604  // vertex color
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]);
611 
612  if ( _opt.color_has_alpha() )
613  writeValue(ValueTypeFLOAT, _out, cf[3]);
614  } else {
615  c = _be.colorA(vh);
616  writeValue(ValueTypeUCHAR, _out, (int)c[0]);
617  writeValue(ValueTypeUCHAR, _out, (int)c[1]);
618  writeValue(ValueTypeUCHAR, _out, (int)c[2]);
619 
620  if ( _opt.color_has_alpha() )
621  writeValue(ValueTypeUCHAR, _out, (int)c[3]);
622  }
623  }
624 
625  for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
626  write_customProp<true>(_out,*iter,i);
627  }
628 
629 
630  for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
631  {
632  //face
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() );
637 
638  for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
639  write_customProp<true>(_out,*iter,i);
640  }
641 
642  return true;
643 }
644 
645 // ----------------------------------------------------------------------------
646 
647 
648 size_t
651 {
652  size_t header(0);
653  size_t data(0);
654  size_t _3floats(3*sizeof(float));
655  size_t _3ui(3*sizeof(unsigned int));
656  size_t _4ui(4*sizeof(unsigned int));
657 
658  if ( !_opt.is_binary() )
659  return 0;
660  else
661  {
662 
663  size_t _3longs(3*sizeof(long));
664 
665  header += 11; // 'OFF BINARY\n'
666  header += _3longs; // #V #F #E
667  data += _be.n_vertices() * _3floats; // vertex data
668  }
669 
670  if ( _opt.vertex_has_normal() && _be.has_vertex_normals() )
671  {
672  header += 1; // N
673  data += _be.n_vertices() * _3floats;
674  }
675 
676  if ( _opt.vertex_has_color() && _be.has_vertex_colors() )
677  {
678  header += 1; // C
679  data += _be.n_vertices() * _3floats;
680  }
681 
682  if ( _opt.vertex_has_texcoord() && _be.has_vertex_texcoords() )
683  {
684  size_t _2floats(2*sizeof(float));
685  header += 2; // ST
686  data += _be.n_vertices() * _2floats;
687  }
688 
689  // topology
690  if (_be.is_triangle_mesh())
691  {
692  data += _be.n_faces() * _4ui;
693  }
694  else
695  {
696  unsigned int i, nF;
697  std::vector<VertexHandle> vhandles;
698 
699  for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
700  {
701  data += _be.get_vhandles(FaceHandle(i), vhandles) * sizeof(unsigned int);
702 
703  }
704  }
705 
706  // face colors
707  if ( _opt.face_has_color() && _be.has_face_colors() ){
708  if ( _opt.color_has_alpha() )
709  data += _be.n_faces() * _4ui;
710  else
711  data += _be.n_faces() * _3ui;
712  }
713 
714  return header+data;
715 }
716 
717 
718 //=============================================================================
719 } // namespace IO
720 } // namespace OpenMesh
721 //=============================================================================
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:267
_PLYWriter_ __PLYWriterInstance
Declare the single entity of the PLY writer.
Definition: PLYWriter.cc:72
bool write(const std::string &, BaseExporter &, Options, std::streamsize _precision=6) const
Definition: PLYWriter.cc:100
short int16_t
Definition: SR_types.hh:86
Set binary mode for r/w.
Definition: Options.hh:105
bool persistent(void) const
Returns true if the persistent flag is enabled else false.
Default property class for any type T.
Definition: Property.hh:94
Has (r) / store (w) face normals.
Definition: Options.hh:113
unsigned short uint16_t
Definition: SR_types.hh:86
Options & unset(const value_type _rhs)
Unset options defined in _rhs.
Definition: Options.hh:178
double float64_t
Definition: SR_types.hh:98
virtual size_t element_size() const =0
Size of one element in bytes or UnknownSize if not known.
unsigned char uint8_t
Definition: SR_types.hh:85
Set options for reader/writer modules.
Definition: Options.hh:95
Handle for a vertex entity.
Definition: Handles.hh:125
const std::string & name() const
Return the name of the property.
bool register_module(BaseReader *_bl)
Definition: IOManager.hh:222
Handle for a face entity.
Definition: Handles.hh:146
size_t binary_size(BaseExporter &_be, Options _opt) const
Returns expected size of file if binary format is supported else 0.
Definition: PLYWriter.cc:650
Has (r) / store (w) face colors.
Definition: Options.hh:114
unsigned int uint32_t
Definition: SR_types.hh:90
Assume big endian byte ordering.
Definition: Options.hh:106
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:169
_IOManager_ & IOManager()
Definition: IOManager.cc:77
signed char int8_t
Definition: SR_types.hh:85
float float32_t
Definition: SR_types.hh:97