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:
17
Core/IO/ACGMakefile
Normal file
17
Core/IO/ACGMakefile
Normal 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
179
Core/IO/BinaryHelper.cc
Normal 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
115
Core/IO/BinaryHelper.hh
Normal 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
91
Core/IO/IOInstances.hh
Normal 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
243
Core/IO/IOManager.cc
Normal 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
224
Core/IO/IOManager.hh
Normal 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
134
Core/IO/MeshIO.hh
Normal 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
76
Core/IO/OFFFormat.hh
Normal 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
231
Core/IO/OMFormat.cc
Normal 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
715
Core/IO/OMFormat.hh
Normal 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
224
Core/IO/OMFormatT.cc
Normal 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
220
Core/IO/Options.hh
Normal 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
118
Core/IO/SR_binary.hh
Normal 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
277
Core/IO/SR_binary_spec.hh
Normal 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
|
||||
//=============================================================================
|
||||
|
||||
99
Core/IO/SR_binary_vector_of_bool.inl
Normal file
99
Core/IO/SR_binary_vector_of_bool.inl
Normal 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;
|
||||
}
|
||||
};
|
||||
53
Core/IO/SR_binary_vector_of_fundamentals.inl
Normal file
53
Core/IO/SR_binary_vector_of_fundamentals.inl
Normal 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
|
||||
39
Core/IO/SR_binary_vector_of_string.inl
Normal file
39
Core/IO/SR_binary_vector_of_string.inl
Normal 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
247
Core/IO/SR_rbo.hh
Normal 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
54
Core/IO/SR_store.hh
Normal 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
94
Core/IO/SR_types.hh
Normal 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
98
Core/IO/StoreRestore.hh
Normal 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
|
||||
//=============================================================================
|
||||
17
Core/IO/exporter/ACGMakefile
Normal file
17
Core/IO/exporter/ACGMakefile
Normal 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
|
||||
#==============================================================================
|
||||
114
Core/IO/exporter/BaseExporter.hh
Normal file
114
Core/IO/exporter/BaseExporter.hh
Normal 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
|
||||
//=============================================================================
|
||||
183
Core/IO/exporter/ExporterT.hh
Normal file
183
Core/IO/exporter/ExporterT.hh
Normal 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
|
||||
//=============================================================================
|
||||
17
Core/IO/importer/ACGMakefile
Normal file
17
Core/IO/importer/ACGMakefile
Normal 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
|
||||
#==============================================================================
|
||||
130
Core/IO/importer/BaseImporter.hh
Normal file
130
Core/IO/importer/BaseImporter.hh
Normal 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
|
||||
//=============================================================================
|
||||
235
Core/IO/importer/ImporterT.hh
Normal file
235
Core/IO/importer/ImporterT.hh
Normal 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
|
||||
//=============================================================================
|
||||
17
Core/IO/reader/ACGMakefile
Normal file
17
Core/IO/reader/ACGMakefile
Normal 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
|
||||
#==============================================================================
|
||||
113
Core/IO/reader/BaseReader.cc
Normal file
113
Core/IO/reader/BaseReader.cc
Normal 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
|
||||
//=============================================================================
|
||||
113
Core/IO/reader/BaseReader.hh
Normal file
113
Core/IO/reader/BaseReader.hh
Normal 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
472
Core/IO/reader/OBJReader.cc
Normal 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
159
Core/IO/reader/OBJReader.hh
Normal 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
597
Core/IO/reader/OFFReader.cc
Normal 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
150
Core/IO/reader/OFFReader.hh
Normal 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
628
Core/IO/reader/OMReader.cc
Normal 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
150
Core/IO/reader/OMReader.hh
Normal 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
683
Core/IO/reader/PLYReader.cc
Normal 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
154
Core/IO/reader/PLYReader.hh
Normal 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
369
Core/IO/reader/STLReader.cc
Normal 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
124
Core/IO/reader/STLReader.hh
Normal 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
|
||||
//=============================================================================
|
||||
17
Core/IO/writer/ACGMakefile
Normal file
17
Core/IO/writer/ACGMakefile
Normal 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
|
||||
#==============================================================================
|
||||
88
Core/IO/writer/BaseWriter.cc
Normal file
88
Core/IO/writer/BaseWriter.cc
Normal 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
|
||||
//=============================================================================
|
||||
108
Core/IO/writer/BaseWriter.hh
Normal file
108
Core/IO/writer/BaseWriter.hh
Normal 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
303
Core/IO/writer/OBJWriter.cc
Normal 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
108
Core/IO/writer/OBJWriter.hh
Normal 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
432
Core/IO/writer/OFFWriter.cc
Normal 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
113
Core/IO/writer/OFFWriter.hh
Normal 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
504
Core/IO/writer/OMWriter.cc
Normal 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
119
Core/IO/writer/OMWriter.hh
Normal 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
476
Core/IO/writer/PLYWriter.cc
Normal 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
116
Core/IO/writer/PLYWriter.hh
Normal 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
278
Core/IO/writer/STLWriter.cc
Normal 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
100
Core/IO/writer/STLWriter.hh
Normal 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
|
||||
//=============================================================================
|
||||
Reference in New Issue
Block a user