Developer Documentation

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

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
OFFWriter.cc
1 /* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openmesh.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenMesh. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 * ========================================================================= */
41
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $Date$ *
46 * *
47 \*===========================================================================*/
48
49
50 //== INCLUDES =================================================================
51
52 #include <fstream>
53 #include <OpenMesh/Core/System/config.h>
54 #include <OpenMesh/Core/System/omstream.hh>
55 #include <OpenMesh/Core/Utils/Endian.hh>
56 #include <OpenMesh/Core/IO/IOManager.hh>
57 #include <OpenMesh/Core/IO/BinaryHelper.hh>
58 #include <OpenMesh/Core/IO/writer/OFFWriter.hh>
59
60 //=== NAMESPACES ==============================================================
61
62
63 namespace OpenMesh {
64 namespace IO {
65
66
67 //=== INSTANCIATE =============================================================
68
69
70 // register the OFFLoader singleton with MeshLoader
71 _OFFWriter_ __OFFWriterInstance;
72 _OFFWriter_& OFFWriter() { return __OFFWriterInstance; }
73
74
75 //=== IMPLEMENTATION ==========================================================
76
77
78 _OFFWriter_::_OFFWriter_() { IOManager().register_module(this); }
79
80
81 //-----------------------------------------------------------------------------
82
83
84 bool
85 _OFFWriter_::
86 write(const std::string& _filename, BaseExporter& _be, Options _opt, std::streamsize _precision) const
87 {
88 std::ofstream out(_filename.c_str(), (_opt.check(Options::Binary) ? std::ios_base::binary | std::ios_base::out
89 : std::ios_base::out) );
90
91 return write(out, _be, _opt, _precision);
92 }
93
94 //-----------------------------------------------------------------------------
95
96
97 bool
98 _OFFWriter_::
99 write(std::ostream& _os, BaseExporter& _be, Options _opt, std::streamsize _precision) const
100 {
101 // check exporter features
102 if ( !check( _be, _opt ) )
103 return false;
104
105
106 // check writer features
107 if ( _opt.check(Options::FaceNormal) ) // not supported by format
108 return false;
109
110
111 if (!_os.good())
112 {
113 omerr() << "[OFFWriter] : cannot write to stream "
114 << std::endl;
115 return false;
116 }
117
118 // write header line
119 if (_opt.check(Options::VertexTexCoord)) _os << "ST";
120 if (_opt.check(Options::VertexColor) || _opt.check(Options::FaceColor)) _os << "C";
121 if (_opt.check(Options::VertexNormal)) _os << "N";
122 _os << "OFF";
123 if (_opt.check(Options::Binary)) _os << " BINARY";
124 _os << "\n";
125
126 if (!_opt.check(Options::Binary))
127 _os.precision(_precision);
128
129 // write to file
130 bool result = (_opt.check(Options::Binary) ?
131 write_binary(_os, _be, _opt) :
132 write_ascii(_os, _be, _opt));
133
134
135 // return result
136 return result;
137 }
138
139 //-----------------------------------------------------------------------------
140
141
142 bool
143 _OFFWriter_::
144 write_ascii(std::ostream& _out, BaseExporter& _be, Options _opt) const
145 {
146
147 unsigned int i, nV, nF;
148 Vec3f v, n;
149 Vec2f t;
150 OpenMesh::Vec3i c;
151 OpenMesh::Vec4i cA;
152 OpenMesh::Vec3f cf;
153 OpenMesh::Vec4f cAf;
154 VertexHandle vh;
155 std::vector<VertexHandle> vhandles;
156
157
158 // #vertices, #faces
159 _out << _be.n_vertices() << " ";
160 _out << _be.n_faces() << " ";
161 _out << 0 << "\n";
162
163 if (_opt.color_is_float())
164 _out << std::fixed;
165
166
167 // vertex data (point, normals, colors, texcoords)
168 for (i=0, nV=int(_be.n_vertices()); i<nV; ++i)
169 {
170 vh = VertexHandle(i);
171 v = _be.point(vh);
172
173 //Vertex
174 _out << v[0] << " " << v[1] << " " << v[2];
175
176 // VertexNormal
177 if ( _opt.vertex_has_normal() ) {
178 n = _be.normal(vh);
179 _out << " " << n[0] << " " << n[1] << " " << n[2];
180 }
181
182 // VertexColor
183 if ( _opt.vertex_has_color() ) {
184 if ( _opt.color_is_float() ) {
185 //with alpha
186 if ( _opt.color_has_alpha() ){
187 cAf = _be.colorAf(vh);
188 _out << " " << cAf;
189 }else{
190 //without alpha
191 cf = _be.colorf(vh);
192 _out << " " << cf;
193 }
194 } else {
195 //with alpha
196 if ( _opt.color_has_alpha() ){
197 cA = _be.colorA(vh);
198 _out << " " << cA;
199 }else{
200 //without alpha
201 c = _be.color(vh);
202 _out << " " << c;
203 }
204 }
205 }
206
207 // TexCoord
208 if (_opt.vertex_has_texcoord() ) {
209 t = _be.texcoord(vh);
210 _out << " " << t[0] << " " << t[1];
211 }
212
213 _out << '\n';
214
215 }
216
217 // faces (indices starting at 0)
218 if (_be.is_triangle_mesh())
219 {
220 for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
221 {
222 _be.get_vhandles(FaceHandle(i), vhandles);
223 _out << 3 << " ";
224 _out << vhandles[0].idx() << " ";
225 _out << vhandles[1].idx() << " ";
226 _out << vhandles[2].idx();
227
228 //face color
229 if ( _opt.face_has_color() ){
230 if ( _opt.color_is_float() ) {
231 //with alpha
232 if ( _opt.color_has_alpha() ){
233 cAf = _be.colorAf( FaceHandle(i) );
234 _out << " " << cAf;
235 }else{
236 //without alpha
237 cf = _be.colorf( FaceHandle(i) );
238 _out << " " << cf;
239 }
240 } else {
241 //with alpha
242 if ( _opt.color_has_alpha() ){
243 cA = _be.colorA( FaceHandle(i) );
244 _out << " " << cA;
245 }else{
246 //without alpha
247 c = _be.color( FaceHandle(i) );
248 _out << " " << c;
249 }
250 }
251 }
252 _out << '\n';
253 }
254 }
255 else
256 {
257 for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
258 {
259 nV = _be.get_vhandles(FaceHandle(i), vhandles);
260 _out << nV << " ";
261 for (size_t j=0; j<vhandles.size(); ++j)
262 _out << vhandles[j].idx() << " ";
263
264 //face color
265 if ( _opt.face_has_color() ){
266 if ( _opt.color_is_float() ) {
267 //with alpha
268 if ( _opt.color_has_alpha() ){
269 cAf = _be.colorAf( FaceHandle(i) );
270 _out << " " << cAf;
271 }else{
272 //without alpha
273 cf = _be.colorf( FaceHandle(i) );
274 _out << " " << cf;
275 }
276 } else {
277 //with alpha
278 if ( _opt.color_has_alpha() ){
279 cA = _be.colorA( FaceHandle(i) );
280 _out << " " << cA;
281 }else{
282 //without alpha
283 c = _be.color( FaceHandle(i) );
284 _out << " " << c;
285 }
286 }
287 }
288
289 _out << '\n';
290 }
291 }
292
293
294 return true;
295 }
296
297
298 //-----------------------------------------------------------------------------
299
300 void _OFFWriter_::writeValue(std::ostream& _out, int value) const {
301
302 uint32_t tmp = value;
303 store(_out, tmp, false);
304 }
305
306 void _OFFWriter_::writeValue(std::ostream& _out, unsigned int value) const {
307
308 uint32_t tmp = value;
309 store(_out, tmp, false);
310 }
311
312 void _OFFWriter_::writeValue(std::ostream& _out, float value) const {
313
314 float32_t tmp = value;
315 store(_out, tmp, false);
316 }
317
318 bool
319 _OFFWriter_::
320 write_binary(std::ostream& _out, BaseExporter& _be, Options _opt) const
321 {
322
323 unsigned int i, nV, nF;
324 Vec3f v, n;
325 Vec2f t;
326 OpenMesh::Vec4i c;
327 OpenMesh::Vec4f cf;
328 VertexHandle vh;
329 std::vector<VertexHandle> vhandles;
330
331 // #vertices, #faces
332 writeValue(_out, (uint)_be.n_vertices() );
333 writeValue(_out, (uint) _be.n_faces() );
334 writeValue(_out, 0 );
335
336 // vertex data (point, normals, texcoords)
337 for (i=0, nV=int(_be.n_vertices()); i<nV; ++i)
338 {
339 vh = VertexHandle(i);
340 v = _be.point(vh);
341
342 //vertex
343 writeValue(_out, v[0]);
344 writeValue(_out, v[1]);
345 writeValue(_out, v[2]);
346
347 // vertex normal
348 if ( _opt.vertex_has_normal() ) {
349 n = _be.normal(vh);
350 writeValue(_out, n[0]);
351 writeValue(_out, n[1]);
352 writeValue(_out, n[2]);
353 }
354 // vertex color
355 if ( _opt.vertex_has_color() ) {
356 if ( _opt.color_is_float() ) {
357 cf = _be.colorAf(vh);
358 writeValue(_out, cf[0]);
359 writeValue(_out, cf[1]);
360 writeValue(_out, cf[2]);
361
362 if ( _opt.color_has_alpha() )
363 writeValue(_out, cf[3]);
364 } else {
365 c = _be.colorA(vh);
366 writeValue(_out, c[0]);
367 writeValue(_out, c[1]);
368 writeValue(_out, c[2]);
369
370 if ( _opt.color_has_alpha() )
371 writeValue(_out, c[3]);
372 }
373 }
374 // texCoords
375 if (_opt.vertex_has_texcoord() ) {
376 t = _be.texcoord(vh);
377 writeValue(_out, t[0]);
378 writeValue(_out, t[1]);
379 }
380
381 }
382
383 // faces (indices starting at 0)
384 if (_be.is_triangle_mesh())
385 {
386 for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
387 {
388 //face
389 _be.get_vhandles(FaceHandle(i), vhandles);
390 writeValue(_out, 3);
391 writeValue(_out, vhandles[0].idx());
392 writeValue(_out, vhandles[1].idx());
393 writeValue(_out, vhandles[2].idx());
394
395 //face color
396 if ( _opt.face_has_color() ){
397 if ( _opt.color_is_float() ) {
398 cf = _be.colorAf( FaceHandle(i) );
399 writeValue(_out, cf[0]);
400 writeValue(_out, cf[1]);
401 writeValue(_out, cf[2]);
402
403 if ( _opt.color_has_alpha() )
404 writeValue(_out, cf[3]);
405 } else {
406 c = _be.colorA( FaceHandle(i) );
407 writeValue(_out, c[0]);
408 writeValue(_out, c[1]);
409 writeValue(_out, c[2]);
410
411 if ( _opt.color_has_alpha() )
412 writeValue(_out, c[3]);
413 }
414 }
415 }
416 }
417 else
418 {
419 for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
420 {
421 //face
422 nV = _be.get_vhandles(FaceHandle(i), vhandles);
423 writeValue(_out, nV);
424 for (size_t j=0; j<vhandles.size(); ++j)
425 writeValue(_out, vhandles[j].idx() );
426
427 //face color
428 if ( _opt.face_has_color() ){
429 if ( _opt.color_is_float() ) {
430 cf = _be.colorAf( FaceHandle(i) );
431 writeValue(_out, cf[0]);
432 writeValue(_out, cf[1]);
433 writeValue(_out, cf[2]);
434
435 if ( _opt.color_has_alpha() )
436 writeValue(_out, cf[3]);
437 } else {
438 c = _be.colorA( FaceHandle(i) );
439 writeValue(_out, c[0]);
440 writeValue(_out, c[1]);
441 writeValue(_out, c[2]);
442
443 if ( _opt.color_has_alpha() )
444 writeValue(_out, c[3]);
445 }
446 }
447 }
448 }
449
450 return true;
451 }
452
453 // ----------------------------------------------------------------------------
454
455
456 size_t
457 _OFFWriter_::
458 binary_size(BaseExporter& _be, Options _opt) const
459 {
460 size_t header(0);
461 size_t data(0);
462
463 size_t _3floats(3*sizeof(float));
464 size_t _3ui(3*sizeof(unsigned int));
465 size_t _4ui(4*sizeof(unsigned int));
466
467 if ( !_opt.is_binary() )
468 return 0;
469 else
470 {
471 size_t _3longs(3*sizeof(long));
472
473 header += 11; // 'OFF BINARY\n'
474 header += _3longs; // #V #F #E
475 data += _be.n_vertices() * _3floats; // vertex data
476 }
477
478 if ( _opt.vertex_has_normal() && _be.has_vertex_normals() )
479 {
480 header += 1; // N
481 data += _be.n_vertices() * _3floats;
482 }
483
484 if ( _opt.vertex_has_color() && _be.has_vertex_colors() )
485 {
486 header += 1; // C
487 data += _be.n_vertices() * _3floats;
488 }
489
490 if ( _opt.vertex_has_texcoord() && _be.has_vertex_texcoords() )
491 {
492 size_t _2floats(2*sizeof(float));
493 header += 2; // ST
494 data += _be.n_vertices() * _2floats;
495 }
496
497 // topology
498 if (_be.is_triangle_mesh())
499 {
500 data += _be.n_faces() * _4ui;
501 }
502 else
503 {
504 unsigned int i, nF;
505 std::vector<VertexHandle> vhandles;
506
507 for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
508 data += _be.get_vhandles(FaceHandle(i), vhandles) * sizeof(unsigned int);
509
510 }
511
512 // face colors
513 if ( _opt.face_has_color() && _be.has_face_colors() ){
514 if ( _opt.color_has_alpha() )
515 data += _be.n_faces() * _4ui;
516 else
517 data += _be.n_faces() * _3ui;
518 }
519
520 return header+data;
521 }
522
523
524 //=============================================================================
525 } // namespace IO
526 } // namespace OpenMesh
527 //=============================================================================
OpenMesh::IO::_OFFWriter_::binary_size
size_t binary_size(BaseExporter &_be, Options _opt) const
Returns expected size of file if binary format is supported else 0.
Definition: OFFWriter.cc:458
OpenMesh::IO::Options::VertexNormal
Has (r) / store (w) vertex normals.
Definition: Options.hh:109
OpenMesh
Definition: MeshItems.hh:64
OpenMesh::IO::_IOManager_::register_module
bool register_module(BaseReader *_bl)
Definition: IOManager.hh:222
OpenMesh::IO::_OFFWriter_
Definition: OFFWriter.hh:97
OpenMesh::IO::Options::FaceNormal
Has (r) / store (w) face normals.
Definition: Options.hh:113
OpenMesh::IO::Options::FaceColor
Has (r) / store (w) face colors.
Definition: Options.hh:114
omstream.hh
OpenMesh::IO::Options::VertexTexCoord
Has (r) / store (w) texture coordinates.
Definition: Options.hh:111
OpenMesh::IO::Options
Set options for reader/writer modules.
Definition: Options.hh:95
config.h
OpenMesh::IO::BaseExporter
Definition: BaseExporter.hh:89
OpenMesh::VectorT< float, 3 >
OpenMesh::VertexHandle
Handle for a vertex entity.
Definition: Handles.hh:125
OpenMesh::IO::float32_t
float float32_t
Definition: SR_types.hh:97
OpenMesh::FaceHandle
Handle for a face entity.
Definition: Handles.hh:146
OpenMesh::IO::Options::Binary
Set binary mode for r/w.
Definition: Options.hh:105
OpenMesh::IO::Options::VertexColor
Has (r) / store (w) vertex colors.
Definition: Options.hh:110
OpenMesh::IO::uint32_t
unsigned int uint32_t
Definition: SR_types.hh:90
OpenMesh::IO::_OFFWriter_::write
bool write(const std::string &, BaseExporter &, Options, std::streamsize _precision=6) const
Definition: OFFWriter.cc:86
OpenMesh::IO::__OFFWriterInstance
_OFFWriter_ __OFFWriterInstance
Declare the single entity of the OFF writer.
Definition: OFFWriter.cc:71
OpenVolumeMesh::Geometry::VectorT
Definition: Vector11T.hh:78
BaseExporter
Definition: BaseExporter.hh:1
OpenMesh::IO::IOManager
_IOManager_ & IOManager()
Definition: IOManager.cc:77