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,1);
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  const bool swap =
181  _opt.check(Options::Swap) || (Endian::local() == Endian::MSB);
182 
183  unsigned int i, nV, nF;
184  Vec3f v;
185  Vec3d vd;
186  Vec2f t;
187 
188  // -------------------- write header
189  OMFormat::Header header;
190 
191  header.magic_[0] = 'O';
192  header.magic_[1] = 'M';
193  header.mesh_ = _be.is_triangle_mesh() ? 'T' : 'P';
194  header.version_ = version_;
195  header.n_vertices_ = int(_be.n_vertices());
196  header.n_faces_ = int(_be.n_faces());
197  header.n_edges_ = int(_be.n_edges());
198 
199  bytes += store( _os, header, swap );
200 
201  // ---------------------------------------- write chunks
202 
203  OMFormat::Chunk::Header chunk_header;
204 
205 
206  // -------------------- write vertex data
207 
208  // ---------- write vertex position
209  if (_be.n_vertices())
210  {
211  v = _be.point(VertexHandle(0));
212  chunk_header.reserved_ = 0;
213  chunk_header.name_ = false;
214  chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
215  chunk_header.type_ = OMFormat::Chunk::Type_Pos;
216  if (_be.is_point_double())
217  {
218  chunk_header.signed_ = OMFormat::is_signed(vd[0]);
219  chunk_header.float_ = OMFormat::is_float(vd[0]);
220  chunk_header.dim_ = OMFormat::dim(vd);
221  chunk_header.bits_ = OMFormat::bits(vd[0]);
222  }
223  else
224  {
225  chunk_header.signed_ = OMFormat::is_signed(v[0]);
226  chunk_header.float_ = OMFormat::is_float(v[0]);
227  chunk_header.dim_ = OMFormat::dim(v);
228  chunk_header.bits_ = OMFormat::bits(v[0]);
229  }
230 
231  bytes += store( _os, chunk_header, swap );
232  if (_be.is_point_double())
233  for (i=0, nV=header.n_vertices_; i<nV; ++i)
234  bytes += vector_store( _os, _be.pointd(VertexHandle(i)), swap );
235  else
236  for (i=0, nV=header.n_vertices_; i<nV; ++i)
237  bytes += vector_store( _os, _be.point(VertexHandle(i)), swap );
238  }
239 
240 
241  // ---------- write vertex normal
242  if (_be.n_vertices() && _opt.check( Options::VertexNormal ))
243  {
244  Vec3f n = _be.normal(VertexHandle(0));
245  Vec3d nd = _be.normald(VertexHandle(0));
246 
247  chunk_header.name_ = false;
248  chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
249  chunk_header.type_ = OMFormat::Chunk::Type_Normal;
250  if (_be.is_normal_double())
251  {
252  chunk_header.signed_ = OMFormat::is_signed(nd[0]);
253  chunk_header.float_ = OMFormat::is_float(nd[0]);
254  chunk_header.dim_ = OMFormat::dim(nd);
255  chunk_header.bits_ = OMFormat::bits(nd[0]);
256  }
257  else
258  {
259  chunk_header.signed_ = OMFormat::is_signed(n[0]);
260  chunk_header.float_ = OMFormat::is_float(n[0]);
261  chunk_header.dim_ = OMFormat::dim(n);
262  chunk_header.bits_ = OMFormat::bits(n[0]);
263  }
264 
265  bytes += store( _os, chunk_header, swap );
266  if (_be.is_normal_double())
267  for (i=0, nV=header.n_vertices_; i<nV; ++i)
268  bytes += vector_store( _os, _be.normald(VertexHandle(i)), swap );
269  else
270  for (i=0, nV=header.n_vertices_; i<nV; ++i)
271  bytes += vector_store( _os, _be.normal(VertexHandle(i)), swap );
272 
273  }
274 
275  // ---------- write vertex color
276  if (_be.n_vertices() && _opt.check( Options::VertexColor ) && _be.has_vertex_colors() )
277  {
278  Vec3uc c = _be.color(VertexHandle(0));
279 
280  chunk_header.name_ = false;
281  chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
282  chunk_header.type_ = OMFormat::Chunk::Type_Color;
283  chunk_header.signed_ = OMFormat::is_signed( c[0] );
284  chunk_header.float_ = OMFormat::is_float( c[0] );
285  chunk_header.dim_ = OMFormat::dim( c );
286  chunk_header.bits_ = OMFormat::bits( c[0] );
287 
288  bytes += store( _os, chunk_header, swap );
289  for (i=0, nV=header.n_vertices_; i<nV; ++i)
290  bytes += vector_store( _os, _be.color(VertexHandle(i)), swap );
291  }
292 
293  // ---------- write vertex texture coords
294  if (_be.n_vertices() && _opt.check(Options::VertexTexCoord)) {
295 
296  t = _be.texcoord(VertexHandle(0));
297 
298  chunk_header.name_ = false;
299  chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
300  chunk_header.type_ = OMFormat::Chunk::Type_Texcoord;
301  chunk_header.signed_ = OMFormat::is_signed(t[0]);
302  chunk_header.float_ = OMFormat::is_float(t[0]);
303  chunk_header.dim_ = OMFormat::dim(t);
304  chunk_header.bits_ = OMFormat::bits(t[0]);
305 
306  // std::clog << chunk_header << std::endl;
307  bytes += store(_os, chunk_header, swap);
308 
309  for (i = 0, nV = header.n_vertices_; i < nV; ++i)
310  bytes += vector_store(_os, _be.texcoord(VertexHandle(i)), swap);
311 
312  }
313 
314  // ---------- wirte halfedge data
315  if (_be.n_edges())
316  {
317  chunk_header.reserved_ = 0;
318  chunk_header.name_ = false;
319  chunk_header.entity_ = OMFormat::Chunk::Entity_Halfedge;
320  chunk_header.type_ = OMFormat::Chunk::Type_Topology;
321  chunk_header.signed_ = true;
322  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?
323  chunk_header.dim_ = OMFormat::Chunk::Dim_3D;
324  chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4); // *2 due to halfedge ids being stored, *2 due to signedness
325 
326  bytes += store( _os, chunk_header, swap );
327  auto nE=header.n_edges_*2;
328  for (i=0; i<nE; ++i)
329  {
330  auto next_id = _be.get_next_halfedge_id(HalfedgeHandle(static_cast<int>(i)));
331  auto to_vertex_id = _be.get_to_vertex_id(HalfedgeHandle(static_cast<int>(i)));
332  auto face_id = _be.get_face_id(HalfedgeHandle(static_cast<int>(i)));
333 
334  bytes += store( _os, next_id, OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap );
335  bytes += store( _os, to_vertex_id, OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap );
336  bytes += store( _os, face_id, OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap );
337  }
338  }
339 
340  // ---------- write vertex topology (outgoing halfedge)
341  if (_be.n_vertices())
342  {
343  chunk_header.reserved_ = 0;
344  chunk_header.name_ = false;
345  chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
346  chunk_header.type_ = OMFormat::Chunk::Type_Topology;
347  chunk_header.signed_ = true;
348  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?
349  chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
350  chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4); // *2 due to halfedge ids being stored, *2 due to signedness
351 
352  bytes += store( _os, chunk_header, swap );
353  for (i=0, nV=header.n_vertices_; i<nV; ++i)
354  bytes += store( _os, _be.get_halfedge_id(VertexHandle(i)), OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap );
355  }
356 
357 
358  // -------------------- write face data
359 
360  // ---------- write topology
361  {
362  chunk_header.name_ = false;
363  chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
364  chunk_header.type_ = OMFormat::Chunk::Type_Topology;
365  chunk_header.signed_ = true;
366  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?
367  chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
368  chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4); // *2 due to halfedge ids being stored, *2 due to signedness
369 
370  bytes += store( _os, chunk_header, swap );
371 
372  for (i=0, nF=header.n_faces_; i<nF; ++i)
373  {
374  auto size = OMFormat::Chunk::Integer_Size(chunk_header.bits_);
375  bytes += store( _os, _be.get_halfedge_id(FaceHandle(i)), size, swap);
376  }
377  }
378 
379  // ---------- write face normals
380 
381  if (_be.n_faces() && _be.has_face_normals() && _opt.check(Options::FaceNormal) )
382  {
383 #define NEW_STYLE 0
384 #if NEW_STYLE
385  const BaseProperty *bp = _be.kernel()._get_fprop("f:normals");
386 
387  if (bp)
388  {
389 #endif
390  Vec3f n = _be.normal(FaceHandle(0));
391  Vec3d nd = _be.normald(FaceHandle(0));
392 
393  chunk_header.name_ = false;
394  chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
395  chunk_header.type_ = OMFormat::Chunk::Type_Normal;
396 
397  if (_be.is_normal_double())
398  {
399  chunk_header.signed_ = OMFormat::is_signed(nd[0]);
400  chunk_header.float_ = OMFormat::is_float(nd[0]);
401  chunk_header.dim_ = OMFormat::dim(nd);
402  chunk_header.bits_ = OMFormat::bits(nd[0]);
403  }
404  else
405  {
406  chunk_header.signed_ = OMFormat::is_signed(n[0]);
407  chunk_header.float_ = OMFormat::is_float(n[0]);
408  chunk_header.dim_ = OMFormat::dim(n);
409  chunk_header.bits_ = OMFormat::bits(n[0]);
410  }
411 
412  bytes += store( _os, chunk_header, swap );
413 #if !NEW_STYLE
414  if (_be.is_normal_double())
415  for (i=0, nF=header.n_faces_; i<nF; ++i)
416  bytes += vector_store( _os, _be.normald(FaceHandle(i)), swap );
417  else
418  for (i=0, nF=header.n_faces_; i<nF; ++i)
419  bytes += vector_store( _os, _be.normal(FaceHandle(i)), swap );
420 
421 #else
422  bytes += bp->store(_os, swap );
423  }
424  else
425  return false;
426 #endif
427 #undef NEW_STYLE
428  }
429 
430 
431  // ---------- write face color
432 
433  if (_be.n_faces() && _be.has_face_colors() && _opt.check( Options::FaceColor ))
434  {
435 #define NEW_STYLE 0
436 #if NEW_STYLE
437  const BaseProperty *bp = _be.kernel()._get_fprop("f:colors");
438 
439  if (bp)
440  {
441 #endif
442  Vec3uc c;
443 
444  chunk_header.name_ = false;
445  chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
446  chunk_header.type_ = OMFormat::Chunk::Type_Color;
447  chunk_header.signed_ = OMFormat::is_signed( c[0] );
448  chunk_header.float_ = OMFormat::is_float( c[0] );
449  chunk_header.dim_ = OMFormat::dim( c );
450  chunk_header.bits_ = OMFormat::bits( c[0] );
451 
452  bytes += store( _os, chunk_header, swap );
453 #if !NEW_STYLE
454  for (i=0, nF=header.n_faces_; i<nF; ++i)
455  bytes += vector_store( _os, _be.color(FaceHandle(i)), swap );
456 #else
457  bytes += bp->store(_os, swap);
458  }
459  else
460  return false;
461 #endif
462  }
463 
464  // ---------- write vertex status
465  if (_be.n_vertices() && _be.has_vertex_status() && _opt.check(Options::Status))
466  {
467  auto s = _be.status(VertexHandle(0));
468  chunk_header.name_ = false;
469  chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
470  chunk_header.type_ = OMFormat::Chunk::Type_Status;
471  chunk_header.signed_ = false;
472  chunk_header.float_ = false;
473  chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
474  chunk_header.bits_ = OMFormat::bits(s);
475 
476  // std::clog << chunk_header << std::endl;
477  bytes += store(_os, chunk_header, swap);
478 
479  for (i = 0, nV = header.n_vertices_; i < nV; ++i)
480  bytes += store(_os, _be.status(VertexHandle(i)), swap);
481  }
482 
483  // ---------- write edge status
484  if (_be.n_edges() && _be.has_edge_status() && _opt.check(Options::Status))
485  {
486  auto s = _be.status(EdgeHandle(0));
487  chunk_header.name_ = false;
488  chunk_header.entity_ = OMFormat::Chunk::Entity_Edge;
489  chunk_header.type_ = OMFormat::Chunk::Type_Status;
490  chunk_header.signed_ = false;
491  chunk_header.float_ = false;
492  chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
493  chunk_header.bits_ = OMFormat::bits(s);
494 
495  // std::clog << chunk_header << std::endl;
496  bytes += store(_os, chunk_header, swap);
497 
498  for (i = 0, nV = header.n_edges_; i < nV; ++i)
499  bytes += store(_os, _be.status(EdgeHandle(i)), swap);
500  }
501 
502  // ---------- write halfedge status
503  if (_be.n_edges() && _be.has_halfedge_status() && _opt.check(Options::Status))
504  {
505  auto s = _be.status(HalfedgeHandle(0));
506  chunk_header.name_ = false;
507  chunk_header.entity_ = OMFormat::Chunk::Entity_Halfedge;
508  chunk_header.type_ = OMFormat::Chunk::Type_Status;
509  chunk_header.signed_ = false;
510  chunk_header.float_ = false;
511  chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
512  chunk_header.bits_ = OMFormat::bits(s);
513 
514  // std::clog << chunk_header << std::endl;
515  bytes += store(_os, chunk_header, swap);
516 
517  for (i = 0, nV = header.n_edges_ * 2; i < nV; ++i)
518  bytes += store(_os, _be.status(HalfedgeHandle(i)), swap);
519  }
520 
521  // ---------- write face status
522  if (_be.n_faces() && _be.has_face_status() && _opt.check(Options::Status))
523  {
524  auto s = _be.status(FaceHandle(0));
525  chunk_header.name_ = false;
526  chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
527  chunk_header.type_ = OMFormat::Chunk::Type_Status;
528  chunk_header.signed_ = false;
529  chunk_header.float_ = false;
530  chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
531  chunk_header.bits_ = OMFormat::bits(s);
532 
533  // std::clog << chunk_header << std::endl;
534  bytes += store(_os, chunk_header, swap);
535 
536  for (i = 0, nV = header.n_faces_; i < nV; ++i)
537  bytes += store(_os, _be.status(FaceHandle(i)), swap);
538  }
539 
540  // -------------------- write custom properties
541 
542 
543 
544  const auto store_property = [this, &_os, swap, &bytes](
545  const BaseKernel::const_prop_iterator _it_begin,
546  const BaseKernel::const_prop_iterator _it_end,
547  const OMFormat::Chunk::Entity _ent)
548  {
549  for (auto prop = _it_begin; prop != _it_end; ++prop)
550  {
551  if (!*prop || (*prop)->name().empty() ||
552  ((*prop)->name().size() > 1 && (*prop)->name()[1] == ':'))
553  { // skip dead and "private" properties (no name or name matches "?:*")
554  continue;
555  }
556  bytes += store_binary_custom_chunk(_os, **prop, _ent, swap);
557  }
558  };
559 
560  store_property(_be.kernel()->vprops_begin(), _be.kernel()->vprops_end(),
561  OMFormat::Chunk::Entity_Vertex);
562  store_property(_be.kernel()->fprops_begin(), _be.kernel()->fprops_end(),
563  OMFormat::Chunk::Entity_Face);
564  store_property(_be.kernel()->eprops_begin(), _be.kernel()->eprops_end(),
565  OMFormat::Chunk::Entity_Edge);
566  store_property(_be.kernel()->hprops_begin(), _be.kernel()->hprops_end(),
567  OMFormat::Chunk::Entity_Halfedge);
568  store_property(_be.kernel()->mprops_begin(), _be.kernel()->mprops_end(),
569  OMFormat::Chunk::Entity_Mesh);
570 
571  memset(&chunk_header, 0, sizeof(chunk_header));
572  chunk_header.name_ = false;
573  chunk_header.entity_ = OMFormat::Chunk::Entity_Sentinel;
574  bytes += store(_os, chunk_header, swap);
575 
576 // std::clog << "#bytes written: " << bytes << std::endl;
577 
578  return true;
579 }
580 
581 // ----------------------------------------------------------------------------
582 
583 size_t _OMWriter_::store_binary_custom_chunk(std::ostream& _os,
584  const BaseProperty& _bp,
585  OMFormat::Chunk::Entity _entity,
586  bool _swap) const
587 {
588  //omlog() << "Custom Property " << OMFormat::as_string(_entity) << " property ["
589  // << _bp.name() << "]" << std::endl;
590 
591  // Don't store if
592  // 1. it is not persistent
593  // 2. it's name is empty
594  if ( !_bp.persistent() || _bp.name().empty() )
595  {
596  //omlog() << " skipped\n";
597  return 0;
598  }
599 
600  size_t bytes = 0;
601 
602  OMFormat::Chunk::esize_t element_size = OMFormat::Chunk::esize_t(_bp.element_size());
603  OMFormat::Chunk::Header chdr;
604 
605  // set header
606  chdr.name_ = true;
607  chdr.entity_ = _entity;
608  chdr.type_ = OMFormat::Chunk::Type_Custom;
609  chdr.signed_ = 0;
610  chdr.float_ = 0;
611  chdr.dim_ = OMFormat::Chunk::Dim_1D; // ignored
612  chdr.bits_ = element_size;
613 
614 
615  // write custom chunk
616 
617  // 1. chunk header
618  bytes += store( _os, chdr, _swap );
619 
620  // 2. property name
621  bytes += store( _os, OMFormat::Chunk::PropertyName(_bp.name()), _swap );
622 
623  // 3. block size
624  bytes += store( _os, _bp.size_of(), OMFormat::Chunk::Integer_32, _swap );
625  //omlog() << " n_bytes = " << _bp.size_of() << std::endl;
626 
627  // 4. data
628  {
629  size_t b;
630  bytes += ( b=_bp.store( _os, _swap ) );
631  //omlog() << " b = " << b << std::endl;
632  assert( b == _bp.size_of() );
633  }
634  return bytes;
635 }
636 
637 // ----------------------------------------------------------------------------
638 
639 size_t _OMWriter_::binary_size(BaseExporter& /* _be */, Options /* _opt */) const
640 {
641  // std::clog << "[OMWriter]: binary_size()" << std::endl;
642  size_t bytes = sizeof( OMFormat::Header );
643 
644  // !!!TODO!!!
645 
646  return bytes;
647 }
648 
649 //=============================================================================
650 } // namespace IO
651 } // namespace OpenMesh
652 //=============================================================================
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:639
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