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
47 #include <OpenMesh/Core/System/config.h>
48 #include <OpenMesh/Core/System/omstream.hh>
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
72 _PLYReader_ __PLYReaderInstance;
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>
181 struct Handle2Prop<T,VertexHandle>
182 {
183 typedef OpenMesh::VPropHandleT<T> PropT;
184 };
185
186 template<typename T>
187 struct Handle2Prop<T,FaceHandle>
188 {
189 typedef OpenMesh::FPropHandleT<T> PropT;
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") {
1245 options_ -= Options::Binary;
1246 } else if (fileType == "binary_little_endian") {
1247 options_ += Options::Binary;
1248 options_ += Options::LSB;
1249 //if (Endian::local() == Endian::MSB)
1250
1251 // options_ += Options::Swap;
1252 } else if (fileType == "binary_big_endian") {
1253 options_ += Options::Binary;
1254 options_ += Options::MSB;
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 {
1339 options_ += Options::Custom;
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);
1373 options_ += Options::VertexNormal;
1374 } else if (propertyName == "ny") {
1375 entry = PropertyInfo(YNORM, valueType);
1376 options_ += Options::VertexNormal;
1377 } else if (propertyName == "nz") {
1378 entry = PropertyInfo(ZNORM, valueType);
1379 options_ += Options::VertexNormal;
1380 } else if (propertyName == "u" || propertyName == "s") {
1381 entry = PropertyInfo(TEXX, valueType);
1382 options_ += Options::VertexTexCoord;
1383 } else if (propertyName == "v" || propertyName == "t") {
1384 entry = PropertyInfo(TEXY, valueType);
1385 options_ += Options::VertexTexCoord;
1386 } else if (propertyName == "red") {
1387 entry = PropertyInfo(COLORRED, valueType);
1388 options_ += Options::VertexColor;
1389 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1390 options_ += Options::ColorFloat;
1391 } else if (propertyName == "green") {
1392 entry = PropertyInfo(COLORGREEN, valueType);
1393 options_ += Options::VertexColor;
1394 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1395 options_ += Options::ColorFloat;
1396 } else if (propertyName == "blue") {
1397 entry = PropertyInfo(COLORBLUE, valueType);
1398 options_ += Options::VertexColor;
1399 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1400 options_ += Options::ColorFloat;
1401 } else if (propertyName == "diffuse_red") {
1402 entry = PropertyInfo(COLORRED, valueType);
1403 options_ += Options::VertexColor;
1404 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1405 options_ += Options::ColorFloat;
1406 } else if (propertyName == "diffuse_green") {
1407 entry = PropertyInfo(COLORGREEN, valueType);
1408 options_ += Options::VertexColor;
1409 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1410 options_ += Options::ColorFloat;
1411 } else if (propertyName == "diffuse_blue") {
1412 entry = PropertyInfo(COLORBLUE, valueType);
1413 options_ += Options::VertexColor;
1414 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1415 options_ += Options::ColorFloat;
1416 } else if (propertyName == "alpha") {
1417 entry = PropertyInfo(COLORALPHA, valueType);
1418 options_ += Options::VertexColor;
1419 options_ += Options::ColorAlpha;
1420 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1421 options_ += Options::ColorFloat;
1422 }
1423 }
1424 else if (elementName == "face") {
1425 if (propertyName == "red") {
1426 entry = PropertyInfo(COLORRED, valueType);
1427 options_ += Options::FaceColor;
1428 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1429 options_ += Options::ColorFloat;
1430 } else if (propertyName == "green") {
1431 entry = PropertyInfo(COLORGREEN, valueType);
1432 options_ += Options::FaceColor;
1433 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1434 options_ += Options::ColorFloat;
1435 } else if (propertyName == "blue") {
1436 entry = PropertyInfo(COLORBLUE, valueType);
1437 options_ += Options::FaceColor;
1438 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1439 options_ += Options::ColorFloat;
1440 } else if (propertyName == "alpha") {
1441 entry = PropertyInfo(COLORALPHA, valueType);
1442 options_ += Options::FaceColor;
1443 options_ += Options::ColorAlpha;
1444 if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
1445 options_ += Options::ColorFloat;
1446 }
1447 }
1448
1449 //not a special property, load as custom
1450 if (entry.value == Unsupported){
1451 Property prop = CUSTOM_PROP;
1452 options_ += Options::Custom;
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 //=============================================================================
OpenMesh::IO::Options::VertexColor
Has (r) / store (w) vertex colors.
Definition: Options.hh:105
OpenMesh::IO::Options::Swap
Swap byte order in binary mode.
Definition: Options.hh:103
OpenMesh::VertexHandle
Handle for a vertex entity.
Definition: Handles.hh:120
OpenMesh::IO::uint8_t
unsigned char uint8_t
Definition: SR_types.hh:80
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:77
OpenMesh::IO::Options::LSB
Assume little endian byte ordering.
Definition: Options.hh:102
OpenMesh::IO::_PLYReader_::read
bool read(const std::string &_filename, BaseImporter &_bi, Options &_opt)
Definition: PLYReader.cc:106
OpenMesh::IO::_IOManager_::register_module
bool register_module(BaseReader *_bl)
Definition: IOManager.hh:217
OpenMesh::IO::Options::FaceColor
Has (r) / store (w) face colors.
Definition: Options.hh:109
OpenMesh::IO::_PLYReader_::consume_input
void consume_input(std::istream &_in, int _count) const
Read unsupported properties in PLY file.
Definition: PLYReader.hh:148
OpenMesh::IO::uint32_t
unsigned int uint32_t
Definition: SR_types.hh:85
OpenMesh::IO::Options::ColorFloat
Has (r) / store (w) float values for colors (currently only implemented for PLY and OFF files) ...
Definition: Options.hh:112
OpenMesh::IO::int8_t
signed char int8_t
Definition: SR_types.hh:80
OpenMesh::IO::_PLYReader_
Definition: PLYReader.hh:94
OpenMesh::IO::_PLYReader_::options_
Options options_
Available per file options for reading.
Definition: PLYReader.hh:155
OpenMesh::IO::Handle2Prop
Definition: PLYReader.cc:178
OpenMesh::IO::IOManager
_IOManager_ & IOManager()
Definition: IOManager.cc:72
OpenMesh::IO::_PLYReader_::scalar_size_
std::map< ValueType, int > scalar_size_
Stores sizes of property types.
Definition: PLYReader.hh:174
OpenMesh::IO::_PLYReader_::ElementInfo
Definition: PLYReader.hh:195
OpenMesh::IO::__PLYReaderInstance
_PLYReader_ __PLYReaderInstance
Declare the single entity of the PLY reader.
Definition: PLYReader.cc:72
config.h
OpenMesh::IO::Options::VertexTexCoord
Has (r) / store (w) texture coordinates.
Definition: Options.hh:106
OpenMesh::BaseKernel::add_property
void add_property(VPropHandleT< T > &_ph, const std::string &_name="<vprop>")
Definition: BaseKernel.hh:141
VectorT< signed int, 4 >
OpenMesh::BaseKernel::property
PropertyT< T > & property(VPropHandleT< T > _ph)
Definition: BaseKernel.hh:310
OpenMesh::IO::uint16_t
unsigned short uint16_t
Definition: SR_types.hh:81
OpenMesh::BaseKernel::get_property_handle
bool get_property_handle(VPropHandleT< T > &_ph, const std::string &_name) const
Definition: BaseKernel.hh:254
OpenMesh::FaceHandle
Handle for a face entity.
Definition: Handles.hh:141
OpenMesh::IO::Options::clear
void clear(void)
Clear all bits.
Definition: Options.hh:147
OpenMesh::IO::int32_t
int int32_t
Definition: SR_types.hh:85
OpenMesh::IO::Options::cleanup
void cleanup(void)
Restore state after default constructor.
Definition: Options.hh:143
OpenMesh::IO::Options::Custom
Has (r) custom properties (currently only implemented in PLY Reader ASCII version) ...
Definition: Options.hh:113
OpenMesh::IO::Options
Set options for reader/writer modules.
Definition: Options.hh:90
OpenMesh::IO::int16_t
short int16_t
Definition: SR_types.hh:81
OpenMesh::IO::_PLYReader_::PropertyInfo
Definition: PLYReader.hh:177
OpenMesh::IO::Options::ColorAlpha
Has (r) / store (w) alpha values for colors.
Definition: Options.hh:111
OpenMesh::VectorT< float, 3 >
OpenMesh::IO::Options::Binary
Set binary mode for r/w.
Definition: Options.hh:100
OpenMesh::IO::Options::VertexNormal
Has (r) / store (w) vertex normals.
Definition: Options.hh:104
OpenMesh::IO::float64_t
double float64_t
Definition: SR_types.hh:93
OpenMesh::BaseHandle::is_valid
bool is_valid() const
The handle is valid iff the index is not negative.
Definition: Handles.hh:72
OpenMesh::IO::BaseImporter
Definition: BaseImporter.hh:83
OpenMesh::IO::float32_t
float float32_t
Definition: SR_types.hh:92
PropertyInfo
Cellection of information about a property.
Definition: Utils.hh:109
OpenMesh
Definition: MeshItems.hh:59
OpenMesh::IO::Options::MSB
Assume big endian byte ordering.
Definition: Options.hh:101
omstream.hh
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:1088
OpenMesh::IO::_PLYReader_::userOptions_
Options userOptions_
Options that the user wants to read.
Definition: PLYReader.hh:158
OpenMesh::FPropHandleT
Definition: Property.hh:524
OpenMesh::VPropHandleT
Definition: Property.hh:482