First checkin for OpenMesh 2.0

git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@2 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
Jan Möbius
2009-02-06 13:37:46 +00:00
parent c3321ebdd9
commit 97f515985d
417 changed files with 76182 additions and 0 deletions

17
Core/IO/ACGMakefile Normal file
View File

@@ -0,0 +1,17 @@
#== SYSTEM PART -- DON'T TOUCH ==============================================
include $(ACGMAKE)/Config
#==============================================================================
SUBDIRS = $(call find-subdirs)
PACKAGES :=
PROJ_LIBS :=
MODULES := cxxlib
#== SYSTEM PART -- DON'T TOUCH ==============================================
include $(ACGMAKE)/Rules
#==============================================================================

179
Core/IO/BinaryHelper.cc Normal file
View File

@@ -0,0 +1,179 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 1801 $
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
//
//=============================================================================
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
// -------------------- STL
#include <algorithm>
// -------------------- OpenMesh
#include <OpenMesh/Core/IO/BinaryHelper.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
#ifndef DOXY_IGNORE_THIS
//== IMPLEMENTATION ===========================================================
union u1 { short int s; unsigned char c[2]; } sc;
union u2 { int i; unsigned char c[4]; } ic;
union u3 { float f; unsigned char c[4]; } fc;
union u4 { double d; unsigned char c[8]; } dc;
//-----------------------------------------------------------------------------
short int read_short(FILE* _in, bool _swap)
{
fread((char*)sc.c, 1, 2, _in);
if (_swap) std::swap(sc.c[0], sc.c[1]);
return sc.s;
}
//-----------------------------------------------------------------------------
int read_int(FILE* _in, bool _swap)
{
fread((char*)ic.c, 1, 4, _in);
if (_swap) {
std::swap(ic.c[0], ic.c[3]);
std::swap(ic.c[1], ic.c[2]);
}
return ic.i;
}
//-----------------------------------------------------------------------------
float read_float(FILE* _in, bool _swap)
{
fread((char*)fc.c, 1, 4, _in);
if (_swap) {
std::swap(fc.c[0], fc.c[3]);
std::swap(fc.c[1], fc.c[2]);
}
return fc.f;
}
//-----------------------------------------------------------------------------
double read_double(FILE* _in, bool _swap)
{
fread((char*)dc.c, 1, 8, _in);
if (_swap) {
std::swap(dc.c[0], dc.c[7]);
std::swap(dc.c[1], dc.c[6]);
std::swap(dc.c[2], dc.c[5]);
std::swap(dc.c[3], dc.c[4]);
}
return dc.d;
}
//-----------------------------------------------------------------------------
void write_short(short int _i, FILE* _out, bool _swap)
{
sc.s = _i;
if (_swap) std::swap(sc.c[0], sc.c[1]);
fwrite((char*)sc.c, 1, 2, _out);
}
//-----------------------------------------------------------------------------
void write_int(int _i, FILE* _out, bool _swap)
{
ic.i = _i;
if (_swap) {
std::swap(ic.c[0], ic.c[3]);
std::swap(ic.c[1], ic.c[2]);
}
fwrite((char*)ic.c, 1, 4, _out);
}
//-----------------------------------------------------------------------------
void write_float(float _f, FILE* _out, bool _swap)
{
fc.f = _f;
if (_swap) {
std::swap(fc.c[0], fc.c[3]);
std::swap(fc.c[1], fc.c[2]);
}
fwrite((char*)fc.c, 1, 4, _out);
}
//-----------------------------------------------------------------------------
void write_double(double _d, FILE* _out, bool _swap)
{
dc.d = _d;
if (_swap) {
std::swap(dc.c[0], dc.c[7]);
std::swap(dc.c[1], dc.c[6]);
std::swap(dc.c[2], dc.c[5]);
std::swap(dc.c[3], dc.c[4]);
}
fwrite((char*)dc.c, 1, 8, _out);
}
#endif
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

115
Core/IO/BinaryHelper.hh Normal file
View File

@@ -0,0 +1,115 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 1801 $
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
//
//=============================================================================
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#ifndef OPENMESH_BINARY_HELPER_HH
#define OPENMESH_BINARY_HELPER_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
// -------------------- STL
#if defined( OM_CC_MIPS )
# include <stdio.h>
#else
# include <cstdio>
#endif
#include <iostream>
// -------------------- OpenMesh
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
/** \name Handling binary input/output.
These functions take care of swapping bytes to get the right Endian.
*/
//@{
//-----------------------------------------------------------------------------
/** Binary read a \c short from \c _is and perform byte swapping if
\c _swap is true */
short int read_short(FILE* _in, bool _swap=false);
/** Binary read an \c int from \c _is and perform byte swapping if
\c _swap is true */
int read_int(FILE* _in, bool _swap=false);
/** Binary read a \c float from \c _is and perform byte swapping if
\c _swap is true */
float read_float(FILE* _in, bool _swap=false);
/** Binary read a \c double from \c _is and perform byte swapping if
\c _swap is true */
double read_double(FILE* _in, bool _swap=false);
/** Binary write a \c short to \c _os and perform byte swapping if
\c _swap is true */
void write_short(short int _i, FILE* _out, bool _swap=false);
/** Binary write an \c int to \c _os and perform byte swapping if
\c _swap is true */
void write_int(int _i, FILE* _out, bool _swap=false);
/** Binary write a \c float to \c _os and perform byte swapping if
\c _swap is true */
void write_float(float _f, FILE* _out, bool _swap=false);
/** Binary write a \c double to \c _os and perform byte swapping if
\c _swap is true */
void write_double(double _d, FILE* _out, bool _swap=false);
//@}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_MESHREADER_HH defined
//=============================================================================

91
Core/IO/IOInstances.hh Normal file
View File

@@ -0,0 +1,91 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Helper file for static builds
//
// In opposite to dynamic builds where the instance of every reader module
// is generated within the OpenMesh library, static builds only instanciate
// objects that are at least referenced once. As all reader modules are
// never used directly, they will not be part of a static build, hence
// this file.
//
//=============================================================================
#ifndef __IOINSTANCES_HH__
#define __IOINSTANCES_HH__
#if defined(OM_STATIC_BUILD) || defined(ARCH_DARWIN)
//=============================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
#include <OpenMesh/Core/IO/reader/OBJReader.hh>
#include <OpenMesh/Core/IO/reader/OFFReader.hh>
#include <OpenMesh/Core/IO/reader/PLYReader.hh>
#include <OpenMesh/Core/IO/reader/STLReader.hh>
#include <OpenMesh/Core/IO/reader/OMReader.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
#include <OpenMesh/Core/IO/writer/OBJWriter.hh>
#include <OpenMesh/Core/IO/writer/OFFWriter.hh>
#include <OpenMesh/Core/IO/writer/STLWriter.hh>
#include <OpenMesh/Core/IO/writer/OMWriter.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
// Instanciate every Reader module
static BaseReader* OFFReaderInstance = &OFFReader();
static BaseReader* OBJReaderInstance = &OBJReader();
static BaseReader* PLYReaderInstance = &PLYReader();
static BaseReader* STLReaderInstance = &STLReader();
static BaseReader* OMReaderInstance = &OMReader();
// Instanciate every writer module
static BaseWriter* OBJWriterInstance = &OBJWriter();
static BaseWriter* OFFWriterInstance = &OFFWriter();
static BaseWriter* STLWriterInstance = &STLWriter();
static BaseWriter* OMWriterInstance = &OMWriter();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif // static ?
#endif //__IOINSTANCES_HH__
//=============================================================================

243
Core/IO/IOManager.cc Normal file
View File

@@ -0,0 +1,243 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements the OpenMesh IOManager singleton
//
//=============================================================================
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/IOManager.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
_IOManager_ *__IOManager_instance = 0;
_IOManager_& IOManager()
{
if (!__IOManager_instance) __IOManager_instance = new _IOManager_();
return *__IOManager_instance;
}
//-----------------------------------------------------------------------------
bool
_IOManager_::
read(const std::string& _filename, BaseImporter& _bi, Options& _opt)
{
std::set<BaseReader*>::const_iterator it = reader_modules_.begin();
std::set<BaseReader*>::const_iterator it_end = reader_modules_.end();
// Try all registered modules
for(; it != it_end; ++it)
if ((*it)->can_u_read(_filename))
{
_bi.prepare();
bool ok = (*it)->read(_filename, _bi, _opt);
_bi.finish();
return ok;
}
// All modules failed to read
return false;
}
//-----------------------------------------------------------------------------
bool
_IOManager_::
write(const std::string& _filename, BaseExporter& _be, Options _opt)
{
std::set<BaseWriter*>::const_iterator it = writer_modules_.begin();
std::set<BaseWriter*>::const_iterator it_end = writer_modules_.end();
if ( it == it_end )
{
omerr() << "[OpenMesh::IO::_IOManager_] No writing modules available!\n";
return false;
}
// Try all registered modules
for(; it != it_end; ++it)
{
if ((*it)->can_u_write(_filename))
{
return (*it)->write(_filename, _be, _opt);
}
}
// All modules failed to save
return false;
}
//-----------------------------------------------------------------------------
bool
_IOManager_::
can_read( const std::string& _format ) const
{
std::set<BaseReader*>::const_iterator it = reader_modules_.begin();
std::set<BaseReader*>::const_iterator it_end = reader_modules_.end();
std::string filename = "dummy." + _format;
for(; it != it_end; ++it)
if ((*it)->can_u_read(filename))
return true;
return false;
}
//-----------------------------------------------------------------------------
bool
_IOManager_::
can_write( const std::string& _format ) const
{
std::set<BaseWriter*>::const_iterator it = writer_modules_.begin();
std::set<BaseWriter*>::const_iterator it_end = writer_modules_.end();
std::string filename = "dummy." + _format;
// Try all registered modules
for(; it != it_end; ++it)
if ((*it)->can_u_write(filename))
return true;
return false;
}
//-----------------------------------------------------------------------------
const BaseWriter*
_IOManager_::
find_writer(const std::string& _format)
{
using std::string;
string::size_type dot = _format.rfind('.');
string ext;
if (dot == string::npos)
ext = _format;
else
ext = _format.substr(dot+1,_format.length()-(dot+1));
std::set<BaseWriter*>::const_iterator it = writer_modules_.begin();
std::set<BaseWriter*>::const_iterator it_end = writer_modules_.end();
std::string filename = "dummy." + ext;
// Try all registered modules
for(; it != it_end; ++it)
if ((*it)->can_u_write(filename))
return *it;
return NULL;
}
//-----------------------------------------------------------------------------
void
_IOManager_::
update_read_filters()
{
std::set<BaseReader*>::const_iterator it = reader_modules_.begin(),
it_end = reader_modules_.end();
std::string s, all, filters;
for(; it != it_end; ++it)
{
filters += (*it)->get_description() + " (";
std::istringstream iss((*it)->get_extensions());
while (iss && !iss.eof() && (iss >> s))
{ s = " *." + s; filters += s; all += s; }
filters += " );;";
}
all = "All files ( " + all + " );;";
read_filters_ = all + filters;
}
//-----------------------------------------------------------------------------
void
_IOManager_::
update_write_filters()
{
std::set<BaseWriter*>::const_iterator it = writer_modules_.begin(),
it_end = writer_modules_.end();
std::string s, all, filters;
for(; it != it_end; ++it)
{
filters += (*it)->get_description() + " (";
std::istringstream iss((*it)->get_extensions());
while (iss && !iss.eof() && (iss >> s))
{ s = " *." + s; filters += s; all += s; }
filters += " );;";
}
all = "All files ( " + all + " );;";
write_filters_ = all + filters;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

224
Core/IO/IOManager.hh Normal file
View File

@@ -0,0 +1,224 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
// $Id: IOManager.hh,v 1.2 2007-05-18 15:17:34 habbecke Exp $
//=============================================================================
//
// Implements the OpenMesh IOManager singleton
//
//=============================================================================
#ifndef __IOMANAGER_HH__
#define __IOMANAGER_HH__
//=== INCLUDES ================================================================
// STL
#include <iostream>
#include <sstream>
#include <string>
#include <set>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/Options.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
#include <OpenMesh/Core/Utils/SingletonT.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/** This is the real IOManager class that is later encapsulated by
SingletonT to enforce its uniqueness. _IOManager_ is not meant to be used
directly by the programmer - the IOManager alias exists for this task.
All reader/writer modules register themselves at this class. For
reading or writing data all modules are asked to do the job. If no
suitable module is found, an error is returned.
For the sake of reading, the target data structure is hidden
behind the BaseImporter interface that takes care of adding
vertices or faces.
Writing from a source structure is encapsulate similarly behind a
BaseExporter interface, providing iterators over vertices/faces to
the writer modules.
\see \ref mesh_io
*/
class _IOManager_
{
private:
_IOManager_() {}
friend _IOManager_& IOManager();
public:
/**
Read a mesh from file _filename. The target data structure is specified
by the given BaseImporter. The \c read method consecutively queries all
of its reader modules. True is returned upon success, false if all
reader modules failed to interprete _filename.
*/
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt);
/** Write a mesh to file _filename. The source data structure is specified
by the given BaseExporter. The \c save method consecutively queries all
of its writer modules. True is returned upon success, false if all
writer modules failed to write the requested format.
Options is determined by _filename's extension.
*/
bool write(const std::string& _filename,
BaseExporter& _be,
Options _opt=Options::Default);
/// Returns true if the format is supported by one of the reader modules.
bool can_read( const std::string& _format ) const;
/// Returns true if the format is supported by one of the writer modules.
bool can_write( const std::string& _format ) const;
size_t binary_size(const std::string& _format,
BaseExporter& _be,
Options _opt = Options::Default)
{
const BaseWriter *bw = find_writer(_format);
return bw ? bw->binary_size(_be,_opt) : 0;
}
public: //-- QT convenience function ------------------------------------------
/** Returns all readable file extension + descriptions in one string.
File formats are separated by <c>;;</c>.
Convenience function for Qt file dialogs.
*/
const std::string& qt_read_filters() const { return read_filters_; }
/** Returns all writeable file extension + descriptions in one string.
File formats are separated by <c>;;</c>.
Convenience function for Qt file dialogs.
*/
const std::string& qt_write_filters() const { return write_filters_; }
private:
// collect all readable file extensions
void update_read_filters();
// collect all writeable file extensions
void update_write_filters();
public: //-- SYSTEM PART------------------------------------------------------
/** Registers a new reader module. A call to this function should be
implemented in the constructor of all classes derived from BaseReader.
*/
bool register_module(BaseReader* _bl)
{
reader_modules_.insert(_bl);
update_read_filters();
return true;
}
/** Registers a new writer module. A call to this function should be
implemented in the constructor of all classed derived from BaseWriter.
*/
bool register_module(BaseWriter* _bw)
{
writer_modules_.insert(_bw);
update_write_filters();
return true;
}
private:
const BaseWriter *find_writer(const std::string& _format);
// stores registered reader modules
std::set<BaseReader*> reader_modules_;
// stores registered writer modules
std::set<BaseWriter*> writer_modules_;
// input filters (e.g. for Qt file dialog)
std::string read_filters_;
// output filters (e.g. for Qt file dialog)
std::string write_filters_;
};
//=============================================================================
extern _IOManager_* __IOManager_instance;
_IOManager_& IOManager();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

134
Core/IO/MeshIO.hh Normal file
View File

@@ -0,0 +1,134 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
#ifndef OM_MESHIO_HH
#define OM_MESHIO_HH
//=== INCLUDES ================================================================
// -------------------- system settings
#include <OpenMesh/Core/System/config.h>
// -------------------- check include order
#if defined (OPENMESH_TRIMESH_ARRAY_KERNEL_HH) || \
defined (OPENMESH_POLYMESH_ARRAY_KERNEL_HH)
# error "Include MeshIO.hh before including a mesh type!"
#endif
// -------------------- OpenMesh
#include <OpenMesh/Core/IO/SR_store.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/IO/importer/ImporterT.hh>
#include <OpenMesh/Core/IO/exporter/ExporterT.hh>
//== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/** \name Mesh Reading / Writing
Convenience functions the map to IOManager functions.
\see OpenMesh::IO::_IOManager_
*/
//@{
//-----------------------------------------------------------------------------
/** Read a mesh from file _filename. The file format is determined by
the file extension. */
template <class Mesh>
bool
read_mesh(Mesh& _mesh,
const std::string& _filename,
bool _clear = true)
{
Options opt;
return read_mesh(_mesh, _filename, opt, _clear);
}
/** Read a mesh from file _filename. The file format is determined by
the file extension. */
template <class Mesh>
bool
read_mesh(Mesh& _mesh,
const std::string& _filename,
Options& _opt,
bool _clear = true)
{
if (_clear) _mesh.clear();
ImporterT<Mesh> importer(_mesh);
return IOManager().read(_filename, importer, _opt);
}
//-----------------------------------------------------------------------------
/** Write a mesh to the file _filename. The file format is determined
by _filename's extension. */
template <class Mesh>
bool write_mesh(const Mesh& _mesh, const std::string& _filename,
Options _opt = Options::Default)
{
ExporterT<Mesh> exporter(_mesh);
return IOManager().write(_filename, exporter, _opt);
}
//-----------------------------------------------------------------------------
template <class Mesh>
size_t binary_size(const Mesh& _mesh, const std::string& _format,
Options _opt = Options::Default)
{
ExporterT<Mesh> exporter(_mesh);
return IOManager().binary_size(_format, exporter, _opt);
}
//-----------------------------------------------------------------------------
//@}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#if defined(OM_STATIC_BUILD) || defined(ARCH_DARWIN)
# include <OpenMesh/Core/IO/IOInstances.hh>
#endif
//=============================================================================
#endif
//=============================================================================

76
Core/IO/OFFFormat.hh Normal file
View File

@@ -0,0 +1,76 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
#ifndef OPENMESH_IO_OFFFORMAT_HH
#define OPENMESH_IO_OFFFORMAT_HH
//=== INCLUDES ================================================================
// OpenMesh
#include <OpenMesh/Core/System/config.h>
//== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/** \name Mesh Reading / Writing
Option for writer modules.
*/
//@{
//-----------------------------------------------------------------------------
#ifndef DOXY_IGNORE_THIS
struct OFFFormat
{
typedef int integer_type;
typedef float float_type;
};
#endif
//@}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

231
Core/IO/OMFormat.cc Normal file
View File

@@ -0,0 +1,231 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 3166 $
// $Date: 2008-09-26 14:49:46 +0200 (Fr, 26. Sep 2008) $
//
//=============================================================================
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
//== INCLUDES =================================================================
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <algorithm>
#include <iomanip>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
namespace OMFormat {
//== IMPLEMENTATION ===========================================================
Chunk::Integer_Size needed_bits( size_t s )
{
if (s <= 0x000100) return Chunk::Integer_8;
if (s <= 0x010000) return Chunk::Integer_16;
#if 0
// !Not tested yet! This most probably won't work!
// NEED a 64bit system!
if ( (sizeof( size_t ) == 8) && (s >= 0x100000000) )
return Chunk::Integer_64;
#endif
return Chunk::Integer_32;
}
//-----------------------------------------------------------------------------
uint16&
operator << (uint16& val, const Chunk::Header& hdr)
{
val = 0;
val |= hdr.name_ << OMFormat::Chunk::OFF_NAME;
val |= hdr.entity_ << OMFormat::Chunk::OFF_ENTITY;
val |= hdr.type_ << OMFormat::Chunk::OFF_TYPE;
val |= hdr.signed_ << OMFormat::Chunk::OFF_SIGNED;
val |= hdr.float_ << OMFormat::Chunk::OFF_FLOAT;
val |= hdr.dim_ << OMFormat::Chunk::OFF_DIM;
val |= hdr.bits_ << OMFormat::Chunk::OFF_BITS;
return val;
}
//-----------------------------------------------------------------------------
Chunk::Header&
operator << (Chunk::Header& hdr, const uint16 val)
{
hdr.reserved_ = 0;
hdr.name_ = val >> OMFormat::Chunk::OFF_NAME;
hdr.entity_ = val >> OMFormat::Chunk::OFF_ENTITY;
hdr.type_ = val >> OMFormat::Chunk::OFF_TYPE;
hdr.signed_ = val >> OMFormat::Chunk::OFF_SIGNED;
hdr.float_ = val >> OMFormat::Chunk::OFF_FLOAT;
hdr.dim_ = val >> OMFormat::Chunk::OFF_DIM;
hdr.bits_ = val >> OMFormat::Chunk::OFF_BITS;
return hdr;
}
//-----------------------------------------------------------------------------
const char *as_string(Chunk::Entity e)
{
switch(e)
{
case Chunk::Entity_Vertex: return "Vertex";
case Chunk::Entity_Mesh: return "Mesh";
case Chunk::Entity_Edge: return "Edge";
case Chunk::Entity_Halfedge: return "Halfedge";
case Chunk::Entity_Face: return "Face";
default:
std::clog << "as_string(Chunk::Entity): Invalid value!";
}
return NULL;
}
//-----------------------------------------------------------------------------
const char *as_string(Chunk::Type t)
{
switch(t)
{
case Chunk::Type_Pos: return "Pos";
case Chunk::Type_Normal: return "Normal";
case Chunk::Type_Texcoord: return "Texcoord";
case Chunk::Type_Status: return "Status";
case Chunk::Type_Color: return "Color";
case Chunk::Type_Custom: return "Custom";
case Chunk::Type_Topology: return "Topology";
}
return NULL;
}
//-----------------------------------------------------------------------------
const char *as_string(Chunk::Dim d)
{
switch(d)
{
case Chunk::Dim_1D: return "1D";
case Chunk::Dim_2D: return "2D";
case Chunk::Dim_3D: return "3D";
case Chunk::Dim_4D: return "4D";
case Chunk::Dim_5D: return "5D";
case Chunk::Dim_6D: return "6D";
case Chunk::Dim_7D: return "7D";
case Chunk::Dim_8D: return "8D";
}
return NULL;
}
//-----------------------------------------------------------------------------
const char *as_string(Chunk::Integer_Size d)
{
switch(d)
{
case Chunk::Integer_8 : return "8";
case Chunk::Integer_16 : return "16";
case Chunk::Integer_32 : return "32";
case Chunk::Integer_64 : return "64";
}
return NULL;
}
const char *as_string(Chunk::Float_Size d)
{
switch(d)
{
case Chunk::Float_32 : return "32";
case Chunk::Float_64 : return "64";
case Chunk::Float_128: return "128";
}
return NULL;
}
//-----------------------------------------------------------------------------
std::ostream& operator << ( std::ostream& _os, const Chunk::Header& _c )
{
_os << "Chunk Header : 0x" << std::setw(4)
<< std::hex << (*(uint16*)(&_c)) << std::dec << std::endl;
_os << "entity = "
<< as_string(Chunk::Entity(_c.entity_)) << std::endl;
_os << "type = "
<< as_string(Chunk::Type(_c.type_));
if ( Chunk::Type(_c.type_)!=Chunk::Type_Custom)
{
_os << std::endl
<< "signed = "
<< _c.signed_ << std::endl;
_os << "float = "
<< _c.float_ << std::endl;
_os << "dim = "
<< as_string(Chunk::Dim(_c.dim_)) << std::endl;
_os << "bits = "
<< (_c.float_
? as_string(Chunk::Float_Size(_c.bits_))
: as_string(Chunk::Integer_Size(_c.bits_)));
}
return _os;
}
//-----------------------------------------------------------------------------
std::ostream& operator << ( std::ostream& _os, const Header& _h )
{
_os << "magic = '" << _h.magic_[0] << _h.magic_[1] << "'\n"
<< "mesh = '" << _h.mesh_ << "'\n"
<< "version = 0x" << std::hex << (uint16)_h.version_ << std::dec
<< " (" << major_version(_h.version_)
<< "." << minor_version(_h.version_) << ")\n"
<< "#V = " << _h.n_vertices_ << std::endl
<< "#F = " << _h.n_faces_ << std::endl
<< "#E = " << _h.n_edges_;
return _os;
}
} // namespace OMFormat
// --------------------------------------------------------------------------
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

715
Core/IO/OMFormat.hh Normal file
View File

