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