49 #if defined( OM_CC_MIPS ) 61 #include <OpenMesh/Core/IO/OMFormat.hh> 62 #include <OpenMesh/Core/IO/exporter/BaseExporter.hh> 63 #include <OpenMesh/Core/IO/writer/OMWriter.hh> 83 const OMFormat::uchar _OMWriter_::magic_[3] =
"OM";
84 const OMFormat::uint8 _OMWriter_::version_ = OMFormat::mk_version(2,0);
96 Options _opt, std::streamsize )
const 99 if (!_be.kernel())
return false;
103 if (_filename.rfind(
".om") == std::string::npos)
108 std::ofstream ofs(_filename.c_str(), std::ios::binary);
113 omerr() <<
"[OMWriter] : cannot open file " << _filename << std::endl;
118 bool rc =
write(ofs, _be, _opt);
136 if ( !check( _be, _opt ) )
138 omerr() <<
"[OMWriter]: exporter does not support wanted feature!\n";
151 return write_binary(_os, _be, _opt);
158 #ifndef DOXY_IGNORE_THIS 159 template <
typename T>
struct Enabler
161 explicit Enabler( T& obj ) : obj_(obj)
164 ~Enabler() { obj_.enable(); }
171 bool _OMWriter_::write_binary(std::ostream& _os,
BaseExporter& _be,
174 #ifndef DOXY_IGNORE_THIS 175 Enabler<mostream> enabler(omlog());
182 unsigned int i, nV, nF;
187 OMFormat::Header header;
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());
197 bytes += store( _os, header, swap );
201 OMFormat::Chunk::Header chunk_header;
207 if (_be.n_vertices())
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]);
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 );
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]);
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 );
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] );
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 );
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]);
275 bytes += store(_os, chunk_header, swap);
277 for (i = 0, nV = header.n_vertices_; i < nV; ++i)
278 bytes += vector_store(_os, _be.texcoord(
VertexHandle(i)), swap);
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;
291 chunk_header.dim_ = OMFormat::Chunk::Dim_3D;
292 chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4);
294 bytes += store( _os, chunk_header, swap );
295 auto nE=header.n_edges_*2;
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)));
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 );
309 if (_be.n_vertices())
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;
317 chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
318 chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4);
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 );
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;
335 chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
336 chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4);
338 bytes += store( _os, chunk_header, swap );
340 for (i=0, nF=header.n_faces_; i<nF; ++i)
342 auto size = OMFormat::Chunk::Integer_Size(chunk_header.bits_);
343 bytes += store( _os, _be.get_halfedge_id(
FaceHandle(i)), size, swap);
353 const BaseProperty *bp = _be.kernel()._get_fprop(
"f:normals");
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]);
368 bytes += store( _os, chunk_header, swap );
370 for (i=0, nF=header.n_faces_; i<nF; ++i)
371 bytes += vector_store( _os, _be.normal(
FaceHandle(i)), swap );
373 bytes += bp->
store(_os, swap );
388 const BaseProperty *bp = _be.kernel()._get_fprop(
"f:colors");
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] );
403 bytes += store( _os, chunk_header, swap );
405 for (i=0, nF=header.n_faces_; i<nF; ++i)
406 bytes += vector_store( _os, _be.color(
FaceHandle(i)), swap );
408 bytes += bp->
store(_os, swap);
416 if (_be.n_vertices() && _be.has_vertex_status() && _opt.check(
Options::Status))
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);
428 bytes += store(_os, chunk_header, swap);
430 for (i = 0, nV = header.n_vertices_; i < nV; ++i)
435 if (_be.n_edges() && _be.has_edge_status() && _opt.check(
Options::Status))
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);
447 bytes += store(_os, chunk_header, swap);
449 for (i = 0, nV = header.n_edges_; i < nV; ++i)
450 bytes += store(_os, _be.status(
EdgeHandle(i)), swap);
454 if (_be.n_edges() && _be.has_halfedge_status() && _opt.check(
Options::Status))
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);
466 bytes += store(_os, chunk_header, swap);
468 for (i = 0, nV = header.n_edges_ * 2; i < nV; ++i)
473 if (_be.n_faces() && _be.has_face_status() && _opt.check(
Options::Status))
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);
485 bytes += store(_os, chunk_header, swap);
487 for (i = 0, nV = header.n_faces_; i < nV; ++i)
488 bytes += store(_os, _be.status(
FaceHandle(i)), swap);
494 BaseKernel::const_prop_iterator prop;
496 for (prop = _be.kernel()->vprops_begin();
497 prop != _be.kernel()->vprops_end(); ++prop)
499 if ( !*prop )
continue;
500 if ( (*prop)->name()[1]==
':')
continue;
501 bytes += store_binary_custom_chunk(_os, **prop,
502 OMFormat::Chunk::Entity_Vertex, swap );
504 for (prop = _be.kernel()->fprops_begin();
505 prop != _be.kernel()->fprops_end(); ++prop)
507 if ( !*prop )
continue;
508 if ( (*prop)->name()[1]==
':')
continue;
509 bytes += store_binary_custom_chunk(_os, **prop,
510 OMFormat::Chunk::Entity_Face, swap );
512 for (prop = _be.kernel()->eprops_begin();
513 prop != _be.kernel()->eprops_end(); ++prop)
515 if ( !*prop )
continue;
516 if ( (*prop)->name()[1]==
':')
continue;
517 bytes += store_binary_custom_chunk(_os, **prop,
518 OMFormat::Chunk::Entity_Edge, swap );
520 for (prop = _be.kernel()->hprops_begin();
521 prop != _be.kernel()->hprops_end(); ++prop)
523 if ( !*prop )
continue;
524 if ( (*prop)->name()[1]==
':')
continue;
525 bytes += store_binary_custom_chunk(_os, **prop,
526 OMFormat::Chunk::Entity_Halfedge, swap );
528 for (prop = _be.kernel()->mprops_begin();
529 prop != _be.kernel()->mprops_end(); ++prop)
531 if ( !*prop )
continue;
532 if ( (*prop)->name()[1]==
':')
continue;
533 bytes += store_binary_custom_chunk(_os, **prop,
534 OMFormat::Chunk::Entity_Mesh, swap );
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);
542 std::clog <<
"#bytes written: " << bytes << std::endl;
549 size_t _OMWriter_::store_binary_custom_chunk(std::ostream& _os,
551 OMFormat::Chunk::Entity _entity,
568 OMFormat::Chunk::esize_t element_size = OMFormat::Chunk::esize_t(_bp.
element_size());
569 OMFormat::Chunk::Header chdr;
573 chdr.entity_ = _entity;
574 chdr.type_ = OMFormat::Chunk::Type_Custom;
577 chdr.dim_ = OMFormat::Chunk::Dim_1D;
578 chdr.bits_ = element_size;
584 bytes += store( _os, chdr, _swap );
587 bytes += store( _os, OMFormat::Chunk::PropertyName(_bp.
name()), _swap );
590 bytes += store( _os, _bp.
size_of(), OMFormat::Chunk::Integer_32, _swap );
596 bytes += ( b=_bp.
store( _os, _swap ) );
608 size_t bytes =
sizeof( OMFormat::Header );
Swap byte order in binary mode.
Handle for a edge entity.
Handle for a face entity.
size_t binary_size(BaseExporter &_be, Options _opt) const override
Returns expected size of file if binary format is supported else 0.
Assume big endian byte ordering.
Has (r) / store (w) vertex colors.
Has (r) / store (w) face colors.
Handle for a halfedge entity.
virtual size_t store(std::ostream &_ostr, bool _swap) const =0
Store self as one binary block.
Handle for a vertex entity.
bool register_module(BaseReader *_bl)
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.
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.
Has (r) / store (w) status properties.
bool write(std::ostream &, BaseExporter &, Options, std::streamsize _precision=6) const override
Has (r) / store (w) vertex normals.
_IOManager_ & IOManager()
Has (r) / store (w) face normals.
big endian (Motorola's 68x family, DEC Alpha, MIPS)
Assume little endian byte ordering.
Has (r) / store (w) texture coordinates.
static Type local()
Return endian type of host system.