@@ -0,0 +1,715 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
#ifndef OPENMESH_IO_OMFORMAT_HH
#define OPENMESH_IO_OMFORMAT_HH
//=== INCLUDES ================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/IO/SR_store.hh>
#include <OpenMesh/Core/Utils/GenProg.hh>
#include <OpenMesh/Core/Utils/Endian.hh>
#include <OpenMesh/Core/Utils/vector_traits.hh>
// --------------------
#include <iostream>
#if defined(OM_CC_GCC) && (OM_GCC_VERSION < 30000)
# include <OpenMesh/Tools/Utils/NumLimitsT.hh>
# define OM_MISSING_HEADER_LIMITS 1
#else
# include <limits>
#endif
//== NAMESPACES ==============================================================
#ifndef DOXY_IGNORE_THIS
namespace OpenMesh {
namespace IO {
namespace OMFormat {
//=== IMPLEMENTATION ==========================================================
/** \name Mesh Reading / Writing
*/
//@{
//-----------------------------------------------------------------------------
// <:Header>
// <:Comment>
// Chunk 0
// <:ChunkHeader>
// <:Comment>
// data
// Chunk 1
// <:ChunkHeader>
// <:Comment>
// data
// .
// .
// .
// Chunk N
//
// NOTICE!
//
// The usage of data types who differ in size
// on different pc architectures (32/64 bit) and/or
// operating systems, e.g. (unsigned) long, size_t,
// is not recommended because of inconsistencies
// in case of cross writing and reading.
//
// Basic types that are supported are:
typedef unsigned char uchar;
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;
typedef float32_t float32;
typedef float64_t float64;
struct Header
{
uchar magic_[2]; // OM
uchar mesh_; // [T]riangles, [Q]uads, [P]olygonals
uint8 version_;
uint32 n_vertices_;
uint32 n_faces_;
uint32 n_edges_;
size_t store( std::ostream& _os, bool _swap ) const
{
_os.write( (char*)this, 4); // magic_, mesh_, version_
size_t bytes = 4;
bytes += binary<uint32_t>::store( _os, n_vertices_, _swap );
bytes += binary<uint32_t>::store( _os, n_faces_, _swap );
bytes += binary<uint32_t>::store( _os, n_edges_, _swap );
return bytes;
}
size_t restore( std::istream& _is, bool _swap )
{
if (_is.read( (char*)this, 4 ).eof())
return 0;
size_t bytes = 4;
bytes += binary<uint32_t>::restore( _is, n_vertices_, _swap );
bytes += binary<uint32_t>::restore( _is, n_faces_, _swap );
bytes += binary<uint32_t>::restore( _is, n_edges_, _swap );
return bytes;
}
};
struct Chunk
{
// Hardcoded this size to an uint32 to make the system 32/64 bit compatible.
// Needs further investigation!
typedef uint32 esize_t; // element size, used for custom properties
enum Type {
Type_Pos = 0x00,
Type_Normal = 0x01,
Type_Texcoord = 0x02,
Type_Status = 0x03,
Type_Color = 0x04,
Type_Custom = 0x06,
Type_Topology = 0x07
};
enum Entity {
Entity_Vertex = 0x00,
Entity_Mesh = 0x01,
Entity_Face = 0x02,
Entity_Edge = 0x04,
Entity_Halfedge = 0x06,
};
enum Dim {
Dim_1D = 0x00,
Dim_2D = 0x01,
Dim_3D = 0x02,
Dim_4D = 0x03,
Dim_5D = 0x04,
Dim_6D = 0x05,
Dim_7D = 0x06,
Dim_8D = 0x07
};
enum Integer_Size {
Integer_8 = 0x00, // 1 byte for (unsigned) char
Integer_16 = 0x01, // 2 bytes for short
Integer_32 = 0x02, // 4 bytes for long
Integer_64 = 0x03 // 8 bytes for long long
};
enum Float_Size {
Float_32 = 0x00, // 4 bytes for float
Float_64 = 0x01, // 8 bytes for double
Float_128 = 0x02 // 16 bytes for long double (an assumption!)
};
static const int SIZE_RESERVED = 1; // 1
static const int SIZE_NAME = 1; // 2
static const int SIZE_ENTITY = 3; // 5
static const int SIZE_TYPE = 4; // 9
static const int SIZE_SIGNED = 1; // 10
static const int SIZE_FLOAT = 1; // 11
static const int SIZE_DIM = 3; // 14
static const int SIZE_BITS = 2; // 16
static const int OFF_RESERVED = 0; // 0
static const int OFF_NAME = SIZE_RESERVED + OFF_RESERVED; // 2
static const int OFF_ENTITY = SIZE_NAME + OFF_NAME; // 3
static const int OFF_TYPE = SIZE_ENTITY + OFF_ENTITY; // 5
static const int OFF_SIGNED = SIZE_TYPE + OFF_TYPE; // 9
static const int OFF_FLOAT = SIZE_SIGNED + OFF_SIGNED; // 10
static const int OFF_DIM = SIZE_FLOAT + OFF_FLOAT; // 11
static const int OFF_BITS = SIZE_DIM + OFF_DIM; // 14
// !Attention! When changing the bit size, the operators
// << (uint16, Header) and << (Header, uint16) must be changed as well
//
// Entries signed_, float_, dim_, bits_ are not used when type_
// equals Type_Custom
//
struct Header // 16 bits long
{
unsigned reserved_: SIZE_RESERVED;
unsigned name_ : SIZE_NAME; // 1 named property, 0 anonymous
unsigned entity_ : SIZE_ENTITY; // 0 vertex, 1 mesh, 2 edge,
// 4 halfedge, 6 face
unsigned type_ : SIZE_TYPE; // 0 pos, 1 normal, 2 texcoord,
// 3 status, 4 color 6 custom 7 topology
unsigned signed_ : SIZE_SIGNED; // bool
unsigned float_ : SIZE_FLOAT; // bool
unsigned dim_ : SIZE_DIM; // 0 1D, 1 2D, 2 3D, .., 7 8D
unsigned bits_ : SIZE_BITS; // {8, 16, 32, 64} | {32, 64, 128}
// (integer) (float)
unsigned unused_ : 16; // fill up to 32 bits
}; // struct Header
class PropertyName : public std::string
{
public:
static const size_t size_max = 256;
PropertyName( ) { }
PropertyName( const std::string& _name ) { *this = _name; }
bool is_valid() const { return is_valid( size() ); }
static bool is_valid( size_t _s ) { return _s <= size_max; }
PropertyName& operator = ( const std::string& _rhs )
{
assert( is_valid( _rhs.size() ) );
if ( is_valid( _rhs.size() ) )
std::string::operator = ( _rhs );
else
{
omerr() << "Warning! Property name too long. Will be shortened!\n";
this->std::string::operator = ( _rhs.substr(0, size_max) );
}
return *this;
}
};
}; // Chunk
// ------------------------------------------------------------ Helper
// -------------------- get size information
/// Return size of header in bytes.
inline size_t header_size(void) { return sizeof(Header); }
/// Return size of chunk header in bytes.
inline size_t chunk_header_size( void ) { return sizeof(uint16); }
/// Return the size of a scale in bytes.
inline size_t scalar_size( const Chunk::Header& _hdr )
{
return _hdr.float_ ? (0x01 << _hdr.bits_) : (0x04 << _hdr.bits_);
}
/// Return the dimension of the vector in a chunk
inline size_t dimensions(const Chunk::Header& _chdr) { return _chdr.dim_+1; }
/// Return the size of a vector in bytes.
inline size_t vector_size( const Chunk::Header& _chdr )
{
return dimensions(_chdr)*scalar_size(_chdr);
}
/// Return the size of chunk data in bytes
inline size_t chunk_data_size( Header& _hdr, Chunk::Header& _chunk_hdr )
{
size_t C = 0;
switch( _chunk_hdr.entity_ )
{
case Chunk::Entity_Vertex: C = _hdr.n_vertices_; break;
case Chunk::Entity_Face: C = _hdr.n_faces_; break;
case Chunk::Entity_Halfedge: C = _hdr.n_edges_; // no break!
case Chunk::Entity_Edge: C += _hdr.n_edges_; break;
case Chunk::Entity_Mesh: C = 1; break;
default:
std::cerr << "Invalid value in _chunk_hdr.entity_\n";
assert( false );
}
return C * vector_size( _chunk_hdr );
}
inline size_t chunk_size( Header& _hdr, Chunk::Header& _chunk_hdr )
{
return chunk_header_size() + chunk_data_size( _hdr, _chunk_hdr );
}
// -------------------- convert from Chunk::Header to storage type
uint16& operator << (uint16& val, const Chunk::Header& hdr);
Chunk::Header& operator << (Chunk::Header& hdr, const uint16 val);
// -------------------- type information
template <typename T> bool is_float(const T&)
{
#if defined(OM_MISSING_HEADER_LIMITS)
return !Utils::NumLimitsT<T>::is_integer();
#else
return !std::numeric_limits<T>::is_integer;
#endif
}
template <typename T> bool is_integer(const T)
{
#if defined(OM_MISSING_HEADER_LIMITS)
return Utils::NumLimitsT<T>::is_integer();
#else
return std::numeric_limits<T>::is_integer;
#endif
}
template <typename T> bool is_signed(const T&)
{
#if defined(OM_MISSING_HEADER_LIMITS)
return Utils::NumLimitsT<T>::is_signed();
#else
return std::numeric_limits<T>::is_signed;
#endif
}
// -------------------- conversions (format type <- type/value)
template <typename VecType>
inline
Chunk::Dim dim( VecType )
{
assert( vector_traits< VecType >::size() < 9 );
return static_cast<Chunk::Dim>(vector_traits< VecType >::size() - 1);
}
template <>
inline
Chunk::Dim dim( const Chunk::Header& _hdr )
{
return static_cast<Chunk::Dim>( _hdr.dim_ );
}
// calc minimum (power-of-2) number of bits needed
Chunk::Integer_Size needed_bits( size_t s );
// Return the storage type (Chunk::Header::bits_)
template <typename T>
inline
unsigned int bits(const T& val)
{
return is_integer(val)
? (static_cast<unsigned int>(integer_size(val)))
: (static_cast<unsigned int>(float_size(val)));
}
// Convert size of type to Integer_Size
#ifdef NDEBUG
template <typename T> Chunk::Integer_Size integer_size(const T&)
#else
template <typename T> Chunk::Integer_Size integer_size(const T& d)
#endif
{
assert( is_integer(d) );
switch( sizeof(T) )
{
case 1: return OMFormat::Chunk::Integer_8;
case 2: return OMFormat::Chunk::Integer_16;
case 4: return OMFormat::Chunk::Integer_32;
case 8: return OMFormat::Chunk::Integer_64;
}
return Chunk::Integer_Size(0);
}
// Convert size of type to FLoat_Size
#ifdef NDEBUG
template <typename T> Chunk::Float_Size float_size(const T&)
#else
template <typename T> Chunk::Float_Size float_size(const T& d)
#endif
{
assert( is_float(d) );
switch( sizeof(T) )
{
case 4: return OMFormat::Chunk::Float_32;
case 8: return OMFormat::Chunk::Float_64;
case 16: return OMFormat::Chunk::Float_128;
}
return Chunk::Float_Size(0);
}
// -------------------- create/read version
inline uint8 mk_version(const uint16 major, const uint16 minor)
{ return (major & 0x07) << 5 | (minor & 0x1f); }
inline uint16 major_version(const uint8 version)
{ return (version >> 5) & 0x07; }
inline uint16 minor_version(const uint8 version)
{ return (version & 0x001f); }
// ---------------------------------------- convenience functions
const char *as_string(Chunk::Type t);
const char *as_string(Chunk::Entity e);
const char *as_string(Chunk::Dim d);
const char *as_string(Chunk::Integer_Size d);
const char *as_string(Chunk::Float_Size d);
std::ostream& operator << ( std::ostream& _os, const Header& _h );
std::ostream& operator << ( std::ostream& _os, const Chunk::Header& _c );
//@}
} // namespace OMFormat
// -------------------- (re-)store header
template <> inline
size_t store( std::ostream& _os, const OMFormat::Header& _hdr, bool _swap)
{ return _hdr.store( _os, _swap ); }
template <> inline
size_t restore( std::istream& _is, OMFormat::Header& _hdr, bool _swap )
{ return _hdr.restore( _is, _swap ); }
// -------------------- (re-)store chunk header
template <> inline
size_t
store( std::ostream& _os, const OMFormat::Chunk::Header& _hdr, bool _swap)
{
OMFormat::uint16 val; val << _hdr;
return binary<uint16_t>::store( _os, val, _swap );
}
template <> inline
size_t
restore( std::istream& _is, OMFormat::Chunk::Header& _hdr, bool _swap )
{
OMFormat::uint16 val;
size_t bytes = binary<uint16_t>::restore( _is, val, _swap );
_hdr << val;
return bytes;
}
// -------------------- (re-)store integer with wanted number of bits (bytes)
typedef GenProg::True t_signed;
typedef GenProg::False t_unsigned;
// helper to store a an integer
template< typename T >
size_t
store( std::ostream& _os,
const T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_signed);
// helper to store a an unsigned integer
template< typename T >
size_t
store( std::ostream& _os,
const T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_unsigned);
/// Store an integer with a wanted number of bits
template< typename T >
inline
size_t
store( std::ostream& _os,
const T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap)
{
assert( OMFormat::is_integer( _val ) );
if ( OMFormat::is_signed( _val ) )
return store( _os, _val, _b, _swap, t_signed() );
return store( _os, _val, _b, _swap, t_unsigned() );
}
// helper to store a an integer
template< typename T > inline
size_t restore( std::istream& _is,
T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_signed);
// helper to store a an unsigned integer
template< typename T > inline
size_t restore( std::istream& _is,
T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_unsigned);
/// Restore an integer with a wanted number of bits
template< typename T >
inline
size_t
restore( std::istream& _is,
T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap)
{
assert( OMFormat::is_integer( _val ) );
if ( OMFormat::is_signed( _val ) )
return restore( _is, _val, _b, _swap, t_signed() );
return restore( _is, _val, _b, _swap, t_unsigned() );
}
//
// ---------------------------------------- storing vectors
template <typename VecT> inline
size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<2>,
bool _swap )
{
size_t bytes = store( _os, _vec[0], _swap );
bytes += store( _os, _vec[1], _swap );
return bytes;
}
template <typename VecT> inline
size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<3>,
bool _swap )
{
size_t bytes = store( _os, _vec[0], _swap );
bytes += store( _os, _vec[1], _swap );
bytes += store( _os, _vec[2], _swap );
return bytes;
}
template <typename VecT> inline
size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<4>,
bool _swap )
{
size_t bytes = store( _os, _vec[0], _swap );
bytes += store( _os, _vec[1], _swap );
bytes += store( _os, _vec[2], _swap );
bytes += store( _os, _vec[3], _swap );
return bytes;
}
template <typename VecT> inline
size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<1>,
bool _swap )
{
return store( _os, _vec[0], _swap );
}
/// storing a vector type
template <typename VecT> inline
size_t vector_store( std::ostream& _os, const VecT& _vec, bool _swap )
{
return store( _os, _vec,
GenProg::Int2Type< vector_traits<VecT>::size_ >(),
_swap );
}
// ---------------------------------------- restoring vectors
template <typename VecT>
inline
size_t
restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<2>,
bool _swap )
{
size_t bytes = restore( _is, _vec[0], _swap );
bytes += restore( _is, _vec[1], _swap );
return bytes;
}
template <typename VecT>
inline
size_t
restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<3>,
bool _swap )
{
typedef typename vector_traits<VecT>::value_type scalar_type;
size_t bytes;
bytes = binary<scalar_type>::restore( _is, _vec[0], _swap );
bytes += binary<scalar_type>::restore( _is, _vec[1], _swap );
bytes += binary<scalar_type>::restore( _is, _vec[2], _swap );
return bytes;
}
template <typename VecT>
inline
size_t
restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<4>,
bool _swap )
{
typedef typename vector_traits<VecT>::value_type scalar_type;
size_t bytes;
bytes = binary<scalar_type>::restore( _is, _vec[0], _swap );
bytes += binary<scalar_type>::restore( _is, _vec[1], _swap );
bytes += binary<scalar_type>::restore( _is, _vec[2], _swap );
bytes += binary<scalar_type>::restore( _is, _vec[3], _swap );
return bytes;
}
template <typename VecT>
inline
size_t
restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<1>,
bool _swap )
{
return restore( _is, _vec[0], _swap );
}
/// Restoring a vector type
template <typename VecT>
inline
size_t
vector_restore( std::istream& _is, VecT& _vec, bool _swap )
{
return restore( _is, _vec,
GenProg::Int2Type< vector_traits<VecT>::size_ >(),
_swap );
}
// ---------------------------------------- storing property names
template <>
inline
size_t store( std::ostream& _os, const OMFormat::Chunk::PropertyName& _pn,
bool _swap )
{
store( _os, _pn.size(), OMFormat::Chunk::Integer_8, _swap ); // 1 byte
if ( _pn.size() )
_os.write( _pn.c_str(), _pn.size() ); // size bytes
return _pn.size() + 1;
}
template <>
inline
size_t restore( std::istream& _is, OMFormat::Chunk::PropertyName& _pn,
bool _swap )
{
size_t size;
restore( _is, size, OMFormat::Chunk::Integer_8, _swap); // 1 byte
assert( OMFormat::Chunk::PropertyName::is_valid( size ) );
if ( size > 0 )
{
char buf[256];
_is.read( buf, size ); // size bytes
buf[size] = '\0';
_pn.resize(size);
_pn = buf;
}
return size+1;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
#endif
//=============================================================================
#if defined(OM_MISSING_HEADER_LIMITS)
# undef OM_MISSING_HEADER_LIMITS
#endif
//=============================================================================
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_IO_OMFORMAT_CC)
# define OPENMESH_IO_OMFORMAT_TEMPLATES
# include "OMFormatT.cc"
#endif
//=============================================================================
#endif
//=============================================================================

224
Core/IO/OMFormatT.cc Normal file
View File

