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