Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
54 #include <OpenMesh/Core/System/config.h>
55 #include <OpenMesh/Core/System/omstream.hh>
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
79 _PLYReader_ __PLYReaderInstance;
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>
180 struct Handle2Prop<T,VertexHandle>
181 {
182 typedef OpenMesh::VPropHandleT<T> PropT;
183 };
184
185 template<typename T>
186 struct Handle2Prop<T,FaceHandle>
187 {
188 typedef OpenMesh::FPropHandleT<T> PropT;
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") {
1109 options_ -= Options::Binary;
1110 } else if (fileType == "binary_little_endian") {
1111 options_ += Options::Binary;
1112 options_ += Options::LSB;
1113 //if (Endian::local() == Endian::MSB)
1114
1115 // options_ += Options::Swap;
1116 } else if (fileType == "binary_big_endian") {
1117 options_ += Options::Binary;
1118 options_ += Options::MSB;
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);
1225 options_ += Options::VertexNormal;
1226 } else if (propertyName == "ny") {
1227 entry = PropertyInfo(YNORM, valueType);
1228 options_ += Options::VertexNormal;
1229 } else if (propertyName == "nz") {
1230 entry = PropertyInfo(ZNORM, valueType);
1231 options_ += Options::VertexNormal;
1232 } else if (propertyName == "u" || propertyName == "s") {
1233 entry = PropertyInfo(TEXX, valueType);
1234 options_ += Options::VertexTexCoord;
1235 } else if (propertyName == "v" || propertyName == "t") {
1236 entry = PropertyInfo(TEXY, valueType);
1237 options_ += Options::VertexTexCoord;
1238 } else if (propertyName == "red") {
1239 entry = PropertyInfo(COLORRED, valueType);
1240 options_ += Options::VertexColor;
1241 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1242 options_ += Options::ColorFloat;
1243 } else if (propertyName == "green") {
1244 entry = PropertyInfo(COLORGREEN, valueType);
1245 options_ += Options::VertexColor;
1246 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1247 options_ += Options::ColorFloat;
1248 } else if (propertyName == "blue") {
1249 entry = PropertyInfo(COLORBLUE, valueType);
1250 options_ += Options::VertexColor;
1251 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1252 options_ += Options::ColorFloat;
1253 } else if (propertyName == "diffuse_red") {
1254 entry = PropertyInfo(COLORRED, valueType);
1255 options_ += Options::VertexColor;
1256 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1257 options_ += Options::ColorFloat;
1258 } else if (propertyName == "diffuse_green") {
1259 entry = PropertyInfo(COLORGREEN, valueType);
1260 options_ += Options::VertexColor;
1261 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1262 options_ += Options::ColorFloat;
1263 } else if (propertyName == "diffuse_blue") {
1264 entry = PropertyInfo(COLORBLUE, valueType);
1265 options_ += Options::VertexColor;
1266 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1267 options_ += Options::ColorFloat;
1268 } else if (propertyName == "alpha") {
1269 entry = PropertyInfo(COLORALPHA, valueType);
1270 options_ += Options::VertexColor;
1271 options_ += Options::ColorAlpha;
1272 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1273 options_ += Options::ColorFloat;
1274 }
1275 }
1276
1277 //not a special property, load as custom
1278 if (entry.value == Unsupported){
1279 Property prop = CUSTOM_PROP;
1280 options_ += Options::Custom;
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 //=============================================================================
OpenMesh::BaseKernel::add_property
void add_property(VPropHandleT< T > &_ph, const std::string &_name="<vprop>")
Definition: BaseKernel.hh:138
OpenMesh::IO::_PLYReader_::userOptions_
Options userOptions_
Options that the user wants to read.
Definition: PLYReader.hh:163
OpenMesh::IO::Options::VertexNormal
Has (r) / store (w) vertex normals.
Definition: Options.hh:109
OpenMesh::BaseKernel::property
PropertyT< T > & property(VPropHandleT< T > _ph)
Definition: BaseKernel.hh:294
OpenMesh
Definition: MeshItems.hh:64
OpenMesh::IO::_IOManager_::register_module
bool register_module(BaseReader *_bl)
Definition: IOManager.hh:222
BaseImporter
Definition: BaseImporter.hh:1
OpenMesh::IO::Options::MSB
Assume big endian byte ordering.
Definition: Options.hh:106
OpenMesh::IO::Options::FaceColor
Has (r) / store (w) face colors.
Definition: Options.hh:114
OpenMesh::IO::_PLYReader_::options_
Options options_
Available per file options for reading.
Definition: PLYReader.hh:160
OpenMesh::IO::_PLYReader_
Definition: PLYReader.hh:99
omstream.hh
OpenMesh::IO::Handle2Prop
Definition: PLYReader.cc:177
OpenMesh::IO::Options::VertexTexCoord
Has (r) / store (w) texture coordinates.
Definition: Options.hh:111
OpenMesh::IO::Options
Set options for reader/writer modules.
Definition: Options.hh:95
config.h
OpenMesh::IO::__PLYReaderInstance
_PLYReader_ __PLYReaderInstance
Declare the single entity of the PLY reader.
Definition: PLYReader.cc:79
OpenMesh::VPropHandleT
Definition: Property.hh:487
OpenMesh::IO::uint16_t
unsigned short uint16_t
Definition: SR_types.hh:86
OpenMesh::VectorT< float, 3 >
OpenMesh::VertexHandle
Handle for a vertex entity.
Definition: Handles.hh:125
OpenMesh::IO::_PLYReader_::can_u_read
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
OpenMesh::IO::Options::ColorFloat
Has (r) / store (w) float values for colors (currently only implemented for PLY and OFF files) ...
Definition: Options.hh:117
OpenMesh::IO::int16_t
short int16_t
Definition: SR_types.hh:86
OpenMesh::IO::float32_t
float float32_t
Definition: SR_types.hh:97
OpenMesh::IO::float64_t
double float64_t
Definition: SR_types.hh:98
OpenMesh::FaceHandle
Handle for a face entity.
Definition: Handles.hh:146
OpenMesh::BaseKernel::get_property_handle
bool get_property_handle(VPropHandleT< T > &_ph, const std::string &_name) const
Definition: BaseKernel.hh:243
OpenMesh::FPropHandleT
Definition: Property.hh:529
OpenMesh::IO::_PLYReader_::scalar_size_
std::map< ValueType, int > scalar_size_
Stores sizes of property types.
Definition: PLYReader.hh:180
OpenMesh::IO::Options::Binary
Set binary mode for r/w.
Definition: Options.hh:105
OpenMesh::IO::_PLYReader_::read
bool read(const std::string &_filename, BaseImporter &_bi, Options &_opt)
Definition: PLYReader.cc:113
OpenMesh::IO::Options::cleanup
void cleanup(void)
Restore state after default constructor.
Definition: Options.hh:147
OpenMesh::IO::Options::Swap
Swap byte order in binary mode.
Definition: Options.hh:108
OpenMesh::IO::Options::clear
void clear(void)
Clear all bits.
Definition: Options.hh:151
OpenMesh::IO::Options::VertexColor
Has (r) / store (w) vertex colors.
Definition: Options.hh:110
OpenMesh::IO::Options::LSB
Assume little endian byte ordering.
Definition: Options.hh:107
OpenMesh::IO::uint32_t
unsigned int uint32_t
Definition: SR_types.hh:90
OpenMesh::IO::int32_t
int int32_t
Definition: SR_types.hh:90
OpenMesh::IO::Options::Custom
Has (r) custom properties (currently only implemented in PLY Reader ASCII version) ...
Definition: Options.hh:118
OpenMesh::IO::Options::ColorAlpha
Has (r) / store (w) alpha values for colors.
Definition: Options.hh:116
OpenMesh::IO::int8_t
signed char int8_t
Definition: SR_types.hh:85
PropertyInfo
Cellection of information about a property.
Definition: Utils.hh:115
OpenMesh::IO::_PLYReader_::consume_input
void consume_input(std::istream &_in, int _count) const
Read unsupported properties in PLY file.
Definition: PLYReader.hh:153
OpenMesh::IO::IOManager
_IOManager_ & IOManager()
Definition: IOManager.cc:77
OpenMesh::IO::uint8_t
unsigned char uint8_t
Definition: SR_types.hh:85
OpenMesh::IO::BaseReader::can_u_read
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
OpenMesh::IO::BaseImporter
Definition: BaseImporter.hh:88