Developer Documentation
OMWriter.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 
48 // -------------------- STL
49 #if defined( OM_CC_MIPS )
50  #include <time.h>
51  #include <string.h>
52 #else
53  #include <ctime>
54  #include <cstring>
55 #endif
56 
57 #include <fstream>
58 #include <vector>
59 
60 // -------------------- OpenMesh
61 #include <OpenMesh/Core/IO/OMFormat.hh>
62 #include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
63 #include <OpenMesh/Core/IO/writer/OMWriter.hh>
64 
65 //=== NAMESPACES ==============================================================
66 
67 
68 namespace OpenMesh {
69 namespace IO {
70 
71 
72 //=== INSTANCIATE =============================================================
73 
74 
75 // register the OMLoader singleton with MeshLoader
77 _OMWriter_& OMWriter() { return __OMWriterInstance; }
78 
79 
80 //=== IMPLEMENTATION ==========================================================
81 
82 
83 const OMFormat::uchar _OMWriter_::magic_[3] = "OM";
84 const OMFormat::uint8 _OMWriter_::version_ = OMFormat::mk_version(2,0);
85 
86 
89 {
90  IOManager().register_module(this);
91 }
92 
93 
94 bool
95 _OMWriter_::write(const std::string& _filename, BaseExporter& _be,
96  Options _opt, std::streamsize /*_precision*/) const
97 {
98  // check whether exporter can give us an OpenMesh BaseKernel
99  if (!_be.kernel()) return false;
100 
101 
102  // check for om extension in filename, we can only handle OM
103  if (_filename.rfind(".om") == std::string::npos)
104  return false;
105 
106  _opt += Options::Binary; // only binary format supported
107 
108  std::ofstream ofs(_filename.c_str(), std::ios::binary);
109 
110  // check if file is open
111  if (!ofs.is_open())
112  {
113  omerr() << "[OMWriter] : cannot open file " << _filename << std::endl;
114  return false;
115  }
116 
117  // call stream save method
118  bool rc = write(ofs, _be, _opt);
119 
120  // close filestream
121  ofs.close();
122 
123  // return success/failure notice
124  return rc;
125 }
126 
127 
128 //-----------------------------------------------------------------------------
129 
130 bool
131 _OMWriter_::write(std::ostream& _os, BaseExporter& _be, Options _opt, std::streamsize /*_precision*/) const
132 {
133 // std::clog << "[OMWriter]::write( stream )\n";
134 
135  // check exporter features
136  if ( !check( _be, _opt ) )
137  {
138  omerr() << "[OMWriter]: exporter does not support wanted feature!\n";
139  return false;
140  }
141 
142  // Maybe an ascii version will be implemented in the future.
143  // For now, support only a binary format
144  if ( !_opt.check( Options::Binary ) )
145  _opt += Options::Binary;
146 
147  // Ignore LSB/MSB bit. Always store in LSB (little endian)
148  _opt += Options::LSB;
149  _opt -= Options::MSB;
150 
151  return write_binary(_os, _be, _opt);
152 }
153 
154 
155 //-----------------------------------------------------------------------------
156 
157 
158 #ifndef DOXY_IGNORE_THIS
159 template <typename T> struct Enabler
160 {
161  explicit Enabler( T& obj ) : obj_(obj)
162  {}
163 
164  ~Enabler() { obj_.enable(); }
165 
166  T& obj_;
167 };
168 #endif
169 
170 
171 bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be,
172  Options _opt) const
173 {
174  #ifndef DOXY_IGNORE_THIS
175  Enabler<mostream> enabler(omlog());
176  #endif
177 
178  size_t bytes = 0;
179 
180  bool swap = _opt.check(Options::Swap) || (Endian::local() == Endian::MSB);
181 
182  unsigned int i, nV, nF;
183  Vec3f v;
184  Vec2f t;
185 
186  // -------------------- write header
187  OMFormat::Header header;
188 
189  header.magic_[0] = 'O';
190  header.magic_[1] = 'M';
191  header.mesh_ = _be.is_triangle_mesh() ? 'T' : 'P';
192  header.version_ = version_;
193  header.n_vertices_ = int(_be.n_vertices());
194  header.n_faces_ = int(_be.n_faces());
195  header.n_edges_ = int(_be.n_edges());
196 
197  bytes += store( _os, header, swap );
198 
199  // ---------------------------------------- write chunks
200 
201  OMFormat::Chunk::Header chunk_header;
202 
203 
204  // -------------------- write vertex data
205 
206  // ---------- write vertex position
207  if (_be.n_vertices())
208  {
209  v = _be.point(VertexHandle(0));
210  chunk_header.reserved_ = 0;
211  chunk_header.name_ = false;
212  chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
213  chunk_header.type_ = OMFormat::Chunk::Type_Pos;
214  chunk_header.signed_ = OMFormat::is_signed(v[0]);
215  chunk_header.float_ = OMFormat::is_float(v[0]);
216  chunk_header.dim_ = OMFormat::dim(v);
217  chunk_header.bits_ = OMFormat::bits(v[0]);
218 
219  bytes += store( _os, chunk_header, swap );
220  for (i=0, nV=header.n_vertices_; i<nV; ++i)
221  bytes += vector_store( _os, _be.point(VertexHandle(i)), swap );
222  }
223 
224 
225  // ---------- write vertex normal
226  if (_be.n_vertices() && _opt.check( Options::VertexNormal ))
227  {
228  Vec3f n = _be.normal(VertexHandle(0));
229 
230  chunk_header.name_ = false;
231  chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
232  chunk_header.type_ = OMFormat::Chunk::Type_Normal;
233  chunk_header.signed_ = OMFormat::is_signed(n[0]);
234  chunk_header.float_ = OMFormat::is_float(n[0]);
235  chunk_header.dim_ = OMFormat::dim(n);
236  chunk_header.bits_ = OMFormat::bits(n[0]);
237 
238  bytes += store( _os, chunk_header, swap );
239  for (i=0, nV=header.n_vertices_; i<nV; ++i)
240  bytes += vector_store( _os, _be.normal(VertexHandle(i)), swap );
241  }
242 
243  // ---------- write vertex color
244  if (_be.n_vertices() && _opt.check( Options::VertexColor ) && _be.has_vertex_colors() )
245  {
246  Vec3uc c = _be.color(VertexHandle(0));
247 
248  chunk_header.name_ = false;
249  chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
250  chunk_header.type_ = OMFormat::Chunk::Type_Color;
251  chunk_header.signed_ = OMFormat::is_signed( c[0] );
252  chunk_header.float_ = OMFormat::is_float( c[0] );
253  chunk_header.dim_ = OMFormat::dim( c );
254  chunk_header.bits_ = OMFormat::bits( c[0] );
255 
256  bytes += store( _os, chunk_header, swap );
257  for (i=0, nV=header.n_vertices_; i<nV; ++i)
258  bytes += vector_store( _os, _be.color(VertexHandle(i)), swap );
259  }
260 
261  // ---------- write vertex texture coords
262  if (_be.n_vertices() && _opt.check(Options::VertexTexCoord)) {
263 
264  t = _be.texcoord(VertexHandle(0));
265 
266  chunk_header.name_ = false;
267  chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
268  chunk_header.type_ = OMFormat::Chunk::Type_Texcoord;
269  chunk_header.signed_ = OMFormat::is_signed(t[0]);
270  chunk_header.float_ = OMFormat::is_float(t[0]);
271  chunk_header.dim_ = OMFormat::dim(t);
272  chunk_header.bits_ = OMFormat::bits(t[0]);
273 
274  // std::clog << chunk_header << std::endl;
275  bytes += store(_os, chunk_header, swap);
276 
277  for (i = 0, nV = header.n_vertices_; i < nV; ++i)
278  bytes += vector_store(_os, _be.texcoord(VertexHandle(i)), swap);
279 
280  }
281 
282  // ---------- wirte halfedge data
283  if (_be.n_edges())
284  {
285  chunk_header.reserved_ = 0;
286  chunk_header.name_ = false;
287  chunk_header.entity_ = OMFormat::Chunk::Entity_Halfedge;
288  chunk_header.type_ = OMFormat::Chunk::Type_Topology;
289  chunk_header.signed_ = true;
290  chunk_header.float_ = true; // TODO: is this correct? This causes a scalar size of 1 in OMFormat.hh scalar_size which we need I think?
291  chunk_header.dim_ = OMFormat::Chunk::Dim_3D;
292  chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4); // *2 due to halfedge ids being stored, *2 due to signedness
293 
294  bytes += store( _os, chunk_header, swap );
295  auto nE=header.n_edges_*2;
296  for (i=0; i<nE; ++i)
297  {
298  auto next_id = _be.get_next_halfedge_id(HalfedgeHandle(static_cast<int>(i)));
299  auto to_vertex_id = _be.get_to_vertex_id(HalfedgeHandle(static_cast<int>(i)));
300  auto face_id = _be.get_face_id(HalfedgeHandle(static_cast<int>(i)));
301 
302  bytes += store( _os, next_id, OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap );
303  bytes += store( _os, to_vertex_id, OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap );
304  bytes += store( _os, face_id, OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap );
305  }
306  }
307 
308  // ---------- write vertex topology (outgoing halfedge)
309  if (_be.n_vertices())
310  {
311  chunk_header.reserved_ = 0;
312  chunk_header.name_ = false;
313  chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
314  chunk_header.type_ = OMFormat::Chunk::Type_Topology;
315  chunk_header.signed_ = true;
316  chunk_header.float_ = true; // TODO: is this correct? This causes a scalar size of 1 in OMFormat.hh scalar_size which we need I think?
317  chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
318  chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4); // *2 due to halfedge ids being stored, *2 due to signedness
319 
320  bytes += store( _os, chunk_header, swap );
321  for (i=0, nV=header.n_vertices_; i<nV; ++i)
322  bytes += store( _os, _be.get_halfedge_id(VertexHandle(i)), OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap );
323  }
324 
325 
326  // -------------------- write face data
327 
328  // ---------- write topology
329  {
330  chunk_header.name_ = false;
331  chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
332  chunk_header.type_ = OMFormat::Chunk::Type_Topology;
333  chunk_header.signed_ = true;
334  chunk_header.float_ = true; // TODO: is this correct? This causes a scalar size of 1 in OMFormat.hh scalar_size which we need I think?
335  chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
336  chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4); // *2 due to halfedge ids being stored, *2 due to signedness
337 
338  bytes += store( _os, chunk_header, swap );
339 
340  for (i=0, nF=header.n_faces_; i<nF; ++i)
341  {
342  auto size = OMFormat::Chunk::Integer_Size(chunk_header.bits_);
343  bytes += store( _os, _be.get_halfedge_id(FaceHandle(i)), size, swap);
344  }
345  }
346 
347  // ---------- write face normals
348 
349  if (_be.n_faces() && _be.has_face_normals() && _opt.check(Options::FaceNormal) )
350  {
351 #define NEW_STYLE 0
352 #if NEW_STYLE
353  const BaseProperty *bp = _be.kernel()._get_fprop("f:normals");
354 
355  if (bp)
356  {
357 #endif
358  Vec3f n = _be.normal(FaceHandle(0));
359 
360  chunk_header.name_ = false;
361  chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
362  chunk_header.type_ = OMFormat::Chunk::Type_Normal;
363  chunk_header.signed_ = OMFormat::is_signed(n[0]);
364  chunk_header.float_ = OMFormat::is_float(n[0]);
365  chunk_header.dim_ = OMFormat::dim(n);
366  chunk_header.bits_ = OMFormat::bits(n[0]);
367 
368  bytes += store( _os, chunk_header, swap );
369 #if !NEW_STYLE
370  for (i=0, nF=header.n_faces_; i<nF; ++i)
371  bytes += vector_store( _os, _be.normal(FaceHandle(i)), swap );
372 #else
373  bytes += bp->store(_os, swap );
374  }
375  else
376  return false;
377 #endif
378 #undef NEW_STYLE
379  }
380 
381 
382  // ---------- write face color
383 
384  if (_be.n_faces() && _be.has_face_colors() && _opt.check( Options::FaceColor ))
385  {
386 #define NEW_STYLE 0
387 #if NEW_STYLE
388  const BaseProperty *bp = _be.kernel()._get_fprop("f:colors");
389 
390  if (bp)
391  {
392 #endif
393  Vec3uc c;
394 
395  chunk_header.name_ = false;
396  chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
397  chunk_header.type_ = OMFormat::Chunk::Type_Color;
398  chunk_header.signed_ = OMFormat::is_signed( c[0] );
399  chunk_header.float_ = OMFormat::is_float( c[0] );
400  chunk_header.dim_ = OMFormat::dim( c );
401  chunk_header.bits_ = OMFormat::bits( c[0] );
402 
403  bytes += store( _os, chunk_header, swap );
404 #if !NEW_STYLE
405  for (i=0, nF=header.n_faces_; i<nF; ++i)
406  bytes += vector_store( _os, _be.color(FaceHandle(i)), swap );
407 #else
408  bytes += bp->store(_os, swap);
409  }
410  else
411  return false;
412 #endif
413  }
414 
415  // ---------- write vertex status
416  if (_be.n_vertices() && _be.has_vertex_status() && _opt.check(Options::Status))
417  {
418  auto s = _be.status(VertexHandle(0));
419  chunk_header.name_ = false;
420  chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
421  chunk_header.type_ = OMFormat::Chunk::Type_Status;
422  chunk_header.signed_ = false;
423  chunk_header.float_ = false;
424  chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
425  chunk_header.bits_ = OMFormat::bits(s);
426 
427  // std::clog << chunk_header << std::endl;
428  bytes += store(_os, chunk_header, swap);
429 
430  for (i = 0, nV = header.n_vertices_; i < nV; ++i)
431  bytes += store(_os, _be.status(VertexHandle(i)), swap);
432  }
433 
434  // ---------- write edge status
435  if (_be.n_edges() && _be.has_edge_status() && _opt.check(Options::Status))
436  {
437  auto s = _be.status(EdgeHandle(0));
438  chunk_header.name_ = false;
439  chunk_header.entity_ = OMFormat::Chunk::Entity_Edge;
440  chunk_header.type_ = OMFormat::Chunk::Type_Status;
441  chunk_header.signed_ = false;
442  chunk_header.float_ = false;
443  chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
444  chunk_header.bits_ = OMFormat::bits(s);
445 
446  // std::clog << chunk_header << std::endl;
447  bytes += store(_os, chunk_header, swap);
448 
449  for (i = 0, nV = header.n_edges_; i < nV; ++i)
450  bytes += store(_os, _be.status(EdgeHandle(i)), swap);
451  }
452 
453  // ---------- write halfedge status
454  if (_be.n_edges() && _be.has_halfedge_status() && _opt.check(Options::Status))
455  {
456  auto s = _be.status(HalfedgeHandle(0));
457  chunk_header.name_ = false;
458  chunk_header.entity_ = OMFormat::Chunk::Entity_Halfedge;
459  chunk_header.type_ = OMFormat::Chunk::Type_Status;
460  chunk_header.signed_ = false;
461  chunk_header.float_ = false;
462  chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
463  chunk_header.bits_ = OMFormat::bits(s);
464 
465  // std::clog << chunk_header << std::endl;
466  bytes += store(_os, chunk_header, swap);
467 
468  for (i = 0, nV = header.n_edges_ * 2; i < nV; ++i)
469  bytes += store(_os, _be.status(HalfedgeHandle(i)), swap);
470  }
471 
472  // ---------- write face status
473  if (_be.n_faces() && _be.has_face_status() && _opt.check(Options::Status))
474  {
475  auto s = _be.status(FaceHandle(0));
476  chunk_header.name_ = false;
477  chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
478  chunk_header.type_ = OMFormat::Chunk::Type_Status;
479  chunk_header.signed_ = false;
480  chunk_header.float_ = false;
481  chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
482  chunk_header.bits_ = OMFormat::bits(s);
483 
484  // std::clog << chunk_header << std::endl;
485  bytes += store(_os, chunk_header, swap);
486 
487  for (i = 0, nV = header.n_faces_; i < nV; ++i)
488  bytes += store(_os, _be.status(FaceHandle(i)), swap);
489  }
490 
491  // -------------------- write custom properties
492 
493 
494  BaseKernel::const_prop_iterator prop;
495 
496  for (prop = _be.kernel()->vprops_begin();
497  prop != _be.kernel()->vprops_end(); ++prop)
498  {
499  if ( !*prop ) continue;
500  if ( (*prop)->name()[1]==':') continue;
501  bytes += store_binary_custom_chunk(_os, **prop,
502  OMFormat::Chunk::Entity_Vertex, swap );
503  }
504  for (prop = _be.kernel()->fprops_begin();
505  prop != _be.kernel()->fprops_end(); ++prop)
506  {
507  if ( !*prop ) continue;
508  if ( (*prop)->name()[1]==':') continue;
509  bytes += store_binary_custom_chunk(_os, **prop,
510  OMFormat::Chunk::Entity_Face, swap );
511  }
512  for (prop = _be.kernel()->eprops_begin();
513  prop != _be.kernel()->eprops_end(); ++prop)
514  {
515  if ( !*prop ) continue;
516  if ( (*prop)->name()[1]==':') continue;
517  bytes += store_binary_custom_chunk(_os, **prop,
518  OMFormat::Chunk::Entity_Edge, swap );
519  }
520  for (prop = _be.kernel()->hprops_begin();
521  prop != _be.kernel()->hprops_end(); ++prop)
522  {
523  if ( !*prop ) continue;
524  if ( (*prop)->name()[1]==':') continue;
525  bytes += store_binary_custom_chunk(_os, **prop,
526  OMFormat::Chunk::Entity_Halfedge, swap );
527  }
528  for (prop = _be.kernel()->mprops_begin();
529  prop != _be.kernel()->mprops_end(); ++prop)
530  {
531  if ( !*prop ) continue;
532  if ( (*prop)->name()[1]==':') continue;
533  bytes += store_binary_custom_chunk(_os, **prop,
534  OMFormat::Chunk::Entity_Mesh, swap );
535  }
536 
537  memset(&chunk_header, 0, sizeof(chunk_header));
538  chunk_header.name_ = false;
539  chunk_header.entity_ = OMFormat::Chunk::Entity_Sentinel;
540  bytes += store(_os, chunk_header, swap);
541 
542  std::clog << "#bytes written: " << bytes << std::endl;
543 
544  return true;
545 }
546 
547 // ----------------------------------------------------------------------------
548 
549 size_t _OMWriter_::store_binary_custom_chunk(std::ostream& _os,
550  const BaseProperty& _bp,
551  OMFormat::Chunk::Entity _entity,
552  bool _swap) const
553 {
554  //omlog() << "Custom Property " << OMFormat::as_string(_entity) << " property ["
555  // << _bp.name() << "]" << std::endl;
556 
557  // Don't store if
558  // 1. it is not persistent
559  // 2. it's name is empty
560  if ( !_bp.persistent() || _bp.name().empty() )
561  {
562  //omlog() << " skipped\n";
563  return 0;
564  }
565 
566  size_t bytes = 0;
567 
568  OMFormat::Chunk::esize_t element_size = OMFormat::Chunk::esize_t(_bp.element_size());
569  OMFormat::Chunk::Header chdr;
570 
571  // set header
572  chdr.name_ = true;
573  chdr.entity_ = _entity;
574  chdr.type_ = OMFormat::Chunk::Type_Custom;
575  chdr.signed_ = 0;
576  chdr.float_ = 0;
577  chdr.dim_ = OMFormat::Chunk::Dim_1D; // ignored
578  chdr.bits_ = element_size;
579 
580 
581  // write custom chunk
582 
583  // 1. chunk header
584  bytes += store( _os, chdr, _swap );
585 
586  // 2. property name
587  bytes += store( _os, OMFormat::Chunk::PropertyName(_bp.name()), _swap );
588 
589  // 3. block size
590  bytes += store( _os, _bp.size_of(), OMFormat::Chunk::Integer_32, _swap );
591  //omlog() << " n_bytes = " << _bp.size_of() << std::endl;
592 
593  // 4. data
594  {
595  size_t b;
596  bytes += ( b=_bp.store( _os, _swap ) );
597  //omlog() << " b = " << b << std::endl;
598  assert( b == _bp.size_of() );
599  }
600  return bytes;
601 }
602 
603 // ----------------------------------------------------------------------------
604 
605 size_t _OMWriter_::binary_size(BaseExporter& /* _be */, Options /* _opt */) const
606 {
607  // std::clog << "[OMWriter]: binary_size()" << std::endl;
608  size_t bytes = sizeof( OMFormat::Header );
609 
610  // !!!TODO!!!
611 
612  return bytes;
613 }
614 
615 //=============================================================================
616 } // namespace IO
617 } // namespace OpenMesh
618 //=============================================================================
Swap byte order in binary mode.
Definition: Options.hh:103
Handle for a edge entity.
Definition: Handles.hh:134
Handle for a face entity.
Definition: Handles.hh:141
size_t binary_size(BaseExporter &_be, Options _opt) const override
Returns expected size of file if binary format is supported else 0.
Definition: OMWriter.cc:605
Assume big endian byte ordering.
Definition: Options.hh:101
Has (r) / store (w) vertex colors.
Definition: Options.hh:105
Has (r) / store (w) face colors.
Definition: Options.hh:109
Handle for a halfedge entity.
Definition: Handles.hh:127
virtual size_t store(std::ostream &_ostr, bool _swap) const =0
Store self as one binary block.
Handle for a vertex entity.
Definition: Handles.hh:120
bool register_module(BaseReader *_bl)
Definition: IOManager.hh:217
bool persistent(void) const
Returns true if the persistent flag is enabled else false.
virtual size_t size_of() const
Return size of property in bytes.
_OMWriter_ __OMWriterInstance
Declare the single entity of the OM writer.
Definition: OMWriter.cc:76
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:90
Has (r) / store (w) status properties.
Definition: Options.hh:114
bool write(std::ostream &, BaseExporter &, Options, std::streamsize _precision=6) const override
Definition: OMWriter.cc:131
Has (r) / store (w) vertex normals.
Definition: Options.hh:104
_IOManager_ & IOManager()
Definition: IOManager.cc:72
Has (r) / store (w) face normals.
Definition: Options.hh:108
big endian (Motorola&#39;s 68x family, DEC Alpha, MIPS)
Definition: Endian.hh:79
Set binary mode for r/w.
Definition: Options.hh:100
_OMWriter_()
Constructor.
Definition: OMWriter.cc:88
Assume little endian byte ordering.
Definition: Options.hh:102
Has (r) / store (w) texture coordinates.
Definition: Options.hh:106
static Type local()
Return endian type of host system.
Definition: Endian.hh:83