Developer Documentation
PLYReader.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 #define LINE_LEN 4096
43 
44 //== INCLUDES =================================================================
45 
46 // OpenMesh
49 #include <OpenMesh/Core/IO/reader/PLYReader.hh>
50 #include <OpenMesh/Core/IO/IOManager.hh>
51 #include <OpenMesh/Core/Utils/color_cast.hh>
52 
53 //STL
54 #include <fstream>
55 #include <iostream>
56 #include <memory>
57 
58 #ifndef WIN32
59 #endif
60 
61 //=== NAMESPACES ==============================================================
62 
63 
64 namespace OpenMesh {
65 namespace IO {
66 
67 //=============================================================================
68 
69 //=== INSTANCIATE =============================================================
70 
71 
73 _PLYReader_& PLYReader() {
74  return __PLYReaderInstance;
75 }
76 
77 //=== IMPLEMENTATION ==========================================================
78 
79 
80 _PLYReader_::_PLYReader_() {
81  IOManager().register_module(this);
82 
83  // Store sizes in byte of each property type
84  scalar_size_[ValueTypeINT8] = 1;
85  scalar_size_[ValueTypeUINT8] = 1;
86  scalar_size_[ValueTypeINT16] = 2;
87  scalar_size_[ValueTypeUINT16] = 2;
88  scalar_size_[ValueTypeINT32] = 4;
89  scalar_size_[ValueTypeUINT32] = 4;
90  scalar_size_[ValueTypeFLOAT32] = 4;
91  scalar_size_[ValueTypeFLOAT64] = 8;
92 
93  scalar_size_[ValueTypeCHAR] = 1;
94  scalar_size_[ValueTypeUCHAR] = 1;
95  scalar_size_[ValueTypeSHORT] = 2;
96  scalar_size_[ValueTypeUSHORT] = 2;
97  scalar_size_[ValueTypeINT] = 4;
98  scalar_size_[ValueTypeUINT] = 4;
99  scalar_size_[ValueTypeFLOAT] = 4;
100  scalar_size_[ValueTypeDOUBLE] = 8;
101 }
102 
103 //-----------------------------------------------------------------------------
104 
105 
106 bool _PLYReader_::read(const std::string& _filename, BaseImporter& _bi, Options& _opt) {
107 
108  std::fstream in(_filename.c_str(), (std::ios_base::binary | std::ios_base::in) );
109 
110  if (!in.is_open() || !in.good()) {
111  omerr() << "[PLYReader] : cannot not open file " << _filename << std::endl;
112  return false;
113  }
114 
115  bool result = read(in, _bi, _opt);
116 
117  in.close();
118  return result;
119 }
120 
121 //-----------------------------------------------------------------------------
122 
123 
124 bool _PLYReader_::read(std::istream& _in, BaseImporter& _bi, Options& _opt) {
125 
126  if (!_in.good()) {
127  omerr() << "[PLYReader] : cannot not use stream" << std::endl;
128  return false;
129  }
130 
131  // Reparse the header
132  if (!can_u_read(_in)) {
133  omerr() << "[PLYReader] : Unable to parse header\n";
134  return false;
135  }
136 
137 
138 
139  // filter relevant options for reading
140  bool swap = _opt.check(Options::Swap);
141 
142  userOptions_ = _opt;
143 
144  // build options to be returned
145  _opt.clear();
146 
147  if (options_.vertex_has_normal() && userOptions_.vertex_has_normal()) {
148  _opt += Options::VertexNormal;
149  }
150  if (options_.vertex_has_texcoord() && userOptions_.vertex_has_texcoord()) {
151  _opt += Options::VertexTexCoord;
152  }
153  if (options_.vertex_has_color() && userOptions_.vertex_has_color()) {
154  _opt += Options::VertexColor;
155  }
156  if (options_.face_has_color() && userOptions_.face_has_color()) {
157  _opt += Options::FaceColor;
158  }
159  if (options_.is_binary()) {
160  _opt += Options::Binary;
161  }
162  if (options_.color_is_float()) {
163  _opt += Options::ColorFloat;
164  }
165  if (options_.check(Options::Custom) && userOptions_.check(Options::Custom)) {
166  _opt += Options::Custom;
167  }
168 
169  // //force user-choice for the alpha value when reading binary
170  // if ( options_.is_binary() && userOptions_.color_has_alpha() )
171  // options_ += Options::ColorAlpha;
172 
173  return (options_.is_binary() ? read_binary(_in, _bi, swap, _opt) : read_ascii(_in, _bi, _opt));
174 
175 }
176 
177 template<typename T, typename Handle>
178 struct Handle2Prop;
179 
180 template<typename T>
182 {
184 };
185 
186 template<typename T>
188 {
190 };
191 
192 //read and assign custom properties with the given type. Also creates property, if not exist
193 template<bool binary, typename T, typename Handle>
194 void _PLYReader_::readCreateCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const _PLYReader_::ValueType _valueType, const _PLYReader_::ValueType _listType) const
195 {
196  if (_listType == Unsupported) //no list type defined -> property is not a list
197  {
198  //get/add property
199  typename Handle2Prop<T,Handle>::PropT prop;
200  if (!_bi.kernel()->get_property_handle(prop,_propName))
201  {
202  _bi.kernel()->add_property(prop,_propName);
203  _bi.kernel()->property(prop).set_persistent(true);
204  }
205 
206  //read and assign
207  T in;
208  read(_valueType, _in, in, OpenMesh::GenProg::Bool2Type<binary>());
209  _bi.kernel()->property(prop,_h) = in;
210  }
211  else
212  {
213  //get/add property
214  typename Handle2Prop<std::vector<T>,Handle>::PropT prop;
215  if (!_bi.kernel()->get_property_handle(prop,_propName))
216  {
217  _bi.kernel()->add_property(prop,_propName);
218  _bi.kernel()->property(prop).set_persistent(true);
219  }
220 
221  //init vector
222  int numberOfValues;
223  read(_listType, _in, numberOfValues, OpenMesh::GenProg::Bool2Type<binary>());
224  std::vector<T> vec;
225  vec.reserve(numberOfValues);
226  //read and assign
227  for (int i = 0; i < numberOfValues; ++i)
228  {
229  T in;
230  read(_valueType, _in, in, OpenMesh::GenProg::Bool2Type<binary>());
231  vec.push_back(in);
232  }
233  _bi.kernel()->property(prop,_h) = vec;
234  }
235 }
236 
237 template<bool binary, typename Handle>
238 void _PLYReader_::readCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const _PLYReader_::ValueType _valueType, const _PLYReader_::ValueType _listIndexType) const
239 {
240  switch (_valueType)
241  {
242  case ValueTypeINT8:
243  case ValueTypeCHAR:
244  readCreateCustomProperty<binary,signed char>(_in,_bi,_h,_propName,_valueType,_listIndexType);
245  break;
246  case ValueTypeUINT8:
247  case ValueTypeUCHAR:
248  readCreateCustomProperty<binary,unsigned char>(_in,_bi,_h,_propName,_valueType,_listIndexType);
249  break;
250  case ValueTypeINT16:
251  case ValueTypeSHORT:
252  readCreateCustomProperty<binary,short>(_in,_bi,_h,_propName,_valueType,_listIndexType);
253  break;
254  case ValueTypeUINT16:
255  case ValueTypeUSHORT:
256  readCreateCustomProperty<binary,unsigned short>(_in,_bi,_h,_propName,_valueType,_listIndexType);
257  break;
258  case ValueTypeINT32:
259  case ValueTypeINT:
260  readCreateCustomProperty<binary,int>(_in,_bi,_h,_propName,_valueType,_listIndexType);
261  break;
262  case ValueTypeUINT32:
263  case ValueTypeUINT:
264  readCreateCustomProperty<binary,unsigned int>(_in,_bi,_h,_propName,_valueType,_listIndexType);
265  break;
266  case ValueTypeFLOAT32:
267  case ValueTypeFLOAT:
268  readCreateCustomProperty<binary,float>(_in,_bi,_h,_propName,_valueType,_listIndexType);
269  break;
270  case ValueTypeFLOAT64:
271  case ValueTypeDOUBLE:
272  readCreateCustomProperty<binary,double>(_in,_bi,_h,_propName,_valueType,_listIndexType);
273  break;
274  default:
275  std::cerr << "unsupported type" << std::endl;
276  break;
277  }
278 }
279 
280 
281 //-----------------------------------------------------------------------------
282 
283 bool _PLYReader_::read_ascii(std::istream& _in, BaseImporter& _bi, const Options& _opt) const {
284 
285  unsigned int i, j, k, l, idx;
286  unsigned int nV;
287  OpenMesh::Vec3f v, n;
288  std::string trash;
289  OpenMesh::Vec2f t;
290  OpenMesh::Vec4i c;
291  float tmp;
292  BaseImporter::VHandles vhandles;
293  VertexHandle vh;
294 
295  _bi.reserve(vertexCount_, 3* vertexCount_ , faceCount_);
296 
297  if (vertexDimension_ != 3) {
298  omerr() << "[PLYReader] : Only vertex dimension 3 is supported." << std::endl;
299  return false;
300  }
301 
302  const bool err_enabled = omerr().is_enabled();
303  size_t complex_faces = 0;
304  if (err_enabled)
305  omerr().disable();
306 
307  for (std::vector<ElementInfo>::iterator e_it = elements_.begin(); e_it != elements_.end(); ++e_it)
308  {
309  if (_in.eof()) {
310  if (err_enabled)
311  omerr().enable();
312 
313  omerr() << "Unexpected end of file while reading." << std::endl;
314  return false;
315  }
316 
317  if (e_it->element_== VERTEX)
318  {
319  // read vertices:
320  for (i = 0; i < e_it->count_ && !_in.eof(); ++i) {
321  vh = _bi.add_vertex();
322 
323  v[0] = 0.0;
324  v[1] = 0.0;
325  v[2] = 0.0;
326 
327  n[0] = 0.0;
328  n[1] = 0.0;
329  n[2] = 0.0;
330 
331  t[0] = 0.0;
332  t[1] = 0.0;
333 
334  c[0] = 0;
335  c[1] = 0;
336  c[2] = 0;
337  c[3] = 255;
338 
339  for (size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex) {
340  PropertyInfo prop = e_it->properties_[propertyIndex];
341  switch (prop.property) {
342  case XCOORD:
343  _in >> v[0];
344  break;
345  case YCOORD:
346  _in >> v[1];
347  break;
348  case ZCOORD:
349  _in >> v[2];
350  break;
351  case XNORM:
352  _in >> n[0];
353  break;
354  case YNORM:
355  _in >> n[1];
356  break;
357  case ZNORM:
358  _in >> n[2];
359  break;
360  case TEXX:
361  _in >> t[0];
362  break;
363  case TEXY:
364  _in >> t[1];
365  break;
366  case COLORRED:
367  if (prop.value == ValueTypeFLOAT32 ||
368  prop.value == ValueTypeFLOAT) {
369  _in >> tmp;
370  c[0] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
371  }
372  else
373  _in >> c[0];
374  break;
375  case COLORGREEN:
376  if (prop.value == ValueTypeFLOAT32 ||
377  prop.value == ValueTypeFLOAT) {
378  _in >> tmp;
379  c[1] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
380  }
381  else
382  _in >> c[1];
383  break;
384  case COLORBLUE:
385  if (prop.value == ValueTypeFLOAT32 ||
386  prop.value == ValueTypeFLOAT) {
387  _in >> tmp;
388  c[2] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
389  }
390  else
391  _in >> c[2];
392  break;
393  case COLORALPHA:
394  if (prop.value == ValueTypeFLOAT32 ||
395  prop.value == ValueTypeFLOAT) {
396  _in >> tmp;
397  c[3] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
398  }
399  else
400  _in >> c[3];
401  break;
402  case CUSTOM_PROP:
403  if (_opt.check(Options::Custom))
404  readCustomProperty<false>(_in, _bi, vh, prop.name, prop.value, prop.listIndexType);
405  else
406  _in >> trash;
407  break;
408  default:
409  _in >> trash;
410  break;
411  }
412  }
413 
414  _bi.set_point(vh, v);
415  if (_opt.vertex_has_normal())
416  _bi.set_normal(vh, n);
417  if (_opt.vertex_has_texcoord())
418  _bi.set_texcoord(vh, t);
419  if (_opt.vertex_has_color())
420  _bi.set_color(vh, Vec4uc(c));
421  }
422  }
423  else if (e_it->element_ == FACE)
424  {
425  // faces
426  for (i = 0; i < faceCount_ && !_in.eof(); ++i) {
427  FaceHandle fh;
428 
429  c[0] = 0;
430  c[1] = 0;
431  c[2] = 0;
432  c[3] = 255;
433 
434  for (size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex) {
435  PropertyInfo prop = e_it->properties_[propertyIndex];
436  switch (prop.property) {
437 
438  case VERTEX_INDICES:
439  // nV = number of Vertices for current face
440  _in >> nV;
441 
442  if (nV == 3) {
443  vhandles.resize(3);
444  _in >> j;
445  _in >> k;
446  _in >> l;
447 
448  vhandles[0] = VertexHandle(j);
449  vhandles[1] = VertexHandle(k);
450  vhandles[2] = VertexHandle(l);
451  }
452  else {
453  vhandles.clear();
454  for (j = 0; j < nV; ++j) {
455  _in >> idx;
456  vhandles.push_back(VertexHandle(idx));
457  }
458  }
459 
460  fh = _bi.add_face(vhandles);
461  if (!fh.is_valid())
462  ++complex_faces;
463  break;
464 
465  case COLORRED:
466  if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
467  _in >> tmp;
468  c[0] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
469  } else
470  _in >> c[0];
471  break;
472 
473  case COLORGREEN:
474  if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
475  _in >> tmp;
476  c[1] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
477  } else
478  _in >> c[1];
479  break;
480 
481  case COLORBLUE:
482  if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
483  _in >> tmp;
484  c[2] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
485  } else
486  _in >> c[2];
487  break;
488 
489  case COLORALPHA:
490  if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
491  _in >> tmp;
492  c[3] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
493  } else
494  _in >> c[3];
495  break;
496 
497  case CUSTOM_PROP:
498  if (_opt.check(Options::Custom) && fh.is_valid())
499  readCustomProperty<false>(_in, _bi, fh, prop.name, prop.value, prop.listIndexType);
500  else
501  _in >> trash;
502  break;
503 
504  default:
505  _in >> trash;
506  break;
507  }
508  }
509  if (_opt.face_has_color())
510  _bi.set_color(fh, Vec4uc(c));
511  }
512  }
513  else
514  {
515  // other elements
516  for (i = 0; i < e_it->count_ && !_in.eof(); ++i) {
517  for (size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex)
518  {
519  // just skip the values
520  _in >> trash;
521  }
522  }
523  }
524 
525  if(e_it->element_== FACE)
526  // stop reading after the faces since additional elements are not preserved anyway
527  break;
528  }
529 
530  if (err_enabled)
531  omerr().enable();
532 
533  if (complex_faces)
534  omerr() << complex_faces << "The reader encountered invalid faces, that could not be added.\n";
535 
536  // File was successfully parsed.
537  return true;
538 }
539 
540 //-----------------------------------------------------------------------------
541 
542 bool _PLYReader_::read_binary(std::istream& _in, BaseImporter& _bi, bool /*_swap*/, const Options& _opt) const {
543 
544  OpenMesh::Vec3f v, n; // Vertex
545  OpenMesh::Vec2f t; // TexCoords
546  BaseImporter::VHandles vhandles;
547  VertexHandle vh;
548  OpenMesh::Vec4i c; // Color
549  float tmp;
550 
551  _bi.reserve(vertexCount_, 3* vertexCount_ , faceCount_);
552 
553  const bool err_enabled = omerr().is_enabled();
554  size_t complex_faces = 0;
555  if (err_enabled)
556  omerr().disable();
557 
558  for (std::vector<ElementInfo>::iterator e_it = elements_.begin(); e_it != elements_.end(); ++e_it)
559  {
560  if (e_it->element_ == VERTEX)
561  {
562  // read vertices:
563  for (unsigned int i = 0; i < e_it->count_ && !_in.eof(); ++i) {
564  vh = _bi.add_vertex();
565 
566  v[0] = 0.0;
567  v[1] = 0.0;
568  v[2] = 0.0;
569 
570  n[0] = 0.0;
571  n[1] = 0.0;
572  n[2] = 0.0;
573 
574  t[0] = 0.0;
575  t[1] = 0.0;
576 
577  c[0] = 0;
578  c[1] = 0;
579  c[2] = 0;
580  c[3] = 255;
581 
582  for (size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex) {
583  PropertyInfo prop = e_it->properties_[propertyIndex];
584  switch (prop.property) {
585  case XCOORD:
586  readValue(prop.value, _in, v[0]);
587  break;
588  case YCOORD:
589  readValue(prop.value, _in, v[1]);
590  break;
591  case ZCOORD:
592  readValue(prop.value, _in, v[2]);
593  break;
594  case XNORM:
595  readValue(prop.value, _in, n[0]);
596  break;
597  case YNORM:
598  readValue(prop.value, _in, n[1]);
599  break;
600  case ZNORM:
601  readValue(prop.value, _in, n[2]);
602  break;
603  case TEXX:
604  readValue(prop.value, _in, t[0]);
605  break;
606  case TEXY:
607  readValue(prop.value, _in, t[1]);
608  break;
609  case COLORRED:
610  if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
611  readValue(prop.value, _in, tmp);
612 
613  c[0] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
614  }
615  else
616  readInteger(prop.value, _in, c[0]);
617 
618  break;
619  case COLORGREEN:
620  if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
621  readValue(prop.value, _in, tmp);
622  c[1] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
623  }
624  else
625  readInteger(prop.value, _in, c[1]);
626 
627  break;
628  case COLORBLUE:
629  if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
630  readValue(prop.value, _in, tmp);
631  c[2] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
632  }
633  else
634  readInteger(prop.value, _in, c[2]);
635 
636  break;
637  case COLORALPHA:
638  if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
639  readValue(prop.value, _in, tmp);
640  c[3] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
641  }
642  else
643  readInteger(prop.value, _in, c[3]);
644 
645  break;
646  case CUSTOM_PROP:
647  if (_opt.check(Options::Custom))
648  readCustomProperty<true>(_in, _bi, vh, prop.name, prop.value, prop.listIndexType);
649  else
650  consume_input(_in, scalar_size_[prop.value]);
651  break;
652  default:
653  // Read unsupported property
654  consume_input(_in, scalar_size_[prop.value]);
655  break;
656  }
657 
658  }
659 
660  _bi.set_point(vh, v);
661  if (_opt.vertex_has_normal())
662  _bi.set_normal(vh, n);
663  if (_opt.vertex_has_texcoord())
664  _bi.set_texcoord(vh, t);
665  if (_opt.vertex_has_color())
666  _bi.set_color(vh, Vec4uc(c));
667  }
668  }
669  else if (e_it->element_ == FACE) {
670  for (unsigned i = 0; i < e_it->count_ && !_in.eof(); ++i) {
671  FaceHandle fh;
672 
673  c[0] = 0;
674  c[1] = 0;
675  c[2] = 0;
676  c[3] = 255;
677 
678  for (size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex)
679  {
680  PropertyInfo prop = e_it->properties_[propertyIndex];
681  switch (prop.property) {
682 
683  case VERTEX_INDICES:
684  // nV = number of Vertices for current face
685  unsigned int nV;
686  readInteger(prop.listIndexType, _in, nV);
687 
688  if (nV == 3) {
689  vhandles.resize(3);
690  unsigned int j, k, l;
691  readInteger(prop.value, _in, j);
692  readInteger(prop.value, _in, k);
693  readInteger(prop.value, _in, l);
694 
695  vhandles[0] = VertexHandle(j);
696  vhandles[1] = VertexHandle(k);
697  vhandles[2] = VertexHandle(l);
698  }
699  else {
700  vhandles.clear();
701  for (unsigned j = 0; j < nV; ++j) {
702  unsigned int idx;
703  readInteger(prop.value, _in, idx);
704  vhandles.push_back(VertexHandle(idx));
705  }
706  }
707 
708  fh = _bi.add_face(vhandles);
709  if (!fh.is_valid())
710  ++complex_faces;
711  break;
712  case COLORRED:
713  if (prop.value == ValueTypeFLOAT32 ||
714  prop.value == ValueTypeFLOAT) {
715  readValue(prop.value, _in, tmp);
716  c[0] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
717  } else
718  readInteger(prop.value, _in, c[0]);
719  break;
720  case COLORGREEN:
721  if (prop.value == ValueTypeFLOAT32 ||
722  prop.value == ValueTypeFLOAT) {
723  readValue(prop.value, _in, tmp);
724  c[1] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
725  } else
726  readInteger(prop.value, _in, c[1]);
727  break;
728  case COLORBLUE:
729  if (prop.value == ValueTypeFLOAT32 ||
730  prop.value == ValueTypeFLOAT) {
731  readValue(prop.value, _in, tmp);
732  c[2] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
733  } else
734  readInteger(prop.value, _in, c[2]);
735  break;
736  case COLORALPHA:
737  if (prop.value == ValueTypeFLOAT32 ||
738  prop.value == ValueTypeFLOAT) {
739  readValue(prop.value, _in, tmp);
740  c[3] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
741  } else
742  readInteger(prop.value, _in, c[3]);
743  break;
744  case CUSTOM_PROP:
745  if (_opt.check(Options::Custom) && fh.is_valid())
746  readCustomProperty<true>(_in, _bi, fh, prop.name, prop.value, prop.listIndexType);
747  else
748  consume_input(_in, scalar_size_[prop.value]);
749  break;
750 
751  default:
752  consume_input(_in, scalar_size_[prop.value]);
753  break;
754  }
755  }
756  if (_opt.face_has_color())
757  _bi.set_color(fh, Vec4uc(c));
758  }
759  }
760  else {
761  for (unsigned int i = 0; i < e_it->count_ && !_in.eof(); ++i)
762  {
763  for (size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex)
764  {
765  PropertyInfo prop = e_it->properties_[propertyIndex];
766  // skip element values
767  consume_input(_in, scalar_size_[prop.value]);
768  }
769  }
770  }
771 
772  if (_in.eof()) {
773  if (err_enabled)
774  omerr().enable();
775 
776  omerr() << "Unexpected end of file while reading." << std::endl;
777  return false;
778  }
779 
780  if (e_it->element_ == FACE)
781  // stop reading after the faces since additional elements are not preserved anyway
782  break;
783  }
784  if (err_enabled)
785  omerr().enable();
786 
787  if (complex_faces)
788  omerr() << complex_faces << "The reader encountered invalid faces, that could not be added.\n";
789 
790 
791  return true;
792 }
793 
794 
795 //-----------------------------------------------------------------------------
796 
797 
798 void _PLYReader_::readValue(ValueType _type, std::istream& _in, float& _value) const {
799 
800  switch (_type) {
801  case ValueTypeFLOAT32:
802  case ValueTypeFLOAT:
803  float32_t tmp;
804  restore(_in, tmp, options_.check(Options::MSB));
805  _value = tmp;
806  break;
807  default:
808  _value = 0.0;
809  std::cerr << "unsupported conversion type to float: " << _type << std::endl;
810  break;
811  }
812 }
813 
814 
815 //-----------------------------------------------------------------------------
816 
817 
818 void _PLYReader_::readValue(ValueType _type, std::istream& _in, double& _value) const {
819 
820  switch (_type) {
821 
822  case ValueTypeFLOAT64:
823 
824  case ValueTypeDOUBLE:
825 
826  float64_t tmp;
827  restore(_in, tmp, options_.check(Options::MSB));
828  _value = tmp;
829 
830  break;
831 
832  default:
833 
834  _value = 0.0;
835  std::cerr << "unsupported conversion type to double: " << _type << std::endl;
836 
837  break;
838  }
839 }
840 
841 
842 //-----------------------------------------------------------------------------
843 
844 void _PLYReader_::readValue(ValueType _type, std::istream& _in, unsigned char& _value) const{
845  unsigned int tmp;
846  readValue(_type,_in,tmp);
847  _value = tmp;
848 }
849 
850 //-----------------------------------------------------------------------------
851 
852 void _PLYReader_::readValue(ValueType _type, std::istream& _in, unsigned short& _value) const{
853  unsigned int tmp;
854  readValue(_type,_in,tmp);
855  _value = tmp;
856 }
857 
858 //-----------------------------------------------------------------------------
859 
860 void _PLYReader_::readValue(ValueType _type, std::istream& _in, signed char& _value) const{
861  int tmp;
862  readValue(_type,_in,tmp);
863  _value = tmp;
864 }
865 
866 //-----------------------------------------------------------------------------
867 
868 void _PLYReader_::readValue(ValueType _type, std::istream& _in, short& _value) const{
869  int tmp;
870  readValue(_type,_in,tmp);
871  _value = tmp;
872 }
873 
874 
875 //-----------------------------------------------------------------------------
876 void _PLYReader_::readValue(ValueType _type, std::istream& _in, unsigned int& _value) const {
877 
878  uint32_t tmp_uint32_t;
879  uint16_t tmp_uint16_t;
880  uint8_t tmp_uchar;
881 
882  switch (_type) {
883 
884  case ValueTypeUINT:
885 
886  case ValueTypeUINT32:
887 
888  restore(_in, tmp_uint32_t, options_.check(Options::MSB));
889  _value = tmp_uint32_t;
890 
891  break;
892 
893  case ValueTypeUSHORT:
894 
895  case ValueTypeUINT16:
896 
897  restore(_in, tmp_uint16_t, options_.check(Options::MSB));
898  _value = tmp_uint16_t;
899 
900  break;
901 
902  case ValueTypeUCHAR:
903 
904  case ValueTypeUINT8:
905 
906  restore(_in, tmp_uchar, options_.check(Options::MSB));
907  _value = tmp_uchar;
908 
909  break;
910 
911  default:
912 
913  _value = 0;
914  std::cerr << "unsupported conversion type to unsigned int: " << _type << std::endl;
915 
916  break;
917  }
918 }
919 
920 
921 //-----------------------------------------------------------------------------
922 
923 
924 void _PLYReader_::readValue(ValueType _type, std::istream& _in, int& _value) const {
925 
926  int32_t tmp_int32_t;
927  int16_t tmp_int16_t;
928  int8_t tmp_char;
929 
930  switch (_type) {
931 
932  case ValueTypeINT:
933 
934  case ValueTypeINT32:
935 
936  restore(_in, tmp_int32_t, options_.check(Options::MSB));
937  _value = tmp_int32_t;
938 
939  break;
940 
941  case ValueTypeSHORT:
942 
943  case ValueTypeINT16:
944 
945  restore(_in, tmp_int16_t, options_.check(Options::MSB));
946  _value = tmp_int16_t;
947 
948  break;
949 
950  case ValueTypeCHAR:
951 
952  case ValueTypeINT8:
953 
954  restore(_in, tmp_char, options_.check(Options::MSB));
955  _value = tmp_char;
956 
957  break;
958 
959  default:
960 
961  _value = 0;
962  std::cerr << "unsupported conversion type to int: " << _type << std::endl;
963 
964  break;
965  }
966 }
967 
968 
969 //-----------------------------------------------------------------------------
970 
971 
972 void _PLYReader_::readInteger(ValueType _type, std::istream& _in, int& _value) const {
973 
974  int32_t tmp_int32_t;
975  uint32_t tmp_uint32_t;
976  int8_t tmp_char;
977  uint8_t tmp_uchar;
978 
979  switch (_type) {
980 
981  case ValueTypeINT:
982 
983  case ValueTypeINT32:
984 
985  restore(_in, tmp_int32_t, options_.check(Options::MSB));
986  _value = tmp_int32_t;
987 
988  break;
989 
990  case ValueTypeUINT:
991 
992  case ValueTypeUINT32:
993 
994  restore(_in, tmp_uint32_t, options_.check(Options::MSB));
995  _value = tmp_uint32_t;
996 
997  break;
998 
999  case ValueTypeCHAR:
1000 
1001  case ValueTypeINT8:
1002 
1003  restore(_in, tmp_char, options_.check(Options::MSB));
1004  _value = tmp_char;
1005 
1006  break;
1007 
1008  case ValueTypeUCHAR:
1009 
1010  case ValueTypeUINT8:
1011 
1012  restore(_in, tmp_uchar, options_.check(Options::MSB));
1013  _value = tmp_uchar;
1014 
1015  break;
1016 
1017  default:
1018 
1019  _value = 0;
1020  std::cerr << "unsupported conversion type to int: " << _type << std::endl;
1021 
1022  break;
1023  }
1024 }
1025 
1026 
1027 //-----------------------------------------------------------------------------
1028 
1029 
1030 void _PLYReader_::readInteger(ValueType _type, std::istream& _in, unsigned int& _value) const {
1031 
1032  int32_t tmp_int32_t;
1033  uint32_t tmp_uint32_t;
1034  int8_t tmp_char;
1035  uint8_t tmp_uchar;
1036 
1037  switch (_type) {
1038 
1039  case ValueTypeUINT:
1040 
1041  case ValueTypeUINT32:
1042 
1043  restore(_in, tmp_uint32_t, options_.check(Options::MSB));
1044  _value = tmp_uint32_t;
1045 
1046  break;
1047 
1048  case ValueTypeINT:
1049 
1050  case ValueTypeINT32:
1051 
1052  restore(_in, tmp_int32_t, options_.check(Options::MSB));
1053  _value = tmp_int32_t;
1054 
1055  break;
1056 
1057  case ValueTypeUCHAR:
1058 
1059  case ValueTypeUINT8:
1060 
1061  restore(_in, tmp_uchar, options_.check(Options::MSB));
1062  _value = tmp_uchar;
1063 
1064  break;
1065 
1066  case ValueTypeCHAR:
1067 
1068  case ValueTypeINT8:
1069 
1070  restore(_in, tmp_char, options_.check(Options::MSB));
1071  _value = tmp_char;
1072 
1073  break;
1074 
1075  default:
1076 
1077  _value = 0;
1078  std::cerr << "unsupported conversion type to unsigned int: " << _type << std::endl;
1079 
1080  break;
1081  }
1082 }
1083 
1084 
1085 //------------------------------------------------------------------------------
1086 
1087 
1088 bool _PLYReader_::can_u_read(const std::string& _filename) const {
1089 
1090  // !!! Assuming BaseReader::can_u_parse( std::string& )
1091  // does not call BaseReader::read_magic()!!!
1092 
1093  if (BaseReader::can_u_read(_filename)) {
1094  std::ifstream ifs(_filename.c_str());
1095  if (ifs.is_open() && can_u_read(ifs)) {
1096  ifs.close();
1097  return true;
1098  }
1099  }
1100  return false;
1101 }
1102 
1103 
1104 
1105 //-----------------------------------------------------------------------------
1106 
1107 std::string get_property_name(std::string _string1, std::string _string2) {
1108 
1109  if (_string1 == "float32" || _string1 == "float64" || _string1 == "float" || _string1 == "double" ||
1110  _string1 == "int8" || _string1 == "uint8" || _string1 == "char" || _string1 == "uchar" ||
1111  _string1 == "int32" || _string1 == "uint32" || _string1 == "int" || _string1 == "uint" ||
1112  _string1 == "int16" || _string1 == "uint16" || _string1 == "short" || _string1 == "ushort")
1113  return _string2;
1114 
1115  if (_string2 == "float32" || _string2 == "float64" || _string2 == "float" || _string2 == "double" ||
1116  _string2 == "int8" || _string2 == "uint8" || _string2 == "char" || _string2 == "uchar" ||
1117  _string2 == "int32" || _string2 == "uint32" || _string2 == "int" || _string2 == "uint" ||
1118  _string2 == "int16" || _string2 == "uint16" || _string2 == "short" || _string2 == "ushort")
1119  return _string1;
1120 
1121 
1122  std::cerr << "Unsupported entry type" << std::endl;
1123  return "Unsupported";
1124 }
1125 
1126 //-----------------------------------------------------------------------------
1127 
1128 _PLYReader_::ValueType get_property_type(std::string& _string1, std::string& _string2) {
1129 
1130  if (_string1 == "float32" || _string2 == "float32")
1131 
1132  return _PLYReader_::ValueTypeFLOAT32;
1133 
1134  else if (_string1 == "float64" || _string2 == "float64")
1135 
1136  return _PLYReader_::ValueTypeFLOAT64;
1137 
1138  else if (_string1 == "float" || _string2 == "float")
1139 
1140  return _PLYReader_::ValueTypeFLOAT;
1141 
1142  else if (_string1 == "double" || _string2 == "double")
1143 
1144  return _PLYReader_::ValueTypeDOUBLE;
1145 
1146  else if (_string1 == "int8" || _string2 == "int8")
1147 
1148  return _PLYReader_::ValueTypeINT8;
1149 
1150  else if (_string1 == "uint8" || _string2 == "uint8")
1151 
1152  return _PLYReader_::ValueTypeUINT8;
1153 
1154  else if (_string1 == "char" || _string2 == "char")
1155 
1156  return _PLYReader_::ValueTypeCHAR;
1157 
1158  else if (_string1 == "uchar" || _string2 == "uchar")
1159 
1160  return _PLYReader_::ValueTypeUCHAR;
1161 
1162  else if (_string1 == "int32" || _string2 == "int32")
1163 
1164  return _PLYReader_::ValueTypeINT32;
1165 
1166  else if (_string1 == "uint32" || _string2 == "uint32")
1167 
1168  return _PLYReader_::ValueTypeUINT32;
1169 
1170  else if (_string1 == "int" || _string2 == "int")
1171 
1172  return _PLYReader_::ValueTypeINT;
1173 
1174  else if (_string1 == "uint" || _string2 == "uint")
1175 
1176  return _PLYReader_::ValueTypeUINT;
1177 
1178  else if (_string1 == "int16" || _string2 == "int16")
1179 
1180  return _PLYReader_::ValueTypeINT16;
1181 
1182  else if (_string1 == "uint16" || _string2 == "uint16")
1183 
1184  return _PLYReader_::ValueTypeUINT16;
1185 
1186  else if (_string1 == "short" || _string2 == "short")
1187 
1188  return _PLYReader_::ValueTypeSHORT;
1189 
1190  else if (_string1 == "ushort" || _string2 == "ushort")
1191 
1192  return _PLYReader_::ValueTypeUSHORT;
1193 
1194  return _PLYReader_::Unsupported;
1195 }
1196 
1197 
1198 //-----------------------------------------------------------------------------
1199 
1200 bool _PLYReader_::can_u_read(std::istream& _is) const {
1201 
1202  // Clear per file options
1203  options_.cleanup();
1204 
1205  // clear element list
1206  elements_.clear();
1207 
1208  // read 1st line
1209  std::string line;
1210  std::getline(_is, line);
1211  trim(line);
1212 
1213  // Handle '\r\n' newlines
1214  const size_t s = line.size();
1215  if( s > 0 && line[s - 1] == '\r') line.resize(s - 1);
1216 
1217  //Check if this file is really a ply format
1218  if (line != "PLY" && line != "ply")
1219  return false;
1220 
1221  vertexCount_ = 0;
1222  faceCount_ = 0;
1223  vertexDimension_ = 0;
1224 
1225  unsigned int elementCount = 0;
1226 
1227  std::string keyword;
1228  std::string fileType;
1229  std::string elementName = "";
1230  std::string propertyName;
1231  std::string listIndexType;
1232  std::string listEntryType;
1233  float version;
1234 
1235  _is >> keyword;
1236  _is >> fileType;
1237  _is >> version;
1238 
1239  if (_is.bad()) {
1240  omerr() << "Defect PLY header detected" << std::endl;
1241  return false;
1242  }
1243 
1244  if (fileType == "ascii") {
1246  } else if (fileType == "binary_little_endian") {
1249  //if (Endian::local() == Endian::MSB)
1250 
1251  // options_ += Options::Swap;
1252  } else if (fileType == "binary_big_endian") {
1255  //if (Endian::local() == Endian::LSB)
1256 
1257  // options_ += Options::Swap;
1258  } else {
1259  omerr() << "Unsupported PLY format: " << fileType << std::endl;
1260  return false;
1261  }
1262 
1263  std::streamoff streamPos = _is.tellg();
1264  _is >> keyword;
1265  while (keyword != "end_header") {
1266 
1267  if (keyword == "comment") {
1268  std::getline(_is, line);
1269  } else if (keyword == "element") {
1270  _is >> elementName;
1271  _is >> elementCount;
1272 
1273  ElementInfo element;
1274  element.name_ = elementName;
1275  element.count_ = elementCount;
1276 
1277  if (elementName == "vertex") {
1278  vertexCount_ = elementCount;
1279  element.element_ = VERTEX;
1280  } else if (elementName == "face") {
1281  faceCount_ = elementCount;
1282  element.element_ = FACE;
1283  } else {
1284  omerr() << "PLY header unsupported element type: " << elementName << std::endl;
1285  element.element_ = UNKNOWN;
1286  }
1287 
1288  elements_.push_back(element);
1289  } else if (keyword == "property") {
1290  std::string tmp1;
1291  std::string tmp2;
1292 
1293  // Read first keyword, as it might be a list
1294  _is >> tmp1;
1295 
1296  if (tmp1 == "list") {
1297  _is >> listIndexType;
1298  _is >> listEntryType;
1299  _is >> propertyName;
1300 
1301  ValueType indexType = Unsupported;
1302  ValueType entryType = Unsupported;
1303 
1304  if (listIndexType == "uint8") {
1305  indexType = ValueTypeUINT8;
1306  } else if (listIndexType == "uint16") {
1307  indexType = ValueTypeUINT16;
1308  } else if (listIndexType == "uchar") {
1309  indexType = ValueTypeUCHAR;
1310  } else if (listIndexType == "int") {
1311  indexType = ValueTypeINT;
1312  } else {
1313  omerr() << "Unsupported Index type for property list: " << listIndexType << std::endl;
1314  return false;
1315  }
1316 
1317  entryType = get_property_type(listEntryType, listEntryType);
1318 
1319  if (entryType == Unsupported) {
1320  omerr() << "Unsupported Entry type for property list: " << listEntryType << std::endl;
1321  }
1322 
1323  PropertyInfo property(CUSTOM_PROP, entryType, propertyName);
1324  property.listIndexType = indexType;
1325 
1326  if (elementName == "face")
1327  {
1328  // special case for vertex indices
1329  if (propertyName == "vertex_index" || propertyName == "vertex_indices")
1330  {
1331  property.property = VERTEX_INDICES;
1332 
1333  if (!elements_.back().properties_.empty())
1334  {
1335  omerr() << "Custom face Properties defined, before 'vertex_indices' property was defined. They will be skipped" << std::endl;
1336  elements_.back().properties_.clear();
1337  }
1338  } else {
1340  }
1341 
1342  }
1343  else
1344  omerr() << "property " << propertyName << " belongs to unsupported element " << elementName << std::endl;
1345 
1346  elements_.back().properties_.push_back(property);
1347 
1348  } else {
1349  // as this is not a list property, read second value of property
1350  _is >> tmp2;
1351 
1352 
1353  // Extract name and type of property
1354  // As the order seems to be different in some files, autodetect it.
1355  ValueType valueType = get_property_type(tmp1, tmp2);
1356  propertyName = get_property_name(tmp1, tmp2);
1357 
1358  PropertyInfo entry;
1359 
1360  //special treatment for some vertex properties.
1361  if (elementName == "vertex") {
1362  if (propertyName == "x") {
1363  entry = PropertyInfo(XCOORD, valueType);
1364  vertexDimension_++;
1365  } else if (propertyName == "y") {
1366  entry = PropertyInfo(YCOORD, valueType);
1367  vertexDimension_++;
1368  } else if (propertyName == "z") {
1369  entry = PropertyInfo(ZCOORD, valueType);
1370  vertexDimension_++;
1371  } else if (propertyName == "nx") {
1372  entry = PropertyInfo(XNORM, valueType);
1374  } else if (propertyName == "ny") {
1375  entry = PropertyInfo(YNORM, valueType);
1377  } else if (propertyName == "nz") {
1378  entry = PropertyInfo(ZNORM, valueType);
1380  } else if (propertyName == "u" || propertyName == "s") {
1381  entry = PropertyInfo(TEXX, valueType);
1383  } else if (propertyName == "v" || propertyName == "t") {
1384  entry = PropertyInfo(TEXY, valueType);
1386  } else if (propertyName == "red") {
1387  entry = PropertyInfo(COLORRED, valueType);
1389  if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1391  } else if (propertyName == "green") {
1392  entry = PropertyInfo(COLORGREEN, valueType);
1394  if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1396  } else if (propertyName == "blue") {
1397  entry = PropertyInfo(COLORBLUE, valueType);
1399  if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1401  } else if (propertyName == "diffuse_red") {
1402  entry = PropertyInfo(COLORRED, valueType);
1404  if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1406  } else if (propertyName == "diffuse_green") {
1407  entry = PropertyInfo(COLORGREEN, valueType);
1409  if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1411  } else if (propertyName == "diffuse_blue") {
1412  entry = PropertyInfo(COLORBLUE, valueType);
1414  if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1416  } else if (propertyName == "alpha") {
1417  entry = PropertyInfo(COLORALPHA, valueType);
1420  if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1422  }
1423  }
1424  else if (elementName == "face") {
1425  if (propertyName == "red") {
1426  entry = PropertyInfo(COLORRED, valueType);
1428  if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1430  } else if (propertyName == "green") {
1431  entry = PropertyInfo(COLORGREEN, valueType);
1433  if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1435  } else if (propertyName == "blue") {
1436  entry = PropertyInfo(COLORBLUE, valueType);
1438  if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1440  } else if (propertyName == "alpha") {
1441  entry = PropertyInfo(COLORALPHA, valueType);
1444  if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1446  }
1447  }
1448 
1449  //not a special property, load as custom
1450  if (entry.value == Unsupported){
1451  Property prop = CUSTOM_PROP;
1453  entry = PropertyInfo(prop, valueType, propertyName);
1454  }
1455 
1456  if (entry.property != UNSUPPORTED)
1457  {
1458  elements_.back().properties_.push_back(entry);
1459  }
1460  }
1461 
1462  } else {
1463  omlog() << "Unsupported keyword : " << keyword << std::endl;
1464  }
1465 
1466  streamPos = _is.tellg();
1467  _is >> keyword;
1468  if (_is.bad()) {
1469  omerr() << "Error while reading PLY file header" << std::endl;
1470  return false;
1471  }
1472  }
1473 
1474  // As the binary data is directy after the end_header keyword
1475  // and the stream removes too many bytes, seek back to the right position
1476  if (options_.is_binary()) {
1477  _is.seekg(streamPos);
1478 
1479  char c1 = 0;
1480  char c2 = 0;
1481  _is.get(c1);
1482  _is.get(c2);
1483 
1484  if (c1 == 0x0D && c2 == 0x0A) {
1485  _is.seekg(streamPos + 14);
1486  }
1487  else {
1488  _is.seekg(streamPos + 12);
1489  }
1490  }
1491 
1492  return true;
1493 }
1494 
1495 //=============================================================================
1496 } // namespace IO
1497 } // namespace OpenMesh
1498 //=============================================================================
Has (r) / store (w) vertex colors.
Definition: Options.hh:105
Swap byte order in binary mode.
Definition: Options.hh:103
Handle for a vertex entity.
Definition: Handles.hh:120
unsigned char uint8_t
Definition: SR_types.hh:80
virtual bool can_u_read(const std::string &_filename) const
Returns true if writer can parse _filename (checks extension). _filename can also provide an extensio...
Definition: BaseReader.cc:77
Assume little endian byte ordering.
Definition: Options.hh:102
bool read(const std::string &_filename, BaseImporter &_bi, Options &_opt)
Definition: PLYReader.cc:106
bool register_module(BaseReader *_bl)
Definition: IOManager.hh:217
Has (r) / store (w) face colors.
Definition: Options.hh:109
void consume_input(std::istream &_in, int _count) const
Read unsupported properties in PLY file.
Definition: PLYReader.hh:148
unsigned int uint32_t
Definition: SR_types.hh:85
Has (r) / store (w) float values for colors (currently only implemented for PLY and OFF files) ...
Definition: Options.hh:112
signed char int8_t
Definition: SR_types.hh:80
Options options_
Available per file options for reading.
Definition: PLYReader.hh:155
_IOManager_ & IOManager()
Definition: IOManager.cc:72
std::map< ValueType, int > scalar_size_
Stores sizes of property types.
Definition: PLYReader.hh:174
_PLYReader_ __PLYReaderInstance
Declare the single entity of the PLY reader.
Definition: PLYReader.cc:72
Has (r) / store (w) texture coordinates.
Definition: Options.hh:106
void add_property(VPropHandleT< T > &_ph, const std::string &_name="<vprop>")
Definition: BaseKernel.hh:141
PropertyT< T > & property(VPropHandleT< T > _ph)
Definition: BaseKernel.hh:310
unsigned short uint16_t
Definition: SR_types.hh:81
bool get_property_handle(VPropHandleT< T > &_ph, const std::string &_name) const
Definition: BaseKernel.hh:254
Handle for a face entity.
Definition: Handles.hh:141
void clear(void)
Clear all bits.
Definition: Options.hh:147
void cleanup(void)
Restore state after default constructor.
Definition: Options.hh:143
Has (r) custom properties (currently only implemented in PLY Reader ASCII version) ...
Definition: Options.hh:113
Set options for reader/writer modules.
Definition: Options.hh:90
short int16_t
Definition: SR_types.hh:81
Has (r) / store (w) alpha values for colors.
Definition: Options.hh:111
Set binary mode for r/w.
Definition: Options.hh:100
Has (r) / store (w) vertex normals.
Definition: Options.hh:104
double float64_t
Definition: SR_types.hh:93
bool is_valid() const
The handle is valid iff the index is not negative.
Definition: Handles.hh:72
float float32_t
Definition: SR_types.hh:92
Cellection of information about a property.
Definition: Utils.hh:109
Assume big endian byte ordering.
Definition: Options.hh:101
bool can_u_read(const std::string &_filename) const
Returns true if writer can parse _filename (checks extension). _filename can also provide an extensio...
Definition: PLYReader.cc:1088
Options userOptions_
Options that the user wants to read.
Definition: PLYReader.hh:158