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,1);
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());
183 unsigned int i, nV, nF;
189 OMFormat::Header header;
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());
199 bytes += store( _os, header, swap );
203 OMFormat::Chunk::Header chunk_header;
209 if (_be.n_vertices())
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())
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]);
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]);
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 );
236 for (i=0, nV=header.n_vertices_; i<nV; ++i)
237 bytes += vector_store( _os, _be.point(
VertexHandle(i)), swap );
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())
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]);
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]);
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 );
270 for (i=0, nV=header.n_vertices_; i<nV; ++i)
271 bytes += vector_store( _os, _be.normal(
VertexHandle(i)), swap );
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] );
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 );
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]);
307 bytes += store(_os, chunk_header, swap);
309 for (i = 0, nV = header.n_vertices_; i < nV; ++i)
310 bytes += vector_store(_os, _be.texcoord(
VertexHandle(i)), swap);
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;
323 chunk_header.dim_ = OMFormat::Chunk::Dim_3D;
324 chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4);
326 bytes += store( _os, chunk_header, swap );
327 auto nE=header.n_edges_*2;
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)));
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 );
341 if (_be.n_vertices())
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;
349 chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
350 chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4);
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 );
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;
367 chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
368 chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4);
370 bytes += store( _os, chunk_header, swap );
372 for (i=0, nF=header.n_faces_; i<nF; ++i)
374 auto size = OMFormat::Chunk::Integer_Size(chunk_header.bits_);
375 bytes += store( _os, _be.get_halfedge_id(
FaceHandle(i)), size, swap);
385 const BaseProperty *bp = _be.kernel()._get_fprop(
"f:normals");
393 chunk_header.name_ =
false;
394 chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
395 chunk_header.type_ = OMFormat::Chunk::Type_Normal;
397 if (_be.is_normal_double())
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]);
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]);
412 bytes += store( _os, chunk_header, swap );
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 );
418 for (i=0, nF=header.n_faces_; i<nF; ++i)
419 bytes += vector_store( _os, _be.normal(
FaceHandle(i)), swap );
422 bytes += bp->
store(_os, swap );
437 const BaseProperty *bp = _be.kernel()._get_fprop(
"f:colors");
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] );
452 bytes += store( _os, chunk_header, swap );
454 for (i=0, nF=header.n_faces_; i<nF; ++i)
455 bytes += vector_store( _os, _be.color(
FaceHandle(i)), swap );
457 bytes += bp->
store(_os, swap);
465 if (_be.n_vertices() && _be.has_vertex_status() && _opt.check(
Options::Status))
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);
477 bytes += store(_os, chunk_header, swap);
479 for (i = 0, nV = header.n_vertices_; i < nV; ++i)
484 if (_be.n_edges() && _be.has_edge_status() && _opt.check(
Options::Status))
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);
496 bytes += store(_os, chunk_header, swap);
498 for (i = 0, nV = header.n_edges_; i < nV; ++i)
499 bytes += store(_os, _be.status(
EdgeHandle(i)), swap);
503 if (_be.n_edges() && _be.has_halfedge_status() && _opt.check(
Options::Status))
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);
515 bytes += store(_os, chunk_header, swap);
517 for (i = 0, nV = header.n_edges_ * 2; i < nV; ++i)
522 if (_be.n_faces() && _be.has_face_status() && _opt.check(
Options::Status))
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);
534 bytes += store(_os, chunk_header, swap);
536 for (i = 0, nV = header.n_faces_; i < nV; ++i)
537 bytes += store(_os, _be.status(
FaceHandle(i)), swap);
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)
549 for (
auto prop = _it_begin; prop != _it_end; ++prop)
551 if (!*prop || (*prop)->name().empty() ||
552 ((*prop)->name().size() > 1 && (*prop)->name()[1] ==
':'))
556 bytes += store_binary_custom_chunk(_os, **prop, _ent, swap);
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);
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);
583 size_t _OMWriter_::store_binary_custom_chunk(std::ostream& _os,
585 OMFormat::Chunk::Entity _entity,
602 OMFormat::Chunk::esize_t element_size = OMFormat::Chunk::esize_t(_bp.
element_size());
603 OMFormat::Chunk::Header chdr;
607 chdr.entity_ = _entity;
608 chdr.type_ = OMFormat::Chunk::Type_Custom;
611 chdr.dim_ = OMFormat::Chunk::Dim_1D;
612 chdr.bits_ = element_size;
618 bytes += store( _os, chdr, _swap );
621 bytes += store( _os, OMFormat::Chunk::PropertyName(_bp.
name()), _swap );
624 bytes += store( _os, _bp.
size_of(), OMFormat::Chunk::Integer_32, _swap );
630 bytes += ( b=_bp.
store( _os, _swap ) );
642 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.