@@ -0,0 +1,224 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 1801 $
// $Date: 2008-05-19 11:53:56 +0200 (Mon, 19 May 2008) $
//
//=============================================================================
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#define OPENMESH_IO_OMFORMAT_CC
//== INCLUDES =================================================================
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <algorithm>
#include <iomanip>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
// helper to store a an integer
template< typename T >
size_t
store( std::ostream& _os,
const T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_signed)
{
assert( OMFormat::is_integer( _val ) );
switch( _b )
{
case OMFormat::Chunk::Integer_8:
{
OMFormat::int8 v = static_cast<OMFormat::int8>(_val);
return store( _os, v, _swap );
}
case OMFormat::Chunk::Integer_16:
{
OMFormat::int16 v = static_cast<OMFormat::int16>(_val);
return store( _os, v, _swap );
}
case OMFormat::Chunk::Integer_32:
{
OMFormat::int32 v = static_cast<OMFormat::int32>(_val);
return store( _os, v, _swap );
}
case OMFormat::Chunk::Integer_64:
{
OMFormat::int64 v = static_cast<OMFormat::int64>(_val);
return store( _os, v, _swap );
}
}
return 0;
}
// helper to store a an unsigned integer
template< typename T >
size_t
store( std::ostream& _os,
const T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_unsigned)
{
assert( OMFormat::is_integer( _val ) );
switch( _b )
{
case OMFormat::Chunk::Integer_8:
{
OMFormat::uint8 v = static_cast<OMFormat::uint8>(_val);
return store( _os, v, _swap );
}
case OMFormat::Chunk::Integer_16:
{
OMFormat::uint16 v = static_cast<OMFormat::uint16>(_val);
return store( _os, v, _swap );
}
case OMFormat::Chunk::Integer_32:
{
OMFormat::uint32 v = static_cast<OMFormat::uint32>(_val);
return store( _os, v, _swap );
}
case OMFormat::Chunk::Integer_64:
{
OMFormat::uint64 v = static_cast<OMFormat::uint64>(_val);
return store( _os, v, _swap );
}
}
return 0;
}
// helper to store a an integer
template< typename T >
size_t
restore( std::istream& _is,
T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_signed)
{
assert( OMFormat::is_integer( _val ) );
size_t bytes = 0;
switch( _b )
{
case OMFormat::Chunk::Integer_8:
{
OMFormat::int8 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
break;
}
case OMFormat::Chunk::Integer_16:
{
OMFormat::int16 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
}
case OMFormat::Chunk::Integer_32:
{
OMFormat::int32 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
}
case OMFormat::Chunk::Integer_64:
{
OMFormat::int64 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
}
}
return bytes;
}
// helper to store a an unsigned integer
template< typename T >
size_t
restore( std::istream& _is,
T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_unsigned)
{
assert( OMFormat::is_integer( _val ) );
size_t bytes = 0;
switch( _b )
{
case OMFormat::Chunk::Integer_8:
{
OMFormat::uint8 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
break;
}
case OMFormat::Chunk::Integer_16:
{
OMFormat::uint16 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
break;
}
case OMFormat::Chunk::Integer_32:
{
OMFormat::uint32 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
break;
}
case OMFormat::Chunk::Integer_64:
{
OMFormat::uint64 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
break;
}
}
return bytes;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

220
Core/IO/Options.hh Normal file
View File

@@ -0,0 +1,220 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
#ifndef OPENMESH_IO_OPTIONS_HH
#define OPENMESH_IO_OPTIONS_HH
//=== INCLUDES ================================================================
// OpenMesh
#include <OpenMesh/Core/System/config.h>
//== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/** \name Mesh Reading / Writing
Option for reader and writer modules.
*/
//@{
//-----------------------------------------------------------------------------
/** \brief Set options for reader/writer modules.
*
* The class is used in a twofold way.
* -# In combination with reader modules the class is used
* - to pass hints to the reading module, whether the input is
* binary and what byte ordering the binary data has
* - to retrieve information about the file contents after
* succesful reading.
* -# In combination with write modules the class gives directions to
* the writer module, whether to
* - use binary mode or not and what byte order to use
* - store one of the standard properties.
*
* The option are defined in \c Options::Flag as bit values and stored in
* an \c int value as a bitset.
*/
class Options
{
public:
typedef int enum_type;
typedef enum_type value_type;
/// Definitions of %Options for reading and writing. The options can be
/// or'ed.
enum Flag {
Default = 0x0000, ///< No options
Binary = 0x0001, ///< Set binary mode for r/w
MSB = 0x0002, ///< Assume big endian byte ordering
LSB = 0x0004, ///< Assume little endian byte ordering
Swap = 0x0006, ///< Swap byte order in binary mode
VertexNormal = 0x0010, ///< Has (r) / store (w) vertex normals
VertexColor = 0x0020, ///< Has (r) / store (w) vertex colors
VertexTexCoord = 0x0040, ///< Has (r) / store (w) texture coordinates
FaceNormal = 0x0100, ///< Has (r) / store (w) face normals
FaceColor = 0x0200, ///< Has (r) / store (w) face colors
ColorAlpha = 0x0400 ///< Has (r) / store (w) alpha values for colors
};
public:
/// Default constructor
Options() : flags_( Default )
{ }
/// Copy constructor
Options(const Options& _opt) : flags_(_opt.flags_)
{ }
/// Initializing constructor setting a single option
Options(Flag _flg) : flags_( _flg)
{ }
/// Initializing constructor setting multiple options
Options(const value_type _flgs) : flags_( _flgs)
{ }
~Options()
{ }
/// Restore state after default constructor.
void cleanup(void)
{ flags_ = Default; }
/// Clear all bits.
void clear(void)
{ flags_ = 0; }
/// Returns true if all bits are zero.
bool is_empty(void) const { return !flags_; }
public:
//@{
/// Copy options defined in _rhs.
Options& operator = ( const Options& _rhs )
{ flags_ = _rhs.flags_; return *this; }
Options& operator = ( const value_type _rhs )
{ flags_ = _rhs; return *this; }
//@}
//@{
/// Unset options defined in _rhs.
Options& operator -= ( const value_type _rhs )
{ flags_ &= ~_rhs; return *this; }
Options& unset( const value_type _rhs)
{ return (*this -= _rhs); }
//@}
//@{
/// Set options defined in _rhs
Options& operator += ( const value_type _rhs )
{ flags_ |= _rhs; return *this; }
Options& set( const value_type _rhs)
{ return (*this += _rhs); }
//@}
public:
// Check if an option or several options are set.
bool check(const value_type _rhs) const
{
return (flags_ & _rhs)==_rhs;
}
bool is_binary() const { return check(Binary); }
bool vertex_has_normal() const { return check(VertexNormal); }
bool vertex_has_color() const { return check(VertexColor); }
bool vertex_has_texcoord() const { return check(VertexTexCoord); }
bool face_has_normal() const { return check(FaceNormal); }
bool face_has_color() const { return check(FaceColor); }
bool color_has_alpha() const { return check(ColorAlpha); }
/// Returns true if _rhs has the same options enabled.
bool operator == (const value_type _rhs) const
{ return flags_ == _rhs; }
/// Returns true if _rhs does not have the same options enabled.
bool operator != (const value_type _rhs) const
{ return flags_ != _rhs; }
/// Returns the option set.
operator value_type () const { return flags_; }
private:
bool operator && (const value_type _rhs) const;
value_type flags_;
};
//-----------------------------------------------------------------------------
//@}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

118
Core/IO/SR_binary.hh Normal file
View File

@@ -0,0 +1,118 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 1801 $
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
//
//=============================================================================
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#ifndef OPENMESH_SR_BINARY_HH
#define OPENMESH_SR_BINARY_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
// -------------------- STL
#include <typeinfo>
#include <stdexcept>
#include <sstream>
#include <numeric> // accumulate
// -------------------- OpenMesh
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
//-----------------------------------------------------------------------------
const static size_t UnknownSize(size_t(-1));
//-----------------------------------------------------------------------------
// struct binary, helper for storing/restoring
#define X \
std::ostringstream msg; \
msg << "Type not supported: " << typeid(value_type).name(); \
throw std::logic_error(msg.str())
/// \struct binary SR_binary.hh <OpenMesh/Core/IO/SR_binary.hh>
///
/// The struct defines how to store and restore the type T.
/// It's used by the OM reader/writer modules.
///
/// The following specialization are provided:
/// - Fundamental types except \c long \c double
/// - %OpenMesh vector types
/// - %OpenMesh::StatusInfo
/// - std::string (max. length 65535)
///
/// \todo Complete documentation of members
template < typename T > struct binary
{
typedef T value_type;
static const bool is_streamable = false;
static size_t size_of(void) { return UnknownSize; }
static size_t size_of(const value_type&) { return UnknownSize; }
static
size_t store( std::ostream& /* _os */,
const value_type& /* _v */,
bool /* _swap=false */)
{ X; return 0; }
static
size_t restore( std::istream& /* _is */,
value_type& /* _v */,
bool /* _swap=false */)
{ X; return 0; }
};
#undef X
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_SR_RBO_HH defined
//=============================================================================

277
Core/IO/SR_binary_spec.hh Normal file
View File

@@ -0,0 +1,277 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 4333 $
// $Date: 2009-01-16 17:13:47 +0100 (Fr, 16. Jan 2009) $
//
//=============================================================================
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#ifndef OPENMESH_SR_BINARY_SPEC_HH
#define OPENMESH_SR_BINARY_SPEC_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
// -------------------- STL
#include <iterator>
#include <string>
#if defined(OM_CC_GCC) && (OM_CC_VERSION < 30000)
# include <OpenMesh/Tools/Utils/NumLimitsT.hh>
#else
# include <limits>
#endif
#include <vector>
#include <stdexcept> // logic_error
#include <numeric> // accumulate
// -------------------- OpenMesh
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include <OpenMesh/Core/Mesh/Status.hh>
#include <OpenMesh/Core/IO/SR_types.hh>
#include <OpenMesh/Core/IO/SR_rbo.hh>
#include <OpenMesh/Core/IO/SR_binary.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
#ifndef DOXY_IGNORE_THIS
//-----------------------------------------------------------------------------
// struct binary, helper for storing/restoring
#define SIMPLE_BINARY( T ) \
template <> struct binary< T > { \
typedef T value_type; \
static const bool is_streamable = true; \
static size_t size_of(const value_type&) { return sizeof(value_type); } \
static size_t size_of(void) { return sizeof(value_type); } \
static size_t store( std::ostream& _os, const value_type& _val, \
bool _swap=false) { \
value_type tmp = _val; \
if (_swap) reverse_byte_order(tmp); \
_os.write( (const char*)&tmp, sizeof(value_type) ); \
return _os.good() ? sizeof(value_type) : 0; \
} \
\
static size_t restore( std::istream& _is, value_type& _val, \
bool _swap=false) { \
_is.read( (char*)&_val, sizeof(value_type) ); \
if (_swap) reverse_byte_order(_val); \
return _is.good() ? sizeof(value_type) : 0; \
} \
}
SIMPLE_BINARY(bool);
// SIMPLE_BINARY(int);
// Why is this needed? Should not be used as not 32 bit compatible
SIMPLE_BINARY(unsigned long);
SIMPLE_BINARY(float);
SIMPLE_BINARY(double);
SIMPLE_BINARY(long double);
SIMPLE_BINARY(int8_t);
SIMPLE_BINARY(int16_t);
SIMPLE_BINARY(int32_t);
SIMPLE_BINARY(int64_t);
SIMPLE_BINARY(uint8_t);
SIMPLE_BINARY(uint16_t);
SIMPLE_BINARY(uint32_t);
SIMPLE_BINARY(uint64_t);
#undef SIMPLE_BINARY
#define VECTORT_BINARY( T ) \
template <> struct binary< T > { \
typedef T value_type; \
static const bool is_streamable = true; \
static size_t size_of(void) { return sizeof(value_type); } \
static size_t size_of(const value_type&) { return size_of(); } \
static size_t store( std::ostream& _os, const value_type& _val, \
bool _swap=false) { \
value_type tmp = _val; \
size_t i, b = size_of(_val), N = value_type::size_; \
if (_swap) for (i=0; i<N; ++i) \
reverse_byte_order( tmp[i] ); \
_os.write( (const char*)&tmp[0], b ); \
return _os.good() ? b : 0; \
} \
\
static size_t restore( std::istream& _is, value_type& _val, \
bool _swap=false) { \
size_t i, N=value_type::size_; \
size_t b = N * sizeof(value_type::value_type); \
_is.read( (char*)&_val[0], b ); \
if (_swap) for (i=0; i<N; ++i) \
reverse_byte_order( _val[i] ); \
return _is.good() ? b : 0; \
} \
}
#define VECTORTS_BINARY( N ) \
VECTORT_BINARY( Vec##N##c ); \
VECTORT_BINARY( Vec##N##uc ); \
VECTORT_BINARY( Vec##N##s ); \
VECTORT_BINARY( Vec##N##us ); \
VECTORT_BINARY( Vec##N##i ); \
VECTORT_BINARY( Vec##N##ui ); \
VECTORT_BINARY( Vec##N##f ); \
VECTORT_BINARY( Vec##N##d );
VECTORTS_BINARY( 1 );
VECTORTS_BINARY( 2 );
VECTORTS_BINARY( 3 );
VECTORTS_BINARY( 4 );
VECTORTS_BINARY( 6 );
#undef VECTORTS_BINARY
#undef VECTORT_BINARY
template <> struct binary< std::string > {
typedef std::string value_type;
typedef uint16_t length_t;
static const bool is_streamable = true;
static size_t size_of() { return UnknownSize; }
static size_t size_of(const value_type &_v)
{ return sizeof(length_t) + _v.size(); }
static
size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
{
#if defined(OM_CC_GCC) && (OM_CC_VERSION < 30000)
if (_v.size() < Utils::NumLimitsT<length_t>::max() )
#else
if (_v.size() < std::numeric_limits<length_t>::max() )
#endif
{
length_t len = _v.size();
if (_swap) reverse_byte_order(len);
size_t bytes = binary<length_t>::store( _os, len, _swap );
_os.write( _v.data(), len );
return _os.good() ? len+bytes : 0;
}
throw std::runtime_error("Cannot store string longer than 64Kb");
}
static
size_t restore(std::istream& _is, value_type& _val, bool _swap=false)
{
length_t len;
size_t bytes = binary<length_t>::restore( _is, len, _swap );
if (_swap)
reverse_byte_order(len);
_val.resize(len);
_is.read( const_cast<char*>(_val.data()), len );
return _is.good() ? (len+bytes) : 0;
}
};
template <> struct binary<OpenMesh::Attributes::StatusInfo>
{
typedef OpenMesh::Attributes::StatusInfo value_type;
typedef value_type::value_type status_t;
static const bool is_streamable = true;
static size_t size_of() { return sizeof(status_t); }
static size_t size_of(const value_type&) { return size_of(); }
static size_t n_bytes(size_t _n_elem)
{ return _n_elem*sizeof(status_t); }
static
size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
{
status_t v=_v.bits();
return binary<status_t>::store(_os, v, _swap);
}
static
size_t restore( std::istream& _os, value_type& _v, bool _swap=false)
{
status_t v;
size_t b = binary<status_t>::restore(_os, v, _swap);
_v.set_bits(v);
return b;
}
};
//-----------------------------------------------------------------------------
// std::vector<T> specializations for struct binary<>
template <typename T>
struct FunctorStore {
FunctorStore( std::ostream& _os, bool _swap) : os_(_os), swap_(_swap) { }
size_t operator () ( size_t _v1, const T& _s2 )
{ return _v1+binary<T>::store(os_, _s2, swap_ ); }
std::ostream& os_;
bool swap_;
};
template <typename T>
struct FunctorRestore {
FunctorRestore( std::istream& _is, bool _swap) : is_(_is), swap_(_swap) { }
size_t operator () ( size_t _v1, T& _s2 )
{ return _v1+binary<T>::restore(is_, _s2, swap_ ); }
std::istream& is_;
bool swap_;
};
#include <OpenMesh/Core/IO/SR_binary_vector_of_fundamentals.inl>
#include <OpenMesh/Core/IO/SR_binary_vector_of_string.inl>
#include <OpenMesh/Core/IO/SR_binary_vector_of_bool.inl>
// ----------------------------------------------------------------------------
#endif // DOXY_IGNORE_THIS
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_SR_BINARY_SPEC_HH defined
//=============================================================================

View File

@@ -0,0 +1,99 @@
template <> struct binary< std::vector<bool> >
{
typedef std::vector< bool > value_type;
typedef value_type::value_type elem_type;
static const bool is_streamable = true;
static size_t size_of(void) { return UnknownSize; }
static size_t size_of(const value_type& _v)
{
return _v.size() / 8 + ((_v.size() % 8)!=0);
}
static
size_t store( std::ostream& _ostr, const value_type& _v, bool )
{
size_t bytes = 0;
size_t N = _v.size() / 8;
size_t R = _v.size() % 8;
size_t idx; // element index
unsigned char bits; // bitset
for (idx=0; idx < N; ++idx)
{
bits = 0;
bits = bits | (_v[idx+0] ? 1 : 0);
bits = bits | ((_v[idx+1] ? 1 : 0) << 1);
bits = bits | ((_v[idx+2] ? 1 : 0) << 2);
bits = bits | ((_v[idx+3] ? 1 : 0) << 3);
bits = bits | ((_v[idx+4] ? 1 : 0) << 4);
bits = bits | ((_v[idx+5] ? 1 : 0) << 5);
bits = bits | ((_v[idx+6] ? 1 : 0) << 6);
bits = bits | ((_v[idx+7] ? 1 : 0) << 7);
_ostr << bits;
}
bytes = N;
if (R)
{
bits = 0;
switch(R)
{
case 7: bits = bits | ((_v[idx+6] ? 1 : 0) << 6);
case 6: bits = bits | ((_v[idx+5] ? 1 : 0) << 5);
case 5: bits = bits | ((_v[idx+4] ? 1 : 0) << 4);
case 4: bits = bits | ((_v[idx+3] ? 1 : 0) << 3);
case 3: bits = bits | ((_v[idx+2] ? 1 : 0) << 2);
case 2: bits = bits | ((_v[idx+1] ? 1 : 0) << 1);
case 1: bits = bits | (_v[idx+0] ? 1 : 0);
}
_ostr << bits;
++bytes;
}
assert( bytes == size_of(_v) );
return bytes;
}
static
size_t restore( std::istream& _istr, value_type& _v, bool )
{
size_t bytes = 0;
size_t N = _v.size() / 8;
size_t R = _v.size() % 8;
size_t idx; // element index
unsigned char bits; // bitset
for (idx=0; idx < N; ++idx)
{
_istr >> bits;
_v[idx+0] = ((bits & 0x01)!=0);
_v[idx+1] = ((bits & 0x02)!=0);
_v[idx+2] = ((bits & 0x04)!=0);
_v[idx+3] = ((bits & 0x08)!=0);
_v[idx+4] = ((bits & 0x10)!=0);
_v[idx+5] = ((bits & 0x20)!=0);
_v[idx+6] = ((bits & 0x40)!=0);
_v[idx+7] = ((bits & 0x80)!=0);
}
bytes = N;
if (R)
{
_istr >> bits;
for(; idx < _v.size(); ++idx)
_v[idx] = (bits & (1 << (idx%8)))!=0;
++bytes;
}
return bytes;
}
};

View File

@@ -0,0 +1,53 @@
#define BINARY_VECTOR( T ) \
template <> struct binary< std::vector< T > > { \
typedef std::vector< T > value_type; \
typedef value_type::value_type elem_type; \
\
static const bool is_streamable = true; \
\
static size_t size_of(void) \
{ return IO::UnknownSize; } \
\
static size_t size_of(const value_type& _v) \
{ return sizeof(elem_type)*_v.size(); } \
\
static \
size_t store(std::ostream& _os, const value_type& _v, bool _swap=false) { \
size_t bytes=0; \
\
if (_swap) \
bytes = std::accumulate( _v.begin(), _v.end(), bytes, \
FunctorStore<elem_type>(_os,_swap) ); \
else { \
bytes = size_of(_v); \
_os.write( reinterpret_cast<const char*>(&_v[0]), bytes ); \
} \
return _os.good() ? bytes : 0; \
} \
\
static size_t restore(std::istream& _is, value_type& _v, bool _swap=false) { \
size_t bytes=0; \
\
if ( _swap) \
bytes = std::accumulate( _v.begin(), _v.end(), 0, \
FunctorRestore<elem_type>(_is, _swap) ); \
else \
{ \
bytes = size_of(_v); \
_is.read( reinterpret_cast<char*>(&_v[0]), bytes ); \
} \
return _is.good() ? bytes : 0; \
} \
}
BINARY_VECTOR( short );
BINARY_VECTOR( unsigned short );
BINARY_VECTOR( int );
BINARY_VECTOR( unsigned int );
BINARY_VECTOR( long );
BINARY_VECTOR( unsigned long );
BINARY_VECTOR( float );
BINARY_VECTOR( double );
#undef BINARY_VECTOR

View File

@@ -0,0 +1,39 @@
template <> struct binary< std::vector< std::string > >
{
// struct binary interface
typedef std::vector< std::string > value_type;
typedef value_type::value_type elem_type;
static const bool is_streamable = true;
// Helper
struct Sum
{
size_t operator() ( size_t _v1, const elem_type& _s2 )
{ return _v1 + binary<elem_type>::size_of(_s2); }
};
// struct binary interface
static size_t size_of(void) { return UnknownSize; }
static size_t size_of(const value_type& _v)
{ return std::accumulate( _v.begin(), _v.end(), 0u, Sum() ); }
static
size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
{
return std::accumulate( _v.begin(), _v.end(), 0,
FunctorStore<elem_type>(_os, _swap) );
}
static
size_t restore(std::istream& _is, value_type& _v, bool _swap=false)
{
return std::accumulate( _v.begin(), _v.end(), 0,
FunctorRestore<elem_type>(_is, _swap) );
}
};

247
Core/IO/SR_rbo.hh Normal file
View File

@@ -0,0 +1,247 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 4333 $
// $Date: 2009-01-16 17:13:47 +0100 (Fr, 16. Jan 2009) $
//
//=============================================================================
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#ifndef OPENMESH_SR_RBO_HH
#define OPENMESH_SR_RBO_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
// -------------------- STL
#if defined(OM_CC_MIPS)
# include <stdio.h> // size_t
#else
# include <cstdio> // size_t
#endif
#include <algorithm>
#include <typeinfo>
// -------------------- OpenMesh
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/IO/SR_types.hh>
#include <OpenMesh/Core/Utils/GenProg.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
/** \name Handling binary input/output.
These functions take care of swapping bytes to get the right Endian.
*/
//@{
//-----------------------------------------------------------------------------
/** this does not compile for g++3.4 and higher, hence we comment the
function body which will result in a linker error */
template < size_t N > inline
void _reverse_byte_order_N(uint8_t* _val)
{
assert_compile(false);
// compile_time_error__only_for_fundamental_types(_val);
}
template <> inline
void _reverse_byte_order_N<1>(uint8_t* /*_val*/) { };
template <> inline
void _reverse_byte_order_N<2>(uint8_t* _val)
{
_val[0] ^= _val[1]; _val[1] ^= _val[0]; _val[0] ^= _val[1];
}
template <> inline
void _reverse_byte_order_N<4>(uint8_t* _val)
{
_val[0] ^= _val[3]; _val[3] ^= _val[0]; _val[0] ^= _val[3]; // 0 <-> 3
_val[1] ^= _val[2]; _val[2] ^= _val[1]; _val[1] ^= _val[2]; // 1 <-> 2
}
template <> inline
void _reverse_byte_order_N<8>(uint8_t* _val)
{
_val[0] ^= _val[7]; _val[7] ^= _val[0]; _val[0] ^= _val[7]; // 0 <-> 7
_val[1] ^= _val[6]; _val[6] ^= _val[1]; _val[1] ^= _val[6]; // 1 <-> 6
_val[2] ^= _val[5]; _val[5] ^= _val[2]; _val[2] ^= _val[5]; // 2 <-> 5
_val[3] ^= _val[4]; _val[4] ^= _val[3]; _val[3] ^= _val[4]; // 3 <-> 4
}
template <> inline
void _reverse_byte_order_N<12>(uint8_t* _val)
{
_val[0] ^= _val[11]; _val[11] ^= _val[0]; _val[0] ^= _val[11]; // 0 <-> 11
_val[1] ^= _val[10]; _val[10] ^= _val[1]; _val[1] ^= _val[10]; // 1 <-> 10
_val[2] ^= _val[ 9]; _val[ 9] ^= _val[2]; _val[2] ^= _val[ 9]; // 2 <-> 9
_val[3] ^= _val[ 8]; _val[ 8] ^= _val[3]; _val[3] ^= _val[ 8]; // 3 <-> 8
_val[4] ^= _val[ 7]; _val[ 7] ^= _val[4]; _val[4] ^= _val[ 7]; // 4 <-> 7
_val[5] ^= _val[ 6]; _val[ 6] ^= _val[5]; _val[5] ^= _val[ 6]; // 5 <-> 6
}
template <> inline
void _reverse_byte_order_N<16>(uint8_t* _val)
{
_reverse_byte_order_N<8>(_val);
_reverse_byte_order_N<8>(_val+8);
std::swap(*(uint64_t*)_val, *(((uint64_t*)_val)+1));
}
//-----------------------------------------------------------------------------
// wrapper for byte reordering
// reverting pointers makes no sense, hence forbid it.
/** this does not compile for g++3.4 and higher, hence we comment the
function body which will result in a linker error */
template <typename T> inline T* reverse_byte_order(T* t)
{
// Should never reach this point. If so, then some operator were not
// overloaded. Especially check for IO::binary<> specialization on
// custom data types.
// compile_time_error__cannot_do_that(a);
assert_compile(false);
return t;
}
inline void compile_time_error__no_fundamental_type()
{
// we should never reach this point
assert(false);
}
// default action for byte reversal: cause an error to avoid
// surprising behaviour!
template <typename T> T& reverse_byte_order( T& _t )
{
omerr() << "Not defined for type " << typeid(T).name() << std::endl;
compile_time_error__no_fundamental_type();
return _t;
}
template <> inline bool& reverse_byte_order(bool & _t) { return _t; }
template <> inline char& reverse_byte_order(char & _t) { return _t; }
#if defined(OM_CC_GCC)
template <> inline signed char& reverse_byte_order(signed char & _t) { return _t; }
#endif
template <> inline uchar& reverse_byte_order(uchar& _t) { return _t; }
// Instead do specializations for the necessary types
#define REVERSE_FUNDAMENTAL_TYPE( T ) \
template <> inline T& reverse_byte_order( T& _t ) {\
_reverse_byte_order_N<sizeof(T)>( reinterpret_cast<uint8_t*>(&_t) ); \
return _t; \
}
// REVERSE_FUNDAMENTAL_TYPE(bool);
// REVERSE_FUNDAMENTAL_TYPE(char);
// REVERSE_FUNDAMENTAL_TYPE(uchar);
REVERSE_FUNDAMENTAL_TYPE(int16_t);
REVERSE_FUNDAMENTAL_TYPE(uint16_t);
// REVERSE_FUNDAMENTAL_TYPE(int);
// REVERSE_FUNDAMENTAL_TYPE(uint);
REVERSE_FUNDAMENTAL_TYPE(unsigned long);
REVERSE_FUNDAMENTAL_TYPE(int32_t);
REVERSE_FUNDAMENTAL_TYPE(uint32_t);
REVERSE_FUNDAMENTAL_TYPE(int64_t);
REVERSE_FUNDAMENTAL_TYPE(uint64_t);
REVERSE_FUNDAMENTAL_TYPE(float);
REVERSE_FUNDAMENTAL_TYPE(double);
REVERSE_FUNDAMENTAL_TYPE(long double);
#undef REVERSE_FUNDAMENTAL_TYPE
#if 0
#define REVERSE_VECTORT_TYPE( T ) \
template <> inline T& reverse_byte_order(T& _v) {\
for (size_t i; i< T::size_; ++i) \
_reverse_byte_order_N< sizeof(T::value_type) >( reinterpret_cast<uint8_t*>(&_v[i])); \
return _v; \
}
#define REVERSE_VECTORT_TYPES( N ) \
REVERSE_VECTORT_TYPE( Vec##N##c ) \
REVERSE_VECTORT_TYPE( Vec##N##uc ) \
REVERSE_VECTORT_TYPE( Vec##N##s ) \
REVERSE_VECTORT_TYPE( Vec##N##us ) \
REVERSE_VECTORT_TYPE( Vec##N##i ) \
REVERSE_VECTORT_TYPE( Vec##N##ui ) \
REVERSE_VECTORT_TYPE( Vec##N##f ) \
REVERSE_VECTORT_TYPE( Vec##N##d ) \
REVERSE_VECTORT_TYPES(1)
REVERSE_VECTORT_TYPES(2)
REVERSE_VECTORT_TYPES(3)
REVERSE_VECTORT_TYPES(4)
REVERSE_VECTORT_TYPES(6)
#undef REVERSE_VECTORT_TYPES
#undef REVERSE_VECTORT_TYPE
#endif
template <typename T> inline
T reverse_byte_order(const T& a)
{
compile_timer_error__const_means_const(a);
return a;
}
//@}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_SR_RBO_HH defined
//=============================================================================

54
Core/IO/SR_store.hh Normal file
View File

@@ -0,0 +1,54 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 1801 $
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
//
//=============================================================================
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#ifndef OPENMESH_SR_STORE_HH
#define OPENMESH_SR_STORE_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/SR_types.hh>
#include <OpenMesh/Core/IO/SR_rbo.hh>
#include <OpenMesh/Core/IO/SR_binary.hh>
#include <OpenMesh/Core/IO/SR_binary_spec.hh>
#include <OpenMesh/Core/IO/StoreRestore.hh>
//=============================================================================
#endif // OPENMESH_STORE_HH defined
//=============================================================================

94
Core/IO/SR_types.hh Normal file
View File

@@ -0,0 +1,94 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 3695 $
// $Date: 2008-11-12 13:21:40 +0100 (Mi, 12. Nov 2008) $
//
//=============================================================================
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#ifndef OPENMESH_SR_TYPES_HH
#define OPENMESH_SR_TYPES_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
/** \name Handling binary input/output.
These functions take care of swapping bytes to get the right Endian.
*/
//@{
//-----------------------------------------------------------------------------
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned long ulong;
typedef char int8_t; typedef unsigned char uint8_t;
typedef short int16_t; typedef unsigned short uint16_t;
// Int should be 32 bit on all archs.
// long is 32 under windows but 64 under unix 64 bit
typedef int int32_t; typedef unsigned int uint32_t;
#if defined(OM_CC_MSVC)
typedef __int64 int64_t; typedef unsigned __int64 uint64_t;
#else
typedef long long int64_t; typedef unsigned long long uint64_t;
#endif
typedef float float32_t;
typedef double float64_t;
typedef uint8_t rgb_t[3];
typedef uint8_t rgba_t[4];
//@}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_MESHREADER_HH defined
//=============================================================================

98
Core/IO/StoreRestore.hh Normal file
View File

@@ -0,0 +1,98 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $Revision: 1801 $
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
//
//=============================================================================
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#ifndef OPENMESH_STORERESTORE_HH
#define OPENMESH_STORERESTORE_HH
//== INCLUDES =================================================================
#include <stdexcept>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/SR_binary.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
/** \name Handling binary input/output.
These functions take care of swapping bytes to get the right Endian.
*/
//@{
//-----------------------------------------------------------------------------
// StoreRestore definitions
template <typename T> inline
bool is_streamable(void)
{ return binary< T >::is_streamable; }
template <typename T> inline
bool is_streamable( const T& )
{ return binary< T >::is_streamable; }
template <typename T> inline
size_t size_of( const T& _v )
{ return binary< T >::size_of(_v); }
template <typename T> inline
size_t size_of(void)
{ return binary< T >::size_of(); }
template <typename T> inline
size_t store( std::ostream& _os, const T& _v, bool _swap=false)
{ return binary< T >::store( _os, _v, _swap ); }
template <typename T> inline
size_t restore( std::istream& _is, T& _v, bool _swap=false)
{ return binary< T >::restore( _is, _v, _swap ); }
//@}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_MESHREADER_HH defined
//=============================================================================

View File

@@ -0,0 +1,17 @@
#== SYSTEM PART -- DON'T TOUCH ==============================================
include $(ACGMAKE)/Config
#==============================================================================
SUBDIRS = $(call find-subdirs)
PACKAGES :=
PROJ_LIBS :=
MODULES := cxxlib
#== SYSTEM PART -- DON'T TOUCH ==============================================
include $(ACGMAKE)/Rules
#==============================================================================

View File

@@ -0,0 +1,114 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements the baseclass for MeshWriter exporter modules
//
//=============================================================================
#ifndef __BASEEXPORTER_HH__
#define __BASEEXPORTER_HH__
//=== INCLUDES ================================================================
// STL
#include <vector>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include <OpenMesh/Core/Mesh/BaseKernel.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== EXPORTER ================================================================
/**
Base class for exporter modules.
The exporter modules provide an interface between the writer modules and
the target data structure.
*/
class BaseExporter
{
public:
virtual ~BaseExporter() { }
// get vertex data
virtual Vec3f point(VertexHandle _vh) const = 0;
virtual Vec3f normal(VertexHandle _vh) const = 0;
virtual Vec3uc color(VertexHandle _vh) const = 0;
virtual Vec4uc colorA(VertexHandle _vh) const = 0;
virtual Vec2f texcoord(VertexHandle _vh) const = 0;
// get face data
virtual unsigned int
get_vhandles(FaceHandle _fh,
std::vector<VertexHandle>& _vhandles) const=0;
virtual Vec3f normal(FaceHandle _fh) const = 0;
virtual Vec3uc color (FaceHandle _fh) const = 0;
virtual Vec4uc colorA(FaceHandle _fh) const = 0;
// get reference to base kernel
virtual const BaseKernel* kernel() { return 0; }
// query number of faces, vertices, normals, texcoords
virtual size_t n_vertices() const = 0;
virtual size_t n_faces() const = 0;
virtual size_t n_edges() const = 0;
// property information
virtual bool is_triangle_mesh() const { return false; }
virtual bool has_vertex_normals() const { return false; }
virtual bool has_vertex_colors() const { return false; }
virtual bool has_vertex_texcoords() const { return false; }
virtual bool has_face_normals() const { return false; }
virtual bool has_face_colors() const { return false; }
};
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@@ -0,0 +1,183 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements an exporter module for arbitrary OpenMesh meshes
//
//=============================================================================
#ifndef __EXPORTERT_HH__
#define __EXPORTERT_HH__
//=== INCLUDES ================================================================
// C++
#include <vector>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include <OpenMesh/Core/Utils/GenProg.hh>
#include <OpenMesh/Core/Utils/vector_cast.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== EXPORTER CLASS ==========================================================
/**
* This class template provides an exporter module for OpenMesh meshes.
*/
template <class Mesh>
class ExporterT : public BaseExporter
{
public:
// Constructor
ExporterT(const Mesh& _mesh) : mesh_(_mesh) {}
// get vertex data
Vec3f point(VertexHandle _vh) const
{
return vector_cast<Vec3f>(mesh_.point(_vh));
}
Vec3f normal(VertexHandle _vh) const
{
return (mesh_.has_vertex_normals()
? vector_cast<Vec3f>(mesh_.normal(_vh))
: Vec3f(0.0f, 0.0f, 0.0f));
}
Vec3uc color(VertexHandle _vh) const
{
return (mesh_.has_vertex_colors()
? color_cast<Vec3uc>(mesh_.color(_vh))
: Vec3uc(0, 0, 0));
}
Vec4uc colorA(VertexHandle _vh) const
{
return (mesh_.has_vertex_colors()
? color_cast<Vec4uc>(mesh_.color(_vh))
: Vec4uc(0, 0, 0, 0));
}
Vec2f texcoord(VertexHandle _vh) const
{
#if defined(OM_CC_GCC) && (OM_CC_VERSION<30000)
// Workaround!
// gcc 2.95.3 exits with internal compiler error at the
// code below!??? **)
if (mesh_.has_vertex_texcoords2D())
return vector_cast<Vec2f>(mesh_.texcoord2D(_vh));
return Vec2f(0.0f, 0.0f);
#else // **)
return (mesh_.has_vertex_texcoords2D()
? vector_cast<Vec2f>(mesh_.texcoord2D(_vh))
: Vec2f(0.0f, 0.0f));
#endif
}
// get face data
unsigned int get_vhandles(FaceHandle _fh,
std::vector<VertexHandle>& _vhandles) const
{
unsigned int count(0);
_vhandles.clear();
for (typename Mesh::CFVIter fv_it=mesh_.cfv_iter(_fh); fv_it; ++fv_it)
{
_vhandles.push_back(fv_it.handle());
++count;
}
return count;
}
Vec3f normal(FaceHandle _fh) const
{
return (mesh_.has_face_normals()
? vector_cast<Vec3f>(mesh_.normal(_fh))
: Vec3f(0.0f, 0.0f, 0.0f));
}
Vec3uc color(FaceHandle _fh) const
{
return (mesh_.has_face_colors()
? color_cast<Vec3uc>(mesh_.color(_fh))
: Vec3uc(0, 0, 0));
}
Vec4uc colorA(FaceHandle _fh) const
{
return (mesh_.has_face_colors()
? color_cast<Vec4uc>(mesh_.color(_fh))
: Vec4uc(0, 0, 0, 0));
}
virtual const BaseKernel* kernel() { return &mesh_; }
// query number of faces, vertices, normals, texcoords
size_t n_vertices() const { return mesh_.n_vertices(); }
size_t n_faces() const { return mesh_.n_faces(); }
size_t n_edges() const { return mesh_.n_edges(); }
// property information
bool is_triangle_mesh() const
{ return Mesh::is_triangles(); }
bool has_vertex_normals() const { return mesh_.has_vertex_normals(); }
bool has_vertex_colors() const { return mesh_.has_vertex_colors(); }
bool has_vertex_texcoords() const { return mesh_.has_vertex_texcoords2D(); }
bool has_face_normals() const { return mesh_.has_face_normals(); }
bool has_face_colors() const { return mesh_.has_face_colors(); }
private:
const Mesh& mesh_;
};
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@@ -0,0 +1,17 @@
#== SYSTEM PART -- DON'T TOUCH ==============================================
include $(ACGMAKE)/Config
#==============================================================================
SUBDIRS = $(call find-subdirs)
PACKAGES :=
PROJ_LIBS :=
MODULES := cxxlib
#== SYSTEM PART -- DON'T TOUCH ==============================================
include $(ACGMAKE)/Rules
#==============================================================================

View File

@@ -0,0 +1,130 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements the baseclass for IOManager importer modules
//
//=============================================================================
#ifndef __BASEIMPORTER_HH__
#define __BASEIMPORTER_HH__
//=== INCLUDES ================================================================
// STL
#include <vector>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include <OpenMesh/Core/Mesh/BaseKernel.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/** Base class for importer modules. Importer modules provide an
* interface between the loader modules and the target data
* structure. This is basically a wrapper providing virtual versions
* for the required mesh functions.
*/
class BaseImporter
{
public:
// base class needs virtual destructor
virtual ~BaseImporter() {}
// add a vertex with coordinate \c _point
virtual VertexHandle add_vertex(const Vec3f& _point) = 0;
// add a face with indices _indices refering to vertices
typedef std::vector<VertexHandle> VHandles;
virtual FaceHandle add_face(const VHandles& _indices) = 0;
// set vertex normal
virtual void set_normal(VertexHandle _vh, const Vec3f& _normal) = 0;
// set vertex color
virtual void set_color(VertexHandle _vh, const Vec3uc& _color) = 0;
// set vertex color
virtual void set_color(VertexHandle _vh, const Vec4uc& _color) = 0;
// set vertex texture coordinate
virtual void set_texcoord(VertexHandle _vh, const Vec2f& _texcoord) = 0;
// set face normal
virtual void set_normal(FaceHandle _fh, const Vec3f& _normal) = 0;
// set face color
virtual void set_color(FaceHandle _fh, const Vec3uc& _color) = 0;
// set face color
virtual void set_color(FaceHandle _fh, const Vec4uc& _color) = 0;
// get reference to base kernel
virtual BaseKernel* kernel() { return 0; }
virtual bool is_triangle_mesh() const { return false; }
// reserve mem for elements
virtual void reserve( unsigned int /* nV */,
unsigned int /* nE */,
unsigned int /* nF */) {}
// query number of faces, vertices, normals, texcoords
virtual size_t n_vertices() const = 0;
virtual size_t n_faces() const = 0;
virtual size_t n_edges() const = 0;
// pre-processing
virtual void prepare() {}
// post-processing
virtual void finish() {}
};
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@@ -0,0 +1,235 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements an importer module for arbitrary OpenMesh meshes
//
//=============================================================================
#ifndef __IMPORTERT_HH__
#define __IMPORTERT_HH__
//=== INCLUDES ================================================================
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/Utils/vector_cast.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
#include <OpenMesh/Core/Mesh/Attributes.hh>
#include <OpenMesh/Core/System/omstream.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
* This class template provides an importer module for OpenMesh meshes.
*/
template <class Mesh>
class ImporterT : public BaseImporter
{
public:
typedef typename Mesh::Point Point;
typedef typename Mesh::Normal Normal;
typedef typename Mesh::Color Color;
typedef typename Mesh::TexCoord2D TexCoord2D;
typedef std::vector<VertexHandle> VHandles;
ImporterT(Mesh& _mesh) : mesh_(_mesh) {}
virtual VertexHandle add_vertex(const Vec3f& _point)
{
return mesh_.add_vertex(vector_cast<Point>(_point));
}
virtual FaceHandle add_face(const VHandles& _indices)
{
FaceHandle fh;
if (_indices.size() > 2)
{
VHandles::const_iterator it, it2, end(_indices.end());
// test for valid vertex indices
for (it=_indices.begin(); it!=end; ++it)
if (! mesh_.is_valid_handle(*it))
{
omerr() << "ImporterT: Face contains invalid vertex index\n";
return fh;
}
// don't allow double vertices
for (it=_indices.begin(); it!=end; ++it)
for (it2=it+1; it2!=end; ++it2)
if (*it == *it2)
{
omerr() << "ImporterT: Face has equal vertices\n";
failed_faces_.push_back(_indices);
return fh;
}
// try to add face
fh = mesh_.add_face(_indices);
if (!fh.is_valid())
{
failed_faces_.push_back(_indices);
return fh;
}
}
return fh;
}
// vertex attributes
virtual void set_normal(VertexHandle _vh, const Vec3f& _normal)
{
if (mesh_.has_vertex_normals())
mesh_.set_normal(_vh, vector_cast<Normal>(_normal));
}
virtual void set_color(VertexHandle _vh, const Vec4uc& _color)
{
if (mesh_.has_vertex_colors())
mesh_.set_color(_vh, color_cast<Color>(_color));
}
virtual void set_color(VertexHandle _vh, const Vec3uc& _color)
{
if (mesh_.has_vertex_colors())
mesh_.set_color(_vh, color_cast<Color>(_color));
}
virtual void set_texcoord(VertexHandle _vh, const Vec2f& _texcoord)
{
if (mesh_.has_vertex_texcoords2D())
mesh_.set_texcoord2D(_vh, vector_cast<TexCoord2D>(_texcoord));
}
// face attributes
virtual void set_normal(FaceHandle _fh, const Vec3f& _normal)
{
if (mesh_.has_face_normals())
mesh_.set_normal(_fh, vector_cast<Normal>(_normal));
}
virtual void set_color(FaceHandle _fh, const Vec3uc& _color)
{
if (mesh_.has_face_colors())
mesh_.set_color(_fh, color_cast<Color>(_color));
}
virtual void set_color(FaceHandle _fh, const Vec4uc& _color)
{
if (mesh_.has_face_colors())
mesh_.set_color(_fh, color_cast<Color>(_color));
}
// low-level access to mesh
virtual BaseKernel* kernel() { return &mesh_; }
bool is_triangle_mesh() const
{ return Mesh::is_triangles(); }
void reserve(unsigned int nV, unsigned int nE, unsigned int nF)
{
mesh_.reserve(nV, nE, nF);
}
// query number of faces, vertices, normals, texcoords
size_t n_vertices() const { return mesh_.n_vertices(); }
size_t n_faces() const { return mesh_.n_faces(); }
size_t n_edges() const { return mesh_.n_edges(); }
void prepare() { failed_faces_.clear(); }
void finish()
{
if (!failed_faces_.empty())
{
omerr() << failed_faces_.size()
<< " faces failed, adding them as isolated faces\n";
for (unsigned int i=0; i<failed_faces_.size(); ++i)
{
VHandles& vhandles = failed_faces_[i];
// double vertices
for (unsigned int j=0; j<vhandles.size(); ++j)
{
Point p = mesh_.point(vhandles[j]);
vhandles[j] = mesh_.add_vertex(p);
// DO STORE p, reference may not work since vertex array
// may be relocated after adding a new vertex !
}
// add face
mesh_.add_face(vhandles);
}
failed_faces_.clear();
}
}
private:
Mesh& mesh_;
std::vector<VHandles> failed_faces_;
};
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@@ -0,0 +1,17 @@
#== SYSTEM PART -- DON'T TOUCH ==============================================
include $(ACGMAKE)/Config
#==============================================================================
SUBDIRS = $(call find-subdirs)
PACKAGES :=
PROJ_LIBS :=
MODULES := cxxlib
#== SYSTEM PART -- DON'T TOUCH ==============================================
include $(ACGMAKE)/Rules
#==============================================================================

View File

@@ -0,0 +1,113 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=== INCLUDES ================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
#include <algorithm>
#include <string>
#include <iterator>
#if defined(OM_CC_MIPS)
# include <ctype.h>
#else
# include <cctype>
#endif
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
static inline char tolower(char c)
{
using namespace std;
return ::tolower(c);
}
//-----------------------------------------------------------------------------
bool
BaseReader::
can_u_read(const std::string& _filename) const
{
// get file extension
std::string extension;
std::string::size_type pos(_filename.rfind("."));
if (pos != std::string::npos)
{
extension = _filename.substr(pos+1, _filename.length()-pos-1);
std::transform( extension.begin(), extension.end(),
extension.begin(), tolower );
}
// locate extension in extension string
return (get_extensions().find(extension) != std::string::npos);
}
//-----------------------------------------------------------------------------
bool
BaseReader::
check_extension(const std::string& _fname, const std::string& _ext) const
{
std::string cmpExt(_ext);
std::transform( _ext.begin(), _ext.end(), cmpExt.begin(), tolower );
std::string::size_type pos(_fname.rfind("."));
if (pos != std::string::npos && !_ext.empty() )
{
std::string ext;
// extension without dot!
ext = _fname.substr(pos+1, _fname.length()-pos-1);
std::transform( ext.begin(), ext.end(), ext.begin(), tolower );
return ext == cmpExt;
}
return false;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@@ -0,0 +1,113 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements the baseclass for IOManager file access modules
//
//=============================================================================
#ifndef __BASEREADER_HH__
#define __BASEREADER_HH__
//=== INCLUDES ================================================================
// STD C++
#include <iostream>
#include <string>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/Options.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/Utils/SingletonT.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
Base class for reader modules.
Reader modules access persistent data and pass them to the desired
data structure by the means of a BaseImporter derivative.
All reader modules must be derived from this class.
*/
class BaseReader
{
public:
/// Returns a brief description of the file type that can be parsed.
virtual std::string get_description() const = 0;
/** Returns a string with the accepted file extensions separated by a
whitespace and in small caps.
*/
virtual std::string get_extensions() const = 0;
/// Return magic bits used to determine file format
virtual std::string get_magic() const { return std::string(""); }
/** Reads a mesh given by a filename. Usually this method opens a stream
and passes it to stream read method. Acceptance checks by filename
extension can be placed here.
Options can be passed via _opt. After execution _opt contains the Options
that were available
*/
virtual bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt) = 0;
/// Returns true if reader can parse _filename (checks extension)
virtual bool can_u_read(const std::string& _filename) const;
protected:
// case insensitive search for _ext in _fname.
bool check_extension(const std::string& _fname,
const std::string& _ext) const;
};
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

472
Core/IO/reader/OBJReader.cc Normal file
View File

@@ -0,0 +1,472 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
// OpenMesh
#include <OpenMesh/Core/IO/reader/OBJReader.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Utils/vector_cast.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
// STL
#if defined(OM_CC_MIPS)
# include <ctype.h>
/// \bug Workaround for STLPORT 4.6: isspace seems not to be in namespace std!
#elif defined(_STLPORT_VERSION) && (_STLPORT_VERSION==0x460)
# include <cctype>
#else
# include <cctype>
using std::isspace;
#endif
#ifndef WIN32
#include <string.h>
#endif
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
_OBJReader_ __OBJReaderInstance;
_OBJReader_& OBJReader() { return __OBJReaderInstance; }
//=== IMPLEMENTATION ==========================================================
_OBJReader_::
_OBJReader_()
{
IOManager().register_module(this);
}
//-----------------------------------------------------------------------------
bool
_OBJReader_::
read(const std::string& _filename, BaseImporter& _bi, Options& _opt)
{
std::fstream in( _filename.c_str(), std::ios_base::in );
if (!in)
{
omerr() << "[OBJReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
{
#if defined(WIN32)
std::string::size_type dot = _filename.find_last_of("\\/");
#else
std::string::size_type dot = _filename.rfind("/");
#endif
path_ = (dot == std::string::npos)
? "./"
: std::string(_filename.substr(0,dot+1));
}
bool result = read(in, _bi, _opt);
in.close();
return result;
}
//-----------------------------------------------------------------------------
bool
_OBJReader_::
read_material(std::fstream& _in)
{
std::string line;
std::string keyWrd;
std::string key;
Material mat;
float f1,f2,f3;
bool indef = false;
mat.cleanup();
while( _in && !_in.eof() )
{
std::getline(_in,line);
if ( _in.bad() ){
omerr() << " Warning! Could not read file properly!\n";
return false;
}
if ( line.empty() )
continue;
std::stringstream stream(line);
stream >> keyWrd;
if( isspace(line[0]) || line[0] == '#' )
{
if (indef && !key.empty() && mat.is_valid())
{
materials_[key] = mat;
mat.cleanup();
}
}
else if (keyWrd == "newmtl") // begin new material definition
{
stream >> key;
indef = true;
}
else if (keyWrd == "Kd") // diffuse color
{
stream >> f1; stream >> f2; stream >> f3;
if( !stream.fail() )
mat.set_Kd(f1,f2,f3);
}
else if (keyWrd == "Ka") // ambient color
{
stream >> f1; stream >> f2; stream >> f3;
if( !stream.fail() )
mat.set_Ka(f1,f2,f3);
}
else if (keyWrd == "Ks") // specular color
{
stream >> f1; stream >> f2; stream >> f3;
if( !stream.fail() )
mat.set_Ks(f1,f2,f3);
}
#if 0
else if (keyWrd == "illum") // diffuse/specular shading model
{
; // just skip this
}
else if (keyWrd == "Ns") // Shininess [0..200]
{
; // just skip this
}
else if (keyWrd == "map_") // map images
{
// map_Kd, diffuse map
// map_Ks, specular map
// map_Ka, ambient map
// map_Bump, bump map
// map_d, opacity map
; // just skip this
}
#endif
else if (keyWrd == "Tr") // transparency value
{
stream >> f1;
if( !stream.fail() )
mat.set_Tr(f1);
}
else if (keyWrd == "d") // transparency value
{
stream >> f1;
if( !stream.fail() )
mat.set_Tr(f1);
}
if ( _in && indef && mat.is_valid() && !key.empty())
materials_[key] = mat;
}
return true;
}
//-----------------------------------------------------------------------------
bool
_OBJReader_::
read(std::fstream& _in, BaseImporter& _bi, Options& _opt)
{
omlog() << "[OBJReader] : read file\n";
std::string line;
std::string keyWrd;
float x, y, z, u, v;
BaseImporter::VHandles vhandles;
std::vector<Vec3f> normals;
std::vector<Vec2f> texcoords;
std::map<std::string,Material> materials;
std::string matname;
while( _in && !_in.eof() )
{
std::getline(_in,line);
if ( _in.bad() ){
omerr() << " Warning! Could not read file properly!\n";
return false;
}
// comment
if ( line.size() == 0 || line[0] == '#' || isspace(line[0]) ) {
continue;
}
std::stringstream stream(line);
stream >> keyWrd;
// material file
if (keyWrd == "mtllib")
{
std::string matFile;
stream >> matFile;
matFile = path_ + matFile;
omlog() << "Load material file " << matFile << std::endl;
std::fstream matStream( matFile.c_str(), std::ios_base::in );
if ( matStream ){
if ( !read_material( matStream ) )
omerr() << " Warning! Could not read file properly!\n";
matStream.close();
omlog() << " " << materials_.size() << " materials loaded.\n";
}else
omerr() << " Warning! Material file '" << matFile << "' not found!\n";
}
// usemtl
else if (keyWrd == "usemtl")
{
stream >> matname;
if (materials_.find(matname)==materials_.end())
{
omerr() << "Warning! Material '" << matname
<< "' not defined in material file.\n";
matname="";
}
}
// vertex
else if (keyWrd == "v")
{
stream >> x; stream >> y; stream >> z;
if ( !stream.fail() )
_bi.add_vertex(OpenMesh::Vec3f(x,y,z));
}
// texture coord
else if (keyWrd == "vt")
{
stream >> u; stream >> v;
if ( !stream.fail() ){
texcoords.push_back(OpenMesh::Vec2f(u, v));
_opt += Options::VertexTexCoord;
}else{
omerr() << "Only single 2D texture coordinate per vertex"
<< "allowed!" << std::endl;
return false;
}
}
// normal
else if (keyWrd == "vn")
{
stream >> x; stream >> y; stream >> z;
if ( !stream.fail() ){
normals.push_back(OpenMesh::Vec3f(x,y,z));
_opt += Options::VertexNormal;
}
}
// face
else if (keyWrd == "f")
{
int component(0), nV(0);
int value;
vhandles.clear();
// read full line after detecting a face
std::string faceLine;
std::getline(stream,faceLine);
std::stringstream lineData( faceLine );
// work on the line until nothing left to read
while ( !lineData.eof() )
{
// read one block from the line ( vertex/texCoord/normal )
std::string vertex;
lineData >> vertex;
do{
//get the component (vertex/texCoord/normal)
size_t found=vertex.find("/");
// parts are seperated by '/' So if no '/' found its the last component
if( found != std::string::npos ){
// read the index value
std::stringstream tmp( vertex.substr(0,found) );
// If we get an empty string this property is undefined in the file
if ( vertex.substr(0,found).empty() ) {
// Switch to next field
vertex = vertex.substr(found+1);
// Now we are at the next component
++component;
// Skip further processing of this component
continue;
}
// Read current value
tmp >> value;
// remove the read part from the string
vertex = vertex.substr(found+1);
} else {
// last component of the vertex, read it.
std::stringstream tmp( vertex );
tmp >> value;
// Nothing to read here ( garbage at end of line )
if ( tmp.fail() ) {
continue;
}
}
// store the component ( each component is referenced by the index here! )
switch (component)
{
case 0: // vertex
if ( value < 0 ) {
// std::cerr << "Handling negativ vertex index value" << std::endl;
value = _bi.n_vertices() + value + 1;
}
vhandles.push_back(VertexHandle(value-1));
break;
case 1: // texture coord
if ( value < 0 ) {
// std::cerr << "Handling negativ texture coordinate index value)" << std::endl;
value = _bi.n_vertices() + value + 1;
}
assert(!vhandles.empty());
assert((unsigned int)(value-1) < texcoords.size());
_bi.set_texcoord(vhandles.back(), texcoords[value-1]);
break;
case 2: // normal
if ( value < 0 ) {
// std::cerr << "Handling negativ normal index value)" << std::endl;
value = _bi.n_vertices() + value + 1;
}
assert(!vhandles.empty());
assert((unsigned int)(value-1) < normals.size());
_bi.set_normal(vhandles.back(), normals[value-1]);
break;
}
// Prepare for reading next component
++component;
} while ( vertex.find("/") != std::string::npos );
component = 0;
nV++;
}
size_t n_faces = _bi.n_faces();
FaceHandle fh = _bi.add_face(vhandles);
if ( !matname.empty() && materials_[matname].has_Kd() )
{
std::vector<FaceHandle> newfaces;
for( size_t i=0; i < _bi.n_faces()-n_faces; ++i )
newfaces.push_back(FaceHandle(n_faces+i));
Material & mat = materials_[matname];
Vec3uc fc = color_cast<Vec3uc, Vec3f>(mat.Kd());
for (std::vector<FaceHandle>::iterator it = newfaces.begin();
it != newfaces.end(); ++it)
_bi.set_color( *it, fc );
_opt += Options::FaceColor;
}
}
}
return true;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

159
Core/IO/reader/OBJReader.hh Normal file
View File

@@ -0,0 +1,159 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements an reader module for OBJ files
//
//=============================================================================
#ifndef __OBJREADER_HH__
#define __OBJREADER_HH__
//=== INCLUDES ================================================================
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <fstream>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== IMPLEMENTATION ===========================================================
/**
Implementation of the OBJ format reader.
*/
class _OBJReader_ : public BaseReader
{
public:
_OBJReader_();
virtual ~_OBJReader_() { }
std::string get_description() const { return "Alias/Wavefront"; }
std::string get_extensions() const { return "obj"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt);
private:
#ifndef DOXY_IGNORE_THIS
class Material
{
public:
Material() { cleanup(); }
void cleanup()
{
Kd_is_set_ = false;
Ka_is_set_ = false;
Ks_is_set_ = false;
Tr_is_set_ = false;
}
bool is_valid(void) const
{ return Kd_is_set_ || Ka_is_set_ || Ks_is_set_ || Tr_is_set_; }
bool has_Kd(void) { return Kd_is_set_; }
bool has_Ka(void) { return Ka_is_set_; }
bool has_Ks(void) { return Ks_is_set_; }
bool has_Tr(void) { return Tr_is_set_; }
void set_Kd( float r, float g, float b )
{ Kd_=Vec3f(r,g,b); Kd_is_set_=true; }
void set_Ka( float r, float g, float b )
{ Ka_=Vec3f(r,g,b); Ka_is_set_=true; }
void set_Ks( float r, float g, float b )
{ Ks_=Vec3f(r,g,b); Ks_is_set_=true; }
void set_Tr( float t )
{ Tr_=t; Tr_is_set_=true; }
const Vec3f& Kd( void ) const { return Kd_; }
const Vec3f& Ka( void ) const { return Ka_; }
const Vec3f& Ks( void ) const { return Ks_; }
float Tr( void ) const { return Tr_; }
private:
Vec3f Kd_; bool Kd_is_set_; // diffuse
Vec3f Ka_; bool Ka_is_set_; // ambient
Vec3f Ks_; bool Ks_is_set_; // specular
float Tr_; bool Tr_is_set_; // transperency
};
#endif
typedef std::map<std::string, Material> MaterialList;
MaterialList materials_;
bool read_material( std::fstream& _in );
private:
bool read(std::fstream& _in, BaseImporter& _bi, Options& _opt);
std::string path_;
};
//== TYPE DEFINITION ==========================================================
extern _OBJReader_ __OBJReaderInstance;
_OBJReader_& OBJReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

597
Core/IO/reader/OFFReader.cc Normal file
View File

@@ -0,0 +1,597 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
#define LINE_LEN 4096
//== INCLUDES =================================================================
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/IO/reader/OFFReader.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
// #include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/IO/SR_store.hh>
//STL
#include <fstream>
#include <memory>
#ifndef WIN32
#include <string.h>
#endif
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
//=== INSTANCIATE =============================================================
_OFFReader_ __OFFReaderInstance;
_OFFReader_& OFFReader() { return __OFFReaderInstance; }
//=== IMPLEMENTATION ==========================================================
_OFFReader_::_OFFReader_()
{
IOManager().register_module(this);
}
//-----------------------------------------------------------------------------
bool
_OFFReader_::read(const std::string& _filename, BaseImporter& _bi,
Options& _opt)
{
std::fstream in(_filename.c_str(), (options_.is_binary() ? std::ios_base::binary | std::ios_base::in
: std::ios_base::in) );
if (!in)
{
omerr() << "[OFFReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
bool result = read(in, _bi, _opt);
in.close();
return result;
}
//-----------------------------------------------------------------------------
bool
_OFFReader_::read(std::fstream& _in, BaseImporter& _bi, Options& _opt ) const
{
// filter relevant options for reading
bool swap = _opt.check( Options::Swap );
userOptions_ = _opt;
// build options to be returned
_opt.clear();
if (options_.vertex_has_normal() && userOptions_.vertex_has_normal()) _opt += Options::VertexNormal;
if (options_.vertex_has_texcoord() && userOptions_.vertex_has_texcoord()) _opt += Options::VertexTexCoord;
if (options_.vertex_has_color() && userOptions_.vertex_has_color()) _opt += Options::VertexColor;
if (options_.face_has_color() && userOptions_.face_has_color()) _opt += Options::FaceColor;
if (options_.is_binary()) _opt += Options::Binary;
//force user-choice for the alpha value when reading binary
if ( options_.is_binary() && userOptions_.color_has_alpha() )
options_ += Options::ColorAlpha;
return (options_.is_binary() ?
read_binary(_in, _bi, swap) :
read_ascii(_in, _bi));
}
//-----------------------------------------------------------------------------
bool
_OFFReader_::read_ascii(std::fstream& _in, BaseImporter& _bi) const
{
omlog() << "[OFFReader] : read ascii file\n";
unsigned int i, j, k, l, idx;
unsigned int nV, nF, dummy;
OpenMesh::Vec3f v, n;
OpenMesh::Vec2f t;
OpenMesh::Vec3i c3;
OpenMesh::Vec3f c3f;
OpenMesh::Vec4i c4;
OpenMesh::Vec4f c4f;
BaseImporter::VHandles vhandles;
VertexHandle vh;
// read header line
std::string header;
std::getline(_in,header);
// + #Vertice, #Faces, #Edges
_in >> nV;
_in >> nF;
_in >> dummy;
_bi.reserve(nV, 3*nV, nF);
// read vertices: coord [hcoord] [normal] [color] [texcoord]
for (i=0; i<nV && !_in.eof(); ++i)
{
// Always read VERTEX
_in >> v[0]; _in >> v[1]; _in >> v[2];
vh = _bi.add_vertex(v);
//perhaps read NORMAL
if ( options_.vertex_has_normal() ){
_in >> n[0]; _in >> n[1]; _in >> n[2];
if ( userOptions_.vertex_has_normal() )
_bi.set_normal(vh, n);
}
//take the rest of the line and check how colors are defined
std::string line;
std::getline(_in,line);
int colorType = getColorType(line, options_.vertex_has_texcoord() );
std::stringstream stream( line );
//perhaps read COLOR
if ( options_.vertex_has_color() ){
std::string trash;
switch (colorType){
case 0 : break; //no color
case 1 : stream >> trash; break; //one int (isn't handled atm)
case 2 : stream >> trash; stream >> trash; break; //corrupt format (ignore)
// rgb int
case 3 : stream >> c3[0]; stream >> c3[1]; stream >> c3[2];
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, Vec3uc( c3 ) );
break;
// rgba int
case 4 : stream >> c4[0]; stream >> c4[1]; stream >> c4[2]; stream >> c4[3];
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, Vec4uc( c4 ) );
break;
// rgb floats
case 5 : stream >> c3f[0]; stream >> c3f[1]; stream >> c3f[2];
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, color_cast<Vec3uc, Vec3f>(c3f) );
break;
// rgba floats
case 6 : stream >> c4f[0]; stream >> c4f[1]; stream >> c4f[2]; stream >> c4f[3];
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, color_cast<Vec4uc, Vec4f>(c4f) );
break;
default:
std::cerr << "Error in file format (colorType = " << colorType << ")\n";
}
}
//perhaps read TEXTURE COORDs
if ( options_.vertex_has_texcoord() ){
stream >> t[0]; stream >> t[1];
if ( userOptions_.vertex_has_texcoord() )
_bi.set_texcoord(vh, t);
}
}
// faces
// #N <v1> <v2> .. <v(n-1)> [color spec]
for (i=0; i<nF; ++i)
{
// nV = number of Vertices for current face
_in >> nV;
if (nV == 3)
{
vhandles.resize(3);
_in >> j;
_in >> k;
_in >> l;
vhandles[0] = VertexHandle(j);
vhandles[1] = VertexHandle(k);
vhandles[2] = VertexHandle(l);
}
else
{
vhandles.clear();
for (j=0; j<nV; ++j)
{
_in >> idx;
vhandles.push_back(VertexHandle(idx));
}
}
FaceHandle fh = _bi.add_face(vhandles);
//perhaps read face COLOR
if ( options_.face_has_color() ){
//take the rest of the line and check how colors are defined
std::string line;
std::getline(_in,line);
int colorType = getColorType(line, false );
std::stringstream stream( line );
std::string trash;
switch (colorType){
case 0 : break; //no color
case 1 : stream >> trash; break; //one int (isn't handled atm)
case 2 : stream >> trash; stream >> trash; break; //corrupt format (ignore)
// rgb int
case 3 : stream >> c3[0]; stream >> c3[1]; stream >> c3[2];
if ( userOptions_.face_has_color() )
_bi.set_color( fh, Vec3uc( c3 ) );
break;
// rgba int
case 4 : stream >> c4[0]; stream >> c4[1]; stream >> c4[2]; stream >> c4[3];
if ( userOptions_.face_has_color() )
_bi.set_color( fh, Vec4uc( c4 ) );
break;
// rgb floats
case 5 : stream >> c3f[0]; stream >> c3f[1]; stream >> c3f[2];
if ( userOptions_.face_has_color() )
_bi.set_color( fh, color_cast<Vec3uc, Vec3f>(c3f) );
break;
// rgba floats
case 6 : stream >> c4f[0]; stream >> c4f[1]; stream >> c4f[2]; stream >> c4f[3];
if ( userOptions_.face_has_color() )
_bi.set_color( fh, color_cast<Vec4uc, Vec4f>(c4f) );
break;
default:
std::cerr << "Error in file format (colorType = " << colorType << ")\n";
}
}
}
// File was successfully parsed.
return true;
}
//-----------------------------------------------------------------------------
int _OFFReader_::getColorType(std::string& _line, bool _texCoordsAvailable) const
{
/*
0 : no Color
1 : one int (e.g colormap index)
2 : two items (error!)
3 : 3 ints
4 : 3 ints
5 : 3 floats
6 : 4 floats
*/
// Check if we have any additional information here
if ( _line.size() < 1 )
return 0;
//first remove spaces at start/end of the line
while (_line[0] == ' ')
_line = _line.substr(1);
while (_line[ _line.length()-1 ] == ' ')
_line = _line.substr(0, _line.length()-2);
//count the remaining items in the line
size_t found;
int count = 0;
found=_line.find_first_of(" ");
while (found!=std::string::npos){
count++;
found=_line.find_first_of(" ",found+1);
}
if (_line != "") count++;
if (_texCoordsAvailable) count -= 2;
if (count == 3 || count == 4){
//get first item
found = _line.find(" ");
std::string c1 = _line.substr (0,found);
if (c1.find(".") != std::string::npos){
if (count == 3)
count = 5;
else
count = 6;
}
}
return count;
}
void _OFFReader_::readValue(std::fstream& _in, float& _value) const{
float32_t tmp;
restore( _in , tmp, false ); //assuming LSB byte order
_value = tmp;
}
void _OFFReader_::readValue(std::fstream& _in, int& _value) const{
uint32_t tmp;
restore( _in , tmp, false ); //assuming LSB byte order
_value = tmp;
}
void _OFFReader_::readValue(std::fstream& _in, unsigned int& _value) const{
uint32_t tmp;
restore( _in , tmp, false ); //assuming LSB byte order
_value = tmp;
}
bool
_OFFReader_::read_binary(std::fstream& _in, BaseImporter& _bi, bool /*_swap*/) const
{
omlog() << "[OFFReader] : read binary file\n";
unsigned int i, j, k, l, idx;
unsigned int nV, nF, dummy;
OpenMesh::Vec3f v, n;
OpenMesh::Vec3i c;
OpenMesh::Vec4i cA;
OpenMesh::Vec2f t;
BaseImporter::VHandles vhandles;
VertexHandle vh;
// read header line
std::string header;
std::getline(_in,header);
// + #Vertice, #Faces, #Edges
readValue(_in, nV);
readValue(_in, nF);
readValue(_in, dummy);
_bi.reserve(nV, 3*nV, nF);
// read vertices: coord [hcoord] [normal] [color] [texcoord]
for (i=0; i<nV && !_in.eof(); ++i)
{
// Always read Vertex
readValue(_in, v[0]);
readValue(_in, v[1]);
readValue(_in, v[2]);
vh = _bi.add_vertex(v);
if ( options_.vertex_has_normal() ) {
readValue(_in, n[0]);
readValue(_in, n[1]);
readValue(_in, n[2]);
if ( userOptions_.vertex_has_normal() )
_bi.set_normal(vh, n);
}
if ( options_.vertex_has_color() ) {
//with alpha
if ( options_.color_has_alpha() ){
readValue(_in, cA[0]);
readValue(_in, cA[1]);
readValue(_in, cA[2]);
readValue(_in, cA[3]);
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, Vec4uc( cA ) );
}else{
//without alpha
readValue(_in, c[0]);
readValue(_in, c[1]);
readValue(_in, c[2]);
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, Vec3uc( c ) );
}
}
if ( options_.vertex_has_texcoord()) {
readValue(_in, t[0]);
readValue(_in, t[1]);
if ( userOptions_.vertex_has_texcoord() )
_bi.set_texcoord(vh, t);
}
}
// faces
// #N <v1> <v2> .. <v(n-1)> [color spec]
// So far color spec is unsupported!
for (i=0; i<nF; ++i)
{
readValue(_in, nV);
if (nV == 3)
{
vhandles.resize(3);
readValue(_in, j);
readValue(_in, k);
readValue(_in, l);
vhandles[0] = VertexHandle(j);
vhandles[1] = VertexHandle(k);
vhandles[2] = VertexHandle(l);
}
else
{
vhandles.clear();
for (j=0; j<nV; ++j)
{
readValue(_in, idx);
vhandles.push_back(VertexHandle(idx));
}
}
FaceHandle fh = _bi.add_face(vhandles);
//face color
if ( options_.face_has_color() ) {
//with alpha
if ( options_.color_has_alpha() ){
readValue(_in, cA[0]);
readValue(_in, cA[1]);
readValue(_in, cA[2]);
readValue(_in, cA[3]);
if ( userOptions_.face_has_color() )
_bi.set_color( fh , Vec4uc( cA ) );
}else{
//without alpha
readValue(_in, c[0]);
readValue(_in, c[1]);
readValue(_in, c[2]);
if ( userOptions_.face_has_color() )
_bi.set_color( fh, Vec3uc( c ) );
}
}
}
// File was successfully parsed.
return true;
}
//-----------------------------------------------------------------------------
bool _OFFReader_::can_u_read(const std::string& _filename) const
{
// !!! Assuming BaseReader::can_u_parse( std::string& )
// does not call BaseReader::read_magic()!!!
if (BaseReader::can_u_read(_filename))
{
std::ifstream ifs(_filename.c_str());
if (ifs.is_open() && can_u_read(ifs))
{
ifs.close();
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
bool _OFFReader_::can_u_read(std::istream& _is) const
{
options_.cleanup();
// read 1st line
char line[LINE_LEN], *p;
_is.getline(line, LINE_LEN);
p = line;
int remainingChars = _is.gcount();
bool vertexDimensionTooHigh = false;
// check header: [ST][C][N][4][n]OFF BINARY
if ( ( remainingChars > 1 ) && ( p[0] == 'S' && p[1] == 'T') )
{ options_ += Options::VertexTexCoord; p += 2; remainingChars -= 2; }
if ( ( remainingChars > 0 ) && ( p[0] == 'C') )
{ options_ += Options::VertexColor;
options_ += Options::FaceColor; ++p; --remainingChars; }
if ( ( remainingChars > 0 ) && ( p[0] == 'N') )
{ options_ += Options::VertexNormal; ++p; --remainingChars; }
if ( ( remainingChars > 0 ) && (p[0] == '4' ) )
{ vertexDimensionTooHigh = true; ++p; --remainingChars; }
if ( ( remainingChars > 0 ) && ( p[0] == 'n') )
{ vertexDimensionTooHigh = true; ++p; --remainingChars; }
if ( ( remainingChars < 3 ) || (!(p[0] == 'O' && p[1] == 'F' && p[2] == 'F') ) )
return false;
p += 4;
remainingChars -= 4;
if ( ( remainingChars >= 6 ) && ( strncmp(p, "BINARY", 6) == 0 ) )
options_+= Options::Binary;
// vertex Dimensions != 3 are currently not supported
if (vertexDimensionTooHigh)
return false;
return true;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

150
Core/IO/reader/OFFReader.hh Normal file
View File

@@ -0,0 +1,150 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a reader module for OFF files
//
//=============================================================================
#ifndef __OFFREADER_HH__
#define __OFFREADER_HH__
//=== INCLUDES ================================================================
#include <iostream>
#include <string>
#include <stdio.h>
#include <fstream>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
#ifndef WIN32
#include <string.h>
#endif
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== FORWARDS =================================================================
class BaseImporter;
//== IMPLEMENTATION ===========================================================
/**
Implementation of the OFF format reader. This class is singleton'ed by
SingletonT to OFFReader.
By passing Options to the read function you can manipulate the reading behavoir.
The following options can be set:
VertexNormal
VertexColor
VertexTexCoord
FaceColor
ColorAlpha [only when reading binary]
These options define if the corresponding data should be read (if available)
or if it should be omitted.
After execution of the read function. The options object contains information about
what was actually read.
e.g. if VertexNormal was true when the read function was called, but the file
did not contain vertex normals then it is false afterwards.
When reading a binary off with Color Flag in the header it is assumed that all vertices
and faces have colors in the format "int int int".
If ColorAlpha is set the format "int int int int" is assumed.
*/
class _OFFReader_ : public BaseReader
{
public:
_OFFReader_();
std::string get_description() const { return "Object File Format"; }
std::string get_extensions() const { return "off"; }
std::string get_magic() const { return "OFF"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt);
bool can_u_read(const std::string& _filename) const;
private:
bool can_u_read(std::istream& _is) const;
bool read(std::fstream& _in, BaseImporter& _bi, Options& _opt ) const;
bool read_ascii(std::fstream& _in, BaseImporter& _bi) const;
bool read_binary(std::fstream& _in, BaseImporter& _bi, bool swap) const;
void readValue(std::fstream& _in, float& _value) const;
void readValue(std::fstream& _in, int& _value) const;
void readValue(std::fstream& _in, unsigned int& _value) const;
int getColorType(std::string & _line, bool _texCoordsAvailable) const;
//available options for reading
mutable Options options_;
//options that the user wants to read
mutable Options userOptions_;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the OFF reader
extern _OFFReader_ __OFFReaderInstance;
_OFFReader_& OFFReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

628
Core/IO/reader/OMReader.cc Normal file
View File

@@ -0,0 +1,628 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
//STL
#include <fstream>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Utils/Endian.hh>
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <OpenMesh/Core/IO/reader/OMReader.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the OMReader singleton with MeshReader
_OMReader_ __OMReaderInstance;
_OMReader_& OMReader() { return __OMReaderInstance; }
//=== IMPLEMENTATION ==========================================================
_OMReader_::_OMReader_()
{
IOManager().register_module(this);
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt)
{
// check whether importer can give us an OpenMesh BaseKernel
if (!_bi.kernel()) return false;
_opt += Options::Binary; // only binary format supported!
// Open file
std::ifstream ifs( _filename.c_str(), std::ios::binary );
if (!ifs.is_open())
{
omerr() << "[OMReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
// Pass stream to read method, remember result
bool result = read(ifs, _bi, _opt);
// close input stream
ifs.close();
return result;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read(std::istream& _is, BaseImporter& _bi, Options& _opt ) const
{
// currently only binary file format is supported
_opt += Options::Binary;
return read_binary( _is, _bi, _opt );
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read_ascii( std::istream& /* _is */, BaseImporter& /* _bi */,
Options& /* _opt */) const
{
// not supported yet!
return false;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read_binary( std::istream& _is, BaseImporter& _bi,
Options& _opt) const
{
bool swap = _opt.check(Options::Swap) || (Endian::local() == Endian::MSB);
// intialize byte counter
bytes_ = 0;
bytes_ += restore( _is, header_, swap );
size_t data_bytes;
while( !_is.eof() )
{
bytes_ += restore( _is, chunk_header_, swap );
if ( _is.eof() )
break;
// Is this a named property restore the name
if ( chunk_header_.name_ )
{
OMFormat::Chunk::PropertyName pn;
bytes_ += restore( _is, property_name_, swap );
}
// Read in the property data. If it is an anonymous or unknown named
// property, then skip data.
data_bytes = bytes_;
switch( chunk_header_.entity_ )
{
case OMFormat::Chunk::Entity_Vertex:
if (!read_binary_vertex_chunk( _is, _bi, _opt, swap ))
return false;
break;
case OMFormat::Chunk::Entity_Face:
if (!read_binary_face_chunk( _is, _bi, _opt, swap ))
return false;
break;
case OMFormat::Chunk::Entity_Edge:
if (!read_binary_edge_chunk( _is, _bi, _opt, swap ))
return false;
break;
case OMFormat::Chunk::Entity_Halfedge:
if (!read_binary_halfedge_chunk( _is, _bi, _opt, swap ))
return false;
break;
case OMFormat::Chunk::Entity_Mesh:
if (!read_binary_mesh_chunk( _is, _bi, _opt, swap ))
return false;
break;
default:
return false;
}
data_bytes = bytes_ - data_bytes;
}
// File was successfully parsed.
return true;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::can_u_read(const std::string& _filename) const
{
// !!! Assuming BaseReader::can_u_parse( std::string& )
// does not call BaseReader::read_magic()!!!
if ( this->BaseReader::can_u_read( _filename ) )
{
std::ifstream ifile( _filename.c_str() );
if ( ifile && can_u_read( ifile ) )
return true;
}
return false;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::can_u_read(std::istream& _is) const
{
std::vector<char> evt;
evt.reserve(20);
// read first 4 characters into a buffer
while( evt.size() < 4 )
evt.push_back( static_cast<char>(_is.get()) );
// put back all read characters
std::vector<char>::reverse_iterator it = evt.rbegin();
while (it != evt.rend() )
_is.putback( *it++ );
// evaluate header information
OMFormat::Header *hdr = (OMFormat::Header*)&evt[0];
// first two characters must be 'OM'
if (hdr->magic_[0] != 'O' || hdr->magic_[1] != 'M')
return false;
// 3rd characters defines the mesh type:
switch(hdr->mesh_)
{
case 'T': // Triangle Mesh
case 'Q': // Quad Mesh
case 'P': // Polygonal Mesh
break;
default: // ?
return false;
}
// 4th characters encodes the version
return supports( hdr->version_ );
}
//-----------------------------------------------------------------------------
bool
_OMReader_::supports( const OMFormat::uint8 /* version */ ) const
{
return true;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read_binary_vertex_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Vertex );
OpenMesh::Vec3f v3f;
OpenMesh::Vec2f v2f;
OpenMesh::Vec3uc v3uc; // rgb
OMFormat::Chunk::PropertyName custom_prop;
size_t vidx=0;
switch (chunk_header_.type_)
{
case Chunk::Type_Pos:
assert( OMFormat::dimensions(chunk_header_)
== size_t(OpenMesh::Vec3f::dim()) );
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx)
{
bytes_ += vector_restore( _is, v3f, _swap );
_bi.add_vertex(v3f);
}
break;
case Chunk::Type_Normal:
assert( OMFormat::dimensions(chunk_header_)
== size_t(OpenMesh::Vec3f::dim()) );
_opt += Options::VertexNormal;
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx)
{
bytes_ += vector_restore( _is, v3f, _swap );
_bi.set_normal(VertexHandle(vidx), v3f);
}
break;
case Chunk::Type_Texcoord:
assert( OMFormat::dimensions(chunk_header_)
== size_t(OpenMesh::Vec2f::dim()) );
_opt += Options::VertexTexCoord;
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx)
{
bytes_ += vector_restore( _is, v2f, _swap );
_bi.set_texcoord(VertexHandle(vidx), v2f);
}
break;
case Chunk::Type_Color:
assert( OMFormat::dimensions(chunk_header_) == 3 );
_opt += Options::VertexColor;
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx)
{
bytes_ += vector_restore( _is, v3uc, _swap );
_bi.set_color( VertexHandle(vidx), v3uc );
}
break;
case Chunk::Type_Custom:
bytes_ +=
restore_binary_custom_data( _is,
_bi.kernel()->_get_vprop( property_name_ ),
header_.n_vertices_,
_swap );
vidx = header_.n_vertices_;
break;
default: // skip unknown chunks
{
omerr() << "Unknown chunk type ignored!\n";
size_t size_of = header_.n_vertices_
* OMFormat::vector_size(chunk_header_);
_is.ignore( size_of );
bytes_ += size_of;
}
}
// all chunk data has been read..?!
return vidx == header_.n_vertices_;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read_binary_face_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap ) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Face );
size_t fidx=0;
OpenMesh::Vec3f v3f; // normal
OpenMesh::Vec3uc v3uc; // rgb
switch( chunk_header_.type_ )
{
case Chunk::Type_Topology:
{
BaseImporter::VHandles vhandles;
size_t nV = 0;
size_t vidx = 0;
switch( header_.mesh_ )
{
case 'T': nV = 3; break;
case 'Q': nV = 4; break;
}
for (; fidx < header_.n_faces_; ++fidx)
{
if ( header_.mesh_ == 'P' )
bytes_ += restore( _is, nV, Chunk::Integer_16, _swap );
vhandles.clear();
for (size_t j=0; j<nV; ++j)
{
bytes_ += restore( _is, vidx,
Chunk::Integer_Size(chunk_header_.bits_),
_swap );
vhandles.push_back(VertexHandle(vidx));
}
_bi.add_face(vhandles);
}
}
break;
case Chunk::Type_Normal:
assert( OMFormat::dimensions(chunk_header_)
== size_t(OpenMesh::Vec3f::dim()) );
_opt += Options::FaceNormal;
for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx)
{
bytes_ += vector_restore( _is, v3f, _swap );
_bi.set_normal(FaceHandle(fidx), v3f);
}
break;
case Chunk::Type_Color:
assert( OMFormat::dimensions(chunk_header_) == 3 );
_opt += Options::FaceColor;
for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx)
{
bytes_ += vector_restore( _is, v3uc, _swap );
_bi.set_color( FaceHandle(fidx), v3uc );
}
break;
case Chunk::Type_Custom:
bytes_ +=
restore_binary_custom_data( _is,
_bi.kernel()->_get_fprop( property_name_ ),
header_.n_faces_,
_swap );
fidx = header_.n_faces_;
break;
default: // skip unknown chunks
{
omerr() << "Unknown chunk type ignore!\n";
size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
_is.ignore( size_of );
bytes_ += size_of;
}
}
return fidx == header_.n_faces_;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read_binary_edge_chunk( std::istream &_is,
BaseImporter &_bi,
Options &/*_opt */,
bool _swap ) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Edge );
size_t b=bytes_;
switch( chunk_header_.type_ )
{
case Chunk::Type_Custom:
bytes_ +=
restore_binary_custom_data( _is,
_bi.kernel()->_get_eprop( property_name_ ),
header_.n_edges_,
_swap );
break;
default:
// skip unknown type
size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
_is.ignore( size_of );
bytes_ += size_of;
}
return b < bytes_;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read_binary_halfedge_chunk( std::istream &_is,
BaseImporter &_bi,
Options &/* _opt */,
bool _swap ) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Halfedge );
size_t b = bytes_;
switch( chunk_header_.type_ )
{
case Chunk::Type_Custom:
bytes_ +=
restore_binary_custom_data( _is,
_bi.kernel()->_get_hprop( property_name_ ),
2*header_.n_edges_,
_swap );
break;
default:
// skip unknown chunk
omerr() << "Unknown chunk type ignored!\n";
size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
_is.ignore( size_of );
bytes_ += size_of;
}
return b < bytes_;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read_binary_mesh_chunk( std::istream &_is,
BaseImporter &_bi,
Options & /* _opt */,
bool _swap ) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Mesh );
size_t b = bytes_;
switch( chunk_header_.type_ )
{
case Chunk::Type_Custom:
bytes_ +=
restore_binary_custom_data( _is,
_bi.kernel()->_get_mprop( property_name_ ),
1,
_swap );
break;
default:
// skip unknown chunk
size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
_is.ignore( size_of );
bytes_ += size_of;
}
return b < bytes_;
}
//-----------------------------------------------------------------------------
size_t
_OMReader_::restore_binary_custom_data( std::istream& _is, BaseProperty* _bp,
size_t _n_elem, bool _swap) const
{
assert( !_bp || (_bp->name() == property_name_) );
using OMFormat::Chunk;
size_t bytes = 0;
Chunk::esize_t block_size;
Chunk::PropertyName custom_prop;
bytes += binary<Chunk::esize_t>::restore( _is, block_size, _swap );
if ( _bp )
{
#if defined(OM_DEBUG)
size_t b;
#endif
size_t n_bytes = _bp->size_of( _n_elem );
if ( ((n_bytes == BaseProperty::UnknownSize) || (n_bytes == block_size)) &&
(_bp->element_size() == BaseProperty::UnknownSize ||
(_n_elem * _bp->element_size() == block_size) ) )
{
#if defined(OM_DEBUG)
bytes += (b=_bp->restore( _is, _swap ));
#else
bytes += _bp->restore( _is, _swap );
#endif
#if defined(OM_DEBUG)
assert( block_size == b );
#endif
assert( block_size == _bp->size_of() );
block_size = 0;
}
else
{
omerr() << "Warning! Property " << _bp->name() << " not loaded: "
<< "Mismatching data sizes!n";
}
}
if (block_size)
{
_is.ignore( block_size );
bytes += block_size;
}
return bytes;
}
//-----------------------------------------------------------------------------
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

150
Core/IO/reader/OMReader.hh Normal file
View File

@@ -0,0 +1,150 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a reader module for OFF files
//
//=============================================================================
#ifndef __OMREADER_HH__
#define __OMREADER_HH__
//=== INCLUDES ================================================================
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
// STD C++
#include <iostream>
#include <string>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== IMPLEMENTATION ===========================================================
/**
Implementation of the OM format reader. This class is singleton'ed by
SingletonT to OMReader.
*/
class _OMReader_ : public BaseReader
{
public:
_OMReader_();
virtual ~_OMReader_() { }
std::string get_description() const { return "OpenMesh File Format"; }
std::string get_extensions() const { return "om"; }
std::string get_magic() const { return "OM"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt );
virtual bool can_u_read(const std::string& _filename) const;
virtual bool can_u_read(std::istream& _is) const;
private:
bool supports( const OMFormat::uint8 version ) const;
bool read(std::istream& _is, BaseImporter& _bi, Options& _opt ) const;
bool read_ascii(std::istream& _is, BaseImporter& _bi, Options& _opt) const;
bool read_binary(std::istream& _is, BaseImporter& _bi, Options& _opt) const;
typedef OMFormat::Header Header;
typedef OMFormat::Chunk::Header ChunkHeader;
typedef OMFormat::Chunk::PropertyName PropertyName;
// initialized/updated by read_binary*/read_ascii*
mutable size_t bytes_;
mutable Header header_;
mutable ChunkHeader chunk_header_;
mutable PropertyName property_name_;
bool read_binary_vertex_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
bool read_binary_face_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
bool read_binary_edge_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
bool read_binary_halfedge_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
bool read_binary_mesh_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
size_t restore_binary_custom_data( std::istream& _is,
BaseProperty* _bp,
size_t _n_elem,
bool _swap) const;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the OM reader.
extern _OMReader_ __OMReaderInstance;
_OMReader_& OMReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

683
Core/IO/reader/PLYReader.cc Normal file
View File

@@ -0,0 +1,683 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
#define LINE_LEN 4096
//== INCLUDES =================================================================
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/IO/reader/PLYReader.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
#include <OpenMesh/Core/IO/SR_store.hh>
//STL
#include <fstream>
#include <memory>
#ifndef WIN32
#include <string.h>
#endif
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
//=== INSTANCIATE =============================================================
_PLYReader_ __PLYReaderInstance;
_PLYReader_& PLYReader() { return __PLYReaderInstance; }
//=== IMPLEMENTATION ==========================================================
_PLYReader_::_PLYReader_()
{
IOManager().register_module(this);
}
//-----------------------------------------------------------------------------
bool
_PLYReader_::read(const std::string& _filename, BaseImporter& _bi,
Options& _opt)
{
std::fstream in(_filename.c_str(), (options_.is_binary() ? std::ios_base::binary | std::ios_base::in
: std::ios_base::in) );
if (!in)
{
omerr() << "[PLYReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
bool result = read(in, _bi, _opt);
in.close();
return result;
}
//-----------------------------------------------------------------------------
bool
_PLYReader_::read(std::fstream& _in, BaseImporter& _bi, Options& _opt ) const
{
// filter relevant options for reading
bool swap = _opt.check( Options::Swap );
userOptions_ = _opt;
// build options to be returned
_opt.clear();
if (options_.vertex_has_normal() && userOptions_.vertex_has_normal()) _opt += Options::VertexNormal;
if (options_.vertex_has_texcoord() && userOptions_.vertex_has_texcoord()) _opt += Options::VertexTexCoord;
if (options_.vertex_has_color() && userOptions_.vertex_has_color()) _opt += Options::VertexColor;
if (options_.face_has_color() && userOptions_.face_has_color()) _opt += Options::FaceColor;
if (options_.is_binary()) _opt += Options::Binary;
// //force user-choice for the alpha value when reading binary
// if ( options_.is_binary() && userOptions_.color_has_alpha() )
// options_ += Options::ColorAlpha;
return (options_.is_binary() ?
read_binary(_in, _bi, swap) :
read_ascii(_in, _bi));
}
//-----------------------------------------------------------------------------
bool
_PLYReader_::read_ascii(std::fstream& _in, BaseImporter& _bi) const
{
omlog() << "[PLYReader] : read ascii file\n";
// Reparse the header
if ( !can_u_read(_in) ) {
omerr() << "[PLYReader] : Unable to parse header\n";
return false;
}
unsigned int i, j, k, l, idx;
unsigned int nV;
OpenMesh::Vec3f v;
std::string trash;
// OpenMesh::Vec2f t;
OpenMesh::Vec4i c;
float tmp;
BaseImporter::VHandles vhandles;
VertexHandle vh;
_bi.reserve(vertexCount_, 3*vertexCount_, faceCount_);
std::cerr << "Vertices : " << vertexCount_ << std::endl;
if ( vertexDimension_ != 3 ) {
omerr() << "[PLYReader] : Only vertex dimension 3 is supported." << std::endl;
return false;
}
// read vertices:
for (i=0; i< vertexCount_ && !_in.eof(); ++i)
{
v[0] = 0.0;
v[1] = 0.0;
v[2] = 0.0;
c[0] = 0;
c[1] = 0;
c[2] = 0;
c[3] = 255;
for ( uint propertyIndex = 0 ; propertyIndex < vertexPropertyCount_; ++propertyIndex ) {
switch ( vertexPropertyMap_ [ propertyIndex].first ) {
case XCOORD:
_in >> v[0];
break;
case YCOORD:
_in >> v[1];
break;
case ZCOORD:
_in >> v[2];
break;
case COLORRED:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
_in >> tmp; c[0] = tmp * 255.0f;
}else
_in >> c[0];
break;
case COLORGREEN:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
_in >> tmp; c[1] = tmp * 255.0f;
}else
_in >> c[1];
break;
case COLORBLUE:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
_in >> tmp; c[2] = tmp * 255.0f;
}else
_in >> c[2];
break;
case COLORALPHA:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
_in >> tmp; c[3] = tmp * 255.0f;
}else
_in >> c[3];
break;
default :
_in >> trash;
break;
}
}
vh = _bi.add_vertex(v);
_bi.set_color( vh, Vec4uc( c ) );
}
// faces
// #N <v1> <v2> .. <v(n-1)> [color spec]
for (i=0; i<faceCount_; ++i)
{
// nV = number of Vertices for current face
_in >> nV;
if (nV == 3)
{
vhandles.resize(3);
_in >> j;
_in >> k;
_in >> l;
vhandles[0] = VertexHandle(j);
vhandles[1] = VertexHandle(k);
vhandles[2] = VertexHandle(l);
}
else
{
vhandles.clear();
for (j=0; j<nV; ++j)
{
_in >> idx;
vhandles.push_back(VertexHandle(idx));
}
}
FaceHandle fh = _bi.add_face(vhandles);
}
// File was successfully parsed.
return true;
}
//-----------------------------------------------------------------------------
void _PLYReader_::readValue(ValueType _type , std::fstream& _in, float& _value) const{
switch (_type) {
case ValueTypeFLOAT32:
case ValueTypeFLOAT:
float32_t tmp;
restore( _in , tmp, options_.check(Options::MSB) );
_value = tmp;
break;
default :
_value = 0.0;
std::cerr << "unsupported conversion type to float: " << _type << std::endl;
break;
}
}
void _PLYReader_::readValue(ValueType _type , std::fstream& _in, unsigned int& _value) const{
int32_t tmp_int32_t;
uint8_t tmp_uchar;
switch (_type) {
case ValueTypeINT:
case ValueTypeINT32:
restore( _in , tmp_int32_t, options_.check(Options::MSB) );
_value = tmp_int32_t;
break;
case ValueTypeUCHAR:
restore( _in , tmp_uchar, options_.check(Options::MSB) );
_value = tmp_uchar;
break;
default :
_value = 0;
std::cerr << "unsupported conversion type to int: " << _type << std::endl;
break;
}
}
void _PLYReader_::readValue(ValueType _type , std::fstream& _in, int& _value) const{
int32_t tmp_int32_t;
uint8_t tmp_uchar;
switch (_type) {
case ValueTypeINT:
case ValueTypeINT32:
restore( _in , tmp_int32_t, options_.check(Options::MSB) );
_value = tmp_int32_t;
break;
case ValueTypeUCHAR:
restore( _in , tmp_uchar, options_.check(Options::MSB) );
_value = tmp_uchar;
break;
default :
_value = 0;
std::cerr << "unsupported conversion type to int: " << _type << std::endl;
break;
}
}
bool
_PLYReader_::read_binary(std::fstream& _in, BaseImporter& _bi, bool /*_swap*/) const
{
omlog() << "[PLYReader] : read binary file format\n";
// Reparse the header
if ( !can_u_read(_in) ) {
omerr() << "[PLYReader] : Unable to parse header\n";
return false;
}
unsigned int i, j, k, l, idx;
unsigned int nV;
OpenMesh::Vec3f v;
BaseImporter::VHandles vhandles;
VertexHandle vh;
OpenMesh::Vec4i c;
float tmp;
_bi.reserve(vertexCount_, 3*vertexCount_, faceCount_);
// read vertices:
for (i=0; i< vertexCount_ && !_in.eof(); ++i)
{
v[0] = 0.0;
v[1] = 0.0;
v[2] = 0.0;
c[0] = 0;
c[1] = 0;
c[2] = 0;
c[3] = 255;
for ( uint propertyIndex = 0 ; propertyIndex < vertexPropertyCount_; ++propertyIndex ) {
switch ( vertexPropertyMap_ [ propertyIndex].first ) {
case XCOORD:
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,v[0]);
break;
case YCOORD:
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,v[1]);
break;
case ZCOORD:
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,v[2]);
break;
case COLORRED:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,tmp);
c[0] = tmp * 255.0f;
}else
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,c[0]);
break;
case COLORGREEN:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,tmp);
c[1] = tmp * 255.0f;
}else
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,c[1]);
break;
case COLORBLUE:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,tmp);
c[2] = tmp * 255.0f;
}else
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,c[2]);
break;
case COLORALPHA:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,tmp);
c[3] = tmp * 255.0f;
}else
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,c[3]);
break;
default :
break;
}
}
vh = _bi.add_vertex(v);
_bi.set_color( vh, Vec4uc( c ) );
}
for (i=0; i<faceCount_; ++i)
{
// Read number of vertices for the current face
readValue(faceIndexType_,_in,nV);
if (nV == 3)
{
vhandles.resize(3);
readValue(faceEntryType_,_in,j);
readValue(faceEntryType_,_in,k);
readValue(faceEntryType_,_in,l);
vhandles[0] = VertexHandle(j);
vhandles[1] = VertexHandle(k);
vhandles[2] = VertexHandle(l);
}
else
{
vhandles.clear();
for (j=0; j<nV; ++j)
{
readValue(faceEntryType_,_in,idx);
vhandles.push_back(VertexHandle(idx));
}
}
FaceHandle fh = _bi.add_face(vhandles);
}
return true;
}
//-----------------------------------------------------------------------------
bool _PLYReader_::can_u_read(const std::string& _filename) const
{
// !!! Assuming BaseReader::can_u_parse( std::string& )
// does not call BaseReader::read_magic()!!!
if (BaseReader::can_u_read(_filename))
{
std::ifstream ifs(_filename.c_str());
if (ifs.is_open() && can_u_read(ifs))
{
ifs.close();
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
std::string get_property_name(std::string _string1 , std::string _string2 ) {
if ( _string1 == "float32" ||
_string1 == "uint8" ||
_string1 == "uchar" ||
_string1 == "float" ||
_string1 == "int32")
return _string2;
if ( _string2 == "float32" ||
_string2 == "uint8" ||
_string2 == "uchar" ||
_string2 == "float" ||
_string2 == "int32")
return _string1;
std::cerr << "Unsupported entry type" << std::endl;
return "Unsupported";
}
//-----------------------------------------------------------------------------
_PLYReader_::ValueType get_property_type(std::string _string1 , std::string _string2 ) {
if ( _string1 == "float32" || _string2 == "float32" )
return _PLYReader_::ValueTypeFLOAT32;
else if ( _string1 == "uint8" || _string2 == "float32" )
return _PLYReader_::ValueTypeUINT8;
else if ( _string1 == "int32" || _string2 == "float32" )
return _PLYReader_::ValueTypeINT32;
else if ( _string1 == "uchar" || _string2 == "uchar" )
return _PLYReader_::ValueTypeINT32;
else if ( _string1 == "float" || _string2 == "float" )
return _PLYReader_::ValueTypeFLOAT;
return _PLYReader_::Unsupported;
}
//-----------------------------------------------------------------------------
bool _PLYReader_::can_u_read(std::istream& _is) const
{
// Clear per file options
options_.cleanup();
// clear vertex property map, will be recreated
vertexPropertyMap_.clear();
vertexPropertyCount_ = 0;
// read 1st line
std::string line;
std::getline(_is,line);
//Check if this file is really a ply format
if ( line != "PLY" && line != "ply" )
return false;
// omlog() << "PLY header found" << std::endl;
vertexCount_ = 0;
faceCount_ = 0;
vertexDimension_ = 0;
std::string keyword;
std::string fileType;
std::string elementName = "";
std::string propertyType;
std::string propertyName;
std::string listIndexType;
std::string listEntryType;
float version;
_is >> keyword;
_is >> fileType;
_is >> version;
if ( _is.bad() ) {
omerr() << "Defect PLY header detected" << std::endl;
return false;
}
if ( fileType == "ascii" ) {
options_ -= Options::Binary;
} else if ( fileType == "binary_little_endian" ){
options_ += Options::Binary;
options_ += Options::LSB;
} else if ( fileType == "binary_big_endian" ){
options_ += Options::Binary;
options_ += Options::MSB;
} else {
omerr() << "Unsupported PLY format: " << fileType << std::endl;
return false;
}
unsigned int streamPos = _is.tellg();
_is >> keyword;
while ( keyword != "end_header") {
if ( keyword == "comment" ) {
std::getline(_is,line);
omlog() << "PLY header comment : " << line << std::endl;
} else if ( keyword == "element") {
_is >> elementName;
if ( elementName == "vertex" ) {
_is >> vertexCount_;
} else if ( elementName == "face" ){
_is >> faceCount_;
} else {
omerr() << "PLY header unsupported element type: " << elementName << std::endl;
}
} else if ( keyword == "property") {
std::string tmp1;
std::string tmp2;
// Read first keyword, as it might be a list
_is >> tmp1;
if ( tmp1 == "list" ) {
if ( elementName == "vertex" ) {
omerr() << "List type not supported for vertices!" << std::endl;
} else if ( elementName == "face" ) {
_is >> listIndexType;
_is >> listEntryType;
_is >> propertyName;
if ( listIndexType == "uint8" ) {
faceIndexType_ = ValueTypeUINT8;
} else if ( listIndexType == "uchar" ) {
faceIndexType_ = ValueTypeUCHAR;
} else {
omerr() << "Unsupported Index type for face list: " << listIndexType << std::endl;
}
if ( listEntryType == "int32" ) {
faceEntryType_ = ValueTypeINT32;
} else if ( listEntryType == "int" ) {
faceEntryType_ = ValueTypeINT;
} else {
omerr() << "Unsupported Entry type for face list: " << listEntryType << std::endl;
}
}
} else {
// as this is not a list property, read second value of property
_is >> tmp2;
if ( elementName == "vertex" ) {
// Extract name and type of property
// As the order seems to be different in some files, autodetect it.
ValueType valueType = get_property_type(tmp1,tmp2);
propertyName = get_property_name(tmp1,tmp2);
std::cerr << "property " << propertyName << " Type " << valueType << std::endl;
if ( propertyName == "x" ) {
std::pair< VertexProperty, ValueType> entry(XCOORD,valueType);
vertexPropertyMap_[vertexPropertyCount_] = entry;
vertexDimension_++;
} else if ( propertyName == "y" ) {
std::pair< VertexProperty, ValueType> entry(YCOORD,valueType);
vertexPropertyMap_[vertexPropertyCount_] = entry;
vertexDimension_++;
} else if ( propertyName == "z" ) {
std::pair< VertexProperty, ValueType> entry(ZCOORD,valueType);
vertexPropertyMap_[vertexPropertyCount_] = entry;
vertexDimension_++;
} else if ( propertyName == "red" ) {
std::pair< VertexProperty, ValueType> entry(COLORRED,valueType);
vertexPropertyMap_[vertexPropertyCount_] = entry;
options_ += Options::VertexColor;
} else if ( propertyName == "green" ) {
std::pair< VertexProperty, ValueType> entry(COLORGREEN,valueType);
vertexPropertyMap_[vertexPropertyCount_] = entry;
options_ += Options::VertexColor;
} else if ( propertyName == "blue" ) {
std::pair< VertexProperty, ValueType> entry(COLORBLUE,valueType);
vertexPropertyMap_[vertexPropertyCount_] = entry;
options_ += Options::VertexColor;
} else if ( propertyName == "alpha" ) {
std::pair< VertexProperty, ValueType> entry(COLORALPHA,valueType);
vertexPropertyMap_[vertexPropertyCount_] = entry;
options_ += Options::VertexColor;
options_ += Options::ColorAlpha;
} else {
std::cerr << "Unsupported property : " << propertyName << std::endl;
}
vertexPropertyCount_++;
} else if ( elementName == "face" ) {
omerr() << "Properties not supported for faces " << std::endl;
}
}
} else {
omlog() << "Unsupported keyword : " << keyword << std::endl;
}
streamPos = _is.tellg();
_is >> keyword;
if ( _is.bad() ) {
omerr() << "Error while reading PLY file header" << std::endl;
return false;
}
}
// As the binary data is directy after the end_header keyword
// and the stream removes too many bytes, seek back to the right position
if ( options_.is_binary() ) {
_is.seekg(streamPos + 12);
}
return true;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

154
Core/IO/reader/PLYReader.hh Normal file
View File

@@ -0,0 +1,154 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a reader module for OFF files
//
//=============================================================================
#ifndef __PLYREADER_HH__
#define __PLYREADER_HH__
//=== INCLUDES ================================================================
#include <iostream>
#include <string>
#include <stdio.h>
#include <fstream>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
#ifndef WIN32
#include <string.h>
#endif
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== FORWARDS =================================================================
class BaseImporter;
//== IMPLEMENTATION ===========================================================
/**
Implementation of the PLY format reader. This class is singleton'ed by
SingletonT to OFFReader.
*/
class _PLYReader_ : public BaseReader
{
public:
_PLYReader_();
std::string get_description() const { return "PLY polygon file format"; }
std::string get_extensions() const { return "ply"; }
std::string get_magic() const { return "PLY"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt);
bool can_u_read(const std::string& _filename) const;
enum ValueType {
Unsupported ,
ValueTypeFLOAT32, ValueTypeFLOAT,
ValueTypeUINT8, ValueTypeINT32, ValueTypeINT ,
ValueTypeUCHAR
};
private:
bool can_u_read(std::istream& _is) const;
bool read(std::fstream& _in, BaseImporter& _bi, Options& _opt ) const;
bool read_ascii(std::fstream& _in, BaseImporter& _bi) const;
bool read_binary(std::fstream& _in, BaseImporter& _bi, bool swap) const;
float readToFloatValue(ValueType _type , std::fstream& _in) const;
void readValue(ValueType _type , std::fstream& _in, float& _value) const;
void readValue(ValueType _type , std::fstream& _in, unsigned int& _value) const;
void readValue(ValueType _type , std::fstream& _in, int& _value) const;
//available options for reading
mutable Options options_;
//options that the user wants to read
mutable Options userOptions_;
mutable unsigned int vertexCount_;
mutable unsigned int faceCount_;
mutable ValueType vertexType_;
mutable uint vertexDimension_;
mutable ValueType faceIndexType_;
mutable ValueType faceEntryType_;
enum VertexProperty {
XCOORD,YCOORD,ZCOORD,
TEXX,TEXY,
COLORRED,COLORGREEN,COLORBLUE,COLORALPHA
};
// number of vertex properties
mutable unsigned int vertexPropertyCount_;
mutable std::map< int , std::pair< VertexProperty, ValueType> > vertexPropertyMap_;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the PLY reader
extern _PLYReader_ __PLYReaderInstance;
_PLYReader_& PLYReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

369
Core/IO/reader/STLReader.cc Normal file
View File

@@ -0,0 +1,369 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
// STL
#include <map>
#include <float.h>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/IO/reader/STLReader.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the STLReader singleton with MeshReader
_STLReader_ __STLReaderInstance;
_STLReader_& STLReader() { return __STLReaderInstance; }
//=== IMPLEMENTATION ==========================================================
_STLReader_::
_STLReader_()
: eps_(FLT_MIN)
{
IOManager().register_module(this);
}
//-----------------------------------------------------------------------------
bool
_STLReader_::
read(const std::string& _filename, BaseImporter& _bi, Options& _opt)
{
bool result = false;
STL_Type file_type = NONE;
if ( check_extension( _filename, "stla" ) )
{
file_type = STLA;
}
else if ( check_extension( _filename, "stlb" ) )
{
file_type = STLB;
}
else if ( check_extension( _filename, "stl" ) )
{
file_type = check_stl_type(_filename);
}
switch (file_type)
{
case STLA:
{
result = read_stla(_filename, _bi);
_opt -= Options::Binary;
break;
}
case STLB:
{
result = read_stlb(_filename, _bi);
_opt += Options::Binary;
break;
}
default:
{
result = false;
break;
}
}
return result;
}
//-----------------------------------------------------------------------------
#ifndef DOXY_IGNORE_THIS
class CmpVec
{
public:
CmpVec(float _eps=FLT_MIN) : eps_(_eps) {}
bool operator()( const Vec3f& _v0, const Vec3f& _v1 ) const
{
if (fabs(_v0[0] - _v1[0]) <= eps_)
{
if (fabs(_v0[1] - _v1[1]) <= eps_)
{
return (_v0[2] < _v1[2] - eps_);
}
else return (_v0[1] < _v1[1] - eps_);
}
else return (_v0[0] < _v1[0] - eps_);
}
private:
float eps_;
};
#endif
//-----------------------------------------------------------------------------
bool
_STLReader_::
read_stla(const std::string& _filename, BaseImporter& _bi) const
{
omlog() << "[STLReader] : read ascii file\n";
FILE* in = fopen(_filename.c_str(), "r");
if (!in)
{
omerr() << "[STLReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
char line[100], *p;
unsigned int i;
OpenMesh::Vec3f v;
unsigned int cur_idx(0);
BaseImporter::VHandles vhandles;
CmpVec comp(eps_);
std::map<Vec3f, VertexHandle, CmpVec> vMap(comp);
std::map<Vec3f, VertexHandle, CmpVec>::iterator vMapIt;
while (in && !feof(in) && fgets(line, 100, in))
{
for (p=line; isspace(*p) && *p!='\0'; ++p) {}; // skip white-space
if ((strncmp(p, "outer", 5) == 0) || (strncmp(p, "OUTER", 5) == 0))
{
vhandles.clear();
for (i=0; i<3; ++i)
{
fgets(line, 100, in);
for (p=line; isspace(*p) && *p!='\0'; ++p) {}; // skip white-space
sscanf(p+6, "%f %f %f", &v[0], &v[1], &v[2]);
// has vector been referenced before?
if ((vMapIt=vMap.find(v)) == vMap.end())
{
// No : add vertex and remember idx/vector mapping
_bi.add_vertex(v);
vhandles.push_back(VertexHandle(cur_idx));
vMap[v] = VertexHandle(cur_idx++);
}
else
// Yes : get index from map
vhandles.push_back(vMapIt->second);
}
// Add face only if it is not degenerated
if ((vhandles[0] != vhandles[1]) &&
(vhandles[0] != vhandles[2]) &&
(vhandles[1] != vhandles[2]))
_bi.add_face(vhandles);
}
}
fclose(in);
// In general a file has data, there the number of vertices cannot be 0.
return _bi.n_vertices() != 0;
}
//-----------------------------------------------------------------------------
bool
_STLReader_::
read_stlb(const std::string& _filename, BaseImporter& _bi) const
{
omlog() << "[STLReader] : read binary file\n";
FILE* in = fopen(_filename.c_str(), "rb");
if (!in)
{
omerr() << "[STLReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
char dummy[100];
bool swapFlag;
unsigned int i, nT;
OpenMesh::Vec3f v;
unsigned int cur_idx(0);
BaseImporter::VHandles vhandles;
std::map<Vec3f, VertexHandle, CmpVec> vMap;
std::map<Vec3f, VertexHandle, CmpVec>::iterator vMapIt;
// check size of types
if ((sizeof(float) != 4) || (sizeof(int) != 4)) {
omerr() << "[STLReader] : wrong type size\n";
return false;
}
// determine endian mode
union { unsigned int i; unsigned char c[4]; } endian_test;
endian_test.i = 1;
swapFlag = (endian_test.c[3] == 1);
// read number of triangles
fread(dummy, 1, 80, in);
nT = read_int(in, swapFlag);
// read triangles
while (nT)
{
vhandles.clear();
// skip triangle normal
fread(dummy, 1, 12, in);
// triangle's vertices
for (i=0; i<3; ++i)
{
v[0] = read_float(in, swapFlag);
v[1] = read_float(in, swapFlag);
v[2] = read_float(in, swapFlag);
// has vector been referenced before?
if ((vMapIt=vMap.find(v)) == vMap.end())
{
// No : add vertex and remember idx/vector mapping
_bi.add_vertex(v);
vhandles.push_back(VertexHandle(cur_idx));
vMap[v] = VertexHandle(cur_idx++);
}
else
// Yes : get index from map
vhandles.push_back(vMapIt->second);
}
// Add face only if it is not degenerated
if ((vhandles[0] != vhandles[1]) &&
(vhandles[0] != vhandles[2]) &&
(vhandles[1] != vhandles[2]))
_bi.add_face(vhandles);
fread(dummy, 1, 2, in);
--nT;
}
return true;
}
//-----------------------------------------------------------------------------
_STLReader_::STL_Type
_STLReader_::
check_stl_type(const std::string& _filename) const
{
// assume it's binary stl, then file size is known from #triangles
// if size matches, it's really binary
// open file
FILE* in = fopen(_filename.c_str(), "rb");
if (!in) return NONE;
// determine endian mode
union { unsigned int i; unsigned char c[4]; } endian_test;
endian_test.i = 1;
bool swapFlag = (endian_test.c[3] == 1);
// read number of triangles
char dummy[100];
fread(dummy, 1, 80, in);
unsigned int nT = read_int(in, swapFlag);
// compute file size from nT
unsigned int binary_size = 84 + nT*50;
// get actual file size
unsigned int file_size(0);
rewind(in);
while (!feof(in))
file_size += fread(dummy, 1, 100, in);
fclose(in);
// if sizes match -> it's STLB
return (binary_size == file_size ? STLB : STLA);
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

124
Core/IO/reader/STLReader.hh Normal file
View File

@@ -0,0 +1,124 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements an reader module for STL files
//
//=============================================================================
#ifndef __STLREADER_HH__
#define __STLREADER_HH__
//=== INCLUDES ================================================================
#include <stdio.h>
#include <string>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
#ifndef WIN32
#include <string.h>
#endif
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== FORWARDS =================================================================
class BaseImporter;
//== IMPLEMENTATION ===========================================================
/**
Implementation of the STL format reader. This class is singleton'ed by
SingletonT to STLReader.
*/
class _STLReader_ : public BaseReader
{
public:
// constructor
_STLReader_();
std::string get_description() const
{ return "Stereolithography Interface Format"; }
std::string get_extensions() const { return "stl stla stlb"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt);
/** Set the threshold to be used for considering two point to be equal.
Can be used to merge small gaps */
void set_epsilon(float _eps) { eps_=_eps; }
/// Returns the threshold to be used for considering two point to be equal.
float epsilon() const { return eps_; }
private:
enum STL_Type { STLA, STLB, NONE };
STL_Type check_stl_type(const std::string& _filename) const;
bool read_stla(const std::string& _filename, BaseImporter& _bi) const;
bool read_stlb(const std::string& _filename, BaseImporter& _bi) const;
private:
float eps_;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the STL reader
extern _STLReader_ __STLReaderInstance;
_STLReader_& STLReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@@ -0,0 +1,17 @@
#== SYSTEM PART -- DON'T TOUCH ==============================================
include $(ACGMAKE)/Config
#==============================================================================
SUBDIRS = $(call find-subdirs)
PACKAGES :=
PROJ_LIBS :=
MODULES := cxxlib
#== SYSTEM PART -- DON'T TOUCH ==============================================
include $(ACGMAKE)/Rules
#==============================================================================

View File

@@ -0,0 +1,88 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=== INCLUDES ================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
#include <algorithm>
#include <string>
#include <iterator>
#if defined(OM_CC_MIPS)
# include <ctype.h>
#else
# include <cctype>
#endif
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
#ifndef DOXY_IGNORE_THIS
static inline char tolower(char c)
{
using namespace std;
return ::tolower(c);
}
#endif
//-----------------------------------------------------------------------------
bool
BaseWriter::
can_u_write(const std::string& _filename) const
{
// get file extension
std::string extension;
std::string::size_type pos(_filename.rfind("."));
if (pos != std::string::npos)
{
extension = _filename.substr(pos+1, _filename.length()-pos-1);
std::transform( extension.begin(), extension.end(),
extension.begin(), tolower );
}
// locate extension in extension string
return (get_extensions().find(extension) != std::string::npos);
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@@ -0,0 +1,108 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements the baseclass for IOManager writer modules
//
//=============================================================================
#ifndef __BASEWRITER_HH__
#define __BASEWRITER_HH__
//=== INCLUDES ================================================================
// STD C++
#include <iostream>
#include <string>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/Options.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
Base class for all writer modules. The module should register itself at
the IOManager by calling the register_module function.
*/
class BaseWriter
{
public:
typedef unsigned int Option;
/// Return short description of the supported file format.
virtual std::string get_description() const = 0;
/// Return file format's extension.
virtual std::string get_extensions() const = 0;
/// Returns true if writer can parse _filename (checks extension)
virtual bool can_u_write(const std::string& _filename) const;
/// Write to file _filename. Data source specified by BaseExporter _be.
virtual bool write(const std::string& _filename,
BaseExporter& _be,
Options _opt) const = 0;
/// Returns expected size of file if binary format is supported else 0.
virtual size_t binary_size(BaseExporter&, Options) const { return 0; }
protected:
bool check(BaseExporter& _be, Options _opt) const
{
return (_opt.check(Options::VertexNormal ) <= _be.has_vertex_normals())
&& (_opt.check(Options::VertexTexCoord)<= _be.has_vertex_texcoords())
&& (_opt.check(Options::VertexColor) <= _be.has_vertex_colors())
&& (_opt.check(Options::FaceNormal) <= _be.has_face_normals())
&& (_opt.check(Options::FaceColor) <= _be.has_face_colors());
}
};
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

303
Core/IO/writer/OBJWriter.cc Normal file
View File

@@ -0,0 +1,303 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
//STL
#include <fstream>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/IO/writer/OBJWriter.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the OBJLoader singleton with MeshLoader
_OBJWriter_ __OBJWriterinstance;
_OBJWriter_& OBJWriter() { return __OBJWriterinstance; }
//=== IMPLEMENTATION ==========================================================
_OBJWriter_::_OBJWriter_() { IOManager().register_module(this); }
//-----------------------------------------------------------------------------
bool
_OBJWriter_::
write(const std::string& _filename, BaseExporter& _be, Options _opt) const
{
std::fstream out(_filename.c_str(), std::ios_base::out );
if (!out)
{
omerr() << "[OBJWriter] : cannot open file "
<< _filename << std::endl;
return false;
}
{
#if defined(WIN32)
std::string::size_type dot = _filename.find_last_of("\\/");
#else
std::string::size_type dot = _filename.rfind("/");
#endif
if (dot == std::string::npos){
path_ = "./";
objName_ = _filename;
}else{
path_ = _filename.substr(0,dot+1);
objName_ = _filename.substr(dot+1);
}
//remove the file extension
dot = _filename.find_last_of(".");
if(dot != std::string::npos)
objName_ = objName_.substr(0,dot-1);
}
bool result = write(out, _be, _opt);
out.close();
return result;
}
//-----------------------------------------------------------------------------
int _OBJWriter_::getMaterial(OpenMesh::Vec3f _color) const
{
for (uint i=0; i < material_.size(); i++)
if(material_[i] == _color)
return i;
//not found add new material
material_.push_back( _color );
return material_.size()-1;
}
//-----------------------------------------------------------------------------
int _OBJWriter_::getMaterial(OpenMesh::Vec4f _color) const
{
for (uint i=0; i < materialA_.size(); i++)
if(materialA_[i] == _color)
return i;
//not found add new material
materialA_.push_back( _color );
return materialA_.size()-1;
}
//-----------------------------------------------------------------------------
bool
_OBJWriter_::
writeMaterial(std::fstream& _out, BaseExporter& _be, Options _opt) const
{
OpenMesh::Vec3f c;
OpenMesh::Vec4f cA;
material_.clear();
materialA_.clear();
//iterate over faces
for (int i=0, nF=_be.n_faces(); i<nF; ++i)
{
//color with alpha
if ( _opt.color_has_alpha() ){
cA = color_cast<OpenMesh::Vec4f> (_be.colorA( FaceHandle(i) ));
getMaterial(cA);
}else{
//and without alpha
c = color_cast<OpenMesh::Vec3f> (_be.color( FaceHandle(i) ));
getMaterial(c);
}
}
//write the materials
if ( _opt.color_has_alpha() )
for (uint i=0; i < materialA_.size(); i++){
_out << "newmtl " << "mat" << i << std::endl;
_out << "Ka 0.5000 0.5000 0.5000" << std::endl;
_out << "Kd " << materialA_[i][0] << materialA_[i][1] << materialA_[i][2] << std::endl;;
_out << "Tr " << materialA_[i][3] << std::endl;
_out << "illum 1" << std::endl;
}
else
for (uint i=0; i < material_.size(); i++){
_out << "newmtl " << "mat" << i << std::endl;
_out << "Ka 0.5000 0.5000 0.5000" << std::endl;
_out << "Kd " << material_[i][0] << material_[i][1] << material_[i][2] << std::endl;;
_out << "illum 1" << std::endl;
}
return true;
}
//-----------------------------------------------------------------------------
bool
_OBJWriter_::
write(std::fstream& _out, BaseExporter& _be, Options _opt) const
{
unsigned int i, j, nV, nF, idx;
Vec3f v, n;
Vec2f t;
VertexHandle vh;
std::vector<VertexHandle> vhandles;
bool useMatrial = false;
OpenMesh::Vec3f c;
OpenMesh::Vec4f cA;
omlog() << "[OBJWriter] : write file\n";
// check exporter features
if (!check( _be, _opt))
return false;
// check writer features
if ( _opt.check(Options::Binary) || // not supported by format
_opt.check(Options::FaceNormal) ||
_opt.check(Options::FaceColor))
return false;
//create material file if needed
if ( _opt.check(Options::FaceColor) ){
std::string matFile = path_ + objName_ + ".mat";
std::fstream matStream(matFile.c_str(), std::ios_base::out );
if (!_out)
{
omerr() << "[OBJWriter] : cannot write material file " << matFile << std::endl;
}else{
useMatrial = writeMaterial(matStream, _be, _opt);
matStream.close();
}
}
// header
_out << "# " << _be.n_vertices() << " vertices, ";
_out << _be.n_faces() << " faces" << std::endl;
// material file
if (useMatrial && _opt.check(Options::FaceColor) )
_out << "mtllib " << objName_ << ".mat" << std::endl;
// vertex data (point, normals, texcoords)
for (i=0, nV=_be.n_vertices(); i<nV; ++i)
{
vh = VertexHandle(i);
v = _be.point(vh);
n = _be.normal(vh);
t = _be.texcoord(vh);
_out << "v " << v[0] <<" "<< v[1] <<" "<< v[2] << std::endl;
if (_opt.check(Options::VertexNormal))
_out << "n " << n[0] <<" "<< n[1] <<" "<< n[2] << std::endl;
if (_opt.check(Options::VertexTexCoord))
_out << "vt " << t[0] <<" "<< t[1] << std::endl;
}
int lastMat = -1;
// faces (indices starting at 1 not 0)
for (i=0, nF=_be.n_faces(); i<nF; ++i)
{
if (useMatrial && _opt.check(Options::FaceColor) ){
int i;
//color with alpha
if ( _opt.color_has_alpha() ){
cA = color_cast<OpenMesh::Vec4f> (_be.colorA( FaceHandle(i) ));
i = getMaterial(cA);
}else{
//and without alpha
c = color_cast<OpenMesh::Vec3f> (_be.color( FaceHandle(i) ));
i = getMaterial(c);
}
if(lastMat != i)
_out << "usemtl mat" << i << std::endl;
}
_out << "f";
_be.get_vhandles(FaceHandle(i), vhandles);
for (j=0; j< vhandles.size(); ++j)
{
idx = vhandles[j].idx() + 1;
_out << " " << idx;
if (_opt.check(Options::VertexTexCoord))
_out << "/" << idx;
if ( _opt.check(Options::VertexNormal) )
_out << "/" << idx;
}
_out << std::endl;
}
material_.clear();
materialA_.clear();
return true;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

108
Core/IO/writer/OBJWriter.hh Normal file
View File

@@ -0,0 +1,108 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements an IOManager writer module for OBJ files
//
//=============================================================================
#ifndef __OBJWRITER_HH__
#define __OBJWRITER_HH__
//=== INCLUDES ================================================================
#include <string>
#include <fstream>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
This class defines the OBJ writer. This class is further singleton'ed
by SingletonT to OBJWriter.
*/
class _OBJWriter_ : public BaseWriter
{
public:
_OBJWriter_();
std::string get_description() const { return "Alias/Wavefront"; }
std::string get_extensions() const { return "obj"; }
bool write(const std::string&, BaseExporter&, Options) const;
size_t binary_size(BaseExporter&, Options) const { return 0; }
private:
mutable std::string path_;
mutable std::string objName_;
mutable std::vector< OpenMesh::Vec3f > material_;
mutable std::vector< OpenMesh::Vec4f > materialA_;
int getMaterial(OpenMesh::Vec3f _color) const;
int getMaterial(OpenMesh::Vec4f _color) const;
bool writeMaterial(std::fstream& _out, BaseExporter&, Options) const;
bool write(std::fstream& _out, BaseExporter&, Options) const;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the OBJ writer
extern _OBJWriter_ __OBJWriterinstance;
_OBJWriter_& OBJWriter();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

432
Core/IO/writer/OFFWriter.cc Normal file
View File

@@ -0,0 +1,432 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Utils/Endian.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/IO/writer/OFFWriter.hh>
#include <OpenMesh/Core/IO/SR_store.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the OFFLoader singleton with MeshLoader
_OFFWriter_ __OFFWriterInstance;
_OFFWriter_& OFFWriter() { return __OFFWriterInstance; }
//=== IMPLEMENTATION ==========================================================
_OFFWriter_::_OFFWriter_() { IOManager().register_module(this); }
//-----------------------------------------------------------------------------
bool
_OFFWriter_::
write(const std::string& _filename, BaseExporter& _be, Options _opt) const
{
// check exporter features
if ( !check( _be, _opt ) )
return false;
// check writer features
if ( _opt.check(Options::FaceNormal) ) // not supported by format
return false;
// open file
std::fstream out(_filename.c_str(), (_opt.check(Options::Binary) ? std::ios_base::binary | std::ios_base::out
: std::ios_base::out) );
if (!out)
{
omerr() << "[OFFWriter] : cannot open file "
<< _filename
<< std::endl;
return false;
}
// write header line
if (_opt.check(Options::VertexTexCoord)) out << "ST";
if (_opt.check(Options::VertexColor) || _opt.check(Options::FaceColor)) out << "C";
if (_opt.check(Options::VertexNormal)) out << "N";
out << "OFF";
if (_opt.check(Options::Binary)) out << " BINARY";
out << "\n";
// write to file
bool result = (_opt.check(Options::Binary) ?
write_binary(out, _be, _opt) :
write_ascii(out, _be, _opt));
// return result
out.close();
return result;
}
//-----------------------------------------------------------------------------
bool
_OFFWriter_::
write_ascii(std::fstream& _out, BaseExporter& _be, Options _opt) const
{
omlog() << "[OFFWriter] : write ascii file\n";
unsigned int i, j, nV, nF;
Vec3f v, n;
Vec2f t;
OpenMesh::Vec3i c;
OpenMesh::Vec4i cA;
VertexHandle vh;
std::vector<VertexHandle> vhandles;
// #vertices, #faces
_out << _be.n_vertices() << " ";
_out << _be.n_faces() << " ";
_out << 0 << "\n";
// vertex data (point, normals, colors, texcoords)
for (i=0, nV=_be.n_vertices(); i<nV; ++i)
{
vh = VertexHandle(i);
v = _be.point(vh);
//Vertex
_out << v[0] << " " << v[1] << " " << v[2];
// VertexNormal
if ( _opt.vertex_has_normal() ) {
n = _be.normal(vh);
_out << " " << n[0] << " " << n[1] << " " << n[2];
}
// VertexColor
if ( _opt.vertex_has_color() ) {
//with alpha
if ( _opt.color_has_alpha() ){
cA = _be.colorA(vh);
_out << " " << cA[0] << " " << cA[1] << " " << cA[2] << " " << cA[3];
}else{
//without alpha
c = _be.color(vh);
_out << " " << c[0] << " " << c[1] << " " << c[2];
}
}
// TexCoord
if (_opt.vertex_has_texcoord() ) {
t = _be.texcoord(vh);
_out << " " << t[0] << " " << t[1];
}
_out << "\n";
}
// faces (indices starting at 0)
if (_be.is_triangle_mesh())
{
for (i=0, nF=_be.n_faces(); i<nF; ++i)
{
_be.get_vhandles(FaceHandle(i), vhandles);
_out << 3 << " ";
_out << vhandles[0].idx() << " ";
_out << vhandles[1].idx() << " ";
_out << vhandles[2].idx();
//face color
if ( _opt.face_has_color() ){
//with alpha
if ( _opt.color_has_alpha() ){
cA = _be.colorA( FaceHandle(i) );
_out << " " << cA[0] << " " << cA[1] << " " << cA[2] << " " << cA[3];
}else{
//without alpha
c = _be.color( FaceHandle(i) );
_out << " " << c[0] << " " << c[1] << " " << c[2];
}
}
_out << "\n";
}
}
else
{
for (i=0, nF=_be.n_faces(); i<nF; ++i)
{
nV = _be.get_vhandles(FaceHandle(i), vhandles);
_out << nV << " ";
for (j=0; j<vhandles.size(); ++j)
_out << vhandles[j].idx() << " ";
//face color
if ( _opt.face_has_color() ){
//with alpha
if ( _opt.color_has_alpha() ){
cA = _be.colorA( FaceHandle(i) );
_out << cA[0] << " " << cA[1] << " " << cA[2] << " " << cA[3];
}else{
//without alpha
c = _be.color( FaceHandle(i) );
_out << c[0] << " " << c[1] << " " << c[2];
}
}
_out << "\n";
}
}
return true;
}
//-----------------------------------------------------------------------------
void _OFFWriter_::writeValue(std::fstream& _out, int value) const {
uint32_t tmp = value;
store(_out, tmp, false);
}
void _OFFWriter_::writeValue(std::fstream& _out, unsigned int value) const {
uint32_t tmp = value;
store(_out, tmp, false);
}
void _OFFWriter_::writeValue(std::fstream& _out, float value) const {
float32_t tmp = value;
store(_out, tmp, false);
}
bool
_OFFWriter_::
write_binary(std::fstream& _out, BaseExporter& _be, Options _opt) const
{
omlog() << "[OFFWriter] : write ascii file\n";
unsigned int i, j, nV, nF;
Vec3f v, n;
Vec2f t;
OpenMesh::Vec4i c;
VertexHandle vh;
std::vector<VertexHandle> vhandles;
// #vertices, #faces
writeValue(_out, (uint)_be.n_vertices() );
writeValue(_out, (uint) _be.n_faces() );
writeValue(_out, 0 );
// vertex data (point, normals, texcoords)
for (i=0, nV=_be.n_vertices(); i<nV; ++i)
{
vh = VertexHandle(i);
v = _be.point(vh);
//vertex
writeValue(_out, v[0]);
writeValue(_out, v[1]);
writeValue(_out, v[2]);
// vertex normal
if ( _opt.vertex_has_normal() ) {
n = _be.normal(vh);
writeValue(_out, n[0]);
writeValue(_out, n[1]);
writeValue(_out, n[2]);
}
// vertex color
if ( _opt.vertex_has_color() ) {
c = _be.colorA(vh);
writeValue(_out, c[0]);
writeValue(_out, c[1]);
writeValue(_out, c[2]);
if ( _opt.color_has_alpha() )
writeValue(_out, c[3]);
}
// texCoords
if (_opt.vertex_has_texcoord() ) {
t = _be.texcoord(vh);
writeValue(_out, t[0]);
writeValue(_out, t[1]);
}
}
// faces (indices starting at 0)
if (_be.is_triangle_mesh())
{
for (i=0, nF=_be.n_faces(); i<nF; ++i)
{
//face
_be.get_vhandles(FaceHandle(i), vhandles);
writeValue(_out, 3);
writeValue(_out, vhandles[0].idx());
writeValue(_out, vhandles[1].idx());
writeValue(_out, vhandles[2].idx());
//face color
if ( _opt.face_has_color() ){
c = _be.colorA( FaceHandle(i) );
writeValue(_out, c[0]);
writeValue(_out, c[1]);
writeValue(_out, c[2]);
if ( _opt.color_has_alpha() )
writeValue(_out, c[3]);
}
}
}
else
{
for (i=0, nF=_be.n_faces(); i<nF; ++i)
{
//face
nV = _be.get_vhandles(FaceHandle(i), vhandles);
writeValue(_out, nV);
for (j=0; j<vhandles.size(); ++j)
writeValue(_out, vhandles[j].idx() );
//face color
if ( _opt.face_has_color() ){
c = _be.colorA( FaceHandle(i) );
writeValue(_out, c[0]);
writeValue(_out, c[1]);
writeValue(_out, c[2]);
if ( _opt.color_has_alpha() )
writeValue(_out, c[3]);
}
}
}
return true;
}
// ----------------------------------------------------------------------------
size_t
_OFFWriter_::
binary_size(BaseExporter& _be, Options _opt) const
{
size_t header(0);
size_t data(0);
size_t _3longs(3*sizeof(long));
size_t _3floats(3*sizeof(float));
size_t _3ui(3*sizeof(unsigned int));
size_t _4ui(4*sizeof(unsigned int));
if ( !_opt.is_binary() )
return 0;
else
{
header += 11; // 'OFF BINARY\n'
header += _3longs; // #V #F #E
data += _be.n_vertices() * _3floats; // vertex data
}
if ( _opt.vertex_has_normal() && _be.has_vertex_normals() )
{
header += 1; // N
data += _be.n_vertices() * _3floats;
}
if ( _opt.vertex_has_color() && _be.has_vertex_colors() )
{
header += 1; // C
data += _be.n_vertices() * _3floats;
}
if ( _opt.vertex_has_texcoord() && _be.has_vertex_texcoords() )
{
size_t _2floats(2*sizeof(float));
header += 2; // ST
data += _be.n_vertices() * _2floats;
}
// topology
if (_be.is_triangle_mesh())
{
data += _be.n_faces() * _4ui;
}
else
{
unsigned int i, nV, nF;
std::vector<VertexHandle> vhandles;
for (i=0, nF=_be.n_faces(); i<nF; ++i)
{
nV = _be.get_vhandles(FaceHandle(i), vhandles);
data += nV * sizeof(unsigned int);
}
}
// face colors
if ( _opt.face_has_color() && _be.has_face_colors() ){
if ( _opt.color_has_alpha() )
data += _be.n_faces() * _4ui;
else
data += _be.n_faces() * _3ui;
}
return header+data;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

113
Core/IO/writer/OFFWriter.hh Normal file
View File

@@ -0,0 +1,113 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a writer module for OFF files
//
//=============================================================================
#ifndef __OFFWRITER_HH__
#define __OFFWRITER_HH__
//=== INCLUDES ================================================================
#include <stdio.h>
#include <string>
#include <fstream>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
Implementation of the OFF format writer. This class is singleton'ed by
SingletonT to OFFWriter.
By passing Options to the write function you can manipulate the writing behavoir.
The following options can be set:
Binary
VertexNormal
VertexColor
VertexTexCoord
FaceColor
ColorAlpha
*/
class _OFFWriter_ : public BaseWriter
{
public:
_OFFWriter_();
std::string get_description() const { return "no description"; }
std::string get_extensions() const { return "off"; }
bool write(const std::string&, BaseExporter&, Options) const;
size_t binary_size(BaseExporter& _be, Options _opt) const;
protected:
void writeValue(std::fstream& _out, int value) const;
void writeValue(std::fstream& _out, unsigned int value) const;
void writeValue(std::fstream& _out, float value) const;
bool write_ascii(std::fstream& _in, BaseExporter&, Options) const;
bool write_binary(std::fstream& _in, BaseExporter&, Options) const;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the OFF writer.
extern _OFFWriter_ __OFFWriterInstance;
_OFFWriter_& OFFWriter();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

504
Core/IO/writer/OMWriter.cc Normal file
View File

@@ -0,0 +1,504 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
// -------------------- STL
#if defined( OM_CC_MIPS )
# include <time.h>
# include <string.h>
#else
# include <ctime>
# include <cstring>
#endif
#include <fstream>
// -------------------- OpenMesh
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Utils/Endian.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
#include <OpenMesh/Core/IO/writer/OMWriter.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the OMLoader singleton with MeshLoader
_OMWriter_ __OMWriterInstance;
_OMWriter_& OMWriter() { return __OMWriterInstance; }
//=== IMPLEMENTATION ==========================================================
const OMFormat::uchar _OMWriter_::magic_[3] = "OM";
const OMFormat::uint8 _OMWriter_::version_ = OMFormat::mk_version(1,2);
_OMWriter_::
_OMWriter_()
{
IOManager().register_module(this);
}
bool
_OMWriter_::write(const std::string& _filename, BaseExporter& _be,
Options _opt) const
{
// check whether exporter can give us an OpenMesh BaseKernel
if (!_be.kernel()) return false;
// check for om extension in filename, we can only handle OM
if (_filename.rfind(".om") == std::string::npos)
return false;
_opt += Options::Binary; // only binary format supported
std::ofstream ofs(_filename.c_str(), std::ios::binary);
// check if file is open
if (!ofs.is_open())
{
omerr() << "[OMWriter] : cannot open file " << _filename << std::endl;
return false;
}
// call stream save method
bool rc = write(ofs, _be, _opt);
// close filestream
ofs.close();
// return success/failure notice
return rc;
}
//-----------------------------------------------------------------------------
bool
_OMWriter_::write(std::ostream& _os, BaseExporter& _be, Options _opt) const
{
// std::clog << "[OMWriter]::write( stream )\n";
// check exporter features
if ( !check( _be, _opt ) )
{
omerr() << "[OMWriter]: exporter does not support wanted feature!\n";
return false;
}
// Maybe an ascii version will be implemented in the future.
// For now, support only a binary format
if ( !_opt.check( Options::Binary ) )
_opt += Options::Binary;
// Ignore LSB/MSB bit. Always store in LSB (little endian)
_opt += Options::LSB;
_opt -= Options::MSB;
// if ( _opt.check(Options::Binary) )
// {
return write_binary(_os, _be, _opt);
// }
// else
// {
// return write_ascii(_os, _be, _opt);
// }
}
//-----------------------------------------------------------------------------
// bool _OMWriter_::write_ascii(std::ostream& _os, BaseExporter& _be,
// Options _opt) const
// {
// return false;
// }
//-----------------------------------------------------------------------------
#ifndef DOXY_IGNORE_THIS
template <typename T> struct Enabler
{
Enabler( T& obj ) : obj_(obj)
{}
~Enabler() { obj_.enable(); }
T& obj_;
};
#endif
bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be,
Options _opt) const
{
Enabler<mostream> enabler(omlog());
omlog() << "[OMWriter] : write binary file\n";
size_t bytes = 0;
bool swap = _opt.check(Options::Swap) || (Endian::local() == Endian::MSB);
unsigned int i, nV, nF;
Vec3f v;
Vec2f t;
std::vector<VertexHandle> vhandles;
// -------------------- write header
OMFormat::Header header;
header.magic_[0] = 'O';
header.magic_[1] = 'M';
header.mesh_ = _be.is_triangle_mesh() ? 'T' : 'P';
header.version_ = version_;
header.n_vertices_ = _be.n_vertices();
header.n_faces_ = _be.n_faces();
header.n_edges_ = _be.n_edges();
bytes += store( _os, header, swap );
// ---------------------------------------- write chunks
OMFormat::Chunk::Header chunk_header;
// -------------------- write vertex data
// ---------- write vertex position
if (_be.n_vertices())
{
v = _be.point(VertexHandle(0));
chunk_header.reserved_ = 0;
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
chunk_header.type_ = OMFormat::Chunk::Type_Pos;
chunk_header.signed_ = OMFormat::is_signed(v[0]);
chunk_header.float_ = OMFormat::is_float(v[0]);
chunk_header.dim_ = OMFormat::dim(v);
chunk_header.bits_ = OMFormat::bits(v[0]);
bytes += store( _os, chunk_header, swap );
for (i=0, nV=_be.n_vertices(); i<nV; ++i)
bytes += vector_store( _os, _be.point(VertexHandle(i)), swap );
}
// ---------- write vertex normal
if (_be.n_vertices() && _opt.check( Options::VertexNormal ))
{
Vec3f n = _be.normal(VertexHandle(0));
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
chunk_header.type_ = OMFormat::Chunk::Type_Normal;
chunk_header.signed_ = OMFormat::is_signed(n[0]);
chunk_header.float_ = OMFormat::is_float(n[0]);
chunk_header.dim_ = OMFormat::dim(n);
chunk_header.bits_ = OMFormat::bits(n[0]);
bytes += store( _os, chunk_header, swap );
for (i=0, nV=_be.n_vertices(); i<nV; ++i)
bytes += vector_store( _os, _be.normal(VertexHandle(i)), swap );
}
// ---------- write vertex color
#if 1
if (_opt.check( Options::VertexColor ) && _be.has_vertex_colors() )
{
Vec3uc c = _be.color(VertexHandle(0));
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
chunk_header.type_ = OMFormat::Chunk::Type_Color;
chunk_header.signed_ = OMFormat::is_signed( c );
chunk_header.float_ = OMFormat::is_float( c );
chunk_header.dim_ = OMFormat::dim( c );
chunk_header.bits_ = OMFormat::bits( c );
bytes += store( _os, chunk_header, swap );
for (i=0, nV=_be.n_vertices(); i<nV; ++i)
bytes += vector_store( _os, _be.color(VertexHandle(i)), swap );
}
#endif
// ---------- write vertex texture coords
if (_be.n_vertices() && _opt.check(Options::VertexTexCoord))
{
t = _be.texcoord(VertexHandle(0));
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
chunk_header.type_ = OMFormat::Chunk::Type_Texcoord;
chunk_header.signed_ = OMFormat::is_signed(t[0]);
chunk_header.float_ = OMFormat::is_float(t[0]);
chunk_header.dim_ = OMFormat::dim(t);
chunk_header.bits_ = OMFormat::bits(t[0]);
// std::clog << chunk_header << std::endl;
bytes += store( _os, chunk_header, swap );
for (i=0, nV=_be.n_vertices(); i<nV; ++i)
bytes += vector_store( _os, _be.texcoord(VertexHandle(i)), swap );
}
// -------------------- write face data
// ---------- write topology
{
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
chunk_header.type_ = OMFormat::Chunk::Type_Topology;
chunk_header.signed_ = 0;
chunk_header.float_ = 0;
chunk_header.dim_ = OMFormat::Chunk::Dim_1D; // ignored
chunk_header.bits_ = OMFormat::needed_bits(_be.n_vertices());
bytes += store( _os, chunk_header, swap );
for (i=0, nF=_be.n_faces(); i<nF; ++i)
{
nV = _be.get_vhandles(FaceHandle(i), vhandles);
if ( header.mesh_ == 'P' )
bytes += store( _os, vhandles.size(),
OMFormat::Chunk::Integer_16, swap );
for (size_t j=0; j < vhandles.size(); ++j)
{
using namespace OMFormat;
using namespace GenProg;
bytes += store( _os, vhandles[j].idx(),
Chunk::Integer_Size(chunk_header.bits_), swap );
}
}
}
// ---------- write face normals
if ( _be.has_face_normals() && _opt.check(Options::FaceNormal) )
{
#define NEW_STYLE 0
#if NEW_STYLE
const BaseProperty *bp = _be.kernel()._get_fprop("f:normals");
if (bp)
{
#endif
Vec3f n = _be.normal(FaceHandle(0));
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
chunk_header.type_ = OMFormat::Chunk::Type_Normal;
chunk_header.signed_ = OMFormat::is_signed(n[0]);
chunk_header.float_ = OMFormat::is_float(n[0]);
chunk_header.dim_ = OMFormat::dim(n);
chunk_header.bits_ = OMFormat::bits(n[0]);
bytes += store( _os, chunk_header, swap );
#if !NEW_STYLE
for (i=0, nF=_be.n_faces(); i<nF; ++i)
bytes += vector_store( _os, _be.normal(FaceHandle(i)), swap );
#else
bytes += bp->store(_os, swap );
}
else
return false;
#endif
#undef NEW_STYLE
}
// ---------- write face color
if (_be.has_face_colors() && _opt.check( Options::FaceColor ))
{
#define NEW_STYLE 0
#if NEW_STYLE
const BaseProperty *bp = _be.kernel()._get_fprop("f:colors");
if (bp)
{
#endif
Vec3uc c;
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
chunk_header.type_ = OMFormat::Chunk::Type_Color;
chunk_header.signed_ = OMFormat::is_signed( c[0] );
chunk_header.float_ = OMFormat::is_float( c[0] );
chunk_header.dim_ = OMFormat::dim( c );
chunk_header.bits_ = OMFormat::bits( c[0] );
bytes += store( _os, chunk_header, swap );
#if !NEW_STYLE
for (i=0, nF=_be.n_faces(); i<nF; ++i)
bytes += vector_store( _os, _be.color(FaceHandle(i)), swap );
#else
bytes += bp->store(_os, swap);
}
else
return false;
#endif
}
// -------------------- write custom properties
BaseKernel::const_prop_iterator prop;
for (prop = _be.kernel()->vprops_begin();
prop != _be.kernel()->vprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Vertex, swap );
}
for (prop = _be.kernel()->fprops_begin();
prop != _be.kernel()->fprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Face, swap );
}
for (prop = _be.kernel()->eprops_begin();
prop != _be.kernel()->eprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Edge, swap );
}
for (prop = _be.kernel()->hprops_begin();
prop != _be.kernel()->hprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Halfedge, swap );
}
for (prop = _be.kernel()->mprops_begin();
prop != _be.kernel()->mprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Mesh, swap );
}
// std::clog << "#bytes written: " << bytes << std::endl;
return true;
}
// ----------------------------------------------------------------------------
size_t _OMWriter_::store_binary_custom_chunk(std::ostream& _os,
const BaseProperty& _bp,
OMFormat::Chunk::Entity _entity,
bool _swap) const
{
omlog() << "Custom Property " << OMFormat::as_string(_entity) << " property ["
<< _bp.name() << "]" << std::endl;
// Don't store if
// 1. it is not persistent
// 2. it's name is empty
if ( !_bp.persistent() || _bp.name().empty() )
{
omlog() << " skipped\n";
return 0;
}
size_t bytes = 0;
OMFormat::Chunk::esize_t element_size = _bp.element_size();
OMFormat::Chunk::Header chdr;
// set header
chdr.name_ = true;
chdr.entity_ = _entity;
chdr.type_ = OMFormat::Chunk::Type_Custom;
chdr.signed_ = 0;
chdr.float_ = 0;
chdr.dim_ = OMFormat::Chunk::Dim_1D; // ignored
chdr.bits_ = element_size;
// write custom chunk
// 1. chunk header
bytes += store( _os, chdr, _swap );
// 2. property name
bytes += store( _os, OMFormat::Chunk::PropertyName(_bp.name()), _swap );
// 3. block size
bytes += store( _os, _bp.size_of(), _swap );
omlog() << " n_bytes = " << _bp.size_of() << std::endl;
// 4. data
{
size_t b;
bytes += ( b=_bp.store( _os, _swap ) );
omlog() << " b = " << b << std::endl;
assert( b == _bp.size_of() );
}
return bytes;
}
// ----------------------------------------------------------------------------
size_t _OMWriter_::binary_size(BaseExporter& /* _be */, Options /* _opt */) const
{
// std::clog << "[OMWriter]: binary_size()" << std::endl;
size_t bytes = sizeof( OMFormat::Header );
// !!!TODO!!!
return bytes;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

119
Core/IO/writer/OMWriter.hh Normal file
View File

@@ -0,0 +1,119 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a writer module for OM files
//
//=============================================================================
#ifndef __OMWRITER_HH__
#define __OMWRITER_HH__
//=== INCLUDES ================================================================
// STD C++
#include <iostream>
#include <string>
// OpenMesh
#include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== FORWARDS ================================================================
class BaseExporter;
//=== IMPLEMENTATION ==========================================================
/**
* Implementation of the OM format writer. This class is singleton'ed by
* SingletonT to OMWriter.
*/
class _OMWriter_ : public BaseWriter
{
public:
// constructor
_OMWriter_();
std::string get_description() const
{ return "OpenMesh Format"; }
std::string get_extensions() const
{ return "om"; }
bool write(std::ostream&, BaseExporter&, Options) const;
size_t binary_size(BaseExporter& _be, Options _opt) const;
protected:
static const OMFormat::uchar magic_[3];
static const OMFormat::uint8 version_;
bool write(const std::string&, BaseExporter&, Options) const;
bool write_binary(std::ostream&, BaseExporter&, Options) const;
size_t store_binary_custom_chunk( std::ostream&, const BaseProperty&,
OMFormat::Chunk::Entity, bool) const;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the OM writer.
extern _OMWriter_ __OMWriterInstance;
_OMWriter_& OMWriter();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

476
Core/IO/writer/PLYWriter.cc Normal file
View File

@@ -0,0 +1,476 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Utils/Endian.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/IO/writer/PLYWriter.hh>
#include <OpenMesh/Core/IO/SR_store.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the PLYLoader singleton with MeshLoader
_PLYWriter_ __PLYWriterInstance;
_PLYWriter_& PLYWriter() { return __PLYWriterInstance; }
//=== IMPLEMENTATION ==========================================================
_PLYWriter_::_PLYWriter_() { IOManager().register_module(this); }
//-----------------------------------------------------------------------------
bool
_PLYWriter_::
write(const std::string& _filename, BaseExporter& _be, Options _opt) const
{
// check exporter features
if ( !check( _be, _opt ) )
return false;
// check writer features
if ( _opt.check(Options::FaceNormal) || _opt.check(Options::FaceColor) ) // not supported yet
return false;
options_ = _opt;
// open file
std::fstream out(_filename.c_str(), (_opt.check(Options::Binary) ? std::ios_base::binary | std::ios_base::out
: std::ios_base::out) );
if (!out)
{
omerr() << "[PLYWriter] : cannot open file "
<< _filename
<< std::endl;
return false;
}
// write to file
bool result = (_opt.check(Options::Binary) ?
write_binary(out, _be, _opt) :
write_ascii(out, _be, _opt));
// return result
out.close();
return result;
}
//-----------------------------------------------------------------------------
bool
_PLYWriter_::
write_ascii(std::fstream& _out, BaseExporter& _be, Options _opt) const
{
omlog() << "[PLYWriter] : write ascii file\n";
unsigned int i, j, nV, nF;
Vec3f v, n;
Vec2f t;
OpenMesh::Vec3f c;
OpenMesh::Vec4f cA;
VertexHandle vh;
std::vector<VertexHandle> vhandles;
//writing header
_out << "ply" << std::endl;
_out << "format ascii 1.0" << std::endl;
_out << "element vertex " << _be.n_vertices() << std::endl;
_out << "property float32 x" << std::endl;
_out << "property float32 y" << std::endl;
_out << "property float32 z" << std::endl;
if ( _opt.vertex_has_color() ){
_out << "property int32 red" << std::endl;
_out << "property int32 green" << std::endl;
_out << "property int32 blue" << std::endl;
if ( _opt.color_has_alpha() )
_out << "property int32 alpha" << std::endl;
}
_out << "element face " << _be.n_faces() << std::endl;
_out << "property list uint8 int32 vertex_indices" << std::endl;
_out << "end_header" << std::endl;
// vertex data (point, normals, colors, texcoords)
for (i=0, nV=_be.n_vertices(); i<nV; ++i)
{
vh = VertexHandle(i);
v = _be.point(vh);
//Vertex
_out << v[0] << " " << v[1] << " " << v[2];
// VertexColor
if ( _opt.vertex_has_color() ) {
//with alpha
if ( _opt.color_has_alpha() ){
cA = _be.colorA(vh);
_out << " " << cA[0] << " " << cA[1] << " " << cA[2] << " " << cA[3];
}else{
//without alpha
c = _be.color(vh);
_out << " " << c[0] << " " << c[1] << " " << c[2];
}
}
_out << "\n";
}
// faces (indices starting at 0)
if (_be.is_triangle_mesh())
{
for (i=0, nF=_be.n_faces(); i<nF; ++i)
{
_be.get_vhandles(FaceHandle(i), vhandles);
_out << 3 << " ";
_out << vhandles[0].idx() << " ";
_out << vhandles[1].idx() << " ";
_out << vhandles[2].idx();
// //face color
// if ( _opt.face_has_color() ){
// //with alpha
// if ( _opt.color_has_alpha() ){
// cA = _be.colorA( FaceHandle(i) );
// _out << " " << cA[0] << " " << cA[1] << " " << cA[2] << " " << cA[3];
// }else{
// //without alpha
// c = _be.color( FaceHandle(i) );
// _out << " " << c[0] << " " << c[1] << " " << c[2];
// }
// }
_out << "\n";
}
}
else
{
for (i=0, nF=_be.n_faces(); i<nF; ++i)
{
nV = _be.get_vhandles(FaceHandle(i), vhandles);
_out << nV << " ";
for (j=0; j<vhandles.size(); ++j)
_out << vhandles[j].idx() << " ";
// //face color
// if ( _opt.face_has_color() ){
// //with alpha
// if ( _opt.color_has_alpha() ){
// cA = _be.colorA( FaceHandle(i) );
// _out << cA[0] << " " << cA[1] << " " << cA[2] << " " << cA[3];
// }else{
// //without alpha
// c = _be.color( FaceHandle(i) );
// _out << c[0] << " " << c[1] << " " << c[2];
// }
// }
_out << "\n";
}
}
return true;
}
//-----------------------------------------------------------------------------
void _PLYWriter_::writeValue(ValueType _type, std::fstream& _out, int value) const {
uint32_t tmp32;
uint8_t tmp8;
switch (_type) {
case ValueTypeINT:
case ValueTypeINT32:
tmp32 = value;
store(_out, tmp32, options_.check(Options::MSB) );
break;
// case ValueTypeUINT8:
default :
tmp8 = value;
store(_out, tmp8, options_.check(Options::MSB) );
break;
// default :
// std::cerr << "unsupported conversion type to int: " << _type << std::endl;
// break;
}
}
void _PLYWriter_::writeValue(ValueType _type, std::fstream& _out, unsigned int value) const {
uint32_t tmp32;
uint8_t tmp8;
switch (_type) {
case ValueTypeINT:
case ValueTypeINT32:
tmp32 = value;
store(_out, tmp32, options_.check(Options::MSB) );
break;
// case ValueTypeUINT8:
default :
tmp8 = value;
store(_out, tmp8, options_.check(Options::MSB) );
break;
// default :
// std::cerr << "unsupported conversion type to int: " << _type << std::endl;
// break;
}
}
void _PLYWriter_::writeValue(ValueType _type, std::fstream& _out, float value) const {
float32_t tmp;
switch (_type) {
case ValueTypeFLOAT32:
case ValueTypeFLOAT:
tmp = value;
store( _out , tmp, options_.check(Options::MSB) );
break;
default :
std::cerr << "unsupported conversion type to float: " << _type << std::endl;
break;
}
}
bool
_PLYWriter_::
write_binary(std::fstream& _out, BaseExporter& _be, Options _opt) const
{
omlog() << "[PLYWriter] : write binary file\n";
unsigned int i, j, nV, nF;
Vec3f v, n;
Vec2f t;
OpenMesh::Vec4f c;
VertexHandle vh;
std::vector<VertexHandle> vhandles;
//writing header
_out << "ply" << std::endl;
_out << "format ";
if ( options_.check(Options::MSB) )
_out << "binary_big_endian ";
else
_out << "binary_little_endian ";
_out << "1.0" << std::endl;
_out << "element vertex " << _be.n_vertices() << std::endl;
_out << "property float32 x" << std::endl;
_out << "property float32 y" << std::endl;
_out << "property float32 z" << std::endl;
if ( _opt.vertex_has_color() ){
_out << "property int32 red" << std::endl;
_out << "property int32 green" << std::endl;
_out << "property int32 blue" << std::endl;
if ( _opt.color_has_alpha() )
_out << "property int32 alpha" << std::endl;
}
_out << "element face " << _be.n_faces() << std::endl;
_out << "property list uchar int32 vertex_indices" << std::endl;
_out << "end_header" << std::endl;
// vertex data (point, normals, texcoords)
for (i=0, nV=_be.n_vertices(); i<nV; ++i)
{
vh = VertexHandle(i);
v = _be.point(vh);
//vertex
writeValue(ValueTypeFLOAT, _out, v[0]);
writeValue(ValueTypeFLOAT, _out, v[1]);
writeValue(ValueTypeFLOAT, _out, v[2]);
// vertex color
if ( _opt.vertex_has_color() ) {
c = _be.colorA(vh);
writeValue(ValueTypeINT32, _out, (int)c[0]);
writeValue(ValueTypeINT32, _out, (int)c[1]);
writeValue(ValueTypeINT32, _out, (int)c[2]);
if ( _opt.color_has_alpha() )
writeValue(ValueTypeINT32, _out, (int)c[3]);
}
}
// faces (indices starting at 0)
if (_be.is_triangle_mesh())
{
for (i=0, nF=_be.n_faces(); i<nF; ++i)
{
//face
_be.get_vhandles(FaceHandle(i), vhandles);
writeValue(ValueTypeUINT8, _out, 3);
writeValue(ValueTypeINT32, _out, vhandles[0].idx());
writeValue(ValueTypeINT32, _out, vhandles[1].idx());
writeValue(ValueTypeINT32, _out, vhandles[2].idx());
// //face color
// if ( _opt.face_has_color() ){
// c = _be.colorA( FaceHandle(i) );
// writeValue(_out, c[0]);
// writeValue(_out, c[1]);
// writeValue(_out, c[2]);
//
// if ( _opt.color_has_alpha() )
// writeValue(_out, c[3]);
// }
}
}
else
{
for (i=0, nF=_be.n_faces(); i<nF; ++i)
{
//face
nV = _be.get_vhandles(FaceHandle(i), vhandles);
writeValue(ValueTypeUINT8, _out, nV);
for (j=0; j<vhandles.size(); ++j)
writeValue(ValueTypeINT32, _out, vhandles[j].idx() );
// //face color
// if ( _opt.face_has_color() ){
// c = _be.colorA( FaceHandle(i) );
// writeValue(_out, c[0]);
// writeValue(_out, c[1]);
// writeValue(_out, c[2]);
//
// if ( _opt.color_has_alpha() )
// writeValue(_out, c[3]);
// }
}
}
return true;
}
// ----------------------------------------------------------------------------
size_t
_PLYWriter_::
binary_size(BaseExporter& _be, Options _opt) const
{
size_t header(0);
size_t data(0);
size_t _3longs(3*sizeof(long));
size_t _3floats(3*sizeof(float));
size_t _3ui(3*sizeof(unsigned int));
size_t _4ui(4*sizeof(unsigned int));
if ( !_opt.is_binary() )
return 0;
else
{
header += 11; // 'OFF BINARY\n'
header += _3longs; // #V #F #E
data += _be.n_vertices() * _3floats; // vertex data
}
if ( _opt.vertex_has_normal() && _be.has_vertex_normals() )
{
header += 1; // N
data += _be.n_vertices() * _3floats;
}
if ( _opt.vertex_has_color() && _be.has_vertex_colors() )
{
header += 1; // C
data += _be.n_vertices() * _3floats;
}
if ( _opt.vertex_has_texcoord() && _be.has_vertex_texcoords() )
{
size_t _2floats(2*sizeof(float));
header += 2; // ST
data += _be.n_vertices() * _2floats;
}
// topology
if (_be.is_triangle_mesh())
{
data += _be.n_faces() * _4ui;
}
else
{
unsigned int i, nV, nF;
std::vector<VertexHandle> vhandles;
for (i=0, nF=_be.n_faces(); i<nF; ++i)
{
nV = _be.get_vhandles(FaceHandle(i), vhandles);
data += nV * sizeof(unsigned int);
}
}
// face colors
if ( _opt.face_has_color() && _be.has_face_colors() ){
if ( _opt.color_has_alpha() )
data += _be.n_faces() * _4ui;
else
data += _be.n_faces() * _3ui;
}
return header+data;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

116
Core/IO/writer/PLYWriter.hh Normal file
View File

@@ -0,0 +1,116 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a writer module for PLY files
//
//=============================================================================
#ifndef __PLYWRITER_HH__
#define __PWRITER_HH__
//=== INCLUDES ================================================================
#include <stdio.h>
#include <string>
#include <fstream>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
Implementation of the PLY format writer. This class is singleton'ed by
SingletonT to PLYWriter.
currently supported options:
- VertexColors
- Binary
- Binary -> MSB
*/
class _PLYWriter_ : public BaseWriter
{
public:
_PLYWriter_();
std::string get_description() const { return "PLY polygon file format"; }
std::string get_extensions() const { return "ply"; }
bool write(const std::string&, BaseExporter&, Options) const;
size_t binary_size(BaseExporter& _be, Options _opt) const;
enum ValueType {
Unsupported ,
ValueTypeFLOAT32, ValueTypeFLOAT,
ValueTypeUINT8, ValueTypeINT32, ValueTypeINT ,
ValueTypeUCHAR
};
private:
mutable Options options_;
protected:
void writeValue(ValueType _type, std::fstream& _out, int value) const;
void writeValue(ValueType _type, std::fstream& _out, unsigned int value) const;
void writeValue(ValueType _type, std::fstream& _out, float value) const;
bool write_ascii(std::fstream& _in, BaseExporter&, Options) const;
bool write_binary(std::fstream& _in, BaseExporter&, Options) const;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the PLY writer.
extern _PLYWriter_ __PLYWriterInstance;
_PLYWriter_& PLYWriter();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

278
Core/IO/writer/STLWriter.cc Normal file
View File

@@ -0,0 +1,278 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
//STL
#include <fstream>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/IO/writer/STLWriter.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
_STLWriter_ __STLWriterInstance;
_STLWriter_& STLWriter() { return __STLWriterInstance; }
//=== IMPLEMENTATION ==========================================================
_STLWriter_::_STLWriter_() { IOManager().register_module(this); }
//-----------------------------------------------------------------------------
bool
_STLWriter_::
write(const std::string& _filename, BaseExporter& _be, Options _opt) const
{
// check exporter features
if (!check(_be, _opt)) return false;
// check writer features
if (_opt.check(Options::VertexNormal) ||
_opt.check(Options::VertexTexCoord) ||
_opt.check(Options::FaceColor))
return false;
// binary or ascii ?
if (_filename.rfind(".stla") != std::string::npos)
{
_opt -= Options::Binary;
return write_stla(_filename, _be, _opt);
}
else if (_filename.rfind(".stlb") != std::string::npos)
{
_opt += Options::Binary;
return write_stlb(_filename, _be, _opt);
}
else if (_filename.rfind(".stl") != std::string::npos)
{
return (_opt.check( Options::Binary )
? write_stlb(_filename, _be, _opt)
: write_stla(_filename, _be, _opt) );
}
return false;
}
//-----------------------------------------------------------------------------
bool
_STLWriter_::
write_stla(const std::string& _filename, BaseExporter& _be, Options /* _opt */) const
{
omlog() << "[STLWriter] : write ascii file\n";
// open file
FILE* out = fopen(_filename.c_str(), "w");
if (!out)
{
omerr() << "[STLWriter] : cannot open file " << _filename << std::endl;
return false;
}
unsigned int i, nF(_be.n_faces()), nV;
Vec3f a, b, c, n;
std::vector<VertexHandle> vhandles;
FaceHandle fh;
// header
fprintf(out, "solid\n");
// write face set
for (i=0; i<nF; ++i)
{
fh = FaceHandle(i);
nV = _be.get_vhandles(fh, vhandles);
if (nV == 3)
{
a = _be.point(vhandles[0]);
b = _be.point(vhandles[1]);
c = _be.point(vhandles[2]);
n = (_be.has_face_normals() ?
_be.normal(fh) :
((c-b) % (a-b)).normalize());
fprintf(out, "facet normal %f %f %f\nouter loop\n", n[0], n[1], n[2]);
fprintf(out, "vertex %.10f %.10f %.10f\n", a[0], a[1], a[2]);
fprintf(out, "vertex %.10f %.10f %.10f\n", b[0], b[1], b[2]);
fprintf(out, "vertex %.10f %.10f %.10f", c[0], c[1], c[2]);
}
else
omerr() << "[STLWriter] : Warning non-triangle data!\n";
fprintf(out, "\nendloop\nendfacet\n");
}
fclose(out);
return true;
}
//-----------------------------------------------------------------------------
bool
_STLWriter_::
write_stlb(const std::string& _filename, BaseExporter& _be, Options /* _opt */) const
{
omlog() << "[STLWriter] : write binary file\n";
// open file
FILE* out = fopen(_filename.c_str(), "wb");
if (!out)
{
omerr() << "[STLWriter] : cannot open file " << _filename << std::endl;
return false;
}
unsigned int i, nF(_be.n_faces()), nV;
Vec3f a, b, c, n;
std::vector<VertexHandle> vhandles;
FaceHandle fh;
// write header
const char header[80] =
"binary stl file"
" ";
fwrite(header, 1, 80, out);
// number of faces
write_int(_be.n_faces(), out);
// write face set
for (i=0; i<nF; ++i)
{
fh = FaceHandle(i);
nV = _be.get_vhandles(fh, vhandles);
if (nV == 3)
{
a = _be.point(vhandles[0]);
b = _be.point(vhandles[1]);
c = _be.point(vhandles[2]);
n = (_be.has_face_normals() ?
_be.normal(fh) :
((c-b) % (a-b)).normalize());
// face normal
write_float(n[0], out);
write_float(n[1], out);
write_float(n[2], out);
// face vertices
write_float(a[0], out);
write_float(a[1], out);
write_float(a[2], out);
write_float(b[0], out);
write_float(b[1], out);
write_float(b[2], out);
write_float(c[0], out);
write_float(c[1], out);
write_float(c[2], out);
// space filler
write_short(0, out);
}
else
omerr() << "[STLWriter] : Warning: Skipped non-triangle data!\n";
}
fclose(out);
return true;
}
//-----------------------------------------------------------------------------
size_t
_STLWriter_::
binary_size(BaseExporter& _be, Options /* _opt */) const
{
size_t bytes(0);
size_t _12floats(12*sizeof(float));
bytes += 80; // header
bytes += 4; // #faces
unsigned int i, nF(_be.n_faces());
std::vector<VertexHandle> vhandles;
for (i=0; i<nF; ++i)
if (_be.get_vhandles(FaceHandle(i), vhandles) == 3)
bytes += _12floats + sizeof(short);
else
omerr() << "[STLWriter] : Warning: Skipped non-triangle data!\n";
return bytes;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

100
Core/IO/writer/STLWriter.hh Normal file
View File

@@ -0,0 +1,100 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, version 2.1. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a writer module for STL ascii files
//
//=============================================================================
// $Id: STLWriter.hh,v 1.2 2007-05-18 15:17:43 habbecke Exp $
#ifndef __STLWRITER_HH__
#define __STLWRITER_HH__
//=== INCLUDES ================================================================
// -------------------- STL
#if defined( OM_CC_MIPS )
# include <stdio.h>
#else
# include <cstdio>
#endif
#include <string>
// -------------------- OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
Implementation of the STL format writer. This class is singleton'ed by
SingletonT to STLWriter.
*/
class _STLWriter_ : public BaseWriter
{
public:
_STLWriter_();
std::string get_description() const { return "Stereolithography Format"; }
std::string get_extensions() const { return "stla stlb"; }
bool write(const std::string&, BaseExporter&, Options) const;
size_t binary_size(BaseExporter&, Options) const;
private:
bool write_stla(const std::string&, BaseExporter&, Options) const;
bool write_stlb(const std::string&, BaseExporter&, Options) const;
};
//== TYPE DEFINITION ==========================================================
// Declare the single entity of STL writer.
extern _STLWriter_ __STLWriterInstance;
_STLWriter_& STLWriter();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================