Developer Documentation

PLYWriter.cc
1 /* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openmesh.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenMesh. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 * ========================================================================= */
41
42
43
44
45 //== INCLUDES =================================================================
46
47 #include <fstream>
48 #include <OpenMesh/Core/System/omstream.hh>
49 #include <OpenMesh/Core/Utils/Endian.hh>
50 #include <OpenMesh/Core/IO/IOManager.hh>
51 #include <OpenMesh/Core/IO/BinaryHelper.hh>
52 #include <OpenMesh/Core/IO/writer/PLYWriter.hh>
53
54 #include <iostream>
55
56 //=== NAMESPACES ==============================================================
57
58
59 namespace OpenMesh {
60 namespace IO {
61
62
63 //=== INSTANCIATE =============================================================
64
65
66 // register the PLYLoader singleton with MeshLoader
67 _PLYWriter_ __PLYWriterInstance;
68 _PLYWriter_& PLYWriter() { return __PLYWriterInstance; }
69
70
71 //=== IMPLEMENTATION ==========================================================
72
73
74 _PLYWriter_::_PLYWriter_()
75 {
76 IOManager().register_module(this);
77
78 nameOfType_[Unsupported] = "";
79 nameOfType_[ValueTypeCHAR] = "char";
80 nameOfType_[ValueTypeUCHAR] = nameOfType_[ValueTypeUINT8] = "uchar";
81 nameOfType_[ValueTypeUSHORT] = "ushort";
82 nameOfType_[ValueTypeSHORT] = "short";
83 nameOfType_[ValueTypeUINT] = "uint";
84 nameOfType_[ValueTypeINT] = "int";
85 nameOfType_[ValueTypeFLOAT32] = nameOfType_[ValueTypeFLOAT] = "float";
86 nameOfType_[ValueTypeDOUBLE] = "double";
87 }
88
89
90 //-----------------------------------------------------------------------------
91
92
93 bool
94 _PLYWriter_::
95 write(const std::string& _filename, BaseExporter& _be, Options _opt, std::streamsize _precision) const
96 {
97
98 // open file
99 std::ofstream out(_filename.c_str(), (_opt.check(Options::Binary) ? std::ios_base::binary | std::ios_base::out
100 : std::ios_base::out) );
101 return write(out, _be, _opt, _precision);
102 }
103
104 //-----------------------------------------------------------------------------
105
106
107 bool
108 _PLYWriter_::
109 write(std::ostream& _os, BaseExporter& _be, Options _opt, std::streamsize _precision) const
110 {
111 // check exporter features
112 if ( !check( _be, _opt ) )
113 return false;
114
115
116 // check writer features
117 if ( _opt.check(Options::FaceNormal) ) {
118 // Face normals are not supported
119 // Uncheck these options and output message that
120 // they are not written out even though they were requested
121 _opt.unset(Options::FaceNormal);
122 omerr() << "[PLYWriter] : Warning: Face normals are not supported and thus not exported! " << std::endl;
123 }
124
125 options_ = _opt;
126
127
128 if (!_os.good())
129 {
130 omerr() << "[PLYWriter] : cannot write to stream "
131 << std::endl;
132 return false;
133 }
134
135 if (!_opt.check(Options::Binary))
136 _os.precision(_precision);
137
138 // write to file
139 bool result = (_opt.check(Options::Binary) ?
140 write_binary(_os, _be, _opt) :
141 write_ascii(_os, _be, _opt));
142
143 return result;
144 }
145
146 //-----------------------------------------------------------------------------
147
148 // helper function for casting a property
149 template<typename T>
150 const PropertyT<T>* castProperty(const BaseProperty* _prop)
151 {
152 return dynamic_cast< const PropertyT<T>* >(_prop);
153 }
154
155 //-----------------------------------------------------------------------------
156 std::vector<_PLYWriter_::CustomProperty> _PLYWriter_::writeCustomTypeHeader(std::ostream& _out, BaseKernel::const_prop_iterator _begin, BaseKernel::const_prop_iterator _end) const
157 {
158 std::vector<CustomProperty> customProps;
159 for (;_begin != _end; ++_begin)
160 {
161 BaseProperty* prop = *_begin;
162
163
164 // check, if property is persistant
165 if (!prop || !prop->persistent())
166 continue;
167
168
169 // identify type of property
170 CustomProperty cProp(prop);
171 size_t propSize = prop->element_size();
172 switch (propSize)
173 {
174 case 1:
175 {
176 assert_compile(sizeof(char) == 1);
177 //check, if prop is a char or unsigned char by dynamic_cast
178 //char, unsigned char and signed char are 3 distinct types
179 if (castProperty<signed char>(prop) != 0 || castProperty<char>(prop) != 0) //treat char as signed char
180 cProp.type = ValueTypeCHAR;
181 else if (castProperty<unsigned char>(prop) != 0)
182 cProp.type = ValueTypeUCHAR;
183 break;
184 }
185 case 2:
186 {
187 assert_compile (sizeof(short) == 2);
188 if (castProperty<signed short>(prop) != 0)
189 cProp.type = ValueTypeSHORT;
190 else if (castProperty<unsigned short>(prop) != 0)
191 cProp.type = ValueTypeUSHORT;
192 break;
193 }
194 case 4:
195 {
196 assert_compile (sizeof(int) == 4);
197 assert_compile (sizeof(float) == 4);
198 if (castProperty<signed int>(prop) != 0)
199 cProp.type = ValueTypeINT;
200 else if (castProperty<unsigned int>(prop) != 0)
201 cProp.type = ValueTypeUINT;
202 else if (castProperty<float>(prop) != 0)
203 cProp.type = ValueTypeFLOAT;
204 break;
205
206 }
207 case 8:
208 assert_compile (sizeof(double) == 8);
209 if (castProperty<double>(prop) != 0)
210 cProp.type = ValueTypeDOUBLE;
211 break;
212 default:
213 break;
214 }
215
216 if (cProp.type != Unsupported)
217 {
218 // property type was identified and it is persistant, write into header
219 customProps.push_back(cProp);
220 _out << "property " << nameOfType_[cProp.type] << " " << cProp.property->name() << "\n";
221 }
222 }
223 return customProps;
224 }
225
226 //-----------------------------------------------------------------------------
227
228 template<bool binary>
229 void _PLYWriter_::write_customProp(std::ostream& _out, const CustomProperty& _prop, size_t _index) const
230 {
231 if (_prop.type == ValueTypeCHAR)
232 writeProxy(_prop.type,_out, castProperty<signed char>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
233 else if (_prop.type == ValueTypeUCHAR || _prop.type == ValueTypeUINT8)
234 writeProxy(_prop.type,_out, castProperty<unsigned char>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
235 else if (_prop.type == ValueTypeSHORT)
236 writeProxy(_prop.type,_out, castProperty<signed short>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
237 else if (_prop.type == ValueTypeUSHORT)
238 writeProxy(_prop.type,_out, castProperty<unsigned short>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
239 else if (_prop.type == ValueTypeUINT)
240 writeProxy(_prop.type,_out, castProperty<unsigned int>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
241 else if (_prop.type == ValueTypeINT || _prop.type == ValueTypeINT32)
242 writeProxy(_prop.type,_out, castProperty<signed int>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
243 else if (_prop.type == ValueTypeFLOAT || _prop.type == ValueTypeFLOAT32)
244 writeProxy(_prop.type,_out, castProperty<float>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
245 else if (_prop.type == ValueTypeDOUBLE)
246 writeProxy(_prop.type,_out, castProperty<double>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
247 }
248
249
250 //-----------------------------------------------------------------------------
251
252
253
254 void _PLYWriter_::write_header(std::ostream& _out, BaseExporter& _be, Options& _opt, std::vector<CustomProperty>& _ovProps, std::vector<CustomProperty>& _ofProps) const {
255 //writing header
256 _out << "ply" << '\n';
257
258 if (_opt.is_binary()) {
259 _out << "format ";
260 if ( options_.check(Options::MSB) )
261 _out << "binary_big_endian ";
262 else
263 _out << "binary_little_endian ";
264 _out << "1.0" << '\n';
265 } else
266 _out << "format ascii 1.0" << '\n';
267
268 _out << "element vertex " << _be.n_vertices() << '\n';
269
270 _out << "property float x" << '\n';
271 _out << "property float y" << '\n';
272 _out << "property float z" << '\n';
273
274 if ( _opt.vertex_has_normal() ){
275 _out << "property float nx" << '\n';
276 _out << "property float ny" << '\n';
277 _out << "property float nz" << '\n';
278 }
279
280 if ( _opt.vertex_has_texcoord() ){
281 _out << "property float u" << '\n';
282 _out << "property float v" << '\n';
283 }
284
285 if ( _opt.vertex_has_color() ){
286 if ( _opt.color_is_float() ) {
287 _out << "property float red" << '\n';
288 _out << "property float green" << '\n';
289 _out << "property float blue" << '\n';
290
291 if ( _opt.color_has_alpha() )
292 _out << "property float alpha" << '\n';
293 } else {
294 _out << "property uchar red" << '\n';
295 _out << "property uchar green" << '\n';
296 _out << "property uchar blue" << '\n';
297
298 if ( _opt.color_has_alpha() )
299 _out << "property uchar alpha" << '\n';
300 }
301 }
302
303 _ovProps = writeCustomTypeHeader(_out, _be.kernel()->vprops_begin(), _be.kernel()->vprops_end());
304
305 _out << "element face " << _be.n_faces() << '\n';
306 _out << "property list uchar int vertex_indices" << '\n';
307
308 if ( _opt.face_has_color() ){
309 if ( _opt.color_is_float() ) {
310 _out << "property float red" << '\n';
311 _out << "property float green" << '\n';
312 _out << "property float blue" << '\n';
313
314 if ( _opt.color_has_alpha() )
315 _out << "property float alpha" << '\n';
316 } else {
317 _out << "property uchar red" << '\n';
318 _out << "property uchar green" << '\n';
319 _out << "property uchar blue" << '\n';
320
321 if ( _opt.color_has_alpha() )
322 _out << "property uchar alpha" << '\n';
323 }
324 }
325
326 _ofProps = writeCustomTypeHeader(_out, _be.kernel()->fprops_begin(), _be.kernel()->fprops_end());
327
328 _out << "end_header" << '\n';
329 }
330
331
332 //-----------------------------------------------------------------------------
333
334
335 bool
336 _PLYWriter_::
337 write_ascii(std::ostream& _out, BaseExporter& _be, Options _opt) const
338 {
339
340 unsigned int i, nV, nF;
341 Vec3f v, n;
342 OpenMesh::Vec3ui c;
343 OpenMesh::Vec4ui cA;
344 OpenMesh::Vec3f cf;
345 OpenMesh::Vec4f cAf;
346 OpenMesh::Vec2f t;
347 VertexHandle vh;
348 FaceHandle fh;
349 std::vector<VertexHandle> vhandles;
350
351 std::vector<CustomProperty> vProps;
352 std::vector<CustomProperty> fProps;
353
354 write_header(_out, _be, _opt, vProps, fProps);
355
356 if (_opt.color_is_float())
357 _out << std::fixed;
358
359 // vertex data (point, normals, colors, texcoords)
360 for (i=0, nV=int(_be.n_vertices()); i<nV; ++i)
361 {
362 vh = VertexHandle(i);
363 v = _be.point(vh);
364
365 //Vertex
366 _out << v[0] << " " << v[1] << " " << v[2];
367
368 // Vertex Normals
369 if ( _opt.vertex_has_normal() ){
370 n = _be.normal(vh);
371 _out << " " << n[0] << " " << n[1] << " " << n[2];
372 }
373
374 // Vertex TexCoords
375 if ( _opt.vertex_has_texcoord() ) {
376 t = _be.texcoord(vh);
377 _out << " " << t[0] << " " << t[1];
378 }
379
380 // VertexColor
381 if ( _opt.vertex_has_color() ) {
382 //with alpha
383 if ( _opt.color_has_alpha() ){
384 if (_opt.color_is_float()) {
385 cAf = _be.colorAf(vh);
386 _out << " " << cAf;
387 } else {
388 cA = _be.colorAi(vh);
389 _out << " " << cA;
390 }
391 }else{
392 //without alpha
393 if (_opt.color_is_float()) {
394 cf = _be.colorf(vh);
395 _out << " " << cf;
396 } else {
397 c = _be.colori(vh);
398 _out << " " << c;
399 }
400 }
401 }
402
403
404 // write custom properties for vertices
405 for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
406 write_customProp<false>(_out,*iter,i);
407
408 _out << "\n";
409 }
410
411 // faces (indices starting at 0)
412 for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
413 {
414 fh = FaceHandle(i);
415
416 // write vertex indices per face
417 nV = _be.get_vhandles(fh, vhandles);
418 _out << nV;
419 for (size_t j=0; j<vhandles.size(); ++j)
420 _out << " " << vhandles[j].idx();
421
422 // FaceColor
423 if ( _opt.face_has_color() ) {
424 //with alpha
425 if ( _opt.color_has_alpha() ){
426 if (_opt.color_is_float()) {
427 cAf = _be.colorAf(fh);
428 _out << " " << cAf;
429 } else {
430 cA = _be.colorAi(fh);
431 _out << " " << cA;
432 }
433 }else{
434 //without alpha
435 if (_opt.color_is_float()) {
436 cf = _be.colorf(fh);
437 _out << " " << cf;
438 } else {
439 c = _be.colori(fh);
440 _out << " " << c;
441 }
442 }
443 }
444
445 // write custom props
446 for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
447 write_customProp<false>(_out,*iter,i);
448 _out << "\n";
449 }
450
451
452 return true;
453 }
454
455
456 //-----------------------------------------------------------------------------
457
458 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, int value) const {
459
460 uint32_t tmp32;
461 uint8_t tmp8;
462
463 switch (_type) {
464 case ValueTypeINT:
465 case ValueTypeINT32:
466 tmp32 = value;
467 store(_out, tmp32, options_.check(Options::MSB) );
468 break;
469 // case ValueTypeUINT8:
470 default :
471 tmp8 = value;
472 store(_out, tmp8, options_.check(Options::MSB) );
473 break;
474 // default :
475 // std::cerr << "unsupported conversion type to int: " << _type << std::endl;
476 // break;
477 }
478 }
479
480 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, unsigned int value) const {
481
482 uint32_t tmp32;
483 uint8_t tmp8;
484
485 switch (_type) {
486 case ValueTypeINT:
487 case ValueTypeINT32:
488 tmp32 = value;
489 store(_out, tmp32, options_.check(Options::MSB) );
490 break;
491 // case ValueTypeUINT8:
492 default :
493 tmp8 = value;
494 store(_out, tmp8, options_.check(Options::MSB) );
495 break;
496 // default :
497 // std::cerr << "unsupported conversion type to int: " << _type << std::endl;
498 // break;
499 }
500 }
501
502 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, float value) const {
503
504 float32_t tmp;
505
506 switch (_type) {
507 case ValueTypeFLOAT32:
508 case ValueTypeFLOAT:
509 tmp = value;
510 store( _out , tmp, options_.check(Options::MSB) );
511 break;
512 default :
513 std::cerr << "unsupported conversion type to float: " << _type << std::endl;
514 break;
515 }
516 }
517
518 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, double value) const {
519
520 float64_t tmp;
521
522 switch (_type) {
523 case ValueTypeDOUBLE:
524 tmp = value;
525 store( _out , tmp, options_.check(Options::MSB) );
526 break;
527 default :
528 std::cerr << "unsupported conversion type to float: " << _type << std::endl;
529 break;
530 }
531 }
532
533 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, signed char value) const{
534
535 int8_t tmp;
536
537 switch (_type) {
538 case ValueTypeCHAR:
539 tmp = value;
540 store(_out, tmp, options_.check(Options::MSB) );
541 break;
542 default :
543 std::cerr << "unsupported conversion type to int: " << _type << std::endl;
544 break;
545 }
546 }
547 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, unsigned char value) const{
548
549 uint8_t tmp;
550
551 switch (_type) {
552 case ValueTypeUCHAR:
553 tmp = value;
554 store(_out, tmp, options_.check(Options::MSB) );
555 break;
556 default :
557 std::cerr << "unsupported conversion type to int: " << _type << std::endl;
558 break;
559 }
560 }
561 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, short value) const{
562
563 int16_t tmp;
564
565 switch (_type) {
566 case ValueTypeSHORT:
567 tmp = value;
568 store(_out, tmp, options_.check(Options::MSB) );
569 break;
570 default :
571 std::cerr << "unsupported conversion type to int: " << _type << std::endl;
572 break;
573 }
574 }
575 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, unsigned short value) const{
576
577 uint16_t tmp;
578
579 switch (_type) {
580 case ValueTypeUSHORT:
581 tmp = value;
582 store(_out, tmp, options_.check(Options::MSB) );
583 break;
584 default :
585 std::cerr << "unsupported conversion type to int: " << _type << std::endl;
586 break;
587 }
588 }
589
590 bool
591 _PLYWriter_::
592 write_binary(std::ostream& _out, BaseExporter& _be, Options _opt) const
593 {
594
595 unsigned int i, nV, nF;
596 Vec3f v, n;
597 Vec2f t;
598 OpenMesh::Vec4uc c;
599 OpenMesh::Vec4f cf;
600 VertexHandle vh;
601 FaceHandle fh;
602 std::vector<VertexHandle> vhandles;
603
604 // vProps and fProps will be empty, until custom properties are supported by the binary writer
605 std::vector<CustomProperty> vProps;
606 std::vector<CustomProperty> fProps;
607
608 write_header(_out, _be, _opt, vProps, fProps);
609
610 // vertex data (point, normals, texcoords)
611 for (i=0, nV=int(_be.n_vertices()); i<nV; ++i)
612 {
613 vh = VertexHandle(i);
614 v = _be.point(vh);
615
616 //vertex
617 writeValue(ValueTypeFLOAT, _out, v[0]);
618 writeValue(ValueTypeFLOAT, _out, v[1]);
619 writeValue(ValueTypeFLOAT, _out, v[2]);
620
621 // Vertex Normal
622 if ( _opt.vertex_has_normal() ){
623 n = _be.normal(vh);
624 writeValue(ValueTypeFLOAT, _out, n[0]);
625 writeValue(ValueTypeFLOAT, _out, n[1]);
626 writeValue(ValueTypeFLOAT, _out, n[2]);
627 }
628
629 // Vertex TexCoords
630 if ( _opt.vertex_has_texcoord() ) {
631 t = _be.texcoord(vh);
632 writeValue(ValueTypeFLOAT, _out, t[0]);
633 writeValue(ValueTypeFLOAT, _out, t[1]);
634 }
635
636 // vertex color
637 if ( _opt.vertex_has_color() ) {
638 if ( _opt.color_is_float() ) {
639 cf = _be.colorAf(vh);
640 writeValue(ValueTypeFLOAT, _out, cf[0]);
641 writeValue(ValueTypeFLOAT, _out, cf[1]);
642 writeValue(ValueTypeFLOAT, _out, cf[2]);
643
644 if ( _opt.color_has_alpha() )
645 writeValue(ValueTypeFLOAT, _out, cf[3]);
646 } else {
647 c = _be.colorA(vh);
648 writeValue(ValueTypeUCHAR, _out, (int)c[0]);
649 writeValue(ValueTypeUCHAR, _out, (int)c[1]);
650 writeValue(ValueTypeUCHAR, _out, (int)c[2]);
651
652 if ( _opt.color_has_alpha() )
653 writeValue(ValueTypeUCHAR, _out, (int)c[3]);
654 }
655 }
656
657 for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
658 write_customProp<true>(_out,*iter,i);
659 }
660
661
662 for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
663 {
664 fh = FaceHandle(i);
665
666 //face
667 nV = _be.get_vhandles(fh, vhandles);
668 writeValue(ValueTypeUINT8, _out, nV);
669 for (size_t j=0; j<vhandles.size(); ++j)
670 writeValue(ValueTypeINT32, _out, vhandles[j].idx() );
671
672 // face color
673 if ( _opt.face_has_color() ) {
674 if ( _opt.color_is_float() ) {
675 cf = _be.colorAf(fh);
676 writeValue(ValueTypeFLOAT, _out, cf[0]);
677 writeValue(ValueTypeFLOAT, _out, cf[1]);
678 writeValue(ValueTypeFLOAT, _out, cf[2]);
679
680 if ( _opt.color_has_alpha() )
681 writeValue(ValueTypeFLOAT, _out, cf[3]);
682 } else {
683 c = _be.colorA(fh);
684 writeValue(ValueTypeUCHAR, _out, (int)c[0]);
685 writeValue(ValueTypeUCHAR, _out, (int)c[1]);
686 writeValue(ValueTypeUCHAR, _out, (int)c[2]);
687
688 if ( _opt.color_has_alpha() )
689 writeValue(ValueTypeUCHAR, _out, (int)c[3]);
690 }
691 }
692
693 for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
694 write_customProp<true>(_out,*iter,i);
695 }
696
697 return true;
698 }
699
700 // ----------------------------------------------------------------------------
701
702
703 size_t
704 _PLYWriter_::
705 binary_size(BaseExporter& _be, Options _opt) const
706 {
707 size_t header(0);
708 size_t data(0);
709 size_t _3floats(3*sizeof(float));
710 size_t _3ui(3*sizeof(unsigned int));
711 size_t _4ui(4*sizeof(unsigned int));
712
713 if ( !_opt.is_binary() )
714 return 0;
715 else
716 {
717
718 size_t _3longs(3*sizeof(long));
719
720 header += 11; // 'OFF BINARY\n'
721 header += _3longs; // #V #F #E
722 data += _be.n_vertices() * _3floats; // vertex data
723 }
724
725 if ( _opt.vertex_has_normal() && _be.has_vertex_normals() )
726 {
727 header += 1; // N
728 data += _be.n_vertices() * _3floats;
729 }
730
731 if ( _opt.vertex_has_color() && _be.has_vertex_colors() )
732 {
733 header += 1; // C
734 data += _be.n_vertices() * _3floats;
735 }
736
737 if ( _opt.vertex_has_texcoord() && _be.has_vertex_texcoords() )
738 {
739 size_t _2floats(2*sizeof(float));
740 header += 2; // ST
741 data += _be.n_vertices() * _2floats;
742 }
743
744 // topology
745 if (_be.is_triangle_mesh())
746 {
747 data += _be.n_faces() * _4ui;
748 }
749 else
750 {
751 unsigned int i, nF;
752 std::vector<VertexHandle> vhandles;
753
754 for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
755 {
756 data += _be.get_vhandles(FaceHandle(i), vhandles) * sizeof(unsigned int);
757
758 }
759 }
760
761 // face colors
762 if ( _opt.face_has_color() && _be.has_face_colors() ){
763 if ( _opt.color_has_alpha() )
764 data += _be.n_faces() * _4ui;
765 else
766 data += _be.n_faces() * _3ui;
767 }
768
769 return header+data;
770 }
771
772
773 //=============================================================================
774 } // namespace IO
775 } // namespace OpenMesh
776 //=============================================================================
OpenMesh::IO::_PLYWriter_::CustomProperty
Definition: PLYWriter.hh:119
OpenMesh::IO::_PLYWriter_::write_header
void write_header(std::ostream &_out, BaseExporter &_be, Options &_opt, std::vector< CustomProperty > &_ovProps, std::vector< CustomProperty > &_ofProps) const
write header into the stream _out. Returns custom properties (vertex and face) which are written into...
Definition: PLYWriter.cc:254
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::_IOManager_::register_module
bool register_module(BaseReader *_bl)
Definition: IOManager.hh:217
OpenMesh::IO::uint32_t
unsigned int uint32_t
Definition: SR_types.hh:85
OpenMesh::IO::int8_t
signed char int8_t
Definition: SR_types.hh:80
OpenMesh::IO::Options::FaceNormal
Has (r) / store (w) face normals.
Definition: Options.hh:108
OpenMesh::IO::IOManager
_IOManager_ & IOManager()
Definition: IOManager.cc:72
OpenMesh::BaseProperty::name
const std::string & name() const
Return the name of the property.
Definition: BaseProperty.hh:120
OpenMesh::IO::Options::unset
Options & unset(const value_type _rhs)
Unset options defined in _rhs.
Definition: Options.hh:174
VectorT< unsigned int, 4 >
OpenMesh::IO::__PLYWriterInstance
_PLYWriter_ __PLYWriterInstance
Declare the single entity of the PLY writer.
Definition: PLYWriter.cc:67
OpenMesh::IO::uint16_t
unsigned short uint16_t
Definition: SR_types.hh:81
OpenMesh::FaceHandle
Handle for a face entity.
Definition: Handles.hh:141
OpenMesh::IO::BaseExporter
Definition: BaseExporter.hh:84
OpenMesh::PropertyT
Default property class for any type T.
Definition: Property.hh:89
OpenMesh::IO::_PLYWriter_
Definition: PLYWriter.hh:89
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::VectorT< float, 3 >
OpenMesh::IO::Options::Binary
Set binary mode for r/w.
Definition: Options.hh:100
OpenMesh::BaseProperty::element_size
virtual size_t element_size() const =0
Size of one element in bytes or UnknownSize if not known.
OpenMesh::IO::float64_t
double float64_t
Definition: SR_types.hh:93
OpenMesh::BaseProperty
Definition: BaseProperty.hh:60
OpenMesh::IO::float32_t
float float32_t
Definition: SR_types.hh:92
OpenMesh::IO::_PLYWriter_::binary_size
size_t binary_size(BaseExporter &_be, Options _opt) const
Returns expected size of file if binary format is supported else 0.
Definition: PLYWriter.cc:705
OpenMesh
Definition: MeshItems.hh:59
OpenMesh::IO::Options::MSB
Assume big endian byte ordering.
Definition: Options.hh:101
omstream.hh
OpenMesh::BaseProperty::persistent
bool persistent(void) const
Returns true if the persistent flag is enabled else false.
Definition: BaseProperty.hh:127
OpenMesh::IO::_PLYWriter_::write
bool write(const std::string &, BaseExporter &, Options, std::streamsize _precision=6) const
Definition: PLYWriter.cc:95
OpenMesh::IO::_PLYWriter_::writeCustomTypeHeader
std::vector< CustomProperty > writeCustomTypeHeader(std::ostream &_out, BaseKernel::const_prop_iterator _begin, BaseKernel::const_prop_iterator _end) const
write custom persistant properties into the header for the current element, returns all properties...
Definition: PLYWriter.cc:156