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:
19
Core/ACGMakefile
Normal file
19
Core/ACGMakefile
Normal file
@@ -0,0 +1,19 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
SUBDIRS = Geometry Utils Mesh IO Tools System
|
||||
|
||||
PACKAGES :=
|
||||
|
||||
PROJ_LIBS :=
|
||||
|
||||
CXXLIB_BUILD_LIB := yes
|
||||
|
||||
MODULES := cxxlib
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
32
Core/Core.pro
Normal file
32
Core/Core.pro
Normal file
@@ -0,0 +1,32 @@
|
||||
################################################################################
|
||||
#
|
||||
################################################################################
|
||||
|
||||
contains( OPENFLIPPER , OpenFlipper ){
|
||||
include( $$TOPDIR/qmake/all.include )
|
||||
} else {
|
||||
include( $$TOPDIR/OpenMesh/qmake/all.include )
|
||||
}
|
||||
|
||||
Library()
|
||||
|
||||
DIRECTORIES = . Geometry IO IO/exporter IO/importer IO/reader IO/writer \
|
||||
Mesh Mesh/gen System Utils
|
||||
|
||||
INCLUDEPATH += ../..
|
||||
|
||||
win32 {
|
||||
DEFINES += _USE_MATH_DEFINES NOMINMAX
|
||||
CONFIG += static
|
||||
contains( OPENFLIPPER , OpenFlipper ){
|
||||
DESTDIR = $${TOPDIR}/OpenFlipper/$${BUILDDIRECTORY}
|
||||
message(OpenMesh Library is Building for OpenFlipper )
|
||||
}
|
||||
}
|
||||
|
||||
# Input
|
||||
HEADERS += $$getFilesFromDir($$DIRECTORIES,*.hh)
|
||||
SOURCES += $$getFilesFromDir($$DIRECTORIES,*.cc)
|
||||
FORMS += $$getFilesFromDir($$DIRECTORIES,*.ui)
|
||||
|
||||
################################################################################
|
||||
17
Core/Geometry/ACGMakefile
Normal file
17
Core/Geometry/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
|
||||
#==============================================================================
|
||||
56
Core/Geometry/Config.hh
Normal file
56
Core/Geometry/Config.hh
Normal file
@@ -0,0 +1,56 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Defines
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_GEOMETRY_CONFIG_HH
|
||||
#define OPENMESH_GEOMETRY_CONFIG_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
// OpenMesh Namespace Defines
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
#define BEGIN_NS_GEOMETRY namespace geometry {
|
||||
#define END_NS_GEOMETRY }
|
||||
|
||||
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_GEOMETRY_CONFIG_HH defined
|
||||
//=============================================================================
|
||||
172
Core/Geometry/LoopSchemeMaskT.hh
Normal file
172
Core/Geometry/LoopSchemeMaskT.hh
Normal file
@@ -0,0 +1,172 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* 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 LOOPSCHEMEMASKT_HH
|
||||
#define LOOPSCHEMEMASKT_HH
|
||||
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Utils/SingletonT.hh>
|
||||
|
||||
namespace OpenMesh
|
||||
{
|
||||
|
||||
/** implements cache for the weights of the original Loop scheme
|
||||
supported:
|
||||
- vertex projection rule on the next level
|
||||
- vertex projection rule on the limit surface
|
||||
- vertex projection rule on the k-th (level) step (Barthe, Kobbelt'2003)
|
||||
- vertex tangents on the limit surface
|
||||
*/
|
||||
|
||||
template <class T_, unsigned int cache_size_ = 100>
|
||||
class LoopSchemeMaskT
|
||||
{
|
||||
public:
|
||||
enum { cache_size = cache_size_ };
|
||||
typedef T_ Scalar;
|
||||
|
||||
protected:
|
||||
|
||||
Scalar proj_weights_[cache_size];
|
||||
Scalar limit_weights_[cache_size];
|
||||
Scalar step_weights_[cache_size];
|
||||
std::vector<Scalar> tang0_weights_[cache_size];
|
||||
std::vector<Scalar> tang1_weights_[cache_size];
|
||||
|
||||
protected:
|
||||
|
||||
inline static Scalar compute_proj_weight(uint _valence)
|
||||
{
|
||||
//return pow(3.0 / 2.0 + cos(2.0 * M_PI / _valence), 2) / 2.0 - 1.0;
|
||||
double denom = (3.0 + 2.0*cos(2.0*M_PI/(double)_valence));
|
||||
double weight = (64.0*_valence)/(40.0 - denom*denom) - _valence;
|
||||
return (Scalar) weight;
|
||||
}
|
||||
|
||||
inline static Scalar compute_limit_weight(uint _valence)
|
||||
{
|
||||
double proj_weight = compute_proj_weight(_valence);
|
||||
proj_weight = proj_weight/(proj_weight + _valence);//normalize the proj_weight
|
||||
double weight = (3.0/8.0)/(1.0 - proj_weight + (3.0/8.0));
|
||||
return (Scalar)weight;
|
||||
}
|
||||
|
||||
inline static Scalar compute_step_weight(uint _valence)
|
||||
{
|
||||
double proj_weight = compute_proj_weight(_valence);
|
||||
proj_weight = proj_weight/(proj_weight + _valence);//normalize the proj_weight
|
||||
double weight = proj_weight - (3.0/8.0);
|
||||
return (Scalar)weight;
|
||||
}
|
||||
|
||||
inline static Scalar compute_tang0_weight(uint _valence, uint _ver_id)
|
||||
{
|
||||
return (Scalar)cos(2.0*M_PI*(double)_ver_id/(double)_valence);
|
||||
}
|
||||
|
||||
inline static Scalar compute_tang1_weight(uint _valence, uint _ver_id)
|
||||
{
|
||||
return (Scalar)sin(2.0*M_PI*(double)_ver_id/(double)_valence);
|
||||
}
|
||||
|
||||
void cache_weights()
|
||||
{
|
||||
proj_weights_[0] = 1;
|
||||
for (uint k = 1; k < cache_size; ++k)
|
||||
{
|
||||
proj_weights_[k] = compute_proj_weight(k);
|
||||
limit_weights_[k] = compute_limit_weight(k);
|
||||
step_weights_[k] = compute_step_weight(k);
|
||||
tang0_weights_[k].resize(k);
|
||||
tang1_weights_[k].resize(k);
|
||||
for (uint i = 0; i < k; ++i)
|
||||
{
|
||||
tang0_weights_[k][i] = compute_tang0_weight(k,i);
|
||||
tang1_weights_[k][i] = compute_tang1_weight(k,i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
LoopSchemeMaskT()
|
||||
{
|
||||
cache_weights();
|
||||
}
|
||||
|
||||
inline Scalar proj_weight(uint _valence) const
|
||||
{
|
||||
assert(_valence < cache_size );
|
||||
return proj_weights_[_valence];
|
||||
}
|
||||
|
||||
inline Scalar limit_weight(uint _valence) const
|
||||
{
|
||||
assert(_valence < cache_size );
|
||||
return limit_weights_[_valence];
|
||||
}
|
||||
|
||||
inline Scalar step_weight(uint _valence, uint _step) const
|
||||
{
|
||||
assert(_valence < cache_size);
|
||||
return pow(step_weights_[_valence], (int)_step);//can be precomputed
|
||||
}
|
||||
|
||||
inline Scalar tang0_weight(uint _valence, uint _ver_id) const
|
||||
{
|
||||
assert(_valence < cache_size );
|
||||
assert(_ver_id < _valence);
|
||||
return tang0_weights_[_valence][_ver_id];
|
||||
}
|
||||
|
||||
inline Scalar tang1_weight(uint _valence, uint _ver_id) const
|
||||
{
|
||||
assert(_valence < cache_size );
|
||||
assert(_ver_id < _valence);
|
||||
return tang1_weights_[_valence][_ver_id];
|
||||
}
|
||||
|
||||
void dump(uint _max_valency = cache_size - 1) const
|
||||
{
|
||||
assert(_max_valency <= cache_size - 1);
|
||||
//CConsole::printf("(k : pw_k, lw_k): ");
|
||||
for (uint i = 0; i <= _max_valency; ++i)
|
||||
{
|
||||
//CConsole::stream() << "(" << i << " : " << proj_weight(i) << ", " << limit_weight(i) << ", " << step_weight(i,1) << "), ";
|
||||
}
|
||||
//CConsole::printf("\n");
|
||||
}
|
||||
};
|
||||
|
||||
typedef LoopSchemeMaskT<double, 100> LoopSchemeMaskDouble;
|
||||
typedef SingletonT<LoopSchemeMaskDouble> LoopSchemeMaskDoubleSingleton;
|
||||
|
||||
};//namespace OpenMesh
|
||||
|
||||
#endif//LOOPSCHEMEMASKT_HH
|
||||
|
||||
148
Core/Geometry/MathDefs.hh
Normal file
148
Core/Geometry/MathDefs.hh
Normal file
@@ -0,0 +1,148 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* 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 MATHDEFS_HH
|
||||
#define MATHDEFS_HH
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265359
|
||||
#endif
|
||||
|
||||
namespace OpenMesh
|
||||
{
|
||||
|
||||
/** comparison operators with user-selected precision control
|
||||
*/
|
||||
template <class T, typename Real>
|
||||
inline bool is_zero(const T& _a, Real _eps)
|
||||
{ return fabs(_a) < _eps; }
|
||||
|
||||
template <class T1, class T2, typename Real>
|
||||
inline bool is_eq(const T1& a, const T2& b, Real _eps)
|
||||
{ return is_zero(a-b, _eps); }
|
||||
|
||||
template <class T1, class T2, typename Real>
|
||||
inline bool is_gt(const T1& a, const T2& b, Real _eps)
|
||||
{ return (a > b) && !is_eq(a,b,_eps); }
|
||||
|
||||
template <class T1, class T2, typename Real>
|
||||
inline bool is_ge(const T1& a, const T2& b, Real _eps)
|
||||
{ return (a > b) || is_eq(a,b,_eps); }
|
||||
|
||||
template <class T1, class T2, typename Real>
|
||||
inline bool is_lt(const T1& a, const T2& b, Real _eps)
|
||||
{ return (a < b) && !is_eq(a,b,_eps); }
|
||||
|
||||
template <class T1, class T2, typename Real>
|
||||
inline bool is_le(const T1& a, const T2& b, Real _eps)
|
||||
{ return (a < b) || is_eq(a,b,_eps); }
|
||||
|
||||
/*const float flt_eps__ = 10*FLT_EPSILON;
|
||||
const double dbl_eps__ = 10*DBL_EPSILON;*/
|
||||
const float flt_eps__ = (float)1e-05;
|
||||
const double dbl_eps__ = 1e-09;
|
||||
|
||||
inline float eps__(float)
|
||||
{ return flt_eps__; }
|
||||
|
||||
inline double eps__(double)
|
||||
{ return dbl_eps__; }
|
||||
|
||||
template <class T>
|
||||
inline bool is_zero(const T& a)
|
||||
{ return is_zero(a, eps__(a)); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool is_eq(const T1& a, const T2& b)
|
||||
{ return is_zero(a-b); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool is_gt(const T1& a, const T2& b)
|
||||
{ return (a > b) && !is_eq(a,b); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool is_ge(const T1& a, const T2& b)
|
||||
{ return (a > b) || is_eq(a,b); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool is_lt(const T1& a, const T2& b)
|
||||
{ return (a < b) && !is_eq(a,b); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool is_le(const T1& a, const T2& b)
|
||||
{ return (a < b) || is_eq(a,b); }
|
||||
|
||||
/// Trigonometry/angles - related
|
||||
|
||||
template <class T>
|
||||
inline T sane_aarg(T _aarg)
|
||||
{
|
||||
if (_aarg < -1)
|
||||
{
|
||||
_aarg = -1;
|
||||
}
|
||||
else if (_aarg > 1)
|
||||
{
|
||||
_aarg = 1;
|
||||
}
|
||||
return _aarg;
|
||||
}
|
||||
|
||||
/** returns the angle determined by its cos and the sign of its sin
|
||||
result is positive if the angle is in [0:pi]
|
||||
and negative if it is in [pi:2pi]
|
||||
*/
|
||||
template <class T>
|
||||
T angle(T _cos_angle, T _sin_angle)
|
||||
{//sanity checks - otherwise acos will return nan
|
||||
_cos_angle = sane_aarg(_cos_angle);
|
||||
return (T) _sin_angle >= 0 ? acos(_cos_angle) : -acos(_cos_angle);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T positive_angle(T _angle)
|
||||
{ return _angle < 0 ? (2*M_PI + _angle) : _angle; }
|
||||
|
||||
template <class T>
|
||||
inline T positive_angle(T _cos_angle, T _sin_angle)
|
||||
{ return positive_angle(angle(_cos_angle, _sin_angle)); }
|
||||
|
||||
template <class T>
|
||||
inline T deg_to_rad(const T& _angle)
|
||||
{ return M_PI*(_angle/180); }
|
||||
|
||||
template <class T>
|
||||
inline T rad_to_deg(const T& _angle)
|
||||
{ return 180*(_angle/M_PI); }
|
||||
|
||||
inline double log_(double _value)
|
||||
{ return log(_value); }
|
||||
|
||||
};//namespace OpenMesh
|
||||
|
||||
#endif//MATHDEFS_HH
|
||||
99
Core/Geometry/Plane3d.hh
Normal file
99
Core/Geometry/Plane3d.hh
Normal file
@@ -0,0 +1,99 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2001-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. *
|
||||
* *
|
||||
\*===========================================================================*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS Plane3D
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_PLANE3D_HH
|
||||
#define OPENMESH_PLANE3D_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/Geometry/VectorT.hh>
|
||||
|
||||
|
||||
//== FORWARDDECLARATIONS ======================================================
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
namespace VDPM {
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \class Plane3d Plane3d.hh <OpenMesh/Tools/VDPM/Plane3d.hh>
|
||||
|
||||
ax + by + cz + d = 0
|
||||
*/
|
||||
|
||||
|
||||
class Plane3d
|
||||
{
|
||||
public:
|
||||
|
||||
typedef OpenMesh::Vec3f vector_type;
|
||||
typedef vector_type::value_type value_type;
|
||||
|
||||
public:
|
||||
|
||||
Plane3d()
|
||||
: d_(0)
|
||||
{ }
|
||||
|
||||
Plane3d(const vector_type &_dir, const vector_type &_pnt)
|
||||
: n_(_dir), d_(0)
|
||||
{
|
||||
n_.normalize();
|
||||
d_ = -dot(n_,_pnt);
|
||||
}
|
||||
|
||||
value_type signed_distance(const OpenMesh::Vec3f &_p)
|
||||
{
|
||||
return dot(n_ , _p) + d_;
|
||||
}
|
||||
|
||||
// back compatibility
|
||||
value_type singed_distance(const OpenMesh::Vec3f &point)
|
||||
{ return signed_distance( point ); }
|
||||
|
||||
public:
|
||||
|
||||
vector_type n_;
|
||||
value_type d_;
|
||||
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
} // namespace VDPM
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_PLANE3D_HH defined
|
||||
//=============================================================================
|
||||
260
Core/Geometry/QuadricT.hh
Normal file
260
Core/Geometry/QuadricT.hh
Normal file
@@ -0,0 +1,260 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file QuadricT.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS QuadricT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_GEOMETRY_QUADRIC_HH
|
||||
#define OPENMESH_GEOMETRY_QUADRIC_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include "Config.hh"
|
||||
#include <OpenMesh/Core/Geometry/VectorT.hh>
|
||||
#include <OpenMesh/Core/Utils/GenProg.hh>
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { //BEGIN_NS_OPENMESH
|
||||
namespace Geometry { //BEGIN_NS_GEOMETRY
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** /class QuadricT QuadricT.hh <OSG/Geometry/Types/QuadricT.hh>
|
||||
|
||||
Stores a quadric as a 4x4 symmetrix matrix. Used by the
|
||||
error quadric based mesh decimation algorithms.
|
||||
**/
|
||||
|
||||
template <class Scalar>
|
||||
class QuadricT
|
||||
{
|
||||
public:
|
||||
typedef Scalar value_type;
|
||||
typedef QuadricT<Scalar> type;
|
||||
typedef QuadricT<Scalar> Self;
|
||||
// typedef VectorInterface<Scalar, VecStorage3<Scalar> > Vec3;
|
||||
// typedef VectorInterface<Scalar, VecStorage4<Scalar> > Vec4;
|
||||
//typedef Vector3Elem Vec3;
|
||||
//typedef Vector4Elem Vec4;
|
||||
|
||||
/// construct with upper triangle of symmetrix 4x4 matrix
|
||||
QuadricT(Scalar _a, Scalar _b, Scalar _c, Scalar _d,
|
||||
Scalar _e, Scalar _f, Scalar _g,
|
||||
Scalar _h, Scalar _i,
|
||||
Scalar _j)
|
||||
: a_(_a), b_(_b), c_(_c), d_(_d),
|
||||
e_(_e), f_(_f), g_(_g),
|
||||
h_(_h), i_(_i),
|
||||
j_(_j)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// constructor from given plane equation: ax+by+cz+d_=0
|
||||
QuadricT( Scalar _a=0.0, Scalar _b=0.0, Scalar _c=0.0, Scalar _d=0.0 )
|
||||
: a_(_a*_a), b_(_a*_b), c_(_a*_c), d_(_a*_d),
|
||||
e_(_b*_b), f_(_b*_c), g_(_b*_d),
|
||||
h_(_c*_c), i_(_c*_d),
|
||||
j_(_d*_d)
|
||||
{}
|
||||
|
||||
template <class _Point>
|
||||
QuadricT(const _Point& _pt)
|
||||
{
|
||||
set_distance_to_point(_pt);
|
||||
}
|
||||
|
||||
template <class _Normal, class _Point>
|
||||
QuadricT(const _Normal& _n, const _Point& _p)
|
||||
{
|
||||
set_distance_to_plane(_n,_p);
|
||||
}
|
||||
|
||||
//set operator
|
||||
void set(Scalar _a, Scalar _b, Scalar _c, Scalar _d,
|
||||
Scalar _e, Scalar _f, Scalar _g,
|
||||
Scalar _h, Scalar _i,
|
||||
Scalar _j)
|
||||
{
|
||||
a_ = _a; b_ = _b; c_ = _c; d_ = _d;
|
||||
e_ = _e; f_ = _f; g_ = _g;
|
||||
h_ = _h; i_ = _i;
|
||||
j_ = _j;
|
||||
}
|
||||
|
||||
//sets the quadric representing the squared distance to _pt
|
||||
template <class _Point>
|
||||
void set_distance_to_point(const _Point& _pt)
|
||||
{
|
||||
set(1, 0, 0, -_pt[0],
|
||||
1, 0, -_pt[1],
|
||||
1, -_pt[2],
|
||||
dot(_pt,_pt));
|
||||
}
|
||||
|
||||
//sets the quadric representing the squared distance to the plane [_a,_b,_c,_d]
|
||||
void set_distance_to_plane(Scalar _a, Scalar _b, Scalar _c, Scalar _d)
|
||||
{
|
||||
a_ = _a*_a; b_ = _a*_b; c_ = _a*_c; d_ = _a*_d;
|
||||
e_ = _b*_b; f_ = _b*_c; g_ = _b*_d;
|
||||
h_ = _c*_c; i_ = _c*_d;
|
||||
j_ = _d*_d;
|
||||
}
|
||||
|
||||
//sets the quadric representing the squared distance to the plane
|
||||
//determined by the normal _n and the point _p
|
||||
template <class _Normal, class _Point>
|
||||
void set_distance_to_plane(const _Normal& _n, const _Point& _p)
|
||||
{
|
||||
set_distance_to_plane(_n[0], _n[1], _n[2], -dot(_n,_p));
|
||||
}
|
||||
|
||||
/// set all entries to zero
|
||||
void clear() { a_ = b_ = c_ = d_ = e_ = f_ = g_ = h_ = i_ = j_ = 0.0; }
|
||||
|
||||
/// add quadrics
|
||||
QuadricT<Scalar>& operator+=( const QuadricT<Scalar>& _q )
|
||||
{
|
||||
a_ += _q.a_; b_ += _q.b_; c_ += _q.c_; d_ += _q.d_;
|
||||
e_ += _q.e_; f_ += _q.f_; g_ += _q.g_;
|
||||
h_ += _q.h_; i_ += _q.i_;
|
||||
j_ += _q.j_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/// multiply by scalar
|
||||
QuadricT<Scalar>& operator*=( Scalar _s)
|
||||
{
|
||||
a_ *= _s; b_ *= _s; c_ *= _s; d_ *= _s;
|
||||
e_ *= _s; f_ *= _s; g_ *= _s;
|
||||
h_ *= _s; i_ *= _s;
|
||||
j_ *= _s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/// multiply 4D vector from right: Q*v
|
||||
template <class _Vec4>
|
||||
_Vec4 operator*(const _Vec4& _v) const
|
||||
{
|
||||
Scalar x(_v[0]), y(_v[1]), z(_v[2]), w(_v[3]);
|
||||
return _Vec4(x*a_ + y*b_ + z*c_ + w*d_,
|
||||
x*b_ + y*e_ + z*f_ + w*g_,
|
||||
x*c_ + y*f_ + z*h_ + w*i_,
|
||||
x*d_ + y*g_ + z*i_ + w*j_);
|
||||
}
|
||||
|
||||
/// evaluate quadric Q at (3D or 4D) vector v: v*Q*v
|
||||
template <class _Vec>
|
||||
Scalar operator()(const _Vec& _v) const
|
||||
{
|
||||
return evaluate(_v, GenProg::Int2Type<_Vec::size_>());
|
||||
}
|
||||
|
||||
Scalar a() const { return a_; }
|
||||
Scalar b() const { return b_; }
|
||||
Scalar c() const { return c_; }
|
||||
Scalar d() const { return d_; }
|
||||
Scalar e() const { return e_; }
|
||||
Scalar f() const { return f_; }
|
||||
Scalar g() const { return g_; }
|
||||
Scalar h() const { return h_; }
|
||||
Scalar i() const { return i_; }
|
||||
Scalar j() const { return j_; }
|
||||
|
||||
Scalar xx() const { return a_; }
|
||||
Scalar xy() const { return b_; }
|
||||
Scalar xz() const { return c_; }
|
||||
Scalar xw() const { return d_; }
|
||||
Scalar yy() const { return e_; }
|
||||
Scalar yz() const { return f_; }
|
||||
Scalar yw() const { return g_; }
|
||||
Scalar zz() const { return h_; }
|
||||
Scalar zw() const { return i_; }
|
||||
Scalar ww() const { return j_; }
|
||||
|
||||
protected:
|
||||
|
||||
/// evaluate quadric Q at 3D vector v: v*Q*v
|
||||
template <class _Vec3>
|
||||
Scalar evaluate(const _Vec3& _v, GenProg::Int2Type<3>/*_dimension*/) const
|
||||
{
|
||||
Scalar x(_v[0]), y(_v[1]), z(_v[2]);
|
||||
return a_*x*x + 2.0*b_*x*y + 2.0*c_*x*z + 2.0*d_*x
|
||||
+ e_*y*y + 2.0*f_*y*z + 2.0*g_*y
|
||||
+ h_*z*z + 2.0*i_*z
|
||||
+ j_;
|
||||
}
|
||||
|
||||
/// evaluate quadric Q at 4D vector v: v*Q*v
|
||||
template <class _Vec4>
|
||||
Scalar evaluate(const _Vec4& _v, GenProg::Int2Type<4>/*_dimension*/) const
|
||||
{
|
||||
Scalar x(_v[0]), y(_v[1]), z(_v[2]), w(_v[3]);
|
||||
return a_*x*x + 2.0*b_*x*y + 2.0*c_*x*z + 2.0*d_*x*w
|
||||
+ e_*y*y + 2.0*f_*y*z + 2.0*g_*y*w
|
||||
+ h_*z*z + 2.0*i_*z*w
|
||||
+ j_*w*w;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Scalar a_, b_, c_, d_,
|
||||
e_, f_, g_,
|
||||
h_, i_,
|
||||
j_;
|
||||
};
|
||||
|
||||
|
||||
/// Quadric using floats
|
||||
typedef QuadricT<float> Quadricf;
|
||||
|
||||
/// Quadric using double
|
||||
typedef QuadricT<double> Quadricd;
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_GEOMETRY
|
||||
} // END_NS_OPENMESH
|
||||
//============================================================================
|
||||
#endif // OPENMESH_GEOMETRY_HH defined
|
||||
//=============================================================================
|
||||
329
Core/Geometry/VectorT.hh
Normal file
329
Core/Geometry/VectorT.hh
Normal file
@@ -0,0 +1,329 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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: 4254 $
|
||||
// $Date: 2009-01-12 14:44:00 +0100 (Mo, 12. Jan 2009) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS VectorT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_VECTOR_HH
|
||||
#define OPENMESH_VECTOR_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#if defined(__GNUC__) && defined(__SSE__)
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
|
||||
/** The N values of the template Scalar type are the only data members
|
||||
of the class VectorT<Scalar,N>. This guarantees 100% compatibility
|
||||
with arrays of type Scalar and size N, allowing us to define the
|
||||
cast operators to and from arrays and array pointers.
|
||||
|
||||
In addition, this class will be specialized for Vec4f to be 16 bit
|
||||
aligned, so that aligned SSE instructions can be used on these
|
||||
vectors.
|
||||
*/
|
||||
template <typename Scalar,int N> struct VectorDataT
|
||||
{
|
||||
Scalar values_[N];
|
||||
};
|
||||
|
||||
|
||||
#if defined(__GNUC__) && defined(__SSE__)
|
||||
|
||||
/// This specialization enables us to use aligned SSE instructions.
|
||||
template <> struct VectorDataT<float, 4>
|
||||
{
|
||||
union
|
||||
{
|
||||
__m128 m128;
|
||||
float values_[4];
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
#define DIM N
|
||||
#define TEMPLATE_HEADER template <typename Scalar, int N>
|
||||
#define CLASSNAME VectorT
|
||||
#define DERIVED VectorDataT<Scalar,N>
|
||||
#define unroll(expr) for (int i=0; i<N; ++i) expr(i)
|
||||
|
||||
/** \class VectorT VectorT.hh <OpenMesh/Core/Math/VectorT.hh>
|
||||
A vector is an array of \<N\> values of type \<Scalar\>.
|
||||
The actual data is stored in an VectorDataT, this class just adds
|
||||
the necessary operators.
|
||||
*/
|
||||
#include "VectorT_inc.hh"
|
||||
|
||||
#undef DIM
|
||||
#undef TEMPLATE_HEADER
|
||||
#undef CLASSNAME
|
||||
#undef DERIVED
|
||||
#undef unroll
|
||||
|
||||
|
||||
|
||||
|
||||
//== PARTIAL TEMPLATE SPECIALIZATIONS =========================================
|
||||
#if OM_PARTIAL_SPECIALIZATION
|
||||
|
||||
|
||||
#define TEMPLATE_HEADER template <typename Scalar>
|
||||
#define CLASSNAME VectorT<Scalar,DIM>
|
||||
#define DERIVED VectorDataT<Scalar,DIM>
|
||||
|
||||
|
||||
#define DIM 2
|
||||
#define unroll(expr) expr(0) expr(1)
|
||||
#define unroll_comb(expr, op) expr(0) op expr(1)
|
||||
#define unroll_csv(expr) expr(0), expr(1)
|
||||
#include "VectorT_inc.hh"
|
||||
#undef DIM
|
||||
#undef unroll
|
||||
#undef unroll_comb
|
||||
#undef unroll_csv
|
||||
|
||||
|
||||
#define DIM 3
|
||||
#define unroll(expr) expr(0) expr(1) expr(2)
|
||||
#define unroll_comb(expr, op) expr(0) op expr(1) op expr(2)
|
||||
#define unroll_csv(expr) expr(0), expr(1), expr(2)
|
||||
#include "VectorT_inc.hh"
|
||||
#undef DIM
|
||||
#undef unroll
|
||||
#undef unroll_comb
|
||||
#undef unroll_csv
|
||||
|
||||
|
||||
#define DIM 4
|
||||
#define unroll(expr) expr(0) expr(1) expr(2) expr(3)
|
||||
#define unroll_comb(expr, op) expr(0) op expr(1) op expr(2) op expr(3)
|
||||
#define unroll_csv(expr) expr(0), expr(1), expr(2), expr(3)
|
||||
#include "VectorT_inc.hh"
|
||||
#undef DIM
|
||||
#undef unroll
|
||||
#undef unroll_comb
|
||||
#undef unroll_csv
|
||||
|
||||
|
||||
#undef TEMPLATE_HEADER
|
||||
#undef CLASSNAME
|
||||
#undef DERIVED
|
||||
|
||||
|
||||
|
||||
|
||||
//== FULL TEMPLATE SPECIALIZATIONS ============================================
|
||||
#else
|
||||
|
||||
# ifndef DOXY_IGNORE_THIS
|
||||
|
||||
/// cross product for Vec3f
|
||||
template<>
|
||||
inline VectorT<float,3>
|
||||
VectorT<float,3>::operator%(const VectorT<float,3>& _rhs) const
|
||||
{
|
||||
return
|
||||
VectorT<float,3>(values_[1]*_rhs.values_[2]-values_[2]*_rhs.values_[1],
|
||||
values_[2]*_rhs.values_[0]-values_[0]*_rhs.values_[2],
|
||||
values_[0]*_rhs.values_[1]-values_[1]*_rhs.values_[0]);
|
||||
}
|
||||
|
||||
|
||||
/// cross product for Vec3d
|
||||
template<>
|
||||
inline VectorT<double,3>
|
||||
VectorT<double,3>::operator%(const VectorT<double,3>& _rhs) const
|
||||
{
|
||||
return
|
||||
VectorT<double,3>(values_[1]*_rhs.values_[2]-values_[2]*_rhs.values_[1],
|
||||
values_[2]*_rhs.values_[0]-values_[0]*_rhs.values_[2],
|
||||
values_[0]*_rhs.values_[1]-values_[1]*_rhs.values_[0]);
|
||||
}
|
||||
|
||||
# endif // DOXY_IGNORE_THIS
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//== GLOBAL FUNCTIONS =========================================================
|
||||
|
||||
|
||||
/// \relates OpenMesh::VectorT
|
||||
/// scalar * vector
|
||||
template<typename Scalar,int N>
|
||||
inline VectorT<Scalar,N> operator*(Scalar _s, const VectorT<Scalar,N>& _v) {
|
||||
return VectorT<Scalar,N>(_v) *= _s;
|
||||
}
|
||||
|
||||
|
||||
/// \relates OpenMesh::VectorT
|
||||
/// symmetric version of the dot product
|
||||
template<typename Scalar, int N>
|
||||
inline Scalar
|
||||
dot(const VectorT<Scalar,N>& _v1, const VectorT<Scalar,N>& _v2) {
|
||||
return (_v1 | _v2);
|
||||
}
|
||||
|
||||
|
||||
/// \relates OpenMesh::VectorT
|
||||
/// symmetric version of the cross product
|
||||
template<typename Scalar, int N>
|
||||
inline VectorT<Scalar,N>
|
||||
cross(const VectorT<Scalar,N>& _v1, const VectorT<Scalar,N>& _v2) {
|
||||
return (_v1 % _v2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//== TYPEDEFS =================================================================
|
||||
|
||||
/** 1-byte signed vector */
|
||||
typedef VectorT<signed char,1> Vec1c;
|
||||
/** 1-byte unsigned vector */
|
||||
typedef VectorT<unsigned char,1> Vec1uc;
|
||||
/** 1-short signed vector */
|
||||
typedef VectorT<signed short int,1> Vec1s;
|
||||
/** 1-short unsigned vector */
|
||||
typedef VectorT<unsigned short int,1> Vec1us;
|
||||
/** 1-int signed vector */
|
||||
typedef VectorT<signed int,1> Vec1i;
|
||||
/** 1-int unsigned vector */
|
||||
typedef VectorT<unsigned int,1> Vec1ui;
|
||||
/** 1-float vector */
|
||||
typedef VectorT<float,1> Vec1f;
|
||||
/** 1-double vector */
|
||||
typedef VectorT<double,1> Vec1d;
|
||||
|
||||
/** 2-byte signed vector */
|
||||
typedef VectorT<signed char,2> Vec2c;
|
||||
/** 2-byte unsigned vector */
|
||||
typedef VectorT<unsigned char,2> Vec2uc;
|
||||
/** 2-short signed vector */
|
||||
typedef VectorT<signed short int,2> Vec2s;
|
||||
/** 2-short unsigned vector */
|
||||
typedef VectorT<unsigned short int,2> Vec2us;
|
||||
/** 2-int signed vector */
|
||||
typedef VectorT<signed int,2> Vec2i;
|
||||
/** 2-int unsigned vector */
|
||||
typedef VectorT<unsigned int,2> Vec2ui;
|
||||
/** 2-float vector */
|
||||
typedef VectorT<float,2> Vec2f;
|
||||
/** 2-double vector */
|
||||
typedef VectorT<double,2> Vec2d;
|
||||
|
||||
/** 3-byte signed vector */
|
||||
typedef VectorT<signed char,3> Vec3c;
|
||||
/** 3-byte unsigned vector */
|
||||
typedef VectorT<unsigned char,3> Vec3uc;
|
||||
/** 3-short signed vector */
|
||||
typedef VectorT<signed short int,3> Vec3s;
|
||||
/** 3-short unsigned vector */
|
||||
typedef VectorT<unsigned short int,3> Vec3us;
|
||||
/** 3-int signed vector */
|
||||
typedef VectorT<signed int,3> Vec3i;
|
||||
/** 3-int unsigned vector */
|
||||
typedef VectorT<unsigned int,3> Vec3ui;
|
||||
/** 3-float vector */
|
||||
typedef VectorT<float,3> Vec3f;
|
||||
/** 3-double vector */
|
||||
typedef VectorT<double,3> Vec3d;
|
||||
|
||||
/** 4-byte signed vector */
|
||||
typedef VectorT<signed char,4> Vec4c;
|
||||
/** 4-byte unsigned vector */
|
||||
typedef VectorT<unsigned char,4> Vec4uc;
|
||||
/** 4-short signed vector */
|
||||
typedef VectorT<signed short int,4> Vec4s;
|
||||
/** 4-short unsigned vector */
|
||||
typedef VectorT<unsigned short int,4> Vec4us;
|
||||
/** 4-int signed vector */
|
||||
typedef VectorT<signed int,4> Vec4i;
|
||||
/** 4-int unsigned vector */
|
||||
typedef VectorT<unsigned int,4> Vec4ui;
|
||||
/** 4-float vector */
|
||||
typedef VectorT<float,4> Vec4f;
|
||||
/** 4-double vector */
|
||||
typedef VectorT<double,4> Vec4d;
|
||||
|
||||
/** 6-byte signed vector */
|
||||
typedef VectorT<signed char,6> Vec6c;
|
||||
/** 6-byte unsigned vector */
|
||||
typedef VectorT<unsigned char,6> Vec6uc;
|
||||
/** 6-short signed vector */
|
||||
typedef VectorT<signed short int,6> Vec6s;
|
||||
/** 6-short unsigned vector */
|
||||
typedef VectorT<unsigned short int,6> Vec6us;
|
||||
/** 6-int signed vector */
|
||||
typedef VectorT<signed int,6> Vec6i;
|
||||
/** 6-int unsigned vector */
|
||||
typedef VectorT<unsigned int,6> Vec6ui;
|
||||
/** 6-float vector */
|
||||
typedef VectorT<float,6> Vec6f;
|
||||
/** 6-double vector */
|
||||
typedef VectorT<double,6> Vec6d;
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_VECTOR_HH defined
|
||||
//=============================================================================
|
||||
541
Core/Geometry/VectorT_inc.hh
Normal file
541
Core/Geometry/VectorT_inc.hh
Normal file
@@ -0,0 +1,541 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#if defined( OPENMESH_VECTOR_HH )
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEMPLATE_HEADER
|
||||
class CLASSNAME : public DERIVED
|
||||
{
|
||||
private:
|
||||
typedef DERIVED Base;
|
||||
public:
|
||||
|
||||
//---------------------------------------------------------------- class info
|
||||
|
||||
/// the type of the scalar used in this template
|
||||
typedef Scalar value_type;
|
||||
|
||||
/// type of this vector
|
||||
typedef VectorT<Scalar,DIM> vector_type;
|
||||
|
||||
/// returns dimension of the vector (deprecated)
|
||||
static inline int dim() { return DIM; }
|
||||
|
||||
/// returns dimension of the vector
|
||||
static inline size_t size() { return DIM; }
|
||||
|
||||
static const size_t size_ = DIM;
|
||||
|
||||
|
||||
//-------------------------------------------------------------- constructors
|
||||
|
||||
/// default constructor creates uninitialized values.
|
||||
inline VectorT() {}
|
||||
|
||||
/// special constructor for 1D vectors
|
||||
explicit inline VectorT(const Scalar& v) {
|
||||
// assert(DIM==1);
|
||||
// values_[0] = v0;
|
||||
vectorize(v);
|
||||
}
|
||||
|
||||
/// special constructor for 2D vectors
|
||||
inline VectorT(const Scalar& v0, const Scalar& v1) {
|
||||
assert(DIM==2);
|
||||
Base::values_[0] = v0; Base::values_[1] = v1;
|
||||
}
|
||||
|
||||
/// special constructor for 3D vectors
|
||||
inline VectorT(const Scalar& v0, const Scalar& v1, const Scalar& v2) {
|
||||
assert(DIM==3);
|
||||
Base::values_[0]=v0; Base::values_[1]=v1; Base::values_[2]=v2;
|
||||
}
|
||||
|
||||
/// special constructor for 4D vectors
|
||||
inline VectorT(const Scalar& v0, const Scalar& v1,
|
||||
const Scalar& v2, const Scalar& v3) {
|
||||
assert(DIM==4);
|
||||
Base::values_[0]=v0; Base::values_[1]=v1; Base::values_[2]=v2; Base::values_[3]=v3;
|
||||
}
|
||||
|
||||
/// special constructor for 5D vectors
|
||||
inline VectorT(const Scalar& v0, const Scalar& v1, const Scalar& v2,
|
||||
const Scalar& v3, const Scalar& v4) {
|
||||
assert(DIM==5);
|
||||
Base::values_[0]=v0; Base::values_[1]=v1;Base::values_[2]=v2; Base::values_[3]=v3; Base::values_[4]=v4;
|
||||
}
|
||||
|
||||
/// special constructor for 6D vectors
|
||||
inline VectorT(const Scalar& v0, const Scalar& v1, const Scalar& v2,
|
||||
const Scalar& v3, const Scalar& v4, const Scalar& v5) {
|
||||
assert(DIM==6);
|
||||
Base::values_[0]=v0; Base::values_[1]=v1; Base::values_[2]=v2;
|
||||
Base::values_[3]=v3; Base::values_[4]=v4; Base::values_[5]=v5;
|
||||
}
|
||||
|
||||
/// construct from a value array (explicit)
|
||||
explicit inline VectorT(const Scalar _values[DIM]) {
|
||||
memcpy(Base::values_, _values, DIM*sizeof(Scalar));
|
||||
}
|
||||
|
||||
|
||||
#ifdef OM_CC_MIPS
|
||||
/// assignment from a vector of the same kind
|
||||
// mipspro need this method
|
||||
inline vector_type& operator=(const vector_type& _rhs) {
|
||||
memcpy(Base::values_, _rhs.Base::values_, DIM*sizeof(Scalar));
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/// copy & cast constructor (explicit)
|
||||
template<typename otherScalarType>
|
||||
explicit inline VectorT(const VectorT<otherScalarType,DIM>& _rhs) {
|
||||
operator=(_rhs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------- casts
|
||||
|
||||
/// cast from vector with a different scalar type
|
||||
template<typename otherScalarType>
|
||||
inline vector_type& operator=(const VectorT<otherScalarType,DIM>& _rhs) {
|
||||
#define expr(i) Base::values_[i] = (Scalar)_rhs[i];
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return *this;
|
||||
}
|
||||
|
||||
// /// cast to Scalar array
|
||||
// inline operator Scalar*() { return Base::values_; }
|
||||
|
||||
// /// cast to const Scalar array
|
||||
// inline operator const Scalar*() const { return Base::values_; }
|
||||
|
||||
/// access to Scalar array
|
||||
inline Scalar* data() { return Base::values_; }
|
||||
|
||||
/// access to const Scalar array
|
||||
inline const Scalar*data() const { return Base::values_; }
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------- element access
|
||||
|
||||
// /// get i'th element read-write
|
||||
// inline Scalar& operator[](int _i) {
|
||||
// assert(_i>=0 && _i<DIM); return Base::values_[_i];
|
||||
// }
|
||||
|
||||
// /// get i'th element read-only
|
||||
// inline const Scalar& operator[](int _i) const {
|
||||
// assert(_i>=0 && _i<DIM); return Base::values_[_i];
|
||||
// }
|
||||
|
||||
/// get i'th element read-write
|
||||
inline Scalar& operator[](size_t _i) {
|
||||
assert(_i<DIM); return Base::values_[_i];
|
||||
}
|
||||
|
||||
/// get i'th element read-only
|
||||
inline const Scalar& operator[](size_t _i) const {
|
||||
assert(_i<DIM); return Base::values_[_i];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------- comparsion
|
||||
|
||||
/// component-wise comparison
|
||||
inline bool operator==(const vector_type& _rhs) const {
|
||||
#define expr(i) if(Base::values_[i]!=_rhs.Base::values_[i]) return false;
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return true;
|
||||
}
|
||||
|
||||
/// component-wise comparison
|
||||
inline bool operator!=(const vector_type& _rhs) const {
|
||||
return !(*this == _rhs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------- scalar operators
|
||||
|
||||
/// component-wise self-multiplication with scalar
|
||||
inline vector_type& operator*=(const Scalar& _s) {
|
||||
#define expr(i) Base::values_[i] *= _s;
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** component-wise self-division by scalar
|
||||
\attention v *= (1/_s) is much faster than this */
|
||||
inline vector_type& operator/=(const Scalar& _s) {
|
||||
#define expr(i) Base::values_[i] /= _s;
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/// component-wise multiplication with scalar
|
||||
inline vector_type operator*(const Scalar& _s) const {
|
||||
#if DIM==N
|
||||
return vector_type(*this) *= _s;
|
||||
#else
|
||||
#define expr(i) Base::values_[i] * _s
|
||||
return vector_type(unroll_csv(expr));
|
||||
#undef expr
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// component-wise division by with scalar
|
||||
inline vector_type operator/(const Scalar& _s) const {
|
||||
#if DIM==N
|
||||
return vector_type(*this) /= _s;
|
||||
#else
|
||||
#define expr(i) Base::values_[i] / _s
|
||||
return vector_type(unroll_csv(expr));
|
||||
#undef expr
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------- vector operators
|
||||
|
||||
/// component-wise self-multiplication
|
||||
inline vector_type& operator*=(const vector_type& _rhs) {
|
||||
#define expr(i) Base::values_[i] *= _rhs[i];
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// component-wise self-division
|
||||
inline vector_type& operator/=(const vector_type& _rhs) {
|
||||
#define expr(i) Base::values_[i] /= _rhs[i];
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// vector difference from this
|
||||
inline vector_type& operator-=(const vector_type& _rhs) {
|
||||
#define expr(i) Base::values_[i] -= _rhs[i];
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// vector self-addition
|
||||
inline vector_type& operator+=(const vector_type& _rhs) {
|
||||
#define expr(i) Base::values_[i] += _rhs[i];
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/// component-wise vector multiplication
|
||||
inline vector_type operator*(const vector_type& _v) const {
|
||||
#if DIM==N
|
||||
return vector_type(*this) *= _v;
|
||||
#else
|
||||
#define expr(i) Base::values_[i] * _v.Base::values_[i]
|
||||
return vector_type(unroll_csv(expr));
|
||||
#undef expr
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// component-wise vector division
|
||||
inline vector_type operator/(const vector_type& _v) const {
|
||||
#if DIM==N
|
||||
return vector_type(*this) /= _v;
|
||||
#else
|
||||
#define expr(i) Base::values_[i] / _v.Base::values_[i]
|
||||
return vector_type(unroll_csv(expr));
|
||||
#undef expr
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// component-wise vector addition
|
||||
inline vector_type operator+(const vector_type& _v) const {
|
||||
#if DIM==N
|
||||
return vector_type(*this) += _v;
|
||||
#else
|
||||
#define expr(i) Base::values_[i] + _v.Base::values_[i]
|
||||
return vector_type(unroll_csv(expr));
|
||||
#undef expr
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// component-wise vector difference
|
||||
inline vector_type operator-(const vector_type& _v) const {
|
||||
#if DIM==N
|
||||
return vector_type(*this) -= _v;
|
||||
#else
|
||||
#define expr(i) Base::values_[i] - _v.Base::values_[i]
|
||||
return vector_type(unroll_csv(expr));
|
||||
#undef expr
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// unary minus
|
||||
inline vector_type operator-(void) const {
|
||||
vector_type v;
|
||||
#define expr(i) v.Base::values_[i] = -Base::values_[i];
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/// cross product: only defined for Vec3* as specialization
|
||||
/// \see OpenMesh::cross
|
||||
inline VectorT<Scalar,3> operator%(const VectorT<Scalar,3>& _rhs) const
|
||||
#if DIM==3
|
||||
{
|
||||
return
|
||||
VectorT<Scalar,3>(Base::values_[1]*_rhs.Base::values_[2]-Base::values_[2]*_rhs.Base::values_[1],
|
||||
Base::values_[2]*_rhs.Base::values_[0]-Base::values_[0]*_rhs.Base::values_[2],
|
||||
Base::values_[0]*_rhs.Base::values_[1]-Base::values_[1]*_rhs.Base::values_[0]);
|
||||
}
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
|
||||
|
||||
/// compute scalar product
|
||||
/// \see OpenMesh::dot
|
||||
inline Scalar operator|(const vector_type& _rhs) const {
|
||||
Scalar p(0);
|
||||
#define expr(i) p += Base::values_[i] * _rhs.Base::values_[i];
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------ euclidean norm
|
||||
|
||||
/// \name Euclidean norm calculations
|
||||
//@{
|
||||
/// compute euclidean norm
|
||||
inline Scalar norm() const { return (Scalar)sqrt(sqrnorm()); }
|
||||
inline Scalar length() const { return norm(); } // OpenSG interface
|
||||
|
||||
/// compute squared euclidean norm
|
||||
inline Scalar sqrnorm() const
|
||||
{
|
||||
#if DIM==N
|
||||
Scalar s(0);
|
||||
#define expr(i) s += Base::values_[i] * Base::values_[i];
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return s;
|
||||
#else
|
||||
#define expr(i) Base::values_[i]*Base::values_[i]
|
||||
return (unroll_comb(expr, +));
|
||||
#undef expr
|
||||
#endif
|
||||
}
|
||||
//@}
|
||||
|
||||
/** normalize vector, return normalized vector
|
||||
*/
|
||||
|
||||
inline vector_type& normalize()
|
||||
{
|
||||
*this /= norm();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** normalize vector, return normalized vector and avoids div by zero
|
||||
*/
|
||||
inline vector_type& normalize_cond()
|
||||
{
|
||||
Scalar n = norm();
|
||||
if (n != (Scalar)0.0)
|
||||
{
|
||||
*this /= n;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------ max, min, mean
|
||||
|
||||
/// return the maximal component
|
||||
inline Scalar max() const
|
||||
{
|
||||
Scalar m(Base::values_[0]);
|
||||
for(int i=1; i<DIM; ++i) if(Base::values_[i]>m) m=Base::values_[i];
|
||||
return m;
|
||||
}
|
||||
|
||||
/// return the minimal component
|
||||
inline Scalar min() const
|
||||
{
|
||||
Scalar m(Base::values_[0]);
|
||||
for(int i=1; i<DIM; ++i) if(Base::values_[i]<m) m=Base::values_[i];
|
||||
return m;
|
||||
}
|
||||
|
||||
/// return arithmetic mean
|
||||
inline Scalar mean() const {
|
||||
Scalar m(Base::values_[0]);
|
||||
for(int i=1; i<DIM; ++i) m+=Base::values_[i];
|
||||
return m/Scalar(DIM);
|
||||
}
|
||||
|
||||
/// minimize values: same as *this = min(*this, _rhs), but faster
|
||||
inline vector_type minimize(const vector_type& _rhs) {
|
||||
#define expr(i) if (_rhs[i] < Base::values_[i]) Base::values_[i] = _rhs[i];
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// maximize values: same as *this = max(*this, _rhs), but faster
|
||||
inline vector_type maximize(const vector_type& _rhs) {
|
||||
#define expr(i) if (_rhs[i] > Base::values_[i]) Base::values_[i] = _rhs[i];
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// component-wise min
|
||||
inline vector_type min(const vector_type& _rhs) {
|
||||
return vector_type(*this).minimize(_rhs);
|
||||
}
|
||||
|
||||
/// component-wise max
|
||||
inline vector_type max(const vector_type& _rhs) {
|
||||
return vector_type(*this).maximize(_rhs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------ misc functions
|
||||
|
||||
/// component-wise apply function object with Scalar operator()(Scalar).
|
||||
template<typename Functor>
|
||||
inline vector_type apply(const Functor& _func) const {
|
||||
vector_type result;
|
||||
#define expr(i) result[i] = _func(Base::values_[i]);
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return result;
|
||||
}
|
||||
|
||||
/// store the same value in each component (e.g. to clear all entries)
|
||||
vector_type& vectorize(const Scalar& _s) {
|
||||
#define expr(i) Base::values_[i] = _s;
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/// store the same value in each component
|
||||
static vector_type vectorized(const Scalar& _s) {
|
||||
return vector_type().vectorize(_s);
|
||||
}
|
||||
|
||||
|
||||
/// lexicographical comparison
|
||||
bool operator<(const vector_type& _rhs) const {
|
||||
#define expr(i) if (Base::values_[i] != _rhs.Base::values_[i]) \
|
||||
return (Base::values_[i] < _rhs.Base::values_[i]);
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// read the space-separated components of a vector from a stream
|
||||
TEMPLATE_HEADER
|
||||
inline std::istream&
|
||||
operator>>(std::istream& is, VectorT<Scalar,DIM>& vec)
|
||||
{
|
||||
#define expr(i) is >> vec[i];
|
||||
unroll(expr);
|
||||
#undef expr
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
/// output a vector by printing its space-separated compontens
|
||||
TEMPLATE_HEADER
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& os, const VectorT<Scalar,DIM>& vec)
|
||||
{
|
||||
#if DIM==N
|
||||
for(int i=0; i<N-1; ++i) os << vec[i] << " ";
|
||||
os << vec[N-1];
|
||||
#else
|
||||
#define expr(i) vec[i]
|
||||
os << unroll_comb(expr, << " " <<);
|
||||
#undef expr
|
||||
#endif
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#endif // included by VectorT.hh
|
||||
//=============================================================================
|
||||
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
|
||||
//=============================================================================
|
||||
17
Core/Mesh/ACGMakefile
Normal file
17
Core/Mesh/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
|
||||
#==============================================================================
|
||||
112
Core/Mesh/ArrayItems.hh
Normal file
112
Core/Mesh/ArrayItems.hh
Normal file
@@ -0,0 +1,112 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_ARRAY_ITEMS_HH
|
||||
#define OPENMESH_ARRAY_ITEMS_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Utils/GenProg.hh>
|
||||
#include <OpenMesh/Core/Mesh/Handles.hh>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/// Definition of mesh items for use in the ArrayKernel
|
||||
struct ArrayItems
|
||||
{
|
||||
|
||||
//------------------------------------------------------ internal vertex type
|
||||
|
||||
/// The vertex item
|
||||
class Vertex
|
||||
{
|
||||
friend class ArrayKernel;
|
||||
HalfedgeHandle halfedge_handle_;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------- internal halfedge type
|
||||
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
class Halfedge_without_prev
|
||||
{
|
||||
friend class ArrayKernel;
|
||||
FaceHandle face_handle_;
|
||||
VertexHandle vertex_handle_;
|
||||
HalfedgeHandle next_halfedge_handle_;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
class Halfedge_with_prev : public Halfedge_without_prev
|
||||
{
|
||||
friend class ArrayKernel;
|
||||
HalfedgeHandle prev_halfedge_handle_;
|
||||
};
|
||||
#endif
|
||||
|
||||
//TODO: should be selected with config.h define
|
||||
typedef Halfedge_with_prev Halfedge;
|
||||
typedef GenProg::Bool2Type<true> HasPrevHalfedge;
|
||||
|
||||
//-------------------------------------------------------- internal edge type
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
class Edge
|
||||
{
|
||||
friend class ArrayKernel;
|
||||
Halfedge halfedges_[2];
|
||||
};
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------- internal face type
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
class Face
|
||||
{
|
||||
friend class ArrayKernel;
|
||||
HalfedgeHandle halfedge_handle_;
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_ITEMS_HH defined
|
||||
//=============================================================================
|
||||
297
Core/Mesh/ArrayKernel.cc
Normal file
297
Core/Mesh/ArrayKernel.cc
Normal file
@@ -0,0 +1,297 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2004 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. *
|
||||
* *
|
||||
\*===========================================================================*/
|
||||
|
||||
#include <OpenMesh/Core/Mesh/ArrayKernel.hh>
|
||||
|
||||
namespace OpenMesh
|
||||
{
|
||||
|
||||
ArrayKernel::ArrayKernel()
|
||||
: refcount_vstatus_(0), refcount_hstatus_(0),
|
||||
refcount_estatus_(0), refcount_fstatus_(0)
|
||||
{
|
||||
init_bit_masks(); //Status bit masks initialization
|
||||
}
|
||||
|
||||
ArrayKernel::~ArrayKernel()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
// ArrayKernel::ArrayKernel(const ArrayKernel& _rhs)
|
||||
// : BaseKernel(_rhs),
|
||||
// vertices_(_rhs.vertices_), edges_(_rhs.edges_), faces_(_rhs.faces_),
|
||||
// vertex_status_(_rhs.vertex_status_), halfedge_status_(_rhs.halfedge_status_),
|
||||
// edge_status_(_rhs.edge_status_), face_status_(_rhs.face_status_),
|
||||
// refcount_vstatus_(_rhs.refcount_vstatus_), refcount_hstatus_(_rhs.refcount_hstatus_),
|
||||
// refcount_estatus_(_rhs.refcount_estatus_), refcount_fstatus_(_rhs.refcount_fstatus_)
|
||||
// {}
|
||||
|
||||
|
||||
void ArrayKernel::assign_connectivity(const ArrayKernel& _other)
|
||||
{
|
||||
vertices_ = _other.vertices_;
|
||||
edges_ = _other.edges_;
|
||||
faces_ = _other.faces_;
|
||||
|
||||
vprops_resize(n_vertices());
|
||||
hprops_resize(n_halfedges());
|
||||
eprops_resize(n_edges());
|
||||
fprops_resize(n_faces());
|
||||
|
||||
#define COPY_STATUS_PROPERTY(ENTITY) \
|
||||
if (_other.ENTITY##_status_.is_valid()) \
|
||||
{ \
|
||||
if (!ENTITY##_status_.is_valid()) \
|
||||
{ \
|
||||
request_##ENTITY##_status(); \
|
||||
} \
|
||||
property(ENTITY##_status_) = _other.property(_other.ENTITY##_status_); \
|
||||
}
|
||||
COPY_STATUS_PROPERTY(vertex)
|
||||
COPY_STATUS_PROPERTY(halfedge)
|
||||
COPY_STATUS_PROPERTY(edge)
|
||||
COPY_STATUS_PROPERTY(face)
|
||||
|
||||
#undef COPY_STATUS_PROPERTY
|
||||
}
|
||||
|
||||
uint ArrayKernel::delete_isolated_vertices()
|
||||
{
|
||||
assert(has_vertex_status());//this function requires vertex status property
|
||||
uint n_isolated = 0;
|
||||
for (KernelVertexIter v_it = vertices_begin(); v_it != vertices_end(); ++v_it)
|
||||
{
|
||||
if (is_isolated(handle(*v_it)))
|
||||
{
|
||||
status(handle(*v_it)).set_deleted(true);
|
||||
n_isolated++;
|
||||
}
|
||||
}
|
||||
return n_isolated;
|
||||
}
|
||||
|
||||
void ArrayKernel::garbage_collection(bool _v, bool _e, bool _f)
|
||||
{
|
||||
int i, i0, i1, nV(n_vertices()), nE(n_edges()), nH(2*n_edges()), nF(n_faces());
|
||||
|
||||
std::vector<VertexHandle> vh_map;
|
||||
std::vector<HalfedgeHandle> hh_map;
|
||||
std::vector<FaceHandle> fh_map;
|
||||
|
||||
// setup handle mapping:
|
||||
vh_map.reserve(nV);
|
||||
for (i=0; i<nV; ++i) vh_map.push_back(VertexHandle(i));
|
||||
|
||||
hh_map.reserve(nH);
|
||||
for (i=0; i<nH; ++i) hh_map.push_back(HalfedgeHandle(i));
|
||||
|
||||
fh_map.reserve(nF);
|
||||
for (i=0; i<nF; ++i) fh_map.push_back(FaceHandle(i));
|
||||
|
||||
// remove deleted vertices
|
||||
if (_v && n_vertices() > 0)
|
||||
{
|
||||
i0=0; i1=nV-1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
// find 1st deleted and last un-deleted
|
||||
while (!status(VertexHandle(i0)).deleted() && i0 < i1) ++i0;
|
||||
while ( status(VertexHandle(i1)).deleted() && i0 < i1) --i1;
|
||||
if (i0 >= i1) break;
|
||||
|
||||
// swap
|
||||
std::swap(vertices_[i0], vertices_[i1]);
|
||||
std::swap(vh_map[i0], vh_map[i1]);
|
||||
vprops_swap(i0, i1);
|
||||
};
|
||||
|
||||
vertices_.resize(status(VertexHandle(i0)).deleted() ? i0 : i0+1);
|
||||
vprops_resize(n_vertices());
|
||||
}
|
||||
|
||||
|
||||
// remove deleted edges
|
||||
if (_e && n_edges() > 0)
|
||||
{
|
||||
i0=0; i1=nE-1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
// find 1st deleted and last un-deleted
|
||||
while (!status(EdgeHandle(i0)).deleted() && i0 < i1) ++i0;
|
||||
while ( status(EdgeHandle(i1)).deleted() && i0 < i1) --i1;
|
||||
if (i0 >= i1) break;
|
||||
|
||||
// swap
|
||||
std::swap(edges_[i0], edges_[i1]);
|
||||
std::swap(hh_map[2*i0], hh_map[2*i1]);
|
||||
std::swap(hh_map[2*i0+1], hh_map[2*i1+1]);
|
||||
eprops_swap(i0, i1);
|
||||
hprops_swap(2*i0, 2*i1);
|
||||
hprops_swap(2*i0+1, 2*i1+1);
|
||||
};
|
||||
|
||||
edges_.resize(status(EdgeHandle(i0)).deleted() ? i0 : i0+1);
|
||||
eprops_resize(n_edges());
|
||||
hprops_resize(n_halfedges());
|
||||
}
|
||||
|
||||
|
||||
// remove deleted faces
|
||||
if (_f && n_faces() > 0)
|
||||
{
|
||||
i0=0; i1=nF-1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
// find 1st deleted and last un-deleted
|
||||
while (!status(FaceHandle(i0)).deleted() && i0 < i1) ++i0;
|
||||
while ( status(FaceHandle(i1)).deleted() && i0 < i1) --i1;
|
||||
if (i0 >= i1) break;
|
||||
|
||||
// swap
|
||||
std::swap(faces_[i0], faces_[i1]);
|
||||
std::swap(fh_map[i0], fh_map[i1]);
|
||||
fprops_swap(i0, i1);
|
||||
};
|
||||
|
||||
faces_.resize(status(FaceHandle(i0)).deleted() ? i0 : i0+1);
|
||||
fprops_resize(n_faces());
|
||||
}
|
||||
|
||||
|
||||
// update handles of vertices
|
||||
if (_e)
|
||||
{
|
||||
KernelVertexIter v_it(vertices_begin()), v_end(vertices_end());
|
||||
VertexHandle vh;
|
||||
|
||||
for (; v_it!=v_end; ++v_it)
|
||||
{
|
||||
vh = handle(*v_it);
|
||||
if (!is_isolated(vh))
|
||||
{
|
||||
set_halfedge_handle(vh, hh_map[halfedge_handle(vh).idx()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HalfedgeHandle hh;
|
||||
// update handles of halfedges
|
||||
for (KernelEdgeIter e_it(edges_begin()); e_it != edges_end(); ++e_it)
|
||||
{//in the first pass update the (half)edges vertices
|
||||
hh = halfedge_handle(handle(*e_it), 0);
|
||||
set_vertex_handle(hh, vh_map[to_vertex_handle(hh).idx()]);
|
||||
hh = halfedge_handle(handle(*e_it), 1);
|
||||
set_vertex_handle(hh, vh_map[to_vertex_handle(hh).idx()]);
|
||||
}
|
||||
for (KernelEdgeIter e_it(edges_begin()); e_it != edges_end(); ++e_it)
|
||||
{//in the second pass update the connectivity of the (half)edges
|
||||
hh = halfedge_handle(handle(*e_it), 0);
|
||||
set_next_halfedge_handle(hh, hh_map[next_halfedge_handle(hh).idx()]);
|
||||
if (!is_boundary(hh))
|
||||
{
|
||||
set_face_handle(hh, fh_map[face_handle(hh).idx()]);
|
||||
}
|
||||
hh = halfedge_handle(handle(*e_it), 1);
|
||||
set_next_halfedge_handle(hh, hh_map[next_halfedge_handle(hh).idx()]);
|
||||
if (!is_boundary(hh))
|
||||
{
|
||||
set_face_handle(hh, fh_map[face_handle(hh).idx()]);
|
||||
}
|
||||
}
|
||||
|
||||
// update handles of faces
|
||||
if (_e)
|
||||
{
|
||||
KernelFaceIter f_it(faces_begin()), f_end(faces_end());
|
||||
FaceHandle fh;
|
||||
|
||||
for (; f_it!=f_end; ++f_it)
|
||||
{
|
||||
fh = handle(*f_it);
|
||||
set_halfedge_handle(fh, hh_map[halfedge_handle(fh).idx()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayKernel::clear()
|
||||
{
|
||||
vertices_.clear();
|
||||
edges_.clear();
|
||||
faces_.clear();
|
||||
|
||||
vprops_resize(0);
|
||||
eprops_resize(0);
|
||||
hprops_resize(0);
|
||||
fprops_resize(0);
|
||||
}
|
||||
|
||||
void ArrayKernel::resize( uint _n_vertices, uint _n_edges, uint _n_faces )
|
||||
{
|
||||
vertices_.resize(_n_vertices);
|
||||
edges_.resize(_n_edges);
|
||||
faces_.resize(_n_faces);
|
||||
|
||||
vprops_resize(n_vertices());
|
||||
hprops_resize(n_halfedges());
|
||||
eprops_resize(n_edges());
|
||||
fprops_resize(n_faces());
|
||||
}
|
||||
|
||||
void ArrayKernel::reserve(uint _n_vertices, uint _n_edges, uint _n_faces )
|
||||
{
|
||||
vertices_.reserve(_n_vertices);
|
||||
edges_.reserve(_n_edges);
|
||||
faces_.reserve(_n_faces);
|
||||
|
||||
vprops_reserve(_n_vertices);
|
||||
hprops_reserve(_n_edges*2);
|
||||
eprops_reserve(_n_edges);
|
||||
fprops_reserve(_n_faces);
|
||||
}
|
||||
|
||||
// Status Sets API
|
||||
void ArrayKernel::init_bit_masks(BitMaskContainer& _bmc)
|
||||
{
|
||||
for (uint i = Attributes::UNUSED; i != 0; i <<= 1)
|
||||
{
|
||||
_bmc.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayKernel::init_bit_masks()
|
||||
{
|
||||
init_bit_masks(vertex_bit_masks_);
|
||||
edge_bit_masks_ = vertex_bit_masks_;//init_bit_masks(edge_bit_masks_);
|
||||
face_bit_masks_ = vertex_bit_masks_;//init_bit_masks(face_bit_masks_);
|
||||
halfedge_bit_masks_= vertex_bit_masks_;//init_bit_masks(halfedge_bit_masks_);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
786
Core/Mesh/ArrayKernel.hh
Normal file
786
Core/Mesh/ArrayKernel.hh
Normal file
@@ -0,0 +1,786 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS ArrayKernel
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_ARRAY_KERNEL_HH
|
||||
#define OPENMESH_ARRAY_KERNEL_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
#include <vector>
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Utils/GenProg.hh>
|
||||
|
||||
#include <OpenMesh/Core/Mesh/ArrayItems.hh>
|
||||
#include <OpenMesh/Core/Mesh/BaseKernel.hh>
|
||||
#include <OpenMesh/Core/Mesh/Status.hh>
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
/** \ingroup mesh_kernels_group
|
||||
|
||||
Mesh kernel using arrays for mesh item storage.
|
||||
|
||||
This mesh kernel uses the std::vector as container to store the
|
||||
mesh items. Therefore all handle types are internally represented
|
||||
by integers. To get the index from a handle use the handle's \c
|
||||
idx() method.
|
||||
|
||||
\note For a description of the minimal kernel interface see
|
||||
OpenMesh::Mesh::BaseKernel.
|
||||
\note You do not have to use this class directly, use the predefined
|
||||
mesh-kernel combinations in \ref mesh_types_group.
|
||||
\see OpenMesh::Concepts::KernelT, \ref mesh_type
|
||||
*/
|
||||
|
||||
class ArrayKernel : public BaseKernel, public ArrayItems
|
||||
{
|
||||
public:
|
||||
|
||||
// handles
|
||||
typedef OpenMesh::VertexHandle VertexHandle;
|
||||
typedef OpenMesh::HalfedgeHandle HalfedgeHandle;
|
||||
typedef OpenMesh::EdgeHandle EdgeHandle;
|
||||
typedef OpenMesh::FaceHandle FaceHandle;
|
||||
typedef Attributes::StatusInfo StatusInfo;
|
||||
typedef VPropHandleT<StatusInfo> VertexStatusPropertyHandle;
|
||||
typedef HPropHandleT<StatusInfo> HalfedgeStatusPropertyHandle;
|
||||
typedef EPropHandleT<StatusInfo> EdgeStatusPropertyHandle;
|
||||
typedef FPropHandleT<StatusInfo> FaceStatusPropertyHandle;
|
||||
|
||||
public:
|
||||
|
||||
// --- constructor/destructor ---
|
||||
ArrayKernel();
|
||||
virtual ~ArrayKernel();
|
||||
|
||||
/** ArrayKernel uses the default copy constructor and assignment operator, which means
|
||||
that the connectivity and all properties are copied, including reference
|
||||
counters, allocated bit status masks, etc.. In contrast assign_connectivity
|
||||
copies only the connectivity, i.e. vertices, edges, faces and their status fields.
|
||||
NOTE: The geometry (the points property) is NOT copied. Poly/TriConnectivity
|
||||
override(and hide) that function to provide connectivity consistence.*/
|
||||
void assign_connectivity(const ArrayKernel& _other);
|
||||
|
||||
// --- handle -> item ---
|
||||
VertexHandle handle(const Vertex& _v) const
|
||||
{return VertexHandle(&_v - &vertices_.front()); }
|
||||
|
||||
HalfedgeHandle handle(const Halfedge& _he) const
|
||||
{
|
||||
uint eh(((char*)&edges_.front() - (char*)&_he) % sizeof(Edge));
|
||||
assert((&_he == &edges_[eh].halfedges_[0]) ||
|
||||
(&_he == &edges_[eh].halfedges_[1]));
|
||||
return ((&_he == &edges_[eh].halfedges_[0]) ?
|
||||
HalfedgeHandle(eh<<1) : HalfedgeHandle((eh<<1)+1));
|
||||
}
|
||||
|
||||
EdgeHandle handle(const Edge& _e) const
|
||||
{ return EdgeHandle(&_e - &edges_.front()); }
|
||||
|
||||
FaceHandle handle(const Face& _f) const
|
||||
{ return FaceHandle(&_f - &faces_.front()); }
|
||||
|
||||
#define SIGNED(x) signed( (x) )
|
||||
//checks handle validity - useful for debugging
|
||||
bool is_valid_handle(VertexHandle _vh) const
|
||||
{ return 0 <= _vh.idx() && _vh.idx() < SIGNED(n_vertices()); }
|
||||
|
||||
bool is_valid_handle(HalfedgeHandle _heh) const
|
||||
{ return 0 <= _heh.idx() && _heh.idx() < SIGNED(n_edges()*2); }
|
||||
|
||||
bool is_valid_handle(EdgeHandle _eh) const
|
||||
{ return 0 <= _eh.idx() && _eh.idx() < SIGNED(n_edges()); }
|
||||
|
||||
bool is_valid_handle(FaceHandle _fh) const
|
||||
{ return 0 <= _fh.idx() && _fh.idx() < SIGNED(n_faces()); }
|
||||
|
||||
// --- item -> handle ---
|
||||
const Vertex& vertex(VertexHandle _vh) const
|
||||
{
|
||||
assert(is_valid_handle(_vh));
|
||||
return vertices_[_vh.idx()];
|
||||
}
|
||||
|
||||
Vertex& vertex(VertexHandle _vh)
|
||||
{
|
||||
assert(is_valid_handle(_vh));
|
||||
return vertices_[_vh.idx()];
|
||||
}
|
||||
|
||||
const Halfedge& halfedge(HalfedgeHandle _heh) const
|
||||
{
|
||||
assert(is_valid_handle(_heh));
|
||||
return edges_[_heh.idx() >> 1].halfedges_[_heh.idx() & 1];
|
||||
}
|
||||
|
||||
Halfedge& halfedge(HalfedgeHandle _heh)
|
||||
{
|
||||
assert(is_valid_handle(_heh));
|
||||
return edges_[_heh.idx() >> 1].halfedges_[_heh.idx() & 1];
|
||||
}
|
||||
|
||||
const Edge& edge(EdgeHandle _eh) const
|
||||
{
|
||||
assert(is_valid_handle(_eh));
|
||||
return edges_[_eh.idx()];
|
||||
}
|
||||
|
||||
Edge& edge(EdgeHandle _eh)
|
||||
{
|
||||
assert(is_valid_handle(_eh));
|
||||
return edges_[_eh.idx()];
|
||||
}
|
||||
|
||||
const Face& face(FaceHandle _fh) const
|
||||
{
|
||||
assert(is_valid_handle(_fh));
|
||||
return faces_[_fh.idx()];
|
||||
}
|
||||
|
||||
Face& face(FaceHandle _fh)
|
||||
{
|
||||
assert(is_valid_handle(_fh));
|
||||
return faces_[_fh.idx()];
|
||||
}
|
||||
|
||||
#undef SIGNED
|
||||
|
||||
// --- get i'th items ---
|
||||
|
||||
VertexHandle vertex_handle(uint _i) const
|
||||
{ return (_i < n_vertices()) ? handle( vertices_[_i] ) : VertexHandle(); }
|
||||
|
||||
HalfedgeHandle halfedge_handle(uint _i) const
|
||||
{
|
||||
return (_i < n_halfedges()) ?
|
||||
halfedge_handle(edge_handle(_i/2), _i%2) : HalfedgeHandle();
|
||||
}
|
||||
|
||||
EdgeHandle edge_handle(uint _i) const
|
||||
{ return (_i < n_edges()) ? handle(edges_[_i]) : EdgeHandle(); }
|
||||
|
||||
FaceHandle face_handle(uint _i) const
|
||||
{ return (_i < n_faces()) ? handle(faces_[_i]) : FaceHandle(); }
|
||||
|
||||
public:
|
||||
|
||||
inline VertexHandle new_vertex()
|
||||
{
|
||||
vertices_.push_back(Vertex());
|
||||
vprops_resize(n_vertices());//TODO:should it be push_back()?
|
||||
|
||||
return handle(vertices_.back());
|
||||
}
|
||||
|
||||
inline HalfedgeHandle new_edge(VertexHandle _start_vh, VertexHandle _end_vh)
|
||||
{
|
||||
// assert(_start_vh != _end_vh);
|
||||
edges_.push_back(Edge());
|
||||
eprops_resize(n_edges());//TODO:should it be push_back()?
|
||||
hprops_resize(n_halfedges());//TODO:should it be push_back()?
|
||||
|
||||
EdgeHandle eh(handle(edges_.back()));
|
||||
HalfedgeHandle heh0(halfedge_handle(eh, 0));
|
||||
HalfedgeHandle heh1(halfedge_handle(eh, 1));
|
||||
set_vertex_handle(heh0, _end_vh);
|
||||
set_vertex_handle(heh1, _start_vh);
|
||||
return heh0;
|
||||
}
|
||||
|
||||
inline FaceHandle new_face()
|
||||
{
|
||||
faces_.push_back(Face());
|
||||
fprops_resize(n_faces());
|
||||
return handle(faces_.back());
|
||||
}
|
||||
|
||||
inline FaceHandle new_face(const Face& _f)
|
||||
{
|
||||
faces_.push_back(_f);
|
||||
fprops_resize(n_faces());
|
||||
return handle(faces_.back());
|
||||
}
|
||||
|
||||
public:
|
||||
// --- resize/reserve ---
|
||||
void resize( uint _n_vertices, uint _n_edges, uint _n_faces );
|
||||
void reserve(uint _n_vertices, uint _n_edges, uint _n_faces );
|
||||
|
||||
// --- deletion ---
|
||||
void garbage_collection(bool _v=true, bool _e=true, bool _f=true);
|
||||
void clear();
|
||||
|
||||
// --- number of items ---
|
||||
uint n_vertices() const { return vertices_.size(); }
|
||||
uint n_halfedges() const { return 2*edges_.size(); }
|
||||
uint n_edges() const { return edges_.size(); }
|
||||
uint n_faces() const { return faces_.size(); }
|
||||
|
||||
bool vertices_empty() const { return vertices_.empty(); }
|
||||
bool halfedges_empty() const { return edges_.empty(); }
|
||||
bool edges_empty() const { return edges_.empty(); }
|
||||
bool faces_empty() const { return faces_.empty(); }
|
||||
|
||||
// --- vertex connectivity ---
|
||||
|
||||
HalfedgeHandle halfedge_handle(VertexHandle _vh) const
|
||||
{ return vertex(_vh).halfedge_handle_; }
|
||||
|
||||
void set_halfedge_handle(VertexHandle _vh, HalfedgeHandle _heh)
|
||||
{
|
||||
// assert(is_valid_handle(_heh));
|
||||
vertex(_vh).halfedge_handle_ = _heh;
|
||||
}
|
||||
|
||||
bool is_isolated(VertexHandle _vh) const
|
||||
{ return !halfedge_handle(_vh).is_valid(); }
|
||||
|
||||
void set_isolated(VertexHandle _vh)
|
||||
{ vertex(_vh).halfedge_handle_.invalidate(); }
|
||||
|
||||
uint delete_isolated_vertices();
|
||||
|
||||
// --- halfedge connectivity ---
|
||||
VertexHandle to_vertex_handle(HalfedgeHandle _heh) const
|
||||
{ return halfedge(_heh).vertex_handle_; }
|
||||
|
||||
VertexHandle from_vertex_handle(HalfedgeHandle _heh) const
|
||||
{ return to_vertex_handle(opposite_halfedge_handle(_heh)); }
|
||||
|
||||
void set_vertex_handle(HalfedgeHandle _heh, VertexHandle _vh)
|
||||
{
|
||||
// assert(is_valid_handle(_vh));
|
||||
halfedge(_heh).vertex_handle_ = _vh;
|
||||
}
|
||||
|
||||
FaceHandle face_handle(HalfedgeHandle _heh) const
|
||||
{ return halfedge(_heh).face_handle_; }
|
||||
|
||||
void set_face_handle(HalfedgeHandle _heh, FaceHandle _fh)
|
||||
{
|
||||
// assert(is_valid_handle(_fh));
|
||||
halfedge(_heh).face_handle_ = _fh;
|
||||
}
|
||||
|
||||
void set_boundary(HalfedgeHandle _heh)
|
||||
{ halfedge(_heh).face_handle_.invalidate(); }
|
||||
|
||||
/// Is halfedge _heh a boundary halfedge (is its face handle invalid) ?
|
||||
bool is_boundary(HalfedgeHandle _heh) const
|
||||
{ return !face_handle(_heh).is_valid(); }
|
||||
|
||||
HalfedgeHandle next_halfedge_handle(HalfedgeHandle _heh) const
|
||||
{ return halfedge(_heh).next_halfedge_handle_; }
|
||||
|
||||
void set_next_halfedge_handle(HalfedgeHandle _heh, HalfedgeHandle _nheh)
|
||||
{
|
||||
assert(is_valid_handle(_nheh));
|
||||
// assert(to_vertex_handle(_heh) == from_vertex_handle(_nheh));
|
||||
halfedge(_heh).next_halfedge_handle_ = _nheh;
|
||||
set_prev_halfedge_handle(_nheh, _heh);
|
||||
}
|
||||
|
||||
|
||||
void set_prev_halfedge_handle(HalfedgeHandle _heh, HalfedgeHandle _pheh)
|
||||
{
|
||||
assert(is_valid_handle(_pheh));
|
||||
set_prev_halfedge_handle(_heh, _pheh, HasPrevHalfedge());
|
||||
}
|
||||
|
||||
void set_prev_halfedge_handle(HalfedgeHandle _heh, HalfedgeHandle _pheh,
|
||||
GenProg::True)
|
||||
{ halfedge(_heh).prev_halfedge_handle_ = _pheh; }
|
||||
|
||||
void set_prev_halfedge_handle(HalfedgeHandle /* _heh */, HalfedgeHandle /* _pheh */,
|
||||
GenProg::False)
|
||||
{}
|
||||
|
||||
HalfedgeHandle prev_halfedge_handle(HalfedgeHandle _heh) const
|
||||
{ return prev_halfedge_handle(_heh, HasPrevHalfedge() ); }
|
||||
|
||||
HalfedgeHandle prev_halfedge_handle(HalfedgeHandle _heh, GenProg::True) const
|
||||
{ return halfedge(_heh).prev_halfedge_handle_; }
|
||||
|
||||
HalfedgeHandle prev_halfedge_handle(HalfedgeHandle _heh, GenProg::False) const
|
||||
{
|
||||
if (is_boundary(_heh))
|
||||
{//iterating around the vertex should be faster than iterating the boundary
|
||||
HalfedgeHandle curr_heh(opposite_halfedge_handle(_heh));
|
||||
HalfedgeHandle next_heh(next_halfedge_handle(curr_heh));
|
||||
do
|
||||
{
|
||||
curr_heh = opposite_halfedge_handle(next_heh);
|
||||
next_heh = next_halfedge_handle(curr_heh);
|
||||
}
|
||||
while (next_heh != _heh);
|
||||
return curr_heh;
|
||||
}
|
||||
else
|
||||
{
|
||||
HalfedgeHandle heh(_heh);
|
||||
HalfedgeHandle next_heh(next_halfedge_handle(heh));
|
||||
while (next_heh != _heh) {
|
||||
heh = next_heh;
|
||||
next_heh = next_halfedge_handle(next_heh);
|
||||
}
|
||||
return heh;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HalfedgeHandle opposite_halfedge_handle(HalfedgeHandle _heh) const
|
||||
{ return HalfedgeHandle((_heh.idx() & 1) ? _heh.idx()-1 : _heh.idx()+1); }
|
||||
|
||||
|
||||
HalfedgeHandle ccw_rotated_halfedge_handle(HalfedgeHandle _heh) const
|
||||
{ return opposite_halfedge_handle(prev_halfedge_handle(_heh)); }
|
||||
|
||||
|
||||
HalfedgeHandle cw_rotated_halfedge_handle(HalfedgeHandle _heh) const
|
||||
{ return next_halfedge_handle(opposite_halfedge_handle(_heh)); }
|
||||
|
||||
// --- edge connectivity ---
|
||||
HalfedgeHandle halfedge_handle(EdgeHandle _eh, uint _i) const
|
||||
{
|
||||
assert(_i<=1);
|
||||
return HalfedgeHandle((_eh.idx() << 1) + _i);
|
||||
}
|
||||
|
||||
EdgeHandle edge_handle(HalfedgeHandle _heh) const
|
||||
{ return EdgeHandle(_heh.idx() >> 1); }
|
||||
|
||||
// --- face connectivity ---
|
||||
HalfedgeHandle halfedge_handle(FaceHandle _fh) const
|
||||
{ return face(_fh).halfedge_handle_; }
|
||||
|
||||
void set_halfedge_handle(FaceHandle _fh, HalfedgeHandle _heh)
|
||||
{
|
||||
// assert(is_valid_handle(_heh));
|
||||
face(_fh).halfedge_handle_ = _heh;
|
||||
}
|
||||
|
||||
/// Status Query API
|
||||
//------------------------------------------------------------ vertex status
|
||||
const StatusInfo& status(VertexHandle _vh) const
|
||||
{ return property(vertex_status_, _vh); }
|
||||
|
||||
StatusInfo& status(VertexHandle _vh)
|
||||
{ return property(vertex_status_, _vh); }
|
||||
|
||||
//----------------------------------------------------------- halfedge status
|
||||
const StatusInfo& status(HalfedgeHandle _hh) const
|
||||
{ return property(halfedge_status_, _hh); }
|
||||
|
||||
StatusInfo& status(HalfedgeHandle _hh)
|
||||
{ return property(halfedge_status_, _hh); }
|
||||
|
||||
//--------------------------------------------------------------- edge status
|
||||
const StatusInfo& status(EdgeHandle _eh) const
|
||||
{ return property(edge_status_, _eh); }
|
||||
|
||||
StatusInfo& status(EdgeHandle _eh)
|
||||
{ return property(edge_status_, _eh); }
|
||||
|
||||
//--------------------------------------------------------------- face status
|
||||
const StatusInfo& status(FaceHandle _fh) const
|
||||
{ return property(face_status_, _fh); }
|
||||
|
||||
StatusInfo& status(FaceHandle _fh)
|
||||
{ return property(face_status_, _fh); }
|
||||
|
||||
inline bool has_vertex_status() const
|
||||
{ return vertex_status_.is_valid(); }
|
||||
|
||||
inline bool has_halfedge_status() const
|
||||
{ return halfedge_status_.is_valid(); }
|
||||
|
||||
inline bool has_edge_status() const
|
||||
{ return edge_status_.is_valid(); }
|
||||
|
||||
inline bool has_face_status() const
|
||||
{ return face_status_.is_valid(); }
|
||||
|
||||
inline VertexStatusPropertyHandle vertex_status_pph() const
|
||||
{ return vertex_status_; }
|
||||
|
||||
inline HalfedgeStatusPropertyHandle halfedge_status_pph() const
|
||||
{ return halfedge_status_; }
|
||||
|
||||
inline EdgeStatusPropertyHandle edge_status_pph() const
|
||||
{ return edge_status_; }
|
||||
|
||||
inline FaceStatusPropertyHandle face_status_pph() const
|
||||
{ return face_status_; }
|
||||
|
||||
/// status property by handle
|
||||
inline VertexStatusPropertyHandle status_pph(VertexHandle /*_hnd*/) const
|
||||
{ return vertex_status_pph(); }
|
||||
|
||||
inline HalfedgeStatusPropertyHandle status_pph(HalfedgeHandle /*_hnd*/) const
|
||||
{ return halfedge_status_pph(); }
|
||||
|
||||
inline EdgeStatusPropertyHandle status_pph(EdgeHandle /*_hnd*/) const
|
||||
{ return edge_status_pph(); }
|
||||
|
||||
inline FaceStatusPropertyHandle status_pph(FaceHandle /*_hnd*/) const
|
||||
{ return face_status_pph(); }
|
||||
|
||||
/// Status Request API
|
||||
void request_vertex_status()
|
||||
{
|
||||
if (!refcount_vstatus_++)
|
||||
add_property( vertex_status_, "v:status" );
|
||||
}
|
||||
|
||||
void request_halfedge_status()
|
||||
{
|
||||
if (!refcount_hstatus_++)
|
||||
add_property( halfedge_status_, "h:status" );
|
||||
}
|
||||
|
||||
void request_edge_status()
|
||||
{
|
||||
if (!refcount_estatus_++)
|
||||
add_property( edge_status_, "e:status" );
|
||||
}
|
||||
|
||||
void request_face_status()
|
||||
{
|
||||
if (!refcount_fstatus_++)
|
||||
add_property( face_status_, "f:status" );
|
||||
}
|
||||
|
||||
/// Status Release API
|
||||
void release_vertex_status()
|
||||
{
|
||||
if ((refcount_vstatus_ > 0) && (! --refcount_vstatus_))
|
||||
remove_property(vertex_status_);
|
||||
}
|
||||
|
||||
void release_halfedge_status()
|
||||
{
|
||||
if ((refcount_hstatus_ > 0) && (! --refcount_hstatus_))
|
||||
remove_property(halfedge_status_);
|
||||
}
|
||||
|
||||
void release_edge_status()
|
||||
{
|
||||
if ((refcount_estatus_ > 0) && (! --refcount_estatus_))
|
||||
remove_property(edge_status_);
|
||||
}
|
||||
|
||||
void release_face_status()
|
||||
{
|
||||
if ((refcount_fstatus_ > 0) && (! --refcount_fstatus_))
|
||||
remove_property(face_status_);
|
||||
}
|
||||
|
||||
/// --- StatusSet API ---
|
||||
|
||||
template <class Handle>
|
||||
class StatusSetT
|
||||
{
|
||||
protected:
|
||||
ArrayKernel& kernel_;
|
||||
|
||||
public:
|
||||
const uint bit_mask_;
|
||||
|
||||
public:
|
||||
StatusSetT(ArrayKernel& _kernel, uint _bit_mask)
|
||||
: kernel_(_kernel), bit_mask_(_bit_mask)
|
||||
{}
|
||||
|
||||
~StatusSetT()
|
||||
{}
|
||||
|
||||
inline bool is_in(Handle _hnd) const
|
||||
{ return kernel_.status(_hnd).is_bit_set(bit_mask_); }
|
||||
|
||||
inline void insert(Handle _hnd)
|
||||
{ return kernel_.status(_hnd).set_bit(bit_mask_); }
|
||||
|
||||
inline void erase(Handle _hnd)
|
||||
{ return kernel_.status(_hnd).unset_bit(bit_mask_); }
|
||||
|
||||
/// Note: 0(n) complexity
|
||||
uint size() const
|
||||
{
|
||||
uint n_elements = kernel_.status_pph(Handle()).is_valid() ?
|
||||
kernel_.property(kernel_.status_pph(Handle())).n_elements() : 0;
|
||||
uint sz = 0;
|
||||
for (uint i = 0; i < n_elements; ++i)
|
||||
{
|
||||
sz += (uint)is_in(Handle(i));
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
/// Note: O(n) complexity
|
||||
void clear()
|
||||
{
|
||||
uint n_elements = kernel_.status_pph(Handle()).is_valid() ?
|
||||
kernel_.property(kernel_.status_pph(Handle())).n_elements() : 0;
|
||||
for (uint i = 0; i < n_elements; ++i)
|
||||
{
|
||||
erase(Handle(i));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
friend class StatusSetT<VertexHandle>;
|
||||
friend class StatusSetT<EdgeHandle>;
|
||||
friend class StatusSetT<FaceHandle>;
|
||||
friend class StatusSetT<HalfedgeHandle>;
|
||||
|
||||
/// --- AutoStatusSet API ---
|
||||
|
||||
template <class Handle>
|
||||
class AutoStatusSetT : public StatusSetT<Handle>
|
||||
{
|
||||
private:
|
||||
typedef StatusSetT<Handle> Base;
|
||||
public:
|
||||
AutoStatusSetT(ArrayKernel& _kernel)
|
||||
: StatusSetT<Handle>(_kernel, _kernel.pop_bit_mask(Handle()))
|
||||
{ /*assert(size() == 0);*/ } //the set should be empty on creation
|
||||
|
||||
~AutoStatusSetT()
|
||||
{
|
||||
//assert(size() == 0);//the set should be empty on leave?
|
||||
Base::kernel_.push_bit_mask(Handle(), Base::bit_mask_);
|
||||
}
|
||||
};
|
||||
|
||||
friend class AutoStatusSetT<VertexHandle>;
|
||||
friend class AutoStatusSetT<EdgeHandle>;
|
||||
friend class AutoStatusSetT<FaceHandle>;
|
||||
friend class AutoStatusSetT<HalfedgeHandle>;
|
||||
|
||||
typedef AutoStatusSetT<VertexHandle> VertexStatusSet;
|
||||
typedef AutoStatusSetT<EdgeHandle> EdgeStatusSet;
|
||||
typedef AutoStatusSetT<FaceHandle> FaceStatusSet;
|
||||
typedef AutoStatusSetT<HalfedgeHandle> HalfedgeStatusSet;
|
||||
|
||||
/// --- ExtStatusSet API --- (hybrid between a set and an array)
|
||||
|
||||
template <class Handle>
|
||||
class ExtStatusSetT : public AutoStatusSetT<Handle>
|
||||
{
|
||||
public:
|
||||
typedef AutoStatusSetT<Handle> Base;
|
||||
|
||||
protected:
|
||||
typedef std::vector<Handle> HandleContainer;
|
||||
HandleContainer handles_;
|
||||
|
||||
public:
|
||||
typedef typename HandleContainer::iterator
|
||||
iterator;
|
||||
typedef typename HandleContainer::const_iterator
|
||||
const_iterator;
|
||||
public:
|
||||
ExtStatusSetT(ArrayKernel& _kernel, uint _capacity_hint = 0)
|
||||
: Base(_kernel)
|
||||
{ handles_.reserve(_capacity_hint); }
|
||||
|
||||
~ExtStatusSetT()
|
||||
{ clear(); }
|
||||
|
||||
//set API
|
||||
// Complexity: O(1)
|
||||
inline void insert(Handle _hnd)
|
||||
{
|
||||
if (!is_in(_hnd))
|
||||
{
|
||||
Base::insert(_hnd);
|
||||
handles_.push_back(_hnd);
|
||||
}
|
||||
}
|
||||
|
||||
// Complexity: O(k), (k - number of the elements in the set)
|
||||
inline void erase(Handle _hnd)
|
||||
{
|
||||
if (is_in(_hnd))
|
||||
{
|
||||
iterator it = std::find(begin(), end(), _hnd);
|
||||
erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// Complexity: O(1)
|
||||
inline void erase(iterator _it)
|
||||
{
|
||||
assert(_it != end() && is_in(*_it));
|
||||
clear(*_it);
|
||||
*_it = handles_.back();
|
||||
*_it.pop_back();
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
for (iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
assert(is_in(*it));
|
||||
Base::erase(*it);
|
||||
}
|
||||
handles_.clear();
|
||||
}
|
||||
|
||||
/// Complexity: 0(1)
|
||||
inline uint size() const
|
||||
{ return handles_.size(); }
|
||||
inline bool empty() const
|
||||
{ return handles_.empty(); }
|
||||
|
||||
//Vector API
|
||||
inline iterator begin()
|
||||
{ return handles_.begin(); }
|
||||
inline const_iterator begin() const
|
||||
{ return handles_.begin(); }
|
||||
|
||||
inline iterator end()
|
||||
{ return handles_.end(); }
|
||||
inline const_iterator end() const
|
||||
{ return handles_.end(); }
|
||||
|
||||
inline Handle& front()
|
||||
{ return handles_.front(); }
|
||||
inline const Handle& front() const
|
||||
{ return handles_.front(); }
|
||||
|
||||
inline Handle& back()
|
||||
{ return handles_.back(); }
|
||||
inline const Handle& back() const
|
||||
{ return handles_.back(); }
|
||||
};
|
||||
|
||||
typedef ExtStatusSetT<FaceHandle> ExtFaceStatusSet;
|
||||
typedef ExtStatusSetT<VertexHandle> ExtVertexStatusSet;
|
||||
typedef ExtStatusSetT<EdgeHandle> ExtEdgeStatusSet;
|
||||
typedef ExtStatusSetT<HalfedgeHandle> ExtHalfedgeStatusSet;
|
||||
|
||||
private:
|
||||
// iterators
|
||||
typedef std::vector<Vertex> VertexContainer;
|
||||
typedef std::vector<Edge> EdgeContainer;
|
||||
typedef std::vector<Face> FaceContainer;
|
||||
typedef VertexContainer::iterator KernelVertexIter;
|
||||
typedef VertexContainer::const_iterator KernelConstVertexIter;
|
||||
typedef EdgeContainer::iterator KernelEdgeIter;
|
||||
typedef EdgeContainer::const_iterator KernelConstEdgeIter;
|
||||
typedef FaceContainer::iterator KernelFaceIter;
|
||||
typedef FaceContainer::const_iterator KernelConstFaceIter;
|
||||
typedef std::vector<uint> BitMaskContainer;
|
||||
|
||||
|
||||
KernelVertexIter vertices_begin() { return vertices_.begin(); }
|
||||
KernelConstVertexIter vertices_begin() const { return vertices_.begin(); }
|
||||
KernelVertexIter vertices_end() { return vertices_.end(); }
|
||||
KernelConstVertexIter vertices_end() const { return vertices_.end(); }
|
||||
|
||||
KernelEdgeIter edges_begin() { return edges_.begin(); }
|
||||
KernelConstEdgeIter edges_begin() const { return edges_.begin(); }
|
||||
KernelEdgeIter edges_end() { return edges_.end(); }
|
||||
KernelConstEdgeIter edges_end() const { return edges_.end(); }
|
||||
|
||||
KernelFaceIter faces_begin() { return faces_.begin(); }
|
||||
KernelConstFaceIter faces_begin() const { return faces_.begin(); }
|
||||
KernelFaceIter faces_end() { return faces_.end(); }
|
||||
KernelConstFaceIter faces_end() const { return faces_.end(); }
|
||||
|
||||
/// bit mask container by handle
|
||||
inline BitMaskContainer& bit_masks(VertexHandle /*_dummy_hnd*/)
|
||||
{ return vertex_bit_masks_; }
|
||||
inline BitMaskContainer& bit_masks(EdgeHandle /*_dummy_hnd*/)
|
||||
{ return edge_bit_masks_; }
|
||||
inline BitMaskContainer& bit_masks(FaceHandle /*_dummy_hnd*/)
|
||||
{ return face_bit_masks_; }
|
||||
inline BitMaskContainer& bit_masks(HalfedgeHandle /*_dummy_hnd*/)
|
||||
{ return halfedge_bit_masks_; }
|
||||
|
||||
template <class Handle>
|
||||
uint pop_bit_mask(Handle _hnd)
|
||||
{
|
||||
assert(!bit_masks(_hnd).empty());//check if the client request too many status sets
|
||||
uint bit_mask = bit_masks(_hnd).back();
|
||||
bit_masks(_hnd).pop_back();
|
||||
return bit_mask;
|
||||
}
|
||||
|
||||
template <class Handle>
|
||||
void push_bit_mask(Handle _hnd, uint _bit_mask)
|
||||
{
|
||||
assert(std::find(bit_masks(_hnd).begin(), bit_masks(_hnd).end(), _bit_mask) ==
|
||||
bit_masks(_hnd).end());//this mask should be not already used
|
||||
bit_masks(_hnd).push_back(_bit_mask);
|
||||
}
|
||||
|
||||
void init_bit_masks(BitMaskContainer& _bmc);
|
||||
void init_bit_masks();
|
||||
|
||||
private:
|
||||
VertexContainer vertices_;
|
||||
EdgeContainer edges_;
|
||||
FaceContainer faces_;
|
||||
|
||||
VertexStatusPropertyHandle vertex_status_;
|
||||
HalfedgeStatusPropertyHandle halfedge_status_;
|
||||
EdgeStatusPropertyHandle edge_status_;
|
||||
FaceStatusPropertyHandle face_status_;
|
||||
|
||||
uint refcount_vstatus_;
|
||||
uint refcount_hstatus_;
|
||||
uint refcount_estatus_;
|
||||
uint refcount_fstatus_;
|
||||
|
||||
BitMaskContainer halfedge_bit_masks_;
|
||||
BitMaskContainer edge_bit_masks_;
|
||||
BitMaskContainer vertex_bit_masks_;
|
||||
BitMaskContainer face_bit_masks_;
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_ARRAY_KERNEL_HH defined
|
||||
//=============================================================================
|
||||
651
Core/Mesh/AttribKernelT.hh
Normal file
651
Core/Mesh/AttribKernelT.hh
Normal file
@@ -0,0 +1,651 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2001-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_ATTRIBKERNEL_HH
|
||||
#define OPENMESH_ATTRIBKERNEL_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/Mesh/Attributes.hh>
|
||||
#include <OpenMesh/Core/Utils/GenProg.hh>
|
||||
#include <OpenMesh/Core/Utils/vector_traits.hh>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/// This class adds the standard properties to the mesh type.
|
||||
///
|
||||
/// The attribute kernel adds all standard properties to the kernel. Therefore
|
||||
/// the functions/types defined here provide a subset of the kernel
|
||||
/// interface as described in Concepts::KernelT.
|
||||
///
|
||||
/// \see Concepts::KernelT
|
||||
template <class MeshItems, class Connectivity>
|
||||
class AttribKernelT : public Connectivity
|
||||
{
|
||||
public:
|
||||
|
||||
//---------------------------------------------------------------- item types
|
||||
|
||||
typedef typename Connectivity::Vertex Vertex;
|
||||
typedef typename Connectivity::Halfedge Halfedge;
|
||||
typedef typename Connectivity::Edge Edge;
|
||||
typedef typename Connectivity::Face Face;
|
||||
|
||||
typedef typename MeshItems::Point Point;
|
||||
typedef typename MeshItems::Normal Normal;
|
||||
typedef typename MeshItems::Color Color;
|
||||
typedef typename MeshItems::TexCoord1D TexCoord1D;
|
||||
typedef typename MeshItems::TexCoord2D TexCoord2D;
|
||||
typedef typename MeshItems::TexCoord3D TexCoord3D;
|
||||
typedef typename MeshItems::Scalar Scalar;
|
||||
typedef typename MeshItems::TextureIndex TextureIndex;
|
||||
|
||||
typedef typename MeshItems::VertexData VertexData;
|
||||
typedef typename MeshItems::HalfedgeData HalfedgeData;
|
||||
typedef typename MeshItems::EdgeData EdgeData;
|
||||
typedef typename MeshItems::FaceData FaceData;
|
||||
|
||||
typedef AttribKernelT<MeshItems,Connectivity> AttribKernel;
|
||||
|
||||
enum Attribs {
|
||||
VAttribs = MeshItems::VAttribs,
|
||||
HAttribs = MeshItems::HAttribs,
|
||||
EAttribs = MeshItems::EAttribs,
|
||||
FAttribs = MeshItems::FAttribs,
|
||||
};
|
||||
|
||||
typedef VPropHandleT<VertexData> DataVPropHandle;
|
||||
typedef HPropHandleT<HalfedgeData> DataHPropHandle;
|
||||
typedef EPropHandleT<EdgeData> DataEPropHandle;
|
||||
typedef FPropHandleT<FaceData> DataFPropHandle;
|
||||
|
||||
public:
|
||||
|
||||
//-------------------------------------------------- constructor / destructor
|
||||
|
||||
AttribKernelT()
|
||||
: refcount_vnormals_(0),
|
||||
refcount_vcolors_(0),
|
||||
refcount_vtexcoords1D_(0),
|
||||
refcount_vtexcoords2D_(0),
|
||||
refcount_vtexcoords3D_(0),
|
||||
refcount_htexcoords1D_(0),
|
||||
refcount_htexcoords2D_(0),
|
||||
refcount_htexcoords3D_(0),
|
||||
refcount_fnormals_(0),
|
||||
refcount_fcolors_(0),
|
||||
refcount_ftextureIndex_(0)
|
||||
{
|
||||
add_property( points_, "v:points" );
|
||||
|
||||
if (VAttribs & Attributes::Normal)
|
||||
request_vertex_normals();
|
||||
|
||||
if (VAttribs & Attributes::Color)
|
||||
request_vertex_colors();
|
||||
|
||||
if (VAttribs & Attributes::TexCoord1D)
|
||||
request_vertex_texcoords1D();
|
||||
|
||||
if (VAttribs & Attributes::TexCoord2D)
|
||||
request_vertex_texcoords2D();
|
||||
|
||||
if (VAttribs & Attributes::TexCoord3D)
|
||||
request_vertex_texcoords3D();
|
||||
|
||||
if (HAttribs & Attributes::TexCoord1D)
|
||||
request_halfedge_texcoords1D();
|
||||
|
||||
if (HAttribs & Attributes::TexCoord2D)
|
||||
request_halfedge_texcoords2D();
|
||||
|
||||
if (HAttribs & Attributes::TexCoord3D)
|
||||
request_halfedge_texcoords3D();
|
||||
|
||||
if (VAttribs & Attributes::Status)
|
||||
Connectivity::request_vertex_status();
|
||||
|
||||
if (HAttribs & Attributes::Status)
|
||||
Connectivity::request_halfedge_status();
|
||||
|
||||
if (EAttribs & Attributes::Status)
|
||||
Connectivity::request_edge_status();
|
||||
|
||||
if (FAttribs & Attributes::Normal)
|
||||
request_face_normals();
|
||||
|
||||
if (FAttribs & Attributes::Color)
|
||||
request_face_colors();
|
||||
|
||||
if (FAttribs & Attributes::Status)
|
||||
Connectivity::request_face_status();
|
||||
|
||||
if (FAttribs & Attributes::TextureIndex)
|
||||
request_face_texture_index();
|
||||
|
||||
//FIXME: data properties might actually cost storage even
|
||||
//if there are no data traits??
|
||||
add_property(data_vpph_);
|
||||
add_property(data_fpph_);
|
||||
add_property(data_hpph_);
|
||||
add_property(data_epph_);
|
||||
}
|
||||
|
||||
virtual ~AttribKernelT()
|
||||
{
|
||||
// should remove properties, but this will be done in
|
||||
// BaseKernel's destructor anyway...
|
||||
}
|
||||
|
||||
// Martin: This below does not make any sense, right?
|
||||
// -------------------------------------------------------- copy & assignment
|
||||
// AttribKernelT(const AttribKernelT& _rhs)
|
||||
// : BaseKernel(_rhs)
|
||||
// { operator=(_rhs); }
|
||||
//
|
||||
// AttribKernelT& operator=(const AttribKernelT& _rhs)
|
||||
// {
|
||||
// // remove old properties
|
||||
// remove_property(points_);
|
||||
// remove_property(vertex_normals_);
|
||||
// remove_property(vertex_colors_);
|
||||
// remove_property(vertex_texcoords_);
|
||||
// remove_property(vertex_status_);
|
||||
// remove_property(halfedge_status_);
|
||||
// remove_property(edge_status_);
|
||||
// remove_property(face_normals_);
|
||||
// remove_property(face_colors_);
|
||||
// remove_property(face_status_);
|
||||
//
|
||||
// // parent deep-copies properties
|
||||
// BaseKernel::operator=(_rhs);
|
||||
//
|
||||
// // copy property handles
|
||||
// points_ = _rhs.points_;
|
||||
// vertex_normals_ = _rhs.vertex_normals_;
|
||||
// vertex_colors_ = _rhs.vertex_colors_;
|
||||
// vertex_texcoords_ = _rhs.vertex_texcoords_;
|
||||
// vertex_status_ = _rhs.vertex_status_;
|
||||
// halfedge_status_ = _rhs.halfedge_status_;
|
||||
// edge_status_ = _rhs.edge_status_;
|
||||
// face_normals_ = _rhs.face_normals_;
|
||||
// face_colors_ = _rhs.face_colors_;
|
||||
// face_status_ = _rhs.face_status_;
|
||||
//
|
||||
// // copy ref-counts
|
||||
// refcount_vnormals_ = _rhs.refcount_vnormals_;
|
||||
// refcount_vcolors_ = _rhs.refcount_vcolors_;
|
||||
// refcount_vtexcoords_ = _rhs.refcount_vtexcoords_;
|
||||
// refcount_vstatus_ = _rhs.refcount_vstatus_;
|
||||
// refcount_hstatus_ = _rhs.refcount_hstatus_;
|
||||
// refcount_estatus_ = _rhs.refcount_estatus_;
|
||||
// refcount_fnormals_ = _rhs.refcount_fnormals_;
|
||||
// refcount_fcolors_ = _rhs.refcount_fcolors_;
|
||||
// refcount_fstatus_ = _rhs.refcount_fstatus_;
|
||||
//
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
/** Assignment from another mesh of \em another type.
|
||||
\note All that's copied is connectivity and vertex positions.
|
||||
All other information (like e.g. attributes or additional
|
||||
elements from traits classes) is not copied.
|
||||
\note If you want to copy all information, including *custom* properties,
|
||||
use PolyMeshT::operator=() instead.
|
||||
TODO: version which copies standard properties specified by the user
|
||||
*/
|
||||
template <class _AttribKernel>
|
||||
void assign(const _AttribKernel& _other)
|
||||
{
|
||||
assign_connectivity(_other);
|
||||
for (typename Connectivity::VertexIter v_it = Connectivity::vertices_begin();
|
||||
v_it != Connectivity::vertices_end(); ++v_it)
|
||||
{//assumes Point constructor supports cast from _AttribKernel::Point
|
||||
set_point(v_it, (Point)_other.point(v_it));
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------- points
|
||||
|
||||
const Point* points() const
|
||||
{ return property(points_).data(); }
|
||||
|
||||
const Point& point(VertexHandle _vh) const
|
||||
{ return property(points_, _vh); }
|
||||
|
||||
Point& point(VertexHandle _vh)
|
||||
{ return property(points_, _vh); }
|
||||
|
||||
void set_point(VertexHandle _vh, const Point& _p)
|
||||
{ property(points_, _vh) = _p; }
|
||||
|
||||
|
||||
//------------------------------------------------------------ vertex normals
|
||||
|
||||
const Normal* vertex_normals() const
|
||||
{ return property(vertex_normals_).data(); }
|
||||
|
||||
const Normal& normal(VertexHandle _vh) const
|
||||
{ return property(vertex_normals_, _vh); }
|
||||
|
||||
void set_normal(VertexHandle _vh, const Normal& _n)
|
||||
{ property(vertex_normals_, _vh) = _n; }
|
||||
|
||||
|
||||
//------------------------------------------------------------- vertex colors
|
||||
|
||||
const Color* vertex_colors() const
|
||||
{ return property(vertex_colors_).data(); }
|
||||
|
||||
const Color& color(VertexHandle _vh) const
|
||||
{ return property(vertex_colors_, _vh); }
|
||||
|
||||
void set_color(VertexHandle _vh, const Color& _c)
|
||||
{ property(vertex_colors_, _vh) = _c; }
|
||||
|
||||
|
||||
//------------------------------------------------------- vertex 1D texcoords
|
||||
|
||||
const TexCoord1D* texcoords1D() const {
|
||||
return property(vertex_texcoords1D_).data();
|
||||
}
|
||||
|
||||
const TexCoord1D& texcoord1D(VertexHandle _vh) const {
|
||||
return property(vertex_texcoords1D_, _vh);
|
||||
}
|
||||
|
||||
void set_texcoord1D(VertexHandle _vh, const TexCoord1D& _t) {
|
||||
property(vertex_texcoords1D_, _vh) = _t;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------- vertex 2D texcoords
|
||||
|
||||
const TexCoord2D* texcoords2D() const {
|
||||
return property(vertex_texcoords2D_).data();
|
||||
}
|
||||
|
||||
const TexCoord2D& texcoord2D(VertexHandle _vh) const {
|
||||
return property(vertex_texcoords2D_, _vh);
|
||||
}
|
||||
|
||||
void set_texcoord2D(VertexHandle _vh, const TexCoord2D& _t) {
|
||||
property(vertex_texcoords2D_, _vh) = _t;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------- vertex 3D texcoords
|
||||
|
||||
const TexCoord3D* texcoords3D() const {
|
||||
return property(vertex_texcoords3D_).data();
|
||||
}
|
||||
|
||||
const TexCoord3D& texcoord3D(VertexHandle _vh) const {
|
||||
return property(vertex_texcoords3D_, _vh);
|
||||
}
|
||||
|
||||
void set_texcoord3D(VertexHandle _vh, const TexCoord3D& _t) {
|
||||
property(vertex_texcoords3D_, _vh) = _t;
|
||||
}
|
||||
|
||||
//.------------------------------------------------------ halfedge 1D texcoords
|
||||
|
||||
const TexCoord1D* htexcoords1D() const {
|
||||
return property(halfedge_texcoords1D_).data();
|
||||
}
|
||||
|
||||
const TexCoord1D& texcoord1D(HalfedgeHandle _heh) const {
|
||||
return property(halfedge_texcoords1D_, _heh);
|
||||
}
|
||||
|
||||
void set_texcoord1D(HalfedgeHandle _heh, const TexCoord1D& _t) {
|
||||
property(halfedge_texcoords1D_, _heh) = _t;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------- halfedge 2D texcoords
|
||||
|
||||
const TexCoord2D* htexcoords2D() const {
|
||||
return property(halfedge_texcoords2D_).data();
|
||||
}
|
||||
|
||||
const TexCoord2D& texcoord2D(HalfedgeHandle _heh) const {
|
||||
return property(halfedge_texcoords2D_, _heh);
|
||||
}
|
||||
|
||||
void set_texcoord2D(HalfedgeHandle _heh, const TexCoord2D& _t) {
|
||||
property(halfedge_texcoords2D_, _heh) = _t;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------- halfedge 3D texcoords
|
||||
|
||||
const TexCoord3D* htexcoords3D() const {
|
||||
return property(halfedge_texcoords3D_).data();
|
||||
}
|
||||
|
||||
const TexCoord3D& texcoord3D(HalfedgeHandle _heh) const {
|
||||
return property(halfedge_texcoords3D_, _heh);
|
||||
}
|
||||
|
||||
void set_texcoord3D(HalfedgeHandle _heh, const TexCoord3D& _t) {
|
||||
property(halfedge_texcoords3D_, _heh) = _t;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------- face normals
|
||||
|
||||
const Normal& normal(FaceHandle _fh) const
|
||||
{ return property(face_normals_, _fh); }
|
||||
|
||||
void set_normal(FaceHandle _fh, const Normal& _n)
|
||||
{ property(face_normals_, _fh) = _n; }
|
||||
|
||||
//-------------------------------------------------------------- per Face Texture index
|
||||
|
||||
const TextureIndex& texture_index(FaceHandle _fh) const
|
||||
{ return property(face_texture_index_, _fh); }
|
||||
|
||||
void set_texture_index(FaceHandle _fh, const TextureIndex& _t)
|
||||
{ property(face_texture_index_, _fh) = _t; }
|
||||
|
||||
//--------------------------------------------------------------- face colors
|
||||
|
||||
const Color& color(FaceHandle _fh) const
|
||||
{ return property(face_colors_, _fh); }
|
||||
|
||||
void set_color(FaceHandle _fh, const Color& _c)
|
||||
{ property(face_colors_, _fh) = _c; }
|
||||
|
||||
//------------------------------------------------ request / alloc properties
|
||||
|
||||
void request_vertex_normals()
|
||||
{
|
||||
if (!refcount_vnormals_++)
|
||||
add_property( vertex_normals_, "v:normals" );
|
||||
}
|
||||
|
||||
void request_vertex_colors()
|
||||
{
|
||||
if (!refcount_vcolors_++)
|
||||
add_property( vertex_colors_, "v:colors" );
|
||||
}
|
||||
|
||||
void request_vertex_texcoords1D()
|
||||
{
|
||||
if (!refcount_vtexcoords1D_++)
|
||||
add_property( vertex_texcoords1D_, "v:texcoords1D" );
|
||||
}
|
||||
|
||||
void request_vertex_texcoords2D()
|
||||
{
|
||||
if (!refcount_vtexcoords2D_++)
|
||||
add_property( vertex_texcoords2D_, "v:texcoords2D" );
|
||||
}
|
||||
|
||||
void request_vertex_texcoords3D()
|
||||
{
|
||||
if (!refcount_vtexcoords3D_++)
|
||||
add_property( vertex_texcoords3D_, "v:texcoords3D" );
|
||||
}
|
||||
|
||||
void request_halfedge_texcoords1D()
|
||||
{
|
||||
if (!refcount_htexcoords1D_++)
|
||||
add_property( halfedge_texcoords1D_, "h:texcoords1D" );
|
||||
}
|
||||
|
||||
void request_halfedge_texcoords2D()
|
||||
{
|
||||
if (!refcount_htexcoords2D_++)
|
||||
add_property( halfedge_texcoords2D_, "h:texcoords2D" );
|
||||
}
|
||||
|
||||
void request_halfedge_texcoords3D()
|
||||
{
|
||||
if (!refcount_htexcoords3D_++)
|
||||
add_property( halfedge_texcoords3D_, "h:texcoords3D" );
|
||||
}
|
||||
|
||||
void request_face_normals()
|
||||
{
|
||||
if (!refcount_fnormals_++)
|
||||
add_property( face_normals_, "f:normals" );
|
||||
}
|
||||
|
||||
void request_face_colors()
|
||||
{
|
||||
if (!refcount_fcolors_++)
|
||||
add_property( face_colors_, "f:colors" );
|
||||
}
|
||||
|
||||
void request_face_texture_index()
|
||||
{
|
||||
if (!refcount_ftextureIndex_++)
|
||||
add_property( face_texture_index_, "f:textureindex" );
|
||||
}
|
||||
|
||||
//------------------------------------------------- release / free properties
|
||||
|
||||
void release_vertex_normals()
|
||||
{
|
||||
if ((refcount_vnormals_ > 0) && (! --refcount_vnormals_))
|
||||
remove_property(vertex_normals_);
|
||||
}
|
||||
|
||||
void release_vertex_colors()
|
||||
{
|
||||
if ((refcount_vcolors_ > 0) && (! --refcount_vcolors_))
|
||||
remove_property(vertex_colors_);
|
||||
}
|
||||
|
||||
void release_vertex_texcoords1D() {
|
||||
if ((refcount_vtexcoords1D_ > 0) && (! --refcount_vtexcoords1D_))
|
||||
remove_property(vertex_texcoords1D_);
|
||||
}
|
||||
|
||||
void release_vertex_texcoords2D() {
|
||||
if ((refcount_vtexcoords2D_ > 0) && (! --refcount_vtexcoords2D_))
|
||||
remove_property(vertex_texcoords2D_);
|
||||
}
|
||||
|
||||
void release_vertex_texcoords3D() {
|
||||
if ((refcount_vtexcoords3D_ > 0) && (! --refcount_vtexcoords3D_))
|
||||
remove_property(vertex_texcoords3D_);
|
||||
}
|
||||
|
||||
void release_halfedge_texcoords1D() {
|
||||
if ((refcount_htexcoords1D_ > 0) && (! --refcount_htexcoords1D_))
|
||||
remove_property(halfedge_texcoords1D_);
|
||||
}
|
||||
|
||||
void release_halfedge_texcoords2D() {
|
||||
if ((refcount_htexcoords2D_ > 0) && (! --refcount_htexcoords2D_))
|
||||
remove_property(halfedge_texcoords2D_);
|
||||
}
|
||||
|
||||
void release_halfedge_texcoords3D() {
|
||||
if ((refcount_htexcoords3D_ > 0) && (! --refcount_htexcoords3D_))
|
||||
remove_property(halfedge_texcoords3D_);
|
||||
}
|
||||
|
||||
void release_face_normals()
|
||||
{
|
||||
if ((refcount_fnormals_ > 0) && (! --refcount_fnormals_))
|
||||
remove_property(face_normals_);
|
||||
}
|
||||
|
||||
void release_face_colors()
|
||||
{
|
||||
if ((refcount_fcolors_ > 0) && (! --refcount_fcolors_))
|
||||
remove_property(face_colors_);
|
||||
}
|
||||
|
||||
void release_face_texture_index()
|
||||
{
|
||||
if ((refcount_ftextureIndex_ > 0) && (! --refcount_ftextureIndex_))
|
||||
remove_property(face_texture_index_);
|
||||
}
|
||||
|
||||
//---------------------------------------------- dynamic check for properties
|
||||
|
||||
bool has_vertex_normals() const { return vertex_normals_.is_valid(); }
|
||||
bool has_vertex_colors() const { return vertex_colors_.is_valid(); }
|
||||
bool has_vertex_texcoords1D() const { return vertex_texcoords1D_.is_valid(); }
|
||||
bool has_vertex_texcoords2D() const { return vertex_texcoords2D_.is_valid(); }
|
||||
bool has_vertex_texcoords3D() const { return vertex_texcoords3D_.is_valid(); }
|
||||
bool has_halfedge_texcoords1D() const { return halfedge_texcoords1D_.is_valid();}
|
||||
bool has_halfedge_texcoords2D() const { return halfedge_texcoords2D_.is_valid();}
|
||||
bool has_halfedge_texcoords3D() const { return halfedge_texcoords3D_.is_valid();}
|
||||
bool has_face_normals() const { return face_normals_.is_valid(); }
|
||||
bool has_face_colors() const { return face_colors_.is_valid(); }
|
||||
bool has_face_texture_index() const { return face_texture_index_.is_valid(); }
|
||||
|
||||
public:
|
||||
|
||||
typedef VPropHandleT<Point> PointsPropertyHandle;
|
||||
typedef VPropHandleT<Normal> VertexNormalsPropertyHandle;
|
||||
typedef VPropHandleT<Color> VertexColorsPropertyHandle;
|
||||
typedef VPropHandleT<TexCoord1D> VertexTexCoords1DPropertyHandle;
|
||||
typedef VPropHandleT<TexCoord2D> VertexTexCoords2DPropertyHandle;
|
||||
typedef VPropHandleT<TexCoord3D> VertexTexCoords3DPropertyHandle;
|
||||
typedef HPropHandleT<TexCoord1D> HalfedgeTexCoords1DPropertyHandle;
|
||||
typedef HPropHandleT<TexCoord2D> HalfedgeTexCoords2DPropertyHandle;
|
||||
typedef HPropHandleT<TexCoord3D> HalfedgeTexCoords3DPropertyHandle;
|
||||
typedef FPropHandleT<Normal> FaceNormalsPropertyHandle;
|
||||
typedef FPropHandleT<Color> FaceColorsPropertyHandle;
|
||||
typedef FPropHandleT<TextureIndex> FaceTextureIndexPropertyHandle;
|
||||
|
||||
public:
|
||||
//standard vertex properties
|
||||
PointsPropertyHandle points_pph() const
|
||||
{ return points_; }
|
||||
|
||||
VertexNormalsPropertyHandle vertex_normals_pph() const
|
||||
{ return vertex_normals_; }
|
||||
|
||||
VertexColorsPropertyHandle vertex_colors_pph() const
|
||||
{ return vertex_colors_; }
|
||||
|
||||
VertexTexCoords1DPropertyHandle vertex_texcoords1D_pph() const
|
||||
{ return vertex_texcoords1D_; }
|
||||
|
||||
VertexTexCoords2DPropertyHandle vertex_texcoords2D_pph() const
|
||||
{ return vertex_texcoords2D_; }
|
||||
|
||||
VertexTexCoords3DPropertyHandle vertex_texcoords3D_pph() const
|
||||
{ return vertex_texcoords3D_; }
|
||||
|
||||
//standard halfedge properties
|
||||
HalfedgeTexCoords1DPropertyHandle halfedge_texcoords1D_pph() const
|
||||
{ return halfedge_texcoords1D_; }
|
||||
|
||||
HalfedgeTexCoords2DPropertyHandle halfedge_texcoords2D_pph() const
|
||||
{ return halfedge_texcoords2D_; }
|
||||
|
||||
HalfedgeTexCoords3DPropertyHandle halfedge_texcoords3D_pph() const
|
||||
{ return halfedge_texcoords3D_; }
|
||||
|
||||
//standard face properties
|
||||
FaceNormalsPropertyHandle face_normals_pph() const
|
||||
{ return face_normals_; }
|
||||
|
||||
FaceColorsPropertyHandle face_colors_pph() const
|
||||
{ return face_colors_; }
|
||||
|
||||
FaceTextureIndexPropertyHandle face_texture_index_pph() const
|
||||
{ return face_texture_index_; }
|
||||
|
||||
VertexData& data(VertexHandle _vh)
|
||||
{ return property(data_vpph_, _vh); }
|
||||
|
||||
const VertexData& data(VertexHandle _vh) const
|
||||
{ return property(data_vpph_, _vh); }
|
||||
|
||||
FaceData& data(FaceHandle _fh)
|
||||
{ return property(data_fpph_, _fh); }
|
||||
|
||||
const FaceData& data(FaceHandle _fh) const
|
||||
{ return property(data_fpph_, _fh); }
|
||||
|
||||
EdgeData& data(EdgeHandle _eh)
|
||||
{ return property(data_epph_, _eh); }
|
||||
|
||||
const EdgeData& data(EdgeHandle _eh) const
|
||||
{ return property(data_epph_, _eh); }
|
||||
|
||||
HalfedgeData& data(HalfedgeHandle _heh)
|
||||
{ return property(data_hpph_, _heh); }
|
||||
|
||||
const HalfedgeData& data(HalfedgeHandle _heh) const
|
||||
{ return property(data_hpph_, _heh); }
|
||||
|
||||
private:
|
||||
//standard vertex properties
|
||||
PointsPropertyHandle points_;
|
||||
VertexNormalsPropertyHandle vertex_normals_;
|
||||
VertexColorsPropertyHandle vertex_colors_;
|
||||
VertexTexCoords1DPropertyHandle vertex_texcoords1D_;
|
||||
VertexTexCoords2DPropertyHandle vertex_texcoords2D_;
|
||||
VertexTexCoords3DPropertyHandle vertex_texcoords3D_;
|
||||
//standard halfedge properties
|
||||
HalfedgeTexCoords1DPropertyHandle halfedge_texcoords1D_;
|
||||
HalfedgeTexCoords2DPropertyHandle halfedge_texcoords2D_;
|
||||
HalfedgeTexCoords3DPropertyHandle halfedge_texcoords3D_;
|
||||
//standard face properties
|
||||
FaceNormalsPropertyHandle face_normals_;
|
||||
FaceColorsPropertyHandle face_colors_;
|
||||
FaceTextureIndexPropertyHandle face_texture_index_;
|
||||
//data properties handles
|
||||
DataVPropHandle data_vpph_;
|
||||
DataHPropHandle data_hpph_;
|
||||
DataEPropHandle data_epph_;
|
||||
DataFPropHandle data_fpph_;
|
||||
|
||||
unsigned int refcount_vnormals_;
|
||||
unsigned int refcount_vcolors_;
|
||||
unsigned int refcount_vtexcoords1D_;
|
||||
unsigned int refcount_vtexcoords2D_;
|
||||
unsigned int refcount_vtexcoords3D_;
|
||||
unsigned int refcount_htexcoords1D_;
|
||||
unsigned int refcount_htexcoords2D_;
|
||||
unsigned int refcount_htexcoords3D_;
|
||||
unsigned int refcount_fnormals_;
|
||||
unsigned int refcount_fcolors_;
|
||||
unsigned int refcount_ftextureIndex_;
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_ATTRIBKERNEL_HH defined
|
||||
//=============================================================================
|
||||
85
Core/Mesh/Attributes.hh
Normal file
85
Core/Mesh/Attributes.hh
Normal file
@@ -0,0 +1,85 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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: 3794 $
|
||||
// $Date: 2008-11-25 19:25:02 +0100 (Di, 25. Nov 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/**
|
||||
\file Attributes.hh
|
||||
This file provides some macros containing attribute usage.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef OPENMESH_ATTRIBUTES_HH
|
||||
#define OPENMESH_ATTRIBUTES_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Mesh/Status.hh>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
namespace Attributes {
|
||||
|
||||
|
||||
//== CLASS DEFINITION ========================================================
|
||||
|
||||
/** Attribute bits
|
||||
*
|
||||
* Use the bits to define a standard property at compile time using traits.
|
||||
*
|
||||
* \include traits5.cc
|
||||
*
|
||||
* \see \ref mesh_type
|
||||
*/
|
||||
enum AttributeBits
|
||||
{
|
||||
None = 0, ///< Clear all attribute bits
|
||||
Normal = 1, ///< Add normals to mesh item (vertices/faces)
|
||||
Color = 2, ///< Add colors to mesh item (vertices/faces)
|
||||
PrevHalfedge = 4, ///< Add storage for previous halfedge (halfedges). The bit is set by default in the DefaultTraits.
|
||||
Status = 8, ///< Add status to mesh item (all items)
|
||||
TexCoord1D = 16, ///< Add 1D texture coordinates (vertices, halfedges)
|
||||
TexCoord2D = 32, ///< Add 2D texture coordinates (vertices, halfedges)
|
||||
TexCoord3D = 64, ///< Add 3D texture coordinates (vertices, halfedges)
|
||||
TextureIndex = 128 ///< Add texture index (faces)
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace Attributes
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_ATTRIBUTES_HH defined
|
||||
//=============================================================================
|
||||
67
Core/Mesh/BaseKernel.cc
Normal file
67
Core/Mesh/BaseKernel.cc
Normal file
@@ -0,0 +1,67 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2001-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. *
|
||||
* *
|
||||
\*===========================================================================*/
|
||||
|
||||
#include <OpenMesh/Core/Mesh/BaseKernel.hh>
|
||||
namespace OpenMesh
|
||||
{
|
||||
|
||||
void BaseKernel::property_stats(std::ostream& _ostr) const
|
||||
{
|
||||
const PropertyContainer::Properties& vps = vprops_.properties();
|
||||
const PropertyContainer::Properties& hps = hprops_.properties();
|
||||
const PropertyContainer::Properties& eps = eprops_.properties();
|
||||
const PropertyContainer::Properties& fps = fprops_.properties();
|
||||
const PropertyContainer::Properties& mps = mprops_.properties();
|
||||
|
||||
PropertyContainer::Properties::const_iterator it;
|
||||
|
||||
_ostr << vprops_.size() << " vprops:\n";
|
||||
for (it=vps.begin(); it!=vps.end(); ++it)
|
||||
{
|
||||
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
|
||||
}
|
||||
_ostr << hprops_.size() << " hprops:\n";
|
||||
for (it=hps.begin(); it!=hps.end(); ++it)
|
||||
{
|
||||
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
|
||||
}
|
||||
_ostr << eprops_.size() << " eprops:\n";
|
||||
for (it=eps.begin(); it!=eps.end(); ++it)
|
||||
{
|
||||
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
|
||||
}
|
||||
_ostr << fprops_.size() << " fprops:\n";
|
||||
for (it=fps.begin(); it!=fps.end(); ++it)
|
||||
{
|
||||
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
|
||||
}
|
||||
_ostr << mprops_.size() << " mprops:\n";
|
||||
for (it=mps.begin(); it!=mps.end(); ++it)
|
||||
{
|
||||
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
568
Core/Mesh/BaseKernel.hh
Normal file
568
Core/Mesh/BaseKernel.hh
Normal file
@@ -0,0 +1,568 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS BaseKernel
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_BASE_KERNEL_HH
|
||||
#define OPENMESH_BASE_KERNEL_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
// --------------------
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
// --------------------
|
||||
#include <OpenMesh/Core/Utils/PropertyContainer.hh>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/// This class provides the basic property management like adding/removing
|
||||
/// properties and access to properties.
|
||||
/// All operations provided by %BaseKernel need at least a property handle
|
||||
/// (VPropHandleT, EPropHandleT, HPropHandleT, FPropHandleT, MPropHandleT).
|
||||
/// which keeps the data type of the property, too.
|
||||
///
|
||||
/// There are two types of properties:
|
||||
/// -# Standard properties - mesh data (e.g. vertex normal or face color)
|
||||
/// -# Custom properties - user defined data
|
||||
///
|
||||
/// The differentiation is only semantically, technically both are
|
||||
/// equally handled. Therefore the methods provided by the %BaseKernel
|
||||
/// are applicable to both property types.
|
||||
///
|
||||
/// \attention Since the class PolyMeshT derives from a kernel, hence all public
|
||||
/// elements of %BaseKernel are usable.
|
||||
|
||||
class BaseKernel
|
||||
{
|
||||
public: //-------------------------------------------- constructor / destructor
|
||||
|
||||
BaseKernel() {}
|
||||
virtual ~BaseKernel() {}
|
||||
|
||||
|
||||
public: //-------------------------------------------------- add new properties
|
||||
|
||||
/// \name Add a property to a mesh item
|
||||
|
||||
//@{
|
||||
|
||||
/** Adds a property
|
||||
*
|
||||
* Depending on the property handle type a vertex, (half-)edge, face or
|
||||
* mesh property is added to the mesh. If the action fails the handle
|
||||
* is invalid.
|
||||
* On success the handle must be used to access the property data with
|
||||
* property().
|
||||
*
|
||||
* \param _ph A property handle defining the data type to bind to mesh.
|
||||
* On success the handle is valid else invalid.
|
||||
* \param _name Optional name of property. Following restrictions apply
|
||||
* to the name:
|
||||
* -# Maximum length of name is 256 characters
|
||||
* -# The prefixes matching "^[vhefm]:" are reserved for
|
||||
* internal usage.
|
||||
* -# The expression "^<.*>$" is reserved for internal usage.
|
||||
* \return \c true on success else \c false.
|
||||
*
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
void add_property( VPropHandleT<T>& _ph, const std::string& _name="<vprop>")
|
||||
{
|
||||
_ph = VPropHandleT<T>( vprops_.add(T(), _name) );
|
||||
vprops_.resize(n_vertices());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void add_property( HPropHandleT<T>& _ph, const std::string& _name="<hprop>")
|
||||
{
|
||||
_ph = HPropHandleT<T>( hprops_.add(T(), _name) );
|
||||
hprops_.resize(n_halfedges());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void add_property( EPropHandleT<T>& _ph, const std::string& _name="<eprop>")
|
||||
{
|
||||
_ph = EPropHandleT<T>( eprops_.add(T(), _name) );
|
||||
eprops_.resize(n_edges());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void add_property( FPropHandleT<T>& _ph, const std::string& _name="<fprop>")
|
||||
{
|
||||
_ph = FPropHandleT<T>( fprops_.add(T(), _name) );
|
||||
fprops_.resize(n_faces());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void add_property( MPropHandleT<T>& _ph, const std::string& _name="<mprop>")
|
||||
{
|
||||
_ph = MPropHandleT<T>( mprops_.add(T(), _name) );
|
||||
mprops_.resize(1);
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
public: //--------------------------------------------------- remove properties
|
||||
|
||||
/// \name Removing a property from a mesh tiem
|
||||
//@{
|
||||
|
||||
/** Remove a property.
|
||||
*
|
||||
* Removes the property represented by the handle from the apropriate
|
||||
* mesh item.
|
||||
* \param _ph Property to be removed. The handle is invalid afterwords.
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
void remove_property(VPropHandleT<T>& _ph)
|
||||
{
|
||||
if (_ph.is_valid())
|
||||
vprops_.remove(_ph);
|
||||
_ph.reset();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void remove_property(HPropHandleT<T>& _ph)
|
||||
{
|
||||
if (_ph.is_valid())
|
||||
hprops_.remove(_ph);
|
||||
_ph.reset();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void remove_property(EPropHandleT<T>& _ph)
|
||||
{
|
||||
if (_ph.is_valid())
|
||||
eprops_.remove(_ph);
|
||||
_ph.reset();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void remove_property(FPropHandleT<T>& _ph)
|
||||
{
|
||||
if (_ph.is_valid())
|
||||
fprops_.remove(_ph);
|
||||
_ph.reset();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void remove_property(MPropHandleT<T>& _ph)
|
||||
{
|
||||
if (_ph.is_valid())
|
||||
mprops_.remove(_ph);
|
||||
_ph.reset();
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
public: //------------------------------------------------ get handle from name
|
||||
|
||||
/// \name Get property handle by name
|
||||
//@{
|
||||
|
||||
/** Retrieves the handle to a named property by it's name.
|
||||
*
|
||||
* \param _ph A property handle. On success the handle is valid else
|
||||
* invalid.
|
||||
* \param _name Name of wanted property.
|
||||
* \return \c true if such a named property is available, else \c false.
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
bool get_property_handle(VPropHandleT<T>& _ph,
|
||||
const std::string& _name) const
|
||||
{
|
||||
return (_ph = VPropHandleT<T>(vprops_.handle(T(), _name))).is_valid();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool get_property_handle(HPropHandleT<T>& _ph,
|
||||
const std::string& _name) const
|
||||
{
|
||||
return (_ph = HPropHandleT<T>(hprops_.handle(T(), _name))).is_valid();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool get_property_handle(EPropHandleT<T>& _ph,
|
||||
const std::string& _name) const
|
||||
{
|
||||
return (_ph = EPropHandleT<T>(eprops_.handle(T(), _name))).is_valid();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool get_property_handle(FPropHandleT<T>& _ph,
|
||||
const std::string& _name) const
|
||||
{
|
||||
return (_ph = FPropHandleT<T>(fprops_.handle(T(), _name))).is_valid();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool get_property_handle(MPropHandleT<T>& _ph,
|
||||
const std::string& _name) const
|
||||
{
|
||||
return (_ph = MPropHandleT<T>(mprops_.handle(T(), _name))).is_valid();
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
public: //--------------------------------------------------- access properties
|
||||
|
||||
/// \name Access a property
|
||||
//@{
|
||||
|
||||
/** Access a property
|
||||
*
|
||||
* This method returns a reference to property. The property handle
|
||||
* must be valid! The result is unpredictable if the handle is invalid!
|
||||
*
|
||||
* \param _ph A \em valid (!) property handle.
|
||||
* \return The wanted property if the handle is valid.
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
PropertyT<T>& property(VPropHandleT<T> _ph) {
|
||||
return vprops_.property(_ph);
|
||||
}
|
||||
template <class T>
|
||||
const PropertyT<T>& property(VPropHandleT<T> _ph) const {
|
||||
return vprops_.property(_ph);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PropertyT<T>& property(HPropHandleT<T> _ph) {
|
||||
return hprops_.property(_ph);
|
||||
}
|
||||
template <class T>
|
||||
const PropertyT<T>& property(HPropHandleT<T> _ph) const {
|
||||
return hprops_.property(_ph);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PropertyT<T>& property(EPropHandleT<T> _ph) {
|
||||
return eprops_.property(_ph);
|
||||
}
|
||||
template <class T>
|
||||
const PropertyT<T>& property(EPropHandleT<T> _ph) const {
|
||||
return eprops_.property(_ph);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PropertyT<T>& property(FPropHandleT<T> _ph) {
|
||||
return fprops_.property(_ph);
|
||||
}
|
||||
template <class T>
|
||||
const PropertyT<T>& property(FPropHandleT<T> _ph) const {
|
||||
return fprops_.property(_ph);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PropertyT<T>& mproperty(MPropHandleT<T> _ph) {
|
||||
return mprops_.property(_ph);
|
||||
}
|
||||
template <class T>
|
||||
const PropertyT<T>& mproperty(MPropHandleT<T> _ph) const {
|
||||
return mprops_.property(_ph);
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
public: //-------------------------------------------- access property elements
|
||||
|
||||
/// \name Access a property element using a handle to a mesh item
|
||||
//@{
|
||||
|
||||
/** Return value of property for an item
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
typename VPropHandleT<T>::reference
|
||||
property(VPropHandleT<T> _ph, VertexHandle _vh) {
|
||||
return vprops_.property(_ph)[_vh.idx()];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename VPropHandleT<T>::const_reference
|
||||
property(VPropHandleT<T> _ph, VertexHandle _vh) const {
|
||||
return vprops_.property(_ph)[_vh.idx()];
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
typename HPropHandleT<T>::reference
|
||||
property(HPropHandleT<T> _ph, HalfedgeHandle _hh) {
|
||||
return hprops_.property(_ph)[_hh.idx()];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename HPropHandleT<T>::const_reference
|
||||
property(HPropHandleT<T> _ph, HalfedgeHandle _hh) const {
|
||||
return hprops_.property(_ph)[_hh.idx()];
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
typename EPropHandleT<T>::reference
|
||||
property(EPropHandleT<T> _ph, EdgeHandle _eh) {
|
||||
return eprops_.property(_ph)[_eh.idx()];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename EPropHandleT<T>::const_reference
|
||||
property(EPropHandleT<T> _ph, EdgeHandle _eh) const {
|
||||
return eprops_.property(_ph)[_eh.idx()];
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
typename FPropHandleT<T>::reference
|
||||
property(FPropHandleT<T> _ph, FaceHandle _fh) {
|
||||
return fprops_.property(_ph)[_fh.idx()];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename FPropHandleT<T>::const_reference
|
||||
property(FPropHandleT<T> _ph, FaceHandle _fh) const {
|
||||
return fprops_.property(_ph)[_fh.idx()];
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
typename MPropHandleT<T>::reference
|
||||
property(MPropHandleT<T> _ph) {
|
||||
return mprops_.property(_ph)[0];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename MPropHandleT<T>::const_reference
|
||||
property(MPropHandleT<T> _ph) const {
|
||||
return mprops_.property(_ph)[0];
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
protected: //------------------------------------------------- low-level access
|
||||
|
||||
public: // used by non-native kernel and MeshIO, should be protected
|
||||
|
||||
size_t n_vprops(void) const { return vprops_.size(); }
|
||||
|
||||
size_t n_eprops(void) const { return eprops_.size(); }
|
||||
|
||||
size_t n_hprops(void) const { return hprops_.size(); }
|
||||
|
||||
size_t n_fprops(void) const { return fprops_.size(); }
|
||||
|
||||
size_t n_mprops(void) const { return mprops_.size(); }
|
||||
|
||||
BaseProperty* _get_vprop( const std::string& _name)
|
||||
{ return vprops_.property(_name); }
|
||||
|
||||
BaseProperty* _get_eprop( const std::string& _name)
|
||||
{ return eprops_.property(_name); }
|
||||
|
||||
BaseProperty* _get_hprop( const std::string& _name)
|
||||
{ return hprops_.property(_name); }
|
||||
|
||||
BaseProperty* _get_fprop( const std::string& _name)
|
||||
{ return fprops_.property(_name); }
|
||||
|
||||
BaseProperty* _get_mprop( const std::string& _name)
|
||||
{ return mprops_.property(_name); }
|
||||
|
||||
const BaseProperty* _get_vprop( const std::string& _name) const
|
||||
{ return vprops_.property(_name); }
|
||||
|
||||
const BaseProperty* _get_eprop( const std::string& _name) const
|
||||
{ return eprops_.property(_name); }
|
||||
|
||||
const BaseProperty* _get_hprop( const std::string& _name) const
|
||||
{ return hprops_.property(_name); }
|
||||
|
||||
const BaseProperty* _get_fprop( const std::string& _name) const
|
||||
{ return fprops_.property(_name); }
|
||||
|
||||
const BaseProperty* _get_mprop( const std::string& _name) const
|
||||
{ return mprops_.property(_name); }
|
||||
|
||||
BaseProperty& _vprop( size_t _idx ) { return vprops_._property( _idx ); }
|
||||
BaseProperty& _eprop( size_t _idx ) { return eprops_._property( _idx ); }
|
||||
BaseProperty& _hprop( size_t _idx ) { return hprops_._property( _idx ); }
|
||||
BaseProperty& _fprop( size_t _idx ) { return fprops_._property( _idx ); }
|
||||
BaseProperty& _mprop( size_t _idx ) { return mprops_._property( _idx ); }
|
||||
|
||||
const BaseProperty& _vprop( size_t _idx ) const
|
||||
{ return vprops_._property( _idx ); }
|
||||
const BaseProperty& _eprop( size_t _idx ) const
|
||||
{ return eprops_._property( _idx ); }
|
||||
const BaseProperty& _hprop( size_t _idx ) const
|
||||
{ return hprops_._property( _idx ); }
|
||||
const BaseProperty& _fprop( size_t _idx ) const
|
||||
{ return fprops_._property( _idx ); }
|
||||
const BaseProperty& _mprop( size_t _idx ) const
|
||||
{ return mprops_._property( _idx ); }
|
||||
|
||||
size_t _add_vprop( BaseProperty* _bp ) { return vprops_._add( _bp ); }
|
||||
size_t _add_eprop( BaseProperty* _bp ) { return eprops_._add( _bp ); }
|
||||
size_t _add_hprop( BaseProperty* _bp ) { return hprops_._add( _bp ); }
|
||||
size_t _add_fprop( BaseProperty* _bp ) { return fprops_._add( _bp ); }
|
||||
size_t _add_mprop( BaseProperty* _bp ) { return mprops_._add( _bp ); }
|
||||
|
||||
protected: // low-level access non-public
|
||||
|
||||
BaseProperty& _vprop( BaseHandle _h )
|
||||
{ return vprops_._property( _h.idx() ); }
|
||||
BaseProperty& _eprop( BaseHandle _h )
|
||||
{ return eprops_._property( _h.idx() ); }
|
||||
BaseProperty& _hprop( BaseHandle _h )
|
||||
{ return hprops_._property( _h.idx() ); }
|
||||
BaseProperty& _fprop( BaseHandle _h )
|
||||
{ return fprops_._property( _h.idx() ); }
|
||||
BaseProperty& _mprop( BaseHandle _h )
|
||||
{ return mprops_._property( _h.idx() ); }
|
||||
|
||||
const BaseProperty& _vprop( BaseHandle _h ) const
|
||||
{ return vprops_._property( _h.idx() ); }
|
||||
const BaseProperty& _eprop( BaseHandle _h ) const
|
||||
{ return eprops_._property( _h.idx() ); }
|
||||
const BaseProperty& _hprop( BaseHandle _h ) const
|
||||
{ return hprops_._property( _h.idx() ); }
|
||||
const BaseProperty& _fprop( BaseHandle _h ) const
|
||||
{ return fprops_._property( _h.idx() ); }
|
||||
const BaseProperty& _mprop( BaseHandle _h ) const
|
||||
{ return mprops_._property( _h.idx() ); }
|
||||
|
||||
|
||||
public: //----------------------------------------------------- element numbers
|
||||
|
||||
|
||||
virtual unsigned int n_vertices() const { return 0; }
|
||||
virtual unsigned int n_halfedges() const { return 0; }
|
||||
virtual unsigned int n_edges() const { return 0; }
|
||||
virtual unsigned int n_faces() const { return 0; }
|
||||
|
||||
|
||||
protected: //------------------------------------------- synchronize properties
|
||||
|
||||
void vprops_reserve(unsigned int _n) const { vprops_.reserve(_n); }
|
||||
void vprops_resize(unsigned int _n) const { vprops_.resize(_n); }
|
||||
void vprops_swap(unsigned int _i0, unsigned int _i1) const {
|
||||
vprops_.swap(_i0, _i1);
|
||||
}
|
||||
|
||||
void hprops_reserve(unsigned int _n) const { hprops_.reserve(_n); }
|
||||
void hprops_resize(unsigned int _n) const { hprops_.resize(_n); }
|
||||
void hprops_swap(unsigned int _i0, unsigned int _i1) const {
|
||||
hprops_.swap(_i0, _i1);
|
||||
}
|
||||
|
||||
void eprops_reserve(unsigned int _n) const { eprops_.reserve(_n); }
|
||||
void eprops_resize(unsigned int _n) const { eprops_.resize(_n); }
|
||||
void eprops_swap(unsigned int _i0, unsigned int _i1) const {
|
||||
eprops_.swap(_i0, _i1);
|
||||
}
|
||||
|
||||
void fprops_reserve(unsigned int _n) const { fprops_.reserve(_n); }
|
||||
void fprops_resize(unsigned int _n) const { fprops_.resize(_n); }
|
||||
void fprops_swap(unsigned int _i0, unsigned int _i1) const {
|
||||
fprops_.swap(_i0, _i1);
|
||||
}
|
||||
|
||||
void mprops_resize(unsigned int _n) const { mprops_.resize(_n); }
|
||||
|
||||
public:
|
||||
|
||||
void property_stats(std::ostream& _ostr = std::clog) const;
|
||||
|
||||
public:
|
||||
|
||||
typedef PropertyContainer::iterator prop_iterator;
|
||||
typedef PropertyContainer::const_iterator const_prop_iterator;
|
||||
|
||||
prop_iterator vprops_begin() { return vprops_.begin(); }
|
||||
prop_iterator vprops_end() { return vprops_.end(); }
|
||||
const_prop_iterator vprops_begin() const { return vprops_.begin(); }
|
||||
const_prop_iterator vprops_end() const { return vprops_.end(); }
|
||||
|
||||
prop_iterator eprops_begin() { return eprops_.begin(); }
|
||||
prop_iterator eprops_end() { return eprops_.end(); }
|
||||
const_prop_iterator eprops_begin() const { return eprops_.begin(); }
|
||||
const_prop_iterator eprops_end() const { return eprops_.end(); }
|
||||
|
||||
prop_iterator hprops_begin() { return hprops_.begin(); }
|
||||
prop_iterator hprops_end() { return hprops_.end(); }
|
||||
const_prop_iterator hprops_begin() const { return hprops_.begin(); }
|
||||
const_prop_iterator hprops_end() const { return hprops_.end(); }
|
||||
|
||||
prop_iterator fprops_begin() { return fprops_.begin(); }
|
||||
prop_iterator fprops_end() { return fprops_.end(); }
|
||||
const_prop_iterator fprops_begin() const { return fprops_.begin(); }
|
||||
const_prop_iterator fprops_end() const { return fprops_.end(); }
|
||||
|
||||
prop_iterator mprops_begin() { return mprops_.begin(); }
|
||||
prop_iterator mprops_end() { return mprops_.end(); }
|
||||
const_prop_iterator mprops_begin() const { return mprops_.begin(); }
|
||||
const_prop_iterator mprops_end() const { return mprops_.end(); }
|
||||
|
||||
private:
|
||||
|
||||
PropertyContainer vprops_;
|
||||
PropertyContainer hprops_;
|
||||
PropertyContainer eprops_;
|
||||
PropertyContainer fprops_;
|
||||
PropertyContainer mprops_;
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_BASE_KERNEL_HH defined
|
||||
//=============================================================================
|
||||
79
Core/Mesh/BaseMesh.hh
Normal file
79
Core/Mesh/BaseMesh.hh
Normal file
@@ -0,0 +1,79 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS BaseMesh
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_BASEMESH_HH
|
||||
#define OPENMESH_BASEMESH_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Mesh/IteratorsT.hh>
|
||||
#include <OpenMesh/Core/Mesh/CirculatorsT.hh>
|
||||
#include <OpenMesh/Core/Mesh/Attributes.hh>
|
||||
#include <vector>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \class BaseMesh BaseMesh.hh <OpenMesh/Mesh/BaseMesh.hh>
|
||||
|
||||
Base class for all meshes.
|
||||
*/
|
||||
|
||||
class BaseMesh {
|
||||
public:
|
||||
virtual ~BaseMesh(void) {;}
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_BASEMESH_HH defined
|
||||
//=============================================================================
|
||||
54
Core/Mesh/Casts.hh
Normal file
54
Core/Mesh/Casts.hh
Normal file
@@ -0,0 +1,54 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2004 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_CASTS_HH
|
||||
#define OPENMESH_CASTS_HH
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
namespace OpenMesh
|
||||
{
|
||||
|
||||
template <class Traits>
|
||||
inline TriMesh_ArrayKernelT<Traits>& TRIMESH_CAST(PolyMesh_ArrayKernelT<Traits>& _poly_mesh)
|
||||
{ return reinterpret_cast< TriMesh_ArrayKernelT<Traits>& >(_poly_mesh); }
|
||||
|
||||
template <class Traits>
|
||||
inline const TriMesh_ArrayKernelT<Traits>& TRIMESH_CAST(const PolyMesh_ArrayKernelT<Traits>& _poly_mesh)
|
||||
{ return reinterpret_cast< const TriMesh_ArrayKernelT<Traits>& >(_poly_mesh); }
|
||||
|
||||
template <class Traits>
|
||||
inline PolyMesh_ArrayKernelT<Traits>& POLYMESH_CAST(TriMesh_ArrayKernelT<Traits>& _tri_mesh)
|
||||
{ return reinterpret_cast< PolyMesh_ArrayKernelT<Traits>& >(_tri_mesh); }
|
||||
|
||||
template <class Traits>
|
||||
inline const PolyMesh_ArrayKernelT<Traits>& POLYMESH_CAST(const TriMesh_ArrayKernelT<Traits>& _tri_mesh)
|
||||
{ return reinterpret_cast< const PolyMesh_ArrayKernelT<Traits>& >(_tri_mesh); }
|
||||
|
||||
};
|
||||
#endif//OPENMESH_CASTS_HH
|
||||
3499
Core/Mesh/CirculatorsT.hh
Normal file
3499
Core/Mesh/CirculatorsT.hh
Normal file
File diff suppressed because it is too large
Load Diff
121
Core/Mesh/FinalMeshItemsT.hh
Normal file
121
Core/Mesh/FinalMeshItemsT.hh
Normal file
@@ -0,0 +1,121 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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: 3794 $
|
||||
// $Date: 2008-11-25 19:25:02 +0100 (Di, 25. Nov 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_MESH_ITEMS_HH
|
||||
#define OPENMESH_MESH_ITEMS_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Utils/GenProg.hh>
|
||||
#include <OpenMesh/Core/Utils/vector_traits.hh>
|
||||
#include <OpenMesh/Core/Mesh/Handles.hh>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/// Definition of the mesh entities (items).
|
||||
template <class Traits, bool IsTriMesh>
|
||||
struct FinalMeshItemsT
|
||||
{
|
||||
//--- build Refs structure ---
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
struct Refs
|
||||
{
|
||||
typedef typename Traits::Point Point;
|
||||
typedef typename vector_traits<Point>::value_type Scalar;
|
||||
|
||||
typedef typename Traits::Normal Normal;
|
||||
typedef typename Traits::Color Color;
|
||||
typedef typename Traits::TexCoord1D TexCoord1D;
|
||||
typedef typename Traits::TexCoord2D TexCoord2D;
|
||||
typedef typename Traits::TexCoord3D TexCoord3D;
|
||||
typedef typename Traits::TextureIndex TextureIndex;
|
||||
typedef OpenMesh::VertexHandle VertexHandle;
|
||||
typedef OpenMesh::FaceHandle FaceHandle;
|
||||
typedef OpenMesh::EdgeHandle EdgeHandle;
|
||||
typedef OpenMesh::HalfedgeHandle HalfedgeHandle;
|
||||
};
|
||||
#endif
|
||||
//--- export Refs types ---
|
||||
typedef typename Refs::Point Point;
|
||||
typedef typename Refs::Scalar Scalar;
|
||||
typedef typename Refs::Normal Normal;
|
||||
typedef typename Refs::Color Color;
|
||||
typedef typename Refs::TexCoord1D TexCoord1D;
|
||||
typedef typename Refs::TexCoord2D TexCoord2D;
|
||||
typedef typename Refs::TexCoord3D TexCoord3D;
|
||||
typedef typename Refs::TextureIndex TextureIndex;
|
||||
|
||||
//--- get attribute bits from Traits ---
|
||||
enum Attribs
|
||||
{
|
||||
VAttribs = Traits::VertexAttributes,
|
||||
HAttribs = Traits::HalfedgeAttributes,
|
||||
EAttribs = Traits::EdgeAttributes,
|
||||
FAttribs = Traits::FaceAttributes
|
||||
};
|
||||
//--- merge internal items with traits items ---
|
||||
|
||||
|
||||
/*
|
||||
typedef typename GenProg::IF<
|
||||
(bool)(HAttribs & Attributes::PrevHalfedge),
|
||||
typename InternalItems::Halfedge_with_prev,
|
||||
typename InternalItems::Halfedge_without_prev
|
||||
>::Result InternalHalfedge;
|
||||
*/
|
||||
//typedef typename InternalItems::Vertex InternalVertex;
|
||||
//typedef typename InternalItems::template Edge<Halfedge> InternalEdge;
|
||||
//typedef typename InternalItems::template Face<IsTriMesh> InternalFace;
|
||||
class ITraits
|
||||
{};
|
||||
|
||||
typedef typename Traits::template VertexT<ITraits, Refs> VertexData;
|
||||
typedef typename Traits::template HalfedgeT<ITraits, Refs> HalfedgeData;
|
||||
typedef typename Traits::template EdgeT<ITraits, Refs> EdgeData;
|
||||
typedef typename Traits::template FaceT<ITraits, Refs> FaceData;
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_MESH_ITEMS_HH defined
|
||||
//=============================================================================
|
||||
|
||||
134
Core/Mesh/Handles.hh
Normal file
134
Core/Mesh/Handles.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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1801 $
|
||||
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_HANDLES_HH
|
||||
#define OPENMESH_HANDLES_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/// Base class for all handle types
|
||||
class BaseHandle
|
||||
{
|
||||
public:
|
||||
|
||||
explicit BaseHandle(int _idx=-1) : idx_(_idx) {}
|
||||
|
||||
/// Get the underlying index of this handle
|
||||
int idx() const { return idx_; }
|
||||
|
||||
/// The handle is valid iff the index is not equal to -1.
|
||||
bool is_valid() const { return idx_ != -1; }
|
||||
|
||||
/// reset handle to be invalid
|
||||
void reset() { idx_=-1; }
|
||||
/// reset handle to be invalid
|
||||
void invalidate() { idx_ = -1; }
|
||||
|
||||
bool operator==(const BaseHandle& _rhs) const {
|
||||
return idx_ == _rhs.idx_;
|
||||
}
|
||||
|
||||
bool operator!=(const BaseHandle& _rhs) const {
|
||||
return idx_ != _rhs.idx_;
|
||||
}
|
||||
|
||||
bool operator<(const BaseHandle& _rhs) const {
|
||||
return idx_ < _rhs.idx_;
|
||||
}
|
||||
|
||||
|
||||
// this is to be used only by the iterators
|
||||
void __increment() { ++idx_; }
|
||||
void __decrement() { --idx_; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
int idx_;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/// Write handle \c _hnd to stream \c _os
|
||||
inline std::ostream& operator<<(std::ostream& _os, const BaseHandle& _hnd)
|
||||
{
|
||||
return (_os << _hnd.idx());
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/// Handle for a vertex entity
|
||||
struct VertexHandle : public BaseHandle
|
||||
{
|
||||
explicit VertexHandle(int _idx=-1) : BaseHandle(_idx) {}
|
||||
};
|
||||
|
||||
|
||||
/// Handle for a halfedge entity
|
||||
struct HalfedgeHandle : public BaseHandle
|
||||
{
|
||||
explicit HalfedgeHandle(int _idx=-1) : BaseHandle(_idx) {}
|
||||
};
|
||||
|
||||
|
||||
/// Handle for a edge entity
|
||||
struct EdgeHandle : public BaseHandle
|
||||
{
|
||||
explicit EdgeHandle(int _idx=-1) : BaseHandle(_idx) {}
|
||||
};
|
||||
|
||||
|
||||
/// Handle for a face entity
|
||||
struct FaceHandle : public BaseHandle
|
||||
{
|
||||
explicit FaceHandle(int _idx=-1) : BaseHandle(_idx) {}
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_HANDLES_HH
|
||||
//=============================================================================
|
||||
1364
Core/Mesh/IteratorsT.hh
Normal file
1364
Core/Mesh/IteratorsT.hh
Normal file
File diff suppressed because it is too large
Load Diff
838
Core/Mesh/PolyConnectivity.cc
Normal file
838
Core/Mesh/PolyConnectivity.cc
Normal file
@@ -0,0 +1,838 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2004 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. *
|
||||
* *
|
||||
\*===========================================================================*/
|
||||
|
||||
//== IMPLEMENTATION ==========================================================
|
||||
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
|
||||
#include <set>
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
const PolyConnectivity::VertexHandle PolyConnectivity::InvalidVertexHandle;
|
||||
const PolyConnectivity::HalfedgeHandle PolyConnectivity::InvalidHalfedgeHandle;
|
||||
const PolyConnectivity::EdgeHandle PolyConnectivity::InvalidEdgeHandle;
|
||||
const PolyConnectivity::FaceHandle PolyConnectivity::InvalidFaceHandle;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
PolyConnectivity::HalfedgeHandle
|
||||
PolyConnectivity::find_halfedge(VertexHandle _start_vh, VertexHandle _end_vh ) const
|
||||
{
|
||||
assert(_start_vh.is_valid() && _end_vh.is_valid());
|
||||
|
||||
for (ConstVertexVertexIter vvIt=cvv_iter(_start_vh); vvIt; ++vvIt)
|
||||
if (vvIt.handle() == _end_vh)
|
||||
return vvIt.current_halfedge_handle();
|
||||
|
||||
return InvalidHalfedgeHandle;
|
||||
}
|
||||
|
||||
|
||||
bool PolyConnectivity::is_boundary(FaceHandle _fh, bool _check_vertex) const
|
||||
{
|
||||
for (ConstFaceEdgeIter cfeit = cfe_iter( _fh ); cfeit; ++cfeit)
|
||||
if (is_boundary( cfeit.handle() ) )
|
||||
return true;
|
||||
|
||||
if (_check_vertex)
|
||||
{
|
||||
for (ConstFaceVertexIter cfvit = cfv_iter( _fh ); cfvit; ++cfvit)
|
||||
if (is_boundary( cfvit.handle() ) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PolyConnectivity::is_manifold(VertexHandle _vh) const
|
||||
{
|
||||
/* The vertex is non-manifold if more than one gap exists, i.e.
|
||||
more than one outgoing boundary halfedge. If (at least) one
|
||||
boundary halfedge exists, the vertex' halfedge must be a
|
||||
boundary halfedge. If iterating around the vertex finds another
|
||||
boundary halfedge, the vertex is non-manifold. */
|
||||
|
||||
ConstVertexOHalfedgeIter vh_it(*this, _vh);
|
||||
if (vh_it)
|
||||
for (++vh_it; vh_it; ++vh_it)
|
||||
if (is_boundary(vh_it.handle()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::adjust_outgoing_halfedge(VertexHandle _vh)
|
||||
{
|
||||
for (ConstVertexOHalfedgeIter vh_it=cvoh_iter(_vh); vh_it; ++vh_it)
|
||||
{
|
||||
if (is_boundary(vh_it.handle()))
|
||||
{
|
||||
set_halfedge_handle(_vh, vh_it.handle());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace
|
||||
{
|
||||
template <class _Handle>
|
||||
struct NextCacheEntryT : public std::pair<_Handle, _Handle>
|
||||
{
|
||||
typedef std::pair<_Handle, _Handle> Base;
|
||||
|
||||
NextCacheEntryT(_Handle _heh0, _Handle _heh1)
|
||||
: Base(_heh0, _heh1)
|
||||
{
|
||||
assert(_heh0.is_valid());
|
||||
assert(_heh1.is_valid());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
PolyConnectivity::FaceHandle
|
||||
PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size)
|
||||
{
|
||||
VertexHandle vh;
|
||||
uint i, ii, n(_vhs_size), id;
|
||||
std::vector<HalfedgeHandle> halfedge_handles(n);
|
||||
std::vector<bool> is_new(n), needs_adjust(n, false);
|
||||
HalfedgeHandle inner_next, inner_prev,
|
||||
outer_next, outer_prev,
|
||||
boundary_next, boundary_prev,
|
||||
patch_start, patch_end;
|
||||
|
||||
// cache for set_next_halfedge and vertex' set_halfedge
|
||||
typedef NextCacheEntryT<HalfedgeHandle> NextCacheEntry;
|
||||
typedef std::vector<NextCacheEntry> NextCache;
|
||||
|
||||
NextCache next_cache;
|
||||
next_cache.reserve(3*n);
|
||||
// don't allow degenerated faces
|
||||
assert (n > 2);
|
||||
|
||||
// test for topological errors
|
||||
for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
|
||||
{
|
||||
if ( !is_boundary(_vertex_handles[i]) )
|
||||
{
|
||||
omerr() << "PolyMeshT::add_face: complex vertex\n";
|
||||
return InvalidFaceHandle;
|
||||
}
|
||||
|
||||
halfedge_handles[i] = find_halfedge(_vertex_handles[i],
|
||||
_vertex_handles[ii]);
|
||||
is_new[i] = !halfedge_handles[i].is_valid();
|
||||
|
||||
if (!is_new[i] && !is_boundary(halfedge_handles[i]))
|
||||
{
|
||||
omerr() << "PolyMeshT::add_face: complex edge\n";
|
||||
return InvalidFaceHandle;
|
||||
}
|
||||
}
|
||||
|
||||
// re-link patches if necessary
|
||||
for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
|
||||
{
|
||||
if (!is_new[i] && !is_new[ii])
|
||||
{
|
||||
inner_prev = halfedge_handles[i];
|
||||
inner_next = halfedge_handles[ii];
|
||||
|
||||
if (next_halfedge_handle(inner_prev) != inner_next)
|
||||
{
|
||||
// here comes the ugly part... we have to relink a whole patch
|
||||
|
||||
// search a free gap
|
||||
// free gap will be between boundary_prev and boundary_next
|
||||
outer_prev = opposite_halfedge_handle(inner_next);
|
||||
outer_next = opposite_halfedge_handle(inner_prev);
|
||||
boundary_prev = outer_prev;
|
||||
do
|
||||
boundary_prev =
|
||||
opposite_halfedge_handle(next_halfedge_handle(boundary_prev));
|
||||
while (!is_boundary(boundary_prev) || boundary_prev==inner_prev);
|
||||
boundary_next = next_halfedge_handle(boundary_prev);
|
||||
assert(is_boundary(boundary_prev));
|
||||
assert(is_boundary(boundary_next));
|
||||
// ok ?
|
||||
if (boundary_next == inner_next)
|
||||
{
|
||||
omerr() << "PolyMeshT::add_face: patch re-linking failed\n";
|
||||
return InvalidFaceHandle;
|
||||
}
|
||||
|
||||
// other halfedges' handles
|
||||
patch_start = next_halfedge_handle(inner_prev);
|
||||
patch_end = prev_halfedge_handle(inner_next);
|
||||
|
||||
// relink
|
||||
next_cache.push_back(NextCacheEntry(boundary_prev, patch_start));
|
||||
next_cache.push_back(NextCacheEntry(patch_end, boundary_next));
|
||||
next_cache.push_back(NextCacheEntry(inner_prev, inner_next));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create missing edges
|
||||
for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
|
||||
if (is_new[i])
|
||||
halfedge_handles[i] = new_edge(_vertex_handles[i], _vertex_handles[ii]);
|
||||
|
||||
// create the face
|
||||
FaceHandle fh(new_face());
|
||||
set_halfedge_handle(fh, halfedge_handles[n-1]);
|
||||
|
||||
// setup halfedges
|
||||
for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
|
||||
{
|
||||
vh = _vertex_handles[ii];
|
||||
inner_prev = halfedge_handles[i];
|
||||
inner_next = halfedge_handles[ii];
|
||||
|
||||
id = 0;
|
||||
if (is_new[i]) id |= 1;
|
||||
if (is_new[ii]) id |= 2;
|
||||
|
||||
if (id)
|
||||
{
|
||||
outer_prev = opposite_halfedge_handle(inner_next);
|
||||
outer_next = opposite_halfedge_handle(inner_prev);
|
||||
|
||||
// set outer links
|
||||
switch (id)
|
||||
{
|
||||
case 1: // prev is new, next is old
|
||||
boundary_prev = prev_halfedge_handle(inner_next);
|
||||
next_cache.push_back(NextCacheEntry(boundary_prev, outer_next));
|
||||
set_halfedge_handle(vh, outer_next);
|
||||
break;
|
||||
|
||||
case 2: // next is new, prev is old
|
||||
boundary_next = next_halfedge_handle(inner_prev);
|
||||
next_cache.push_back(NextCacheEntry(outer_prev, boundary_next));
|
||||
set_halfedge_handle(vh, boundary_next);
|
||||
break;
|
||||
|
||||
case 3: // both are new
|
||||
if (!halfedge_handle(vh).is_valid())
|
||||
{
|
||||
set_halfedge_handle(vh, outer_next);
|
||||
next_cache.push_back(NextCacheEntry(outer_prev, outer_next));
|
||||
}
|
||||
else
|
||||
{
|
||||
boundary_next = halfedge_handle(vh);
|
||||
boundary_prev = prev_halfedge_handle(boundary_next);
|
||||
next_cache.push_back(NextCacheEntry(boundary_prev, outer_next));
|
||||
next_cache.push_back(NextCacheEntry(outer_prev, boundary_next));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// set inner link
|
||||
next_cache.push_back(NextCacheEntry(inner_prev, inner_next));
|
||||
}
|
||||
else needs_adjust[ii] = (halfedge_handle(vh) == inner_next);
|
||||
|
||||
// set face handle
|
||||
set_face_handle(halfedge_handles[i], fh);
|
||||
}
|
||||
|
||||
// process next halfedge cache
|
||||
NextCache::const_iterator ncIt(next_cache.begin()), ncEnd(next_cache.end());
|
||||
for (; ncIt != ncEnd; ++ncIt)
|
||||
set_next_halfedge_handle(ncIt->first, ncIt->second);
|
||||
|
||||
// adjust vertices' halfedge handle
|
||||
for (i=0; i<n; ++i)
|
||||
if (needs_adjust[i])
|
||||
adjust_outgoing_halfedge(_vertex_handles[i]);
|
||||
|
||||
return fh;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void PolyConnectivity::delete_vertex(VertexHandle _vh, bool _delete_isolated_vertices)
|
||||
{
|
||||
// store incident faces
|
||||
std::vector<FaceHandle> face_handles;
|
||||
face_handles.reserve(8);
|
||||
for (VFIter vf_it(vf_iter(_vh)); vf_it; ++vf_it)
|
||||
face_handles.push_back(vf_it.handle());
|
||||
|
||||
|
||||
// delete collected faces
|
||||
std::vector<FaceHandle>::iterator fh_it(face_handles.begin()),
|
||||
fh_end(face_handles.end());
|
||||
|
||||
for (; fh_it!=fh_end; ++fh_it)
|
||||
delete_face(*fh_it, _delete_isolated_vertices);
|
||||
|
||||
status(_vh).set_deleted(true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void PolyConnectivity::delete_edge(EdgeHandle _eh, bool _delete_isolated_vertices)
|
||||
{
|
||||
FaceHandle fh0(face_handle(halfedge_handle(_eh, 0)));
|
||||
FaceHandle fh1(face_handle(halfedge_handle(_eh, 1)));
|
||||
|
||||
if (fh0.is_valid()) delete_face(fh0, _delete_isolated_vertices);
|
||||
if (fh1.is_valid()) delete_face(fh1, _delete_isolated_vertices);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void PolyConnectivity::delete_face(FaceHandle _fh, bool _delete_isolated_vertices)
|
||||
{
|
||||
assert(_fh.is_valid() && !status(_fh).deleted());
|
||||
|
||||
// mark face deleted
|
||||
status(_fh).set_deleted(true);
|
||||
|
||||
|
||||
// this vector will hold all boundary edges of face _fh
|
||||
// these edges will be deleted
|
||||
std::vector<EdgeHandle> deleted_edges;
|
||||
deleted_edges.reserve(3);
|
||||
|
||||
|
||||
// this vector will hold all vertices of face _fh
|
||||
// for updating their outgoing halfedge
|
||||
std::vector<VertexHandle> vhandles;
|
||||
vhandles.reserve(3);
|
||||
|
||||
|
||||
// for all halfedges of face _fh do:
|
||||
// 1) invalidate face handle.
|
||||
// 2) collect all boundary halfedges, set them deleted
|
||||
// 3) store vertex handles
|
||||
HalfedgeHandle hh;
|
||||
for (FaceHalfedgeIter fh_it(fh_iter(_fh)); fh_it; ++fh_it)
|
||||
{
|
||||
hh = fh_it.handle();
|
||||
|
||||
set_boundary(hh);//set_face_handle(hh, InvalidFaceHandle);
|
||||
|
||||
if (is_boundary(opposite_halfedge_handle(hh)))
|
||||
deleted_edges.push_back(edge_handle(hh));
|
||||
|
||||
vhandles.push_back(to_vertex_handle(hh));
|
||||
}
|
||||
|
||||
|
||||
// delete all collected (half)edges
|
||||
// delete isolated vertices (if _delete_isolated_vertices is true)
|
||||
if (!deleted_edges.empty())
|
||||
{
|
||||
std::vector<EdgeHandle>::iterator del_it(deleted_edges.begin()),
|
||||
del_end(deleted_edges.end());
|
||||
HalfedgeHandle h0, h1, next0, next1, prev0, prev1;
|
||||
VertexHandle v0, v1;
|
||||
|
||||
for (; del_it!=del_end; ++del_it)
|
||||
{
|
||||
h0 = halfedge_handle(*del_it, 0);
|
||||
v0 = to_vertex_handle(h0);
|
||||
next0 = next_halfedge_handle(h0);
|
||||
prev0 = prev_halfedge_handle(h0);
|
||||
|
||||
h1 = halfedge_handle(*del_it, 1);
|
||||
v1 = to_vertex_handle(h1);
|
||||
next1 = next_halfedge_handle(h1);
|
||||
prev1 = prev_halfedge_handle(h1);
|
||||
|
||||
// adjust next and prev handles
|
||||
set_next_halfedge_handle(prev0, next1);
|
||||
set_next_halfedge_handle(prev1, next0);
|
||||
|
||||
// mark edge deleted
|
||||
status(*del_it).set_deleted(true);
|
||||
|
||||
// update v0
|
||||
if (halfedge_handle(v0) == h1)
|
||||
{
|
||||
// isolated ?
|
||||
if (next0 == h1)
|
||||
{
|
||||
if (_delete_isolated_vertices)
|
||||
status(v0).set_deleted(true);
|
||||
set_isolated(v0);
|
||||
}
|
||||
else set_halfedge_handle(v0, next0);
|
||||
}
|
||||
|
||||
// update v1
|
||||
if (halfedge_handle(v1) == h0)
|
||||
{
|
||||
// isolated ?
|
||||
if (next1 == h0)
|
||||
{
|
||||
if (_delete_isolated_vertices)
|
||||
status(v1).set_deleted(true);
|
||||
set_isolated(v1);
|
||||
}
|
||||
else set_halfedge_handle(v1, next1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update outgoing halfedge handles of remaining vertices
|
||||
std::vector<VertexHandle>::iterator v_it(vhandles.begin()),
|
||||
v_end(vhandles.end());
|
||||
for (; v_it!=v_end; ++v_it)
|
||||
adjust_outgoing_halfedge(*v_it);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::collapse(HalfedgeHandle _hh)
|
||||
{
|
||||
HalfedgeHandle h0 = _hh;
|
||||
HalfedgeHandle h1 = next_halfedge_handle(h0);
|
||||
HalfedgeHandle o0 = opposite_halfedge_handle(h0);
|
||||
HalfedgeHandle o1 = next_halfedge_handle(o0);
|
||||
|
||||
// remove edge
|
||||
collapse_edge(h0);
|
||||
|
||||
// remove loops
|
||||
if (next_halfedge_handle(next_halfedge_handle(h1)) == h1)
|
||||
collapse_loop(next_halfedge_handle(h1));
|
||||
if (next_halfedge_handle(next_halfedge_handle(o1)) == o1)
|
||||
collapse_loop(o1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::collapse_edge(HalfedgeHandle _hh)
|
||||
{
|
||||
HalfedgeHandle h = _hh;
|
||||
HalfedgeHandle hn = next_halfedge_handle(h);
|
||||
HalfedgeHandle hp = prev_halfedge_handle(h);
|
||||
|
||||
HalfedgeHandle o = opposite_halfedge_handle(h);
|
||||
HalfedgeHandle on = next_halfedge_handle(o);
|
||||
HalfedgeHandle op = prev_halfedge_handle(o);
|
||||
|
||||
FaceHandle fh = face_handle(h);
|
||||
FaceHandle fo = face_handle(o);
|
||||
|
||||
VertexHandle vh = to_vertex_handle(h);
|
||||
VertexHandle vo = to_vertex_handle(o);
|
||||
|
||||
|
||||
|
||||
// halfedge -> vertex
|
||||
for (VertexIHalfedgeIter vih_it(vih_iter(vo)); vih_it; ++vih_it)
|
||||
set_vertex_handle(vih_it.handle(), vh);
|
||||
|
||||
|
||||
// halfedge -> halfedge
|
||||
set_next_halfedge_handle(hp, hn);
|
||||
set_next_halfedge_handle(op, on);
|
||||
|
||||
|
||||
// face -> halfedge
|
||||
if (fh.is_valid()) set_halfedge_handle(fh, hn);
|
||||
if (fo.is_valid()) set_halfedge_handle(fo, on);
|
||||
|
||||
|
||||
// vertex -> halfedge
|
||||
if (halfedge_handle(vh) == o) set_halfedge_handle(vh, hn);
|
||||
adjust_outgoing_halfedge(vh);
|
||||
set_isolated(vo);
|
||||
|
||||
// delete stuff
|
||||
status(edge_handle(h)).set_deleted(true);
|
||||
status(vo).set_deleted(true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::collapse_loop(HalfedgeHandle _hh)
|
||||
{
|
||||
HalfedgeHandle h0 = _hh;
|
||||
HalfedgeHandle h1 = next_halfedge_handle(h0);
|
||||
|
||||
HalfedgeHandle o0 = opposite_halfedge_handle(h0);
|
||||
HalfedgeHandle o1 = opposite_halfedge_handle(h1);
|
||||
|
||||
VertexHandle v0 = to_vertex_handle(h0);
|
||||
VertexHandle v1 = to_vertex_handle(h1);
|
||||
|
||||
FaceHandle fh = face_handle(h0);
|
||||
FaceHandle fo = face_handle(o0);
|
||||
|
||||
|
||||
|
||||
// is it a loop ?
|
||||
assert ((next_halfedge_handle(h1) == h0) && (h1 != o0));
|
||||
|
||||
|
||||
// halfedge -> halfedge
|
||||
set_next_halfedge_handle(h1, next_halfedge_handle(o0));
|
||||
set_next_halfedge_handle(prev_halfedge_handle(o0), h1);
|
||||
|
||||
|
||||
// halfedge -> face
|
||||
set_face_handle(h1, fo);
|
||||
|
||||
|
||||
// vertex -> halfedge
|
||||
set_halfedge_handle(v0, h1); adjust_outgoing_halfedge(v0);
|
||||
set_halfedge_handle(v1, o1); adjust_outgoing_halfedge(v1);
|
||||
|
||||
|
||||
// face -> halfedge
|
||||
if (fo.is_valid() && halfedge_handle(fo) == o0)
|
||||
{
|
||||
set_halfedge_handle(fo, h1);
|
||||
}
|
||||
|
||||
// delete stuff
|
||||
if (fh.is_valid())
|
||||
{
|
||||
set_halfedge_handle(fh, InvalidHalfedgeHandle);
|
||||
status(fh).set_deleted(true);
|
||||
}
|
||||
status(edge_handle(h0)).set_deleted(true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool PolyConnectivity::is_simple_link(EdgeHandle _eh) const
|
||||
{
|
||||
HalfedgeHandle heh0 = halfedge_handle(_eh, 0);
|
||||
HalfedgeHandle heh1 = halfedge_handle(_eh, 1);
|
||||
|
||||
FaceHandle fh0 = face_handle(heh0);//fh0 or fh1 might be a invalid,
|
||||
FaceHandle fh1 = face_handle(heh1);//i.e., representing the boundary
|
||||
|
||||
HalfedgeHandle next_heh = next_halfedge_handle(heh0);
|
||||
while (next_heh != heh0)
|
||||
{//check if there are no other edges shared between fh0 & fh1
|
||||
if (opposite_face_handle(next_heh) == fh1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
next_heh = next_halfedge_handle(next_heh);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool PolyConnectivity::is_simply_connected(FaceHandle _fh) const
|
||||
{
|
||||
std::set<FaceHandle> nb_fhs;
|
||||
for (ConstFaceFaceIter cff_it = cff_iter(_fh); cff_it; ++cff_it)
|
||||
{
|
||||
if (nb_fhs.find(cff_it) == nb_fhs.end())
|
||||
{
|
||||
nb_fhs.insert(cff_it);
|
||||
}
|
||||
else
|
||||
{//there is more than one link
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
PolyConnectivity::FaceHandle
|
||||
PolyConnectivity::remove_edge(EdgeHandle _eh)
|
||||
{
|
||||
//don't allow "dangling" vertices and edges
|
||||
assert(!status(_eh).deleted() && is_simple_link(_eh));
|
||||
|
||||
HalfedgeHandle heh0 = halfedge_handle(_eh, 0);
|
||||
HalfedgeHandle heh1 = halfedge_handle(_eh, 1);
|
||||
|
||||
//deal with the faces
|
||||
FaceHandle rem_fh = face_handle(heh0), del_fh = face_handle(heh1);
|
||||
if (!del_fh.is_valid())
|
||||
{//boundary case - we must delete the rem_fh
|
||||
std::swap(del_fh, rem_fh);
|
||||
}
|
||||
assert(del_fh.is_valid());
|
||||
/* for (FaceHalfedgeIter fh_it = fh_iter(del_fh); fh_it; ++fh_it)
|
||||
{//set the face handle of the halfedges of del_fh to point to rem_fh
|
||||
set_face_handle(fh_it, rem_fh);
|
||||
} */
|
||||
//fix the halfedge relations
|
||||
HalfedgeHandle prev_heh0 = prev_halfedge_handle(heh0);
|
||||
HalfedgeHandle prev_heh1 = prev_halfedge_handle(heh1);
|
||||
|
||||
HalfedgeHandle next_heh0 = next_halfedge_handle(heh0);
|
||||
HalfedgeHandle next_heh1 = next_halfedge_handle(heh1);
|
||||
|
||||
set_next_halfedge_handle(prev_heh0, next_heh1);
|
||||
set_next_halfedge_handle(prev_heh1, next_heh0);
|
||||
//correct outgoing vertex handles for the _eh vertices (if needed)
|
||||
VertexHandle vh0 = to_vertex_handle(heh0);
|
||||
VertexHandle vh1 = to_vertex_handle(heh1);
|
||||
|
||||
if (halfedge_handle(vh0) == heh1)
|
||||
{
|
||||
set_halfedge_handle(vh0, next_heh0);
|
||||
}
|
||||
if (halfedge_handle(vh1) == heh0)
|
||||
{
|
||||
set_halfedge_handle(vh1, next_heh1);
|
||||
}
|
||||
|
||||
//correct the hafledge handle of rem_fh if needed and preserve its first vertex
|
||||
if (halfedge_handle(rem_fh) == heh0)
|
||||
{//rem_fh is the face at heh0
|
||||
set_halfedge_handle(rem_fh, prev_heh1);
|
||||
}
|
||||
else if (halfedge_handle(rem_fh) == heh1)
|
||||
{//rem_fh is the face at heh1
|
||||
set_halfedge_handle(rem_fh, prev_heh0);
|
||||
}
|
||||
for (FaceHalfedgeIter fh_it = fh_iter(rem_fh); fh_it; ++fh_it)
|
||||
{//set the face handle of the halfedges of del_fh to point to rem_fh
|
||||
set_face_handle(fh_it, rem_fh);
|
||||
}
|
||||
|
||||
status(_eh).set_deleted(true);
|
||||
status(del_fh).set_deleted(true);
|
||||
return rem_fh;//returns the remaining face handle
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::reinsert_edge(EdgeHandle _eh)
|
||||
{
|
||||
//this does not work without prev_halfedge_handle
|
||||
assert_compile(sizeof(Halfedge) == sizeof(Halfedge_with_prev));
|
||||
//shoudl be deleted
|
||||
assert(status(_eh).deleted());
|
||||
status(_eh).set_deleted(false);
|
||||
|
||||
HalfedgeHandle heh0 = halfedge_handle(_eh, 0);
|
||||
HalfedgeHandle heh1 = halfedge_handle(_eh, 1);
|
||||
FaceHandle rem_fh = face_handle(heh0), del_fh = face_handle(heh1);
|
||||
if (!del_fh.is_valid())
|
||||
{//boundary case - we must delete the rem_fh
|
||||
std::swap(del_fh, rem_fh);
|
||||
}
|
||||
assert(status(del_fh).deleted());
|
||||
status(del_fh).set_deleted(false);
|
||||
|
||||
//restore halfedge relations
|
||||
HalfedgeHandle prev_heh0 = prev_halfedge_handle(heh0);
|
||||
HalfedgeHandle prev_heh1 = prev_halfedge_handle(heh1);
|
||||
|
||||
HalfedgeHandle next_heh0 = next_halfedge_handle(heh0);
|
||||
HalfedgeHandle next_heh1 = next_halfedge_handle(heh1);
|
||||
|
||||
set_next_halfedge_handle(prev_heh0, heh0);
|
||||
set_prev_halfedge_handle(next_heh0, heh0);
|
||||
|
||||
set_next_halfedge_handle(prev_heh1, heh1);
|
||||
set_prev_halfedge_handle(next_heh1, heh1);
|
||||
|
||||
for (FaceHalfedgeIter fh_it = fh_iter(del_fh); fh_it; ++fh_it)
|
||||
{//reassign halfedges to del_fh
|
||||
set_face_handle(fh_it, del_fh);
|
||||
}
|
||||
|
||||
if (face_handle(halfedge_handle(rem_fh)) == del_fh)
|
||||
{//correct the halfedge handle of rem_fh
|
||||
if (halfedge_handle(rem_fh) == prev_heh0)
|
||||
{//rem_fh is the face at heh1
|
||||
set_halfedge_handle(rem_fh, heh1);
|
||||
}
|
||||
else
|
||||
{//rem_fh is the face at heh0
|
||||
assert(halfedge_handle(rem_fh) == prev_heh1);
|
||||
set_halfedge_handle(rem_fh, heh0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
PolyConnectivity::HalfedgeHandle
|
||||
PolyConnectivity::insert_edge(HalfedgeHandle _prev_heh, HalfedgeHandle _next_heh)
|
||||
{
|
||||
assert(face_handle(_prev_heh) == face_handle(_next_heh));//only the manifold case
|
||||
assert(next_halfedge_handle(_prev_heh) != _next_heh);//this can not be done
|
||||
VertexHandle vh0 = to_vertex_handle(_prev_heh);
|
||||
VertexHandle vh1 = from_vertex_handle(_next_heh);
|
||||
//create the link between vh0 and vh1
|
||||
HalfedgeHandle heh0 = new_edge(vh0, vh1);
|
||||
HalfedgeHandle heh1 = opposite_halfedge_handle(heh0);
|
||||
HalfedgeHandle next_prev_heh = next_halfedge_handle(_prev_heh);
|
||||
HalfedgeHandle prev_next_heh = prev_halfedge_handle(_next_heh);
|
||||
set_next_halfedge_handle(_prev_heh, heh0);
|
||||
set_next_halfedge_handle(heh0, _next_heh);
|
||||
set_next_halfedge_handle(prev_next_heh, heh1);
|
||||
set_next_halfedge_handle(heh1, next_prev_heh);
|
||||
|
||||
//now set the face handles - the new face is assigned to heh0
|
||||
FaceHandle new_fh = new_face();
|
||||
set_halfedge_handle(new_fh, heh0);
|
||||
for (FaceHalfedgeIter fh_it = fh_iter(new_fh); fh_it; ++fh_it)
|
||||
{
|
||||
set_face_handle(fh_it, new_fh);
|
||||
}
|
||||
FaceHandle old_fh = face_handle(next_prev_heh);
|
||||
set_face_handle(heh1, old_fh);
|
||||
if (old_fh.is_valid() && face_handle(halfedge_handle(old_fh)) == new_fh)
|
||||
{//fh pointed to one of the halfedges now assigned to new_fh
|
||||
set_halfedge_handle(old_fh, heh1);
|
||||
}
|
||||
adjust_outgoing_halfedge(vh0);
|
||||
adjust_outgoing_halfedge(vh1);
|
||||
return heh0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::triangulate(FaceHandle _fh)
|
||||
{
|
||||
/*
|
||||
Split an arbitrary face into triangles by connecting
|
||||
each vertex of fh after its second to vh.
|
||||
|
||||
- fh will remain valid (it will become one of the
|
||||
triangles)
|
||||
- the halfedge handles of the new triangles will
|
||||
point to the old halfedges
|
||||
*/
|
||||
|
||||
HalfedgeHandle base_heh(halfedge_handle(_fh));
|
||||
VertexHandle start_vh = from_vertex_handle(base_heh);
|
||||
HalfedgeHandle next_heh(next_halfedge_handle(base_heh));
|
||||
|
||||
while (to_vertex_handle(next_halfedge_handle(next_heh)) != start_vh)
|
||||
{
|
||||
HalfedgeHandle next_next_heh(next_halfedge_handle(next_heh));
|
||||
|
||||
FaceHandle new_fh = new_face();
|
||||
set_halfedge_handle(new_fh, base_heh);
|
||||
|
||||
HalfedgeHandle new_heh = new_edge(to_vertex_handle(next_heh), start_vh);
|
||||
|
||||
set_next_halfedge_handle(base_heh, next_heh);
|
||||
set_next_halfedge_handle(next_heh, new_heh);
|
||||
set_next_halfedge_handle(new_heh, base_heh);
|
||||
|
||||
set_face_handle(base_heh, new_fh);
|
||||
set_face_handle(next_heh, new_fh);
|
||||
set_face_handle(new_heh, new_fh);
|
||||
|
||||
base_heh = opposite_halfedge_handle(new_heh);
|
||||
next_heh = next_next_heh;
|
||||
}
|
||||
set_halfedge_handle(_fh, base_heh); //the last face takes the handle _fh
|
||||
|
||||
set_next_halfedge_handle(base_heh, next_heh);
|
||||
set_next_halfedge_handle(next_halfedge_handle(next_heh), base_heh);
|
||||
|
||||
set_face_handle(base_heh, _fh);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::triangulate()
|
||||
{
|
||||
/* The iterators will stay valid, even though new faces are added,
|
||||
because they are now implemented index-based instead of
|
||||
pointer-based.
|
||||
*/
|
||||
FaceIter f_it(faces_begin()), f_end(faces_end());
|
||||
for (; f_it!=f_end; ++f_it)
|
||||
triangulate(f_it);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::split(FaceHandle fh, VertexHandle vh)
|
||||
{
|
||||
/*
|
||||
Split an arbitrary face into triangles by connecting
|
||||
each vertex of fh to vh.
|
||||
|
||||
- fh will remain valid (it will become one of the
|
||||
triangles)
|
||||
- the halfedge handles of the new triangles will
|
||||
point to the old halfeges
|
||||
*/
|
||||
|
||||
HalfedgeHandle hend = halfedge_handle(fh);
|
||||
HalfedgeHandle hh = next_halfedge_handle(hend);
|
||||
|
||||
HalfedgeHandle hold = new_edge(to_vertex_handle(hend), vh);
|
||||
|
||||
set_next_halfedge_handle(hend, hold);
|
||||
set_face_handle(hold, fh);
|
||||
|
||||
hold = opposite_halfedge_handle(hold);
|
||||
|
||||
while (hh != hend) {
|
||||
|
||||
HalfedgeHandle hnext = next_halfedge_handle(hh);
|
||||
|
||||
FaceHandle fnew = new_face();
|
||||
set_halfedge_handle(fnew, hh);
|
||||
|
||||
HalfedgeHandle hnew = new_edge(to_vertex_handle(hh), vh);
|
||||
|
||||
set_next_halfedge_handle(hnew, hold);
|
||||
set_next_halfedge_handle(hold, hh);
|
||||
set_next_halfedge_handle(hh, hnew);
|
||||
|
||||
set_face_handle(hnew, fnew);
|
||||
set_face_handle(hold, fnew);
|
||||
set_face_handle(hh, fnew);
|
||||
|
||||
hold = opposite_halfedge_handle(hnew);
|
||||
|
||||
hh = hnext;
|
||||
}
|
||||
|
||||
set_next_halfedge_handle(hold, hend);
|
||||
set_next_halfedge_handle(next_halfedge_handle(hend), hold);
|
||||
|
||||
set_face_handle(hold, fh);
|
||||
|
||||
set_halfedge_handle(vh, hold);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint PolyConnectivity::valence(VertexHandle _vh) const
|
||||
{
|
||||
uint count(0);
|
||||
for (ConstVertexVertexIter vv_it=cvv_iter(_vh); vv_it; ++vv_it)
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint PolyConnectivity::valence(FaceHandle _fh) const
|
||||
{
|
||||
uint count(0);
|
||||
for (ConstFaceVertexIter fv_it=cfv_iter(_fh); fv_it; ++fv_it)
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
}//namespace OpenMesh
|
||||
|
||||
513
Core/Mesh/PolyConnectivity.hh
Normal file
513
Core/Mesh/PolyConnectivity.hh
Normal file
@@ -0,0 +1,513 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2004 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_POLYCONNECTIVITY_HH
|
||||
#define OPENMESH_POLYCONNECTIVITY_HH
|
||||
|
||||
#include <OpenMesh/Core/Mesh/ArrayKernel.hh>
|
||||
#include <OpenMesh/Core/Mesh/IteratorsT.hh>
|
||||
#include <OpenMesh/Core/Mesh/CirculatorsT.hh>
|
||||
|
||||
namespace OpenMesh
|
||||
{
|
||||
|
||||
class PolyConnectivity : public ArrayKernel
|
||||
{
|
||||
public:
|
||||
/// \name Mesh Handles
|
||||
//@{
|
||||
/// Invalid handle
|
||||
static const VertexHandle InvalidVertexHandle;
|
||||
/// Invalid handle
|
||||
static const HalfedgeHandle InvalidHalfedgeHandle;
|
||||
/// Invalid handle
|
||||
static const EdgeHandle InvalidEdgeHandle;
|
||||
/// Invalid handle
|
||||
static const FaceHandle InvalidFaceHandle;
|
||||
//@}
|
||||
|
||||
typedef PolyConnectivity This;
|
||||
|
||||
//--- iterators ---
|
||||
|
||||
/** \name Mesh Iterators
|
||||
Refer to OpenMesh::Mesh::Iterators or \ref mesh_iterators for
|
||||
documentation.
|
||||
*/
|
||||
//@{
|
||||
/// Linear iterator
|
||||
typedef Iterators::VertexIterT<This> VertexIter;
|
||||
typedef Iterators::HalfedgeIterT<This> HalfedgeIter;
|
||||
typedef Iterators::EdgeIterT<This> EdgeIter;
|
||||
typedef Iterators::FaceIterT<This> FaceIter;
|
||||
|
||||
typedef Iterators::ConstVertexIterT<This> ConstVertexIter;
|
||||
typedef Iterators::ConstHalfedgeIterT<This> ConstHalfedgeIter;
|
||||
typedef Iterators::ConstEdgeIterT<This> ConstEdgeIter;
|
||||
typedef Iterators::ConstFaceIterT<This> ConstFaceIter;
|
||||
//@}
|
||||
|
||||
//--- circulators ---
|
||||
|
||||
/** \name Mesh Circulators
|
||||
Refer to OpenMesh::Mesh::Iterators or \ref mesh_iterators
|
||||
for documentation.
|
||||
*/
|
||||
//@{
|
||||
/// Circulator
|
||||
typedef Iterators::VertexVertexIterT<This> VertexVertexIter;
|
||||
typedef Iterators::VertexOHalfedgeIterT<This> VertexOHalfedgeIter;
|
||||
typedef Iterators::VertexIHalfedgeIterT<This> VertexIHalfedgeIter;
|
||||
typedef Iterators::VertexEdgeIterT<This> VertexEdgeIter;
|
||||
typedef Iterators::VertexFaceIterT<This> VertexFaceIter;
|
||||
typedef Iterators::FaceVertexIterT<This> FaceVertexIter;
|
||||
typedef Iterators::FaceHalfedgeIterT<This> FaceHalfedgeIter;
|
||||
typedef Iterators::FaceEdgeIterT<This> FaceEdgeIter;
|
||||
typedef Iterators::FaceFaceIterT<This> FaceFaceIter;
|
||||
|
||||
typedef Iterators::ConstVertexVertexIterT<This> ConstVertexVertexIter;
|
||||
typedef Iterators::ConstVertexOHalfedgeIterT<This> ConstVertexOHalfedgeIter;
|
||||
typedef Iterators::ConstVertexIHalfedgeIterT<This> ConstVertexIHalfedgeIter;
|
||||
typedef Iterators::ConstVertexEdgeIterT<This> ConstVertexEdgeIter;
|
||||
typedef Iterators::ConstVertexFaceIterT<This> ConstVertexFaceIter;
|
||||
typedef Iterators::ConstFaceVertexIterT<This> ConstFaceVertexIter;
|
||||
typedef Iterators::ConstFaceHalfedgeIterT<This> ConstFaceHalfedgeIter;
|
||||
typedef Iterators::ConstFaceEdgeIterT<This> ConstFaceEdgeIter;
|
||||
typedef Iterators::ConstFaceFaceIterT<This> ConstFaceFaceIter;
|
||||
//@}
|
||||
|
||||
// --- shortcuts
|
||||
|
||||
/** \name Typedef Shortcuts
|
||||
Provided for convenience only
|
||||
*/
|
||||
//@{
|
||||
/// Alias typedef
|
||||
typedef VertexHandle VHandle;
|
||||
typedef HalfedgeHandle HHandle;
|
||||
typedef EdgeHandle EHandle;
|
||||
typedef FaceHandle FHandle;
|
||||
|
||||
typedef VertexIter VIter;
|
||||
typedef HalfedgeIter HIter;
|
||||
typedef EdgeIter EIter;
|
||||
typedef FaceIter FIter;
|
||||
|
||||
typedef ConstVertexIter CVIter;
|
||||
typedef ConstHalfedgeIter CHIter;
|
||||
typedef ConstEdgeIter CEIter;
|
||||
typedef ConstFaceIter CFIter;
|
||||
|
||||
typedef VertexVertexIter VVIter;
|
||||
typedef VertexOHalfedgeIter VOHIter;
|
||||
typedef VertexIHalfedgeIter VIHIter;
|
||||
typedef VertexEdgeIter VEIter;
|
||||
typedef VertexFaceIter VFIter;
|
||||
typedef FaceVertexIter FVIter;
|
||||
typedef FaceHalfedgeIter FHIter;
|
||||
typedef FaceEdgeIter FEIter;
|
||||
typedef FaceFaceIter FFIter;
|
||||
|
||||
typedef ConstVertexVertexIter CVVIter;
|
||||
typedef ConstVertexOHalfedgeIter CVOHIter;
|
||||
typedef ConstVertexIHalfedgeIter CVIHIter;
|
||||
typedef ConstVertexEdgeIter CVEIter;
|
||||
typedef ConstVertexFaceIter CVFIter;
|
||||
typedef ConstFaceVertexIter CFVIter;
|
||||
typedef ConstFaceHalfedgeIter CFHIter;
|
||||
typedef ConstFaceEdgeIter CFEIter;
|
||||
typedef ConstFaceFaceIter CFFIter;
|
||||
//@}
|
||||
|
||||
public:
|
||||
|
||||
PolyConnectivity() {}
|
||||
virtual ~PolyConnectivity() {}
|
||||
|
||||
inline static bool is_triangles()
|
||||
{ return false; }
|
||||
|
||||
/** assign_connectivity() method. See ArrayKernel::assign_connectivity()
|
||||
for more details. */
|
||||
inline void assign_connectivity(const PolyConnectivity& _other)
|
||||
{ ArrayKernel::assign_connectivity(_other); }
|
||||
|
||||
/** \name Adding items to a mesh
|
||||
*/
|
||||
//@{
|
||||
/// Add a new vertex
|
||||
inline VertexHandle add_vertex()
|
||||
{ return new_vertex(); }
|
||||
|
||||
/// Add and connect a new face
|
||||
FaceHandle add_face(const std::vector<VertexHandle>& _vhandles)
|
||||
{ return add_face(&_vhandles.front(), _vhandles.size()); }
|
||||
|
||||
FaceHandle add_face(VertexHandle _vh0, VertexHandle _vh1, VertexHandle _vh2)
|
||||
{
|
||||
VertexHandle vhs[3] = { _vh0, _vh1, _vh2 };
|
||||
return add_face(vhs, 3);
|
||||
}
|
||||
|
||||
FaceHandle add_face(VertexHandle _vh0, VertexHandle _vh1, VertexHandle _vh2, VertexHandle _vh3)
|
||||
{
|
||||
VertexHandle vhs[4] = { _vh0, _vh1, _vh2, _vh3 };
|
||||
return add_face(vhs, 4);
|
||||
}
|
||||
|
||||
FaceHandle add_face(const VertexHandle* _vhandles, uint _vhs_size);
|
||||
//@}
|
||||
|
||||
/// \name Deleting mesh items and other connectivity/topology modifications
|
||||
//@{
|
||||
|
||||
/** Mark vertex and all incident edges and faces deleted.
|
||||
Items marked deleted will be removed by garbageCollection().
|
||||
\attention Needs the Attributes::Status attribute for vertices,
|
||||
edges and faces.
|
||||
*/
|
||||
void delete_vertex(VertexHandle _vh, bool _delete_isolated_vertices = true);
|
||||
|
||||
/** Mark edge (two opposite halfedges) and incident faces deleted.
|
||||
Resulting isolated vertices are marked deleted if
|
||||
_delete_isolated_vertices is true. Items marked deleted will be
|
||||
removed by garbageCollection().
|
||||
|
||||
\attention Needs the Attributes::Status attribute for vertices,
|
||||
edges and faces.
|
||||
*/
|
||||
void delete_edge(EdgeHandle _eh, bool _delete_isolated_vertices=true);
|
||||
|
||||
/** Delete face _fh and resulting degenerated empty halfedges as
|
||||
well. Resultling isolated vertices will be deleted if
|
||||
_delete_isolated_vertices is true.
|
||||
|
||||
\attention All item will only be marked to be deleted. They will
|
||||
actually be removed by calling garbage_collection().
|
||||
|
||||
\attention Needs the Attributes::Status attribute for vertices,
|
||||
edges and faces.
|
||||
*/
|
||||
void delete_face(FaceHandle _fh, bool _delete_isolated_vertices=true);
|
||||
|
||||
//@}
|
||||
|
||||
/** \name Begin and end iterators
|
||||
*/
|
||||
//@{
|
||||
|
||||
/// Begin iterator for vertices
|
||||
VertexIter vertices_begin()
|
||||
{ return VertexIter(*this, VertexHandle(0)); }
|
||||
/// Const begin iterator for vertices
|
||||
ConstVertexIter vertices_begin() const
|
||||
{ return ConstVertexIter(*this, VertexHandle(0)); }
|
||||
/// End iterator for vertices
|
||||
VertexIter vertices_end()
|
||||
{ return VertexIter(*this, VertexHandle(n_vertices())); }
|
||||
/// Const end iterator for vertices
|
||||
ConstVertexIter vertices_end() const
|
||||
{ return ConstVertexIter(*this, VertexHandle(n_vertices())); }
|
||||
|
||||
/// Begin iterator for halfedges
|
||||
HalfedgeIter halfedges_begin()
|
||||
{ return HalfedgeIter(*this, HalfedgeHandle(0)); }
|
||||
/// Const begin iterator for halfedges
|
||||
ConstHalfedgeIter halfedges_begin() const
|
||||
{ return ConstHalfedgeIter(*this, HalfedgeHandle(0)); }
|
||||
/// End iterator for halfedges
|
||||
HalfedgeIter halfedges_end()
|
||||
{ return HalfedgeIter(*this, HalfedgeHandle(n_halfedges())); }
|
||||
/// Const end iterator for halfedges
|
||||
ConstHalfedgeIter halfedges_end() const
|
||||
{ return ConstHalfedgeIter(*this, HalfedgeHandle(n_halfedges())); }
|
||||
|
||||
/// Begin iterator for edges
|
||||
EdgeIter edges_begin()
|
||||
{ return EdgeIter(*this, EdgeHandle(0)); }
|
||||
/// Const begin iterator for edges
|
||||
ConstEdgeIter edges_begin() const
|
||||
{ return ConstEdgeIter(*this, EdgeHandle(0)); }
|
||||
/// End iterator for edges
|
||||
EdgeIter edges_end()
|
||||
{ return EdgeIter(*this, EdgeHandle(n_edges())); }
|
||||
/// Const end iterator for edges
|
||||
ConstEdgeIter edges_end() const
|
||||
{ return ConstEdgeIter(*this, EdgeHandle(n_edges())); }
|
||||
|
||||
/// Begin iterator for faces
|
||||
FaceIter faces_begin()
|
||||
{ return FaceIter(*this, FaceHandle(0)); }
|
||||
/// Const begin iterator for faces
|
||||
ConstFaceIter faces_begin() const
|
||||
{ return ConstFaceIter(*this, FaceHandle(0)); }
|
||||
/// End iterator for faces
|
||||
FaceIter faces_end()
|
||||
{ return FaceIter(*this, FaceHandle(n_faces())); }
|
||||
/// Const end iterator for faces
|
||||
ConstFaceIter faces_end() const
|
||||
{ return ConstFaceIter(*this, FaceHandle(n_faces())); }
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
|
||||
/** \name Begin for skipping iterators
|
||||
*/
|
||||
//@{
|
||||
|
||||
/// Begin iterator for vertices
|
||||
VertexIter vertices_sbegin()
|
||||
{ return VertexIter(*this, VertexHandle(0), true); }
|
||||
/// Const begin iterator for vertices
|
||||
ConstVertexIter vertices_sbegin() const
|
||||
{ return ConstVertexIter(*this, VertexHandle(0), true); }
|
||||
|
||||
/// Begin iterator for halfedges
|
||||
HalfedgeIter halfedges_sbegin()
|
||||
{ return HalfedgeIter(*this, HalfedgeHandle(0), true); }
|
||||
/// Const begin iterator for halfedges
|
||||
ConstHalfedgeIter halfedges_sbegin() const
|
||||
{ return ConstHalfedgeIter(*this, HalfedgeHandle(0), true); }
|
||||
|
||||
/// Begin iterator for edges
|
||||
EdgeIter edges_sbegin()
|
||||
{ return EdgeIter(*this, EdgeHandle(0), true); }
|
||||
/// Const begin iterator for edges
|
||||
ConstEdgeIter edges_sbegin() const
|
||||
{ return ConstEdgeIter(*this, EdgeHandle(0), true); }
|
||||
|
||||
/// Begin iterator for faces
|
||||
FaceIter faces_sbegin()
|
||||
{ return FaceIter(*this, FaceHandle(0), true); }
|
||||
/// Const begin iterator for faces
|
||||
ConstFaceIter faces_sbegin() const
|
||||
{ return ConstFaceIter(*this, FaceHandle(0), true); }
|
||||
|
||||
//@}
|
||||
|
||||
//--- circulators ---
|
||||
|
||||
/** \name Vertex and Face circulators
|
||||
*/
|
||||
//@{
|
||||
|
||||
/// vertex - vertex circulator
|
||||
VertexVertexIter vv_iter(VertexHandle _vh) {
|
||||
return VertexVertexIter(*this, _vh); }
|
||||
/// vertex - incoming halfedge circulator
|
||||
VertexIHalfedgeIter vih_iter(VertexHandle _vh)
|
||||
{ return VertexIHalfedgeIter(*this, _vh); }
|
||||
/// vertex - outgoing halfedge circulator
|
||||
VertexOHalfedgeIter voh_iter(VertexHandle _vh)
|
||||
{ return VertexOHalfedgeIter(*this, _vh); }
|
||||
/// vertex - edge circulator
|
||||
VertexEdgeIter ve_iter(VertexHandle _vh)
|
||||
{ return VertexEdgeIter(*this, _vh); }
|
||||
/// vertex - face circulator
|
||||
VertexFaceIter vf_iter(VertexHandle _vh)
|
||||
{ return VertexFaceIter(*this, _vh); }
|
||||
|
||||
/// const vertex circulator
|
||||
ConstVertexVertexIter cvv_iter(VertexHandle _vh) const
|
||||
{ return ConstVertexVertexIter(*this, _vh); }
|
||||
/// const vertex - incoming halfedge circulator
|
||||
ConstVertexIHalfedgeIter cvih_iter(VertexHandle _vh) const
|
||||
{ return ConstVertexIHalfedgeIter(*this, _vh); }
|
||||
/// const vertex - outgoing halfedge circulator
|
||||
ConstVertexOHalfedgeIter cvoh_iter(VertexHandle _vh) const
|
||||
{ return ConstVertexOHalfedgeIter(*this, _vh); }
|
||||
/// const vertex - edge circulator
|
||||
ConstVertexEdgeIter cve_iter(VertexHandle _vh) const
|
||||
{ return ConstVertexEdgeIter(*this, _vh); }
|
||||
/// const vertex - face circulator
|
||||
ConstVertexFaceIter cvf_iter(VertexHandle _vh) const
|
||||
{ return ConstVertexFaceIter(*this, _vh); }
|
||||
|
||||
/// face - vertex circulator
|
||||
FaceVertexIter fv_iter(FaceHandle _fh)
|
||||
{ return FaceVertexIter(*this, _fh); }
|
||||
/// face - halfedge circulator
|
||||
FaceHalfedgeIter fh_iter(FaceHandle _fh)
|
||||
{ return FaceHalfedgeIter(*this, _fh); }
|
||||
/// face - edge circulator
|
||||
FaceEdgeIter fe_iter(FaceHandle _fh)
|
||||
{ return FaceEdgeIter(*this, _fh); }
|
||||
/// face - face circulator
|
||||
FaceFaceIter ff_iter(FaceHandle _fh)
|
||||
{ return FaceFaceIter(*this, _fh); }
|
||||
|
||||
/// const face - vertex circulator
|
||||
ConstFaceVertexIter cfv_iter(FaceHandle _fh) const
|
||||
{ return ConstFaceVertexIter(*this, _fh); }
|
||||
/// const face - halfedge circulator
|
||||
ConstFaceHalfedgeIter cfh_iter(FaceHandle _fh) const
|
||||
{ return ConstFaceHalfedgeIter(*this, _fh); }
|
||||
/// const face - edge circulator
|
||||
ConstFaceEdgeIter cfe_iter(FaceHandle _fh) const
|
||||
{ return ConstFaceEdgeIter(*this, _fh); }
|
||||
/// const face - face circulator
|
||||
ConstFaceFaceIter cff_iter(FaceHandle _fh) const
|
||||
{ return ConstFaceFaceIter(*this, _fh); }
|
||||
//@}
|
||||
|
||||
/** \name Boundary and manifold tests
|
||||
*/
|
||||
//@{
|
||||
bool is_boundary(HalfedgeHandle _heh) const
|
||||
{ return ArrayKernel::is_boundary(_heh); }
|
||||
|
||||
/** Is the edge _eh a boundary edge, i.e. is one of its halfedges
|
||||
a boundary halfege ? */
|
||||
bool is_boundary(EdgeHandle _eh) const
|
||||
{
|
||||
return (is_boundary(halfedge_handle(_eh, 0)) ||
|
||||
is_boundary(halfedge_handle(_eh, 1)));
|
||||
}
|
||||
/// Is vertex _vh a boundary vertex ?
|
||||
bool is_boundary(VertexHandle _vh) const
|
||||
{
|
||||
HalfedgeHandle heh(halfedge_handle(_vh));
|
||||
return (!(heh.is_valid() && face_handle(heh).is_valid()));
|
||||
}
|
||||
|
||||
/** Is face _fh at boundary, i.e. is one of its edges (or vertices)
|
||||
* a boundary edge?
|
||||
* \param _fh Check this face
|
||||
* \param _check_vertex If \c true, check the corner vertices of
|
||||
* the face, too.
|
||||
*/
|
||||
bool is_boundary(FaceHandle _fh, bool _check_vertex=false) const;
|
||||
/// Is (the mesh at) vertex _vh two-manifold ?
|
||||
bool is_manifold(VertexHandle _vh) const;
|
||||
//@}
|
||||
|
||||
// --- shortcuts ---
|
||||
|
||||
/// returns the face handle of the opposite halfedge
|
||||
inline FaceHandle opposite_face_handle(HalfedgeHandle _heh) const
|
||||
{ return face_handle(opposite_halfedge_handle(_heh)); }
|
||||
|
||||
// --- misc ---
|
||||
|
||||
/** Adjust outgoing halfedge handle for vertices, so that it is a
|
||||
boundary halfedge whenever possible.
|
||||
*/
|
||||
void adjust_outgoing_halfedge(VertexHandle _vh);
|
||||
/// Find halfedge from _vh0 to _vh1. Returns invalid handle if not found.
|
||||
HalfedgeHandle find_halfedge(VertexHandle _start_vh, VertexHandle _end_vh) const;
|
||||
/// Vertex valence
|
||||
uint valence(VertexHandle _vh) const;
|
||||
/// Face valence
|
||||
uint valence(FaceHandle _fh) const;
|
||||
|
||||
// --- connectivity operattions
|
||||
|
||||
/** Halfedge collapse: collapse the from-vertex of halfedge _heh
|
||||
into its to-vertex.
|
||||
|
||||
\attention Needs vertex/edge/face status attribute in order to
|
||||
delete the items that degenerate.
|
||||
|
||||
\note This function does not perform a garbage collection. It
|
||||
only marks degenerate items as deleted.
|
||||
|
||||
\attention A halfedge collapse may lead to topological inconsistencies.
|
||||
Therefore you should check this using is_collapse_ok().
|
||||
\TODO: implement is_collapse_ok() const for polygonal/triangle meshes
|
||||
*/
|
||||
void collapse(HalfedgeHandle _heh);
|
||||
/** return true if the this the only link between the faces adjacent to _eh.
|
||||
_eh is allowed to be boundary, in which case true is returned iff _eh is
|
||||
the only boundary edge of its ajdacent face.
|
||||
*/
|
||||
bool is_simple_link(EdgeHandle _eh) const;
|
||||
/** return true if _fh shares only one edge with all of its adjacent faces.
|
||||
Boundary is treated as one face, i.e., the function false if _fh has more
|
||||
than one boundary edge.
|
||||
*/
|
||||
bool is_simply_connected(FaceHandle _fh) const;
|
||||
/** Removes the edge _eh. Its adjacent faces are merged. _eh and one of the
|
||||
adjacent faces are set deleted. The handle of the remaining face is
|
||||
returned (InvalidFaceHandle is returned if _eh is a boundary edge).
|
||||
|
||||
\precondition is_simple_link(_eh). This ensures that there are no hole faces
|
||||
or isolated vertices appearing in result of the operation.
|
||||
|
||||
\attention Needs the Attributes::Status attribute for edges and faces.
|
||||
|
||||
\note This function does not perform a garbage collection. It
|
||||
only marks items as deleted.
|
||||
*/
|
||||
FaceHandle remove_edge(EdgeHandle _eh);
|
||||
/** Inverse of remove_edge. _eh should be the handle of the edge and the
|
||||
vertex and halfedge handles pointed by edge(_eh) should be valid.
|
||||
*/
|
||||
void reinsert_edge(EdgeHandle _eh);
|
||||
/** Inserts an edge between to_vh(_prev_heh) and from_vh(_next_heh).
|
||||
A new face is created started at heh0 of the inserted edge and
|
||||
its halfedges loop includes both _prev_heh and _next_heh. If an
|
||||
old face existed which includes the argument halfedges, it is
|
||||
split at the new edge. heh0 is returned.
|
||||
|
||||
\note assumes _prev_heh and _next_heh are either boundary or pointed
|
||||
to the same face
|
||||
*/
|
||||
HalfedgeHandle insert_edge(HalfedgeHandle _prev_heh, HalfedgeHandle _next_heh);
|
||||
|
||||
/// Face split (= 1-to-n split)
|
||||
void split(FaceHandle _fh, VertexHandle _vh);
|
||||
/// triangulate the face _fh
|
||||
void triangulate(FaceHandle _fh);
|
||||
/// triangulate the entire mesh
|
||||
void triangulate();
|
||||
|
||||
|
||||
/** \name Generic handle derefertiation.
|
||||
Calls the respective vertex(), halfedge(), edge(), face()
|
||||
method of the mesh kernel.
|
||||
*/
|
||||
//@{
|
||||
/// Get item from handle
|
||||
const Vertex& deref(VertexHandle _h) const { return vertex(_h); }
|
||||
Vertex& deref(VertexHandle _h) { return vertex(_h); }
|
||||
const Halfedge& deref(HalfedgeHandle _h) const { return halfedge(_h); }
|
||||
Halfedge& deref(HalfedgeHandle _h) { return halfedge(_h); }
|
||||
const Edge& deref(EdgeHandle _h) const { return edge(_h); }
|
||||
Edge& deref(EdgeHandle _h) { return edge(_h); }
|
||||
const Face& deref(FaceHandle _h) const { return face(_h); }
|
||||
Face& deref(FaceHandle _h) { return face(_h); }
|
||||
//@}
|
||||
|
||||
protected:
|
||||
/// Helper for halfedge collapse
|
||||
void collapse_edge(HalfedgeHandle _hh);
|
||||
/// Helper for halfedge collapse
|
||||
void collapse_loop(HalfedgeHandle _hh);
|
||||
};
|
||||
|
||||
}//namespace OpenMesh
|
||||
|
||||
#endif//OPENMESH_POLYCONNECTIVITY_HH
|
||||
265
Core/Mesh/PolyMeshT.cc
Normal file
265
Core/Mesh/PolyMeshT.cc
Normal file
@@ -0,0 +1,265 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS PolyMeshT - IMPLEMENTATION
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#define OPENMESH_POLYMESH_C
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/Mesh/PolyMeshT.hh>
|
||||
#include <OpenMesh/Core/Geometry/LoopSchemeMaskT.hh>
|
||||
#include <OpenMesh/Core/Utils/vector_cast.hh>
|
||||
#include <OpenMesh/Core/System/omstream.hh>
|
||||
#include <vector>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
//== IMPLEMENTATION ==========================================================
|
||||
|
||||
template <class Kernel>
|
||||
uint PolyMeshT<Kernel>::find_feature_edges(Scalar _angle_tresh)
|
||||
{
|
||||
assert(Kernel::has_edge_status());//this function needs edge status property
|
||||
uint n_feature_edges = 0;
|
||||
for (EdgeIter e_it = Kernel::edges_begin(); e_it != Kernel::edges_end(); ++e_it)
|
||||
{
|
||||
if (fabs(calc_dihedral_angle(e_it)) > _angle_tresh)
|
||||
{//note: could be optimized by comparing cos(dih_angle) vs. cos(_angle_tresh)
|
||||
status(e_it).set_feature(true);
|
||||
n_feature_edges++;
|
||||
}
|
||||
else
|
||||
{
|
||||
status(e_it).set_feature(false);
|
||||
}
|
||||
}
|
||||
return n_feature_edges;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <class Kernel>
|
||||
typename PolyMeshT<Kernel>::Normal
|
||||
PolyMeshT<Kernel>::
|
||||
calc_face_normal(FaceHandle _fh) const
|
||||
{
|
||||
assert(halfedge_handle(_fh).is_valid());
|
||||
ConstFaceVertexIter fv_it(cfv_iter(_fh));
|
||||
|
||||
const Point& p0(point(fv_it)); ++fv_it;
|
||||
const Point& p1(point(fv_it)); ++fv_it;
|
||||
const Point& p2(point(fv_it));
|
||||
|
||||
return calc_face_normal(p0, p1, p2);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <class Kernel>
|
||||
typename PolyMeshT<Kernel>::Normal
|
||||
PolyMeshT<Kernel>::
|
||||
calc_face_normal(const Point& _p0,
|
||||
const Point& _p1,
|
||||
const Point& _p2) const
|
||||
{
|
||||
#if 1
|
||||
// The OpenSG <Vector>::operator -= () does not support the type Point
|
||||
// as rhs. Therefore use vector_cast at this point!!!
|
||||
// Note! OpenSG distinguishes between Normal and Point!!!
|
||||
Normal p1p0(_p0); p1p0 -= vector_cast<Normal>(_p1);
|
||||
Normal p1p2(_p2); p1p2 -= vector_cast<Normal>(_p1);
|
||||
|
||||
Normal n = cross(p1p2, p1p0);
|
||||
Scalar norm = n.length();
|
||||
|
||||
// The expression ((n *= (1.0/norm)),n) is used because the OpenSG
|
||||
// vector class does not return self after component-wise
|
||||
// self-multiplication with a scalar!!!
|
||||
return (norm != Scalar(0)) ? ((n *= (Scalar(1)/norm)),n) : Normal(0,0,0);
|
||||
#else
|
||||
Point p1p0 = _p0; p1p0 -= _p1;
|
||||
Point p1p2 = _p2; p1p2 -= _p1;
|
||||
|
||||
Normal n = vector_cast<Normal>(cross(p1p2, p1p0));
|
||||
Scalar norm = n.length();
|
||||
|
||||
return (norm != 0.0) ? n *= (1.0/norm) : Normal(0,0,0);
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <class Kernel>
|
||||
void
|
||||
PolyMeshT<Kernel>::
|
||||
calc_face_centroid(FaceHandle _fh, Point& _pt) const
|
||||
{
|
||||
_pt.vectorize(0);
|
||||
uint valence = 0;
|
||||
for (ConstFaceVertexIter cfv_it = cfv_iter(_fh); cfv_it; ++cfv_it, ++valence)
|
||||
{
|
||||
_pt += point(cfv_it);
|
||||
}
|
||||
_pt /= valence;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <class Kernel>
|
||||
void
|
||||
PolyMeshT<Kernel>::
|
||||
update_normals()
|
||||
{
|
||||
if (Kernel::has_face_normals()) update_face_normals();
|
||||
if (Kernel::has_vertex_normals()) update_vertex_normals();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <class Kernel>
|
||||
void
|
||||
PolyMeshT<Kernel>::
|
||||
update_face_normals()
|
||||
{
|
||||
FaceIter f_it(Kernel::faces_begin()), f_end(Kernel::faces_end());
|
||||
|
||||
for (; f_it != f_end; ++f_it)
|
||||
set_normal(f_it.handle(), calc_face_normal(f_it.handle()));
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <class Kernel>
|
||||
typename PolyMeshT<Kernel>::Normal
|
||||
PolyMeshT<Kernel>::
|
||||
calc_vertex_normal(VertexHandle _vh) const
|
||||
{
|
||||
Normal n;
|
||||
calc_vertex_normal_fast(_vh,n);
|
||||
|
||||
Scalar norm = n.length();
|
||||
if (norm != 0.0) n *= (1.0/norm);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class Kernel>
|
||||
void PolyMeshT<Kernel>::
|
||||
calc_vertex_normal_fast(VertexHandle _vh, Normal& _n) const
|
||||
{
|
||||
_n.vectorize(0.0);
|
||||
for (ConstVertexFaceIter vf_it=cvf_iter(_vh); vf_it; ++vf_it)
|
||||
_n += normal(vf_it.handle());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class Kernel>
|
||||
void PolyMeshT<Kernel>::
|
||||
calc_vertex_normal_correct(VertexHandle _vh, Normal& _n) const
|
||||
{
|
||||
_n.vectorize(0.0);
|
||||
ConstVertexIHalfedgeIter cvih_it = cvih_iter(_vh);
|
||||
if (!cvih_it)
|
||||
{//don't crash on isolated vertices
|
||||
return;
|
||||
}
|
||||
Normal in_he_vec;
|
||||
calc_edge_vector(cvih_it, in_he_vec);
|
||||
for ( ; cvih_it; ++cvih_it)
|
||||
{//calculates the sector normal defined by cvih_it and adds it to _n
|
||||
if (is_boundary(cvih_it))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
HalfedgeHandle out_heh(next_halfedge_handle(cvih_it));
|
||||
Normal out_he_vec;
|
||||
calc_edge_vector(out_heh, out_he_vec);
|
||||
_n += cross(in_he_vec, out_he_vec);//sector area is taken into account
|
||||
in_he_vec = out_he_vec;
|
||||
in_he_vec *= -1;//change the orientation
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class Kernel>
|
||||
void PolyMeshT<Kernel>::
|
||||
calc_vertex_normal_loop(VertexHandle _vh, Normal& _n) const
|
||||
{
|
||||
static const LoopSchemeMaskDouble& loop_scheme_mask__ =
|
||||
LoopSchemeMaskDoubleSingleton::Instance();
|
||||
|
||||
Normal t_v(0.0,0.0,0.0), t_w(0.0,0.0,0.0);
|
||||
unsigned int vh_val = valence(_vh);
|
||||
unsigned int i = 0;
|
||||
for (ConstVertexOHalfedgeIter cvoh_it = cvoh_iter(_vh); cvoh_it; ++cvoh_it, ++i)
|
||||
{
|
||||
VertexHandle r1_v(to_vertex_handle(cvoh_it));
|
||||
t_v += (typename Point::value_type)(loop_scheme_mask__.tang0_weight(vh_val, i))*point(r1_v);
|
||||
t_w += (typename Point::value_type)(loop_scheme_mask__.tang1_weight(vh_val, i))*point(r1_v);
|
||||
}
|
||||
_n = cross(t_w, t_v);//hack: should be cross(t_v, t_w), but then the normals are reversed?
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <class Kernel>
|
||||
void
|
||||
PolyMeshT<Kernel>::
|
||||
update_vertex_normals()
|
||||
{
|
||||
VertexIter v_it(Kernel::vertices_begin()), v_end(Kernel::vertices_end());
|
||||
|
||||
for (; v_it!=v_end; ++v_it)
|
||||
set_normal(v_it.handle(), calc_vertex_normal(v_it.handle()));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
434
Core/Mesh/PolyMeshT.hh
Normal file
434
Core/Mesh/PolyMeshT.hh
Normal file
@@ -0,0 +1,434 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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: 2983 $
|
||||
// $Date: 2008-09-22 17:13:19 +0200 (Mo, 22. Sep 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS PolyMeshT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_POLYMESHT_HH
|
||||
#define OPENMESH_POLYMESHT_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Geometry/MathDefs.hh>
|
||||
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
|
||||
#include <vector>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \class PolyMeshT PolyMeshT.hh <OpenMesh/Mesh/PolyMeshT.hh>
|
||||
|
||||
Base type for a polygonal mesh.
|
||||
|
||||
This is the base class for a polygonal mesh. It is parameterized
|
||||
by a mesh kernel that is given as a template argument. This class
|
||||
inherits all methods from its mesh kernel.
|
||||
|
||||
\param Kernel: template argument for the mesh kernel
|
||||
\note You should use the predefined mesh-kernel combinations in
|
||||
\ref mesh_types_group
|
||||
\see \ref mesh_type
|
||||
*/
|
||||
|
||||
template <class Kernel>
|
||||
class PolyMeshT : public Kernel
|
||||
{
|
||||
public:
|
||||
|
||||
/// Self type. Used to specify iterators/circulators.
|
||||
typedef PolyMeshT<Kernel> This;
|
||||
//--- item types ---
|
||||
|
||||
//@{
|
||||
/// Determine whether this is a PolyMeshT or TriMeshT
|
||||
enum { IsPolyMesh = 1 };
|
||||
enum { IsTriMesh = 0 };
|
||||
static bool is_polymesh() { return true; }
|
||||
static bool is_trimesh() { return false; }
|
||||
//@}
|
||||
|
||||
/// \name Mesh Items
|
||||
//@{
|
||||
/// Scalar type
|
||||
typedef typename Kernel::Scalar Scalar;
|
||||
/// Coordinate type
|
||||
typedef typename Kernel::Point Point;
|
||||
/// Normal type
|
||||
typedef typename Kernel::Normal Normal;
|
||||
/// Color type
|
||||
typedef typename Kernel::Color Color;
|
||||
/// TexCoord1D type
|
||||
typedef typename Kernel::TexCoord1D TexCoord1D;
|
||||
/// TexCoord2D type
|
||||
typedef typename Kernel::TexCoord2D TexCoord2D;
|
||||
/// TexCoord3D type
|
||||
typedef typename Kernel::TexCoord3D TexCoord3D;
|
||||
/// Vertex type
|
||||
typedef typename Kernel::Vertex Vertex;
|
||||
/// Halfedge type
|
||||
typedef typename Kernel::Halfedge Halfedge;
|
||||
/// Edge type
|
||||
typedef typename Kernel::Edge Edge;
|
||||
/// Face type
|
||||
typedef typename Kernel::Face Face;
|
||||
//@}
|
||||
|
||||
//--- handle types ---
|
||||
|
||||
/// Handle for referencing the corresponding item
|
||||
typedef typename Kernel::VertexHandle VertexHandle;
|
||||
typedef typename Kernel::HalfedgeHandle HalfedgeHandle;
|
||||
typedef typename Kernel::EdgeHandle EdgeHandle;
|
||||
typedef typename Kernel::FaceHandle FaceHandle;
|
||||
|
||||
|
||||
|
||||
typedef typename Kernel::VertexIter VertexIter;
|
||||
typedef typename Kernel::HalfedgeIter HalfedgeIter;
|
||||
typedef typename Kernel::EdgeIter EdgeIter;
|
||||
typedef typename Kernel::FaceIter FaceIter;
|
||||
|
||||
typedef typename Kernel::ConstVertexIter ConstVertexIter;
|
||||
typedef typename Kernel::ConstHalfedgeIter ConstHalfedgeIter;
|
||||
typedef typename Kernel::ConstEdgeIter ConstEdgeIter;
|
||||
typedef typename Kernel::ConstFaceIter ConstFaceIter;
|
||||
//@}
|
||||
|
||||
//--- circulators ---
|
||||
|
||||
/** \name Mesh Circulators
|
||||
Refer to OpenMesh::Mesh::Iterators or \ref mesh_iterators
|
||||
for documentation.
|
||||
*/
|
||||
//@{
|
||||
/// Circulator
|
||||
typedef typename Kernel::VertexVertexIter VertexVertexIter;
|
||||
typedef typename Kernel::VertexOHalfedgeIter VertexOHalfedgeIter;
|
||||
typedef typename Kernel::VertexIHalfedgeIter VertexIHalfedgeIter;
|
||||
typedef typename Kernel::VertexEdgeIter VertexEdgeIter;
|
||||
typedef typename Kernel::VertexFaceIter VertexFaceIter;
|
||||
typedef typename Kernel::FaceVertexIter FaceVertexIter;
|
||||
typedef typename Kernel::FaceHalfedgeIter FaceHalfedgeIter;
|
||||
typedef typename Kernel::FaceEdgeIter FaceEdgeIter;
|
||||
typedef typename Kernel::FaceFaceIter FaceFaceIter;
|
||||
|
||||
typedef typename Kernel::ConstVertexVertexIter ConstVertexVertexIter;
|
||||
typedef typename Kernel::ConstVertexOHalfedgeIter ConstVertexOHalfedgeIter;
|
||||
typedef typename Kernel::ConstVertexIHalfedgeIter ConstVertexIHalfedgeIter;
|
||||
typedef typename Kernel::ConstVertexEdgeIter ConstVertexEdgeIter;
|
||||
typedef typename Kernel::ConstVertexFaceIter ConstVertexFaceIter;
|
||||
typedef typename Kernel::ConstFaceVertexIter ConstFaceVertexIter;
|
||||
typedef typename Kernel::ConstFaceHalfedgeIter ConstFaceHalfedgeIter;
|
||||
typedef typename Kernel::ConstFaceEdgeIter ConstFaceEdgeIter;
|
||||
typedef typename Kernel::ConstFaceFaceIter ConstFaceFaceIter;
|
||||
//@}
|
||||
|
||||
|
||||
// --- constructor/destructor
|
||||
PolyMeshT() {}
|
||||
virtual ~PolyMeshT() {}
|
||||
|
||||
/** Uses default copy and assignment operator.
|
||||
Use them to assign two meshes of \b equal type.
|
||||
If the mesh types vary, use PolyMeshT::assign() instead. */
|
||||
|
||||
// --- creation ---
|
||||
inline VertexHandle new_vertex()
|
||||
{ return Kernel::new_vertex(); }
|
||||
|
||||
inline VertexHandle new_vertex(const Point& _p)
|
||||
{
|
||||
VertexHandle vh(Kernel::new_vertex());
|
||||
set_point(vh, _p);
|
||||
return vh;
|
||||
}
|
||||
|
||||
inline VertexHandle add_vertex(const Point& _p)
|
||||
{ return new_vertex(_p); }
|
||||
|
||||
// --- normal vectors ---
|
||||
|
||||
/** \name Normal vector computation
|
||||
*/
|
||||
//@{
|
||||
|
||||
/** Calls update_face_normals() and update_vertex_normals() if
|
||||
these normals (i.e. the properties) exist */
|
||||
void update_normals();
|
||||
|
||||
/// Update normal for face _fh
|
||||
void update_normal(FaceHandle _fh)
|
||||
{ set_normal(_fh, calc_face_normal(_fh)); }
|
||||
|
||||
/** Update normal vectors for all faces.
|
||||
\attention Needs the Attributes::Normal attribute for faces. */
|
||||
void update_face_normals();
|
||||
|
||||
/** Calculate normal vector for face _fh. */
|
||||
Normal calc_face_normal(FaceHandle _fh) const;
|
||||
|
||||
/** Calculate normal vector for face (_p0, _p1, _p2). */
|
||||
Normal calc_face_normal(const Point& _p0, const Point& _p1,
|
||||
const Point& _p2) const;
|
||||
// calculates the average of the vertices defining _fh
|
||||
void calc_face_centroid(FaceHandle _fh, Point& _pt) const;
|
||||
/// Update normal for vertex _vh
|
||||
void update_normal(VertexHandle _vh)
|
||||
{ set_normal(_vh, calc_vertex_normal(_vh)); }
|
||||
|
||||
/** Update normal vectors for all vertices. \attention Needs the
|
||||
Attributes::Normal attribute for faces and vertices. */
|
||||
void update_vertex_normals();
|
||||
|
||||
/** Calculate normal vector for vertex _vh by averaging normals
|
||||
of adjacent faces. Face normals have to be computed first.
|
||||
\attention Needs the Attributes::Normal attribute for faces. */
|
||||
Normal calc_vertex_normal(VertexHandle _vh) const;
|
||||
|
||||
/** Different methods for calculation of the normal at _vh:
|
||||
- -"-_fast - the default one - the same as calc vertex_normal()
|
||||
- needs the Attributes::Normal attribute for faces
|
||||
- -"-_correct - works properly for non-triangular meshes
|
||||
- does not need any attributes
|
||||
- -"-_loop - calculates loop surface normals
|
||||
- does not need any attributes */
|
||||
void calc_vertex_normal_fast(VertexHandle _vh, Normal& _n) const;
|
||||
void calc_vertex_normal_correct(VertexHandle _vh, Normal& _n) const;
|
||||
void calc_vertex_normal_loop(VertexHandle _vh, Normal& _n) const;
|
||||
|
||||
|
||||
//@}
|
||||
|
||||
// --- Geometry API - still in development ---
|
||||
|
||||
/** Calculates the edge vector as the vector defined by
|
||||
the halfedge with id #0 (see below) */
|
||||
void calc_edge_vector(EdgeHandle _eh, Normal& _edge_vec) const
|
||||
{ calc_edge_vector(halfedge_handle(_eh,0), _edge_vec); }
|
||||
|
||||
/** Calculates the edge vector as the difference of the
|
||||
the points defined by to_vertex_handle() and from_vertex_handle() */
|
||||
void calc_edge_vector(HalfedgeHandle _heh, Normal& _edge_vec) const
|
||||
{
|
||||
_edge_vec = point(to_vertex_handle(_heh));
|
||||
_edge_vec -= point(from_vertex_handle(_heh));
|
||||
}
|
||||
|
||||
// Calculates the length of the edge _eh
|
||||
Scalar calc_edge_length(EdgeHandle _eh) const
|
||||
{ return calc_edge_length(halfedge_handle(_eh,0)); }
|
||||
|
||||
/** Calculates the length of the edge _heh
|
||||
*/
|
||||
Scalar calc_edge_length(HalfedgeHandle _heh) const
|
||||
{ return (Scalar)sqrt(calc_edge_sqr_length(_heh)); }
|
||||
|
||||
Scalar calc_edge_sqr_length(EdgeHandle _eh) const
|
||||
{ return calc_edge_sqr_length(halfedge_handle(_eh,0)); }
|
||||
|
||||
Scalar calc_edge_sqr_length(HalfedgeHandle _heh) const
|
||||
{
|
||||
Normal edge_vec;
|
||||
calc_edge_vector(_heh, edge_vec);
|
||||
return edge_vec.sqrnorm();
|
||||
}
|
||||
|
||||
/** defines a consistent representation of a sector geometry:
|
||||
the halfedge _in_heh defines the sector orientation
|
||||
the vertex pointed by _in_heh defines the sector center
|
||||
_vec0 and _vec1 are resp. the first and the second vectors defining the sector */
|
||||
void calc_sector_vectors(HalfedgeHandle _in_heh, Normal& _vec0, Normal& _vec1) const
|
||||
{
|
||||
calc_edge_vector(next_halfedge_handle(_in_heh), _vec0);//p2 - p1
|
||||
calc_edge_vector(opposite_halfedge_handle(_in_heh), _vec1);//p0 - p1
|
||||
}
|
||||
|
||||
/** calculates the sector angle.\n
|
||||
* The vertex pointed by _in_heh defines the sector center
|
||||
* The angle will be calculated between the given halfedge and the next halfedge.\n
|
||||
* Seen from the center vertex this will be the next halfedge in clockwise direction.\n
|
||||
NOTE: only boundary concave sectors are treated correctly */
|
||||
Scalar calc_sector_angle(HalfedgeHandle _in_heh) const
|
||||
{
|
||||
Normal v0, v1;
|
||||
calc_sector_vectors(_in_heh, v0, v1);
|
||||
Scalar denom = v0.norm()*v1.norm();
|
||||
if (is_zero(denom))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Scalar cos_a = (v0 | v1) / denom;
|
||||
if (is_boundary(_in_heh))
|
||||
{//determine if the boundary sector is concave or convex
|
||||
FaceHandle fh(face_handle(opposite_halfedge_handle(_in_heh)));
|
||||
Normal f_n(calc_face_normal(fh));//this normal is (for convex fh) OK
|
||||
Scalar sign_a = dot(cross(v0, v1), f_n);
|
||||
return angle(cos_a, sign_a);
|
||||
}
|
||||
else
|
||||
{
|
||||
return acos(sane_aarg(cos_a));
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the cos and the sin of angle <(_in_heh,next_halfedge(_in_heh))
|
||||
/*
|
||||
void calc_sector_angle_cos_sin(HalfedgeHandle _in_heh, Scalar& _cos_a, Scalar& _sin_a) const
|
||||
{
|
||||
Normal in_vec, out_vec;
|
||||
calc_edge_vector(_in_heh, in_vec);
|
||||
calc_edge_vector(next_halfedge_handle(_in_heh), out_vec);
|
||||
Scalar denom = in_vec.norm()*out_vec.norm();
|
||||
if (is_zero(denom))
|
||||
{
|
||||
_cos_a = 1;
|
||||
_sin_a = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_cos_a = dot(in_vec, out_vec)/denom;
|
||||
_sin_a = cross(in_vec, out_vec).norm()/denom;
|
||||
}
|
||||
}
|
||||
*/
|
||||
/** calculates the normal (non-normalized) of the face sector defined by
|
||||
the angle <(_in_heh,next_halfedge(_in_heh)) */
|
||||
void calc_sector_normal(HalfedgeHandle _in_heh, Normal& _sector_normal) const
|
||||
{
|
||||
Normal vec0, vec1;
|
||||
calc_sector_vectors(_in_heh, vec0, vec1);
|
||||
_sector_normal = cross(vec0, vec1);//(p2-p1)^(p0-p1)
|
||||
}
|
||||
|
||||
/** calculates the area of the face sector defined by
|
||||
the angle <(_in_heh,next_halfedge(_in_heh))
|
||||
NOTE: special cases (e.g. concave sectors) are not handled correctly */
|
||||
Scalar calc_sector_area(HalfedgeHandle _in_heh) const
|
||||
{
|
||||
Normal sector_normal;
|
||||
calc_sector_normal(_in_heh, sector_normal);
|
||||
return sector_normal.norm()/2;
|
||||
}
|
||||
|
||||
/** calculates the dihedral angle on the halfedge _heh
|
||||
\attention Needs the Attributes::Normal attribute for faces */
|
||||
Scalar calc_dihedral_angle_fast(HalfedgeHandle _heh) const
|
||||
{
|
||||
CHECK(Kernel::has_face_normals());
|
||||
if (is_boundary(edge_handle(_heh)))
|
||||
{//the dihedral angle at a boundary edge is 0
|
||||
return 0;
|
||||
}
|
||||
const Normal& n0 = normal(face_handle(_heh));
|
||||
const Normal& n1 = normal(face_handle(opposite_halfedge_handle(_heh)));
|
||||
Normal he;
|
||||
calc_edge_vector(_heh, he);
|
||||
Scalar da_cos = dot(n0, n1);
|
||||
//should be normalized, but we need only the sign
|
||||
Scalar da_sin_sign = dot(cross(n0, n1), he);
|
||||
return angle(da_cos, da_sin_sign);
|
||||
}
|
||||
|
||||
/** calculates the dihedral angle on the edge _eh
|
||||
\attention Needs the Attributes::Normal attribute for faces */
|
||||
Scalar calc_dihedral_angle_fast(EdgeHandle _eh) const
|
||||
{ return calc_dihedral_angle_fast(halfedge_handle(_eh,0)); }
|
||||
|
||||
// calculates the dihedral angle on the halfedge _heh
|
||||
Scalar calc_dihedral_angle(HalfedgeHandle _heh) const
|
||||
{
|
||||
if (is_boundary(edge_handle(_heh)))
|
||||
{//the dihedral angle at a boundary edge is 0
|
||||
return 0;
|
||||
}
|
||||
Normal n0, n1, he;
|
||||
calc_sector_normal(_heh, n0);
|
||||
calc_sector_normal(opposite_halfedge_handle(_heh), n1);
|
||||
calc_edge_vector(_heh, he);
|
||||
Scalar denom = n0.norm()*n1.norm();
|
||||
if (denom == Scalar(0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Scalar da_cos = dot(n0, n1)/denom;
|
||||
//should be normalized, but we need only the sign
|
||||
Scalar da_sin_sign = dot(cross(n0, n1), he);
|
||||
return angle(da_cos, da_sin_sign);
|
||||
}
|
||||
|
||||
// calculates the dihedral angle on the edge _eh
|
||||
Scalar calc_dihedral_angle(EdgeHandle _eh) const
|
||||
{ return calc_dihedral_angle(halfedge_handle(_eh,0)); }
|
||||
|
||||
/** tags an edge as a feature if its dihedral angle is larger than _angle_tresh
|
||||
returns the number of the found feature edges, requires edge_status property*/
|
||||
uint find_feature_edges(Scalar _angle_tresh = OpenMesh::deg_to_rad(44.0));
|
||||
// --- misc ---
|
||||
|
||||
/// Face split (= 1-to-n split)
|
||||
inline void split(FaceHandle _fh, const Point& _p)
|
||||
{ Kernel::split(_fh, add_vertex(_p)); }
|
||||
|
||||
inline void split(FaceHandle _fh, VertexHandle _vh)
|
||||
{ Kernel::split(_fh, _vh); }
|
||||
|
||||
inline void split(EdgeHandle _eh, const Point& _p)
|
||||
{ Kernel::split(_eh, add_vertex(_p)); }
|
||||
|
||||
inline void split(EdgeHandle _eh, VertexHandle _vh)
|
||||
{ Kernel::split(_eh, _vh); }
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_POLYMESH_C)
|
||||
# define OPENMESH_POLYMESH_TEMPLATES
|
||||
# include "PolyMeshT.cc"
|
||||
#endif
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_POLYMESHT_HH defined
|
||||
//=============================================================================
|
||||
89
Core/Mesh/PolyMesh_ArrayKernelT.hh
Normal file
89
Core/Mesh/PolyMesh_ArrayKernelT.hh
Normal file
@@ -0,0 +1,89 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS PolyMesh_ArrayKernelT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_POLY_MESH_ARRAY_KERNEL_HH
|
||||
#define OPENMESH_POLY_MESH_ARRAY_KERNEL_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
|
||||
#include <OpenMesh/Core/Mesh/Traits.hh>
|
||||
#include <OpenMesh/Core/Mesh/FinalMeshItemsT.hh>
|
||||
#include <OpenMesh/Core/Mesh/AttribKernelT.hh>
|
||||
#include <OpenMesh/Core/Mesh/PolyMeshT.hh>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/// Helper class to build a PolyMesh-type
|
||||
template <class Traits>
|
||||
struct PolyMesh_ArrayKernel_GeneratorT
|
||||
{
|
||||
typedef FinalMeshItemsT<Traits, false> MeshItems;
|
||||
typedef AttribKernelT<MeshItems, PolyConnectivity> AttribKernel;
|
||||
typedef PolyMeshT<AttribKernel> Mesh;
|
||||
};
|
||||
|
||||
|
||||
/** \class PolyMesh_ArrayKernelT PolyMesh_ArrayKernelT.hh <OpenMesh/Mesh/Types/PolyMesh_ArrayKernelT.hh>
|
||||
|
||||
\ingroup mesh_types_group
|
||||
Polygonal mesh based on the ArrayKernel.
|
||||
\see OpenMesh::PolyMeshT
|
||||
\see OpenMesh::ArrayKernel
|
||||
*/
|
||||
template <class Traits = DefaultTraits>
|
||||
class PolyMesh_ArrayKernelT
|
||||
: public PolyMesh_ArrayKernel_GeneratorT<Traits>::Mesh
|
||||
{};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_POLY_MESH_ARRAY_KERNEL_HH
|
||||
//=============================================================================
|
||||
158
Core/Mesh/Status.hh
Normal file
158
Core/Mesh/Status.hh
Normal file
@@ -0,0 +1,158 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS Status
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_ATTRIBUTE_STATUS_HH
|
||||
#define OPENMESH_ATTRIBUTE_STATUS_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
namespace Attributes {
|
||||
|
||||
|
||||
//== CLASS DEFINITION ========================================================
|
||||
|
||||
|
||||
/** Status bits used by the Status class.
|
||||
* \see OpenMesh::Attributes::StatusInfo
|
||||
*/
|
||||
enum StatusBits {
|
||||
|
||||
DELETED = 1, ///< Item has been deleted
|
||||
LOCKED = 2, ///< Item is locked.
|
||||
SELECTED = 4, ///< Item is selected.
|
||||
HIDDEN = 8, ///< Item is hidden.
|
||||
FEATURE = 16, ///< Item is a feature or belongs to a feature.
|
||||
TAGGED = 32, ///< Item is tagged.
|
||||
TAGGED2 = 64, ///< Alternate bit for tagging an item.
|
||||
UNUSED = 128 ///<
|
||||
};
|
||||
|
||||
|
||||
/** \class StatusInfo Status.hh <OpenMesh/Attributes/Status.hh>
|
||||
*
|
||||
* Add status information to a base class.
|
||||
*
|
||||
* \see StatusBits
|
||||
*/
|
||||
class StatusInfo
|
||||
{
|
||||
public:
|
||||
|
||||
typedef unsigned int value_type;
|
||||
|
||||
StatusInfo() : status_(0) {}
|
||||
|
||||
/// is deleted ?
|
||||
bool deleted() const { return is_bit_set(DELETED); }
|
||||
/// set deleted
|
||||
void set_deleted(bool _b) { change_bit(DELETED, _b); }
|
||||
|
||||
|
||||
/// is locked ?
|
||||
bool locked() const { return is_bit_set(LOCKED); }
|
||||
/// set locked
|
||||
void set_locked(bool _b) { change_bit(LOCKED, _b); }
|
||||
|
||||
|
||||
/// is selected ?
|
||||
bool selected() const { return is_bit_set(SELECTED); }
|
||||
/// set selected
|
||||
void set_selected(bool _b) { change_bit(SELECTED, _b); }
|
||||
|
||||
|
||||
/// is hidden ?
|
||||
bool hidden() const { return is_bit_set(HIDDEN); }
|
||||
/// set hidden
|
||||
void set_hidden(bool _b) { change_bit(HIDDEN, _b); }
|
||||
|
||||
|
||||
/// is feature ?
|
||||
bool feature() const { return is_bit_set(FEATURE); }
|
||||
/// set feature
|
||||
void set_feature(bool _b) { change_bit(FEATURE, _b); }
|
||||
|
||||
|
||||
/// is tagged ?
|
||||
bool tagged() const { return is_bit_set(TAGGED); }
|
||||
/// set tagged
|
||||
void set_tagged(bool _b) { change_bit(TAGGED, _b); }
|
||||
|
||||
|
||||
/// is tagged2 ? This is just one more tag info.
|
||||
bool tagged2() const { return is_bit_set(TAGGED2); }
|
||||
/// set tagged
|
||||
void set_tagged2(bool _b) { change_bit(TAGGED2, _b); }
|
||||
|
||||
|
||||
/// return whole status
|
||||
unsigned int bits() const { return status_; }
|
||||
/// set whole status at once
|
||||
void set_bits(unsigned int _bits) { status_ = _bits; }
|
||||
|
||||
|
||||
/// is a certain bit set ?
|
||||
bool is_bit_set(unsigned int _s) const { return (status_ & _s) > 0; }
|
||||
/// set a certain bit
|
||||
void set_bit(unsigned int _s) { status_ |= _s; }
|
||||
/// unset a certain bit
|
||||
void unset_bit(unsigned int _s) { status_ &= ~_s; }
|
||||
/// set or unset a certain bit
|
||||
void change_bit(unsigned int _s, bool _b) {
|
||||
if (_b) status_ |= _s; else status_ &= ~_s; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
value_type status_;
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace Attributes
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_ATTRIBUTE_STATUS_HH defined
|
||||
//=============================================================================
|
||||
227
Core/Mesh/Traits.hh
Normal file
227
Core/Mesh/Traits.hh
Normal file
@@ -0,0 +1,227 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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: 3794 $
|
||||
// $Date: 2008-11-25 19:25:02 +0100 (Di, 25. Nov 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** \file Core/Mesh/Traits.hh
|
||||
This file defines the default traits and some convenience macros.
|
||||
*/
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS Traits
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_TRAITS_HH
|
||||
#define OPENMESH_TRAITS_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Geometry/VectorT.hh>
|
||||
#include <OpenMesh/Core/Mesh/Attributes.hh>
|
||||
#include <OpenMesh/Core/Mesh/Handles.hh>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/// Macro for defining the vertex attributes. See \ref mesh_type.
|
||||
#define VertexAttributes(_i) enum { VertexAttributes = _i }
|
||||
|
||||
/// Macro for defining the halfedge attributes. See \ref mesh_type.
|
||||
#define HalfedgeAttributes(_i) enum { HalfedgeAttributes = _i }
|
||||
|
||||
/// Macro for defining the edge attributes. See \ref mesh_type.
|
||||
#define EdgeAttributes(_i) enum { EdgeAttributes = _i }
|
||||
|
||||
/// Macro for defining the face attributes. See \ref mesh_type.
|
||||
#define FaceAttributes(_i) enum { FaceAttributes = _i }
|
||||
|
||||
/// Macro for defining the vertex traits. See \ref mesh_type.
|
||||
#define VertexTraits \
|
||||
template <class Base, class Refs> struct VertexT : public Base
|
||||
|
||||
/// Macro for defining the halfedge traits. See \ref mesh_type.
|
||||
#define HalfedgeTraits \
|
||||
template <class Base, class Refs> struct HalfedgeT : public Base
|
||||
|
||||
/// Macro for defining the edge traits. See \ref mesh_type.
|
||||
#define EdgeTraits \
|
||||
template <class Base, class Refs> struct EdgeT : public Base
|
||||
|
||||
/// Macro for defining the face traits. See \ref mesh_type.
|
||||
#define FaceTraits \
|
||||
template <class Base, class Refs> struct FaceT : public Base
|
||||
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \class DefaultTraits Traits.hh <OpenMesh/Mesh/Traits.hh>
|
||||
|
||||
Base class for all traits. All user traits should be derived from
|
||||
this class. You may enrich all basic items by additional
|
||||
properties or define one or more of the types \c Point, \c Normal,
|
||||
\c TexCoord, or \c Color.
|
||||
|
||||
\see The Mesh docu section on \ref mesh_type.
|
||||
\see Traits.hh for a list of macros for traits classes.
|
||||
*/
|
||||
struct DefaultTraits
|
||||
{
|
||||
/// The default coordinate type is OpenMesh::Vec3f.
|
||||
typedef Vec3f Point;
|
||||
|
||||
/// The default normal type is OpenMesh::Vec3f.
|
||||
typedef Vec3f Normal;
|
||||
|
||||
/// The default 1D texture coordinate type is float.
|
||||
typedef float TexCoord1D;
|
||||
/// The default 2D texture coordinate type is OpenMesh::Vec2f.
|
||||
typedef Vec2f TexCoord2D;
|
||||
/// The default 3D texture coordinate type is OpenMesh::Vec3f.
|
||||
typedef Vec3f TexCoord3D;
|
||||
|
||||
/// The default texture index type
|
||||
typedef int TextureIndex;
|
||||
|
||||
/// The default color type is OpenMesh::Vec3uc.
|
||||
typedef Vec3uc Color;
|
||||
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
VertexTraits {};
|
||||
HalfedgeTraits {};
|
||||
EdgeTraits {};
|
||||
FaceTraits {};
|
||||
#endif
|
||||
|
||||
VertexAttributes(0);
|
||||
HalfedgeAttributes(Attributes::PrevHalfedge);
|
||||
EdgeAttributes(0);
|
||||
FaceAttributes(0);
|
||||
};
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** Helper class to merge two mesh traits.
|
||||
* \internal
|
||||
*
|
||||
* With the help of this class it's possible to merge two mesh traits.
|
||||
* Whereby \c _Traits1 overrides equally named symbols of \c _Traits2.
|
||||
*
|
||||
* For your convenience use the provided defines \c OM_Merge_Traits
|
||||
* and \c OM_Merge_Traits_In_Template instead.
|
||||
*
|
||||
* \see OM_Merge_Traits, OM_Merge_Traits_In_Template
|
||||
*/
|
||||
template <class _Traits1, class _Traits2> struct MergeTraits
|
||||
{
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
struct Result
|
||||
{
|
||||
// Mipspro needs this (strange) typedef
|
||||
typedef _Traits1 T1;
|
||||
typedef _Traits2 T2;
|
||||
|
||||
|
||||
VertexAttributes ( T1::VertexAttributes | T2::VertexAttributes );
|
||||
HalfedgeAttributes ( T1::HalfedgeAttributes | T2::HalfedgeAttributes );
|
||||
EdgeAttributes ( T1::EdgeAttributes | T2::EdgeAttributes );
|
||||
FaceAttributes ( T1::FaceAttributes | T2::FaceAttributes );
|
||||
|
||||
|
||||
typedef typename T1::Point Point;
|
||||
typedef typename T1::Normal Normal;
|
||||
typedef typename T1::Color Color;
|
||||
typedef typename T1::TexCoord TexCoord;
|
||||
|
||||
template <class Base, class Refs> class VertexT :
|
||||
public T1::template VertexT<
|
||||
typename T2::template VertexT<Base, Refs>, Refs>
|
||||
{};
|
||||
|
||||
template <class Base, class Refs> class HalfedgeT :
|
||||
public T1::template HalfedgeT<
|
||||
typename T2::template HalfedgeT<Base, Refs>, Refs>
|
||||
{};
|
||||
|
||||
|
||||
template <class Base, class Refs> class EdgeT :
|
||||
public T1::template EdgeT<
|
||||
typename T2::template EdgeT<Base, Refs>, Refs>
|
||||
{};
|
||||
|
||||
|
||||
template <class Base, class Refs> class FaceT :
|
||||
public T1::template FaceT<
|
||||
typename T2::template FaceT<Base, Refs>, Refs>
|
||||
{};
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Macro for merging two traits classes _S1 and _S2 into one traits class _D.
|
||||
Note that in case of ambiguities class _S1 overrides _S2, especially
|
||||
the point/normal/color/texcoord type to be used is taken from _S1::Point/
|
||||
_S1::Normal/_S1::Color/_S1::TexCoord.
|
||||
*/
|
||||
#define OM_Merge_Traits(_S1, _S2, _D) \
|
||||
typedef OpenMesh::MergeTraits<_S1, _S2>::Result _D;
|
||||
|
||||
|
||||
/**
|
||||
Macro for merging two traits classes _S1 and _S2 into one traits class _D.
|
||||
Same as OM_Merge_Traits, but this can be used inside template classes.
|
||||
*/
|
||||
#define OM_Merge_Traits_In_Template(_S1, _S2, _D) \
|
||||
typedef typename OpenMesh::MergeTraits<_S1, _S2>::Result _D;
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_TRAITS_HH defined
|
||||
//=============================================================================
|
||||
|
||||
448
Core/Mesh/TriConnectivity.cc
Normal file
448
Core/Mesh/TriConnectivity.cc
Normal file
@@ -0,0 +1,448 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
// CLASS TriMeshT - IMPLEMENTATION
|
||||
|
||||
#include <OpenMesh/Core/Mesh/TriConnectivity.hh>
|
||||
#include <OpenMesh/Core/System/omstream.hh>
|
||||
|
||||
namespace OpenMesh
|
||||
{
|
||||
|
||||
TriConnectivity::FaceHandle
|
||||
TriConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size)
|
||||
{
|
||||
// need at least 3 vertices
|
||||
if (_vhs_size < 3) return InvalidFaceHandle;
|
||||
|
||||
/// face is triangle -> ok
|
||||
if (_vhs_size == 3)
|
||||
return PolyConnectivity::add_face(_vertex_handles, _vhs_size);
|
||||
|
||||
/// face is not a triangle -> triangulate
|
||||
else
|
||||
{
|
||||
//omlog() << "triangulating " << _vhs_size << "_gon\n";
|
||||
|
||||
VertexHandle vhandles[3];
|
||||
vhandles[0] = _vertex_handles[0];
|
||||
|
||||
FaceHandle fh;
|
||||
unsigned int i(1);
|
||||
--_vhs_size;
|
||||
|
||||
while (i < _vhs_size)
|
||||
{
|
||||
vhandles[1] = _vertex_handles[i];
|
||||
vhandles[2] = _vertex_handles[++i];
|
||||
fh = PolyConnectivity::add_face(vhandles, 3);
|
||||
}
|
||||
|
||||
return fh;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool TriConnectivity::is_collapse_ok(HalfedgeHandle v0v1)
|
||||
{
|
||||
HalfedgeHandle v1v0(opposite_halfedge_handle(v0v1));
|
||||
VertexHandle v0(to_vertex_handle(v1v0));
|
||||
VertexHandle v1(to_vertex_handle(v0v1));
|
||||
|
||||
// are vertices already deleted ?
|
||||
if (status(v0).deleted() || status(v1).deleted())
|
||||
return false;
|
||||
|
||||
|
||||
VertexHandle vl, vr;
|
||||
HalfedgeHandle h1, h2;
|
||||
|
||||
|
||||
// the edges v1-vl and vl-v0 must not be both boundary edges
|
||||
if (!is_boundary(v0v1))
|
||||
{
|
||||
vl = to_vertex_handle(next_halfedge_handle(v0v1));
|
||||
|
||||
h1 = next_halfedge_handle(v0v1);
|
||||
h2 = next_halfedge_handle(h1);
|
||||
if (is_boundary(opposite_halfedge_handle(h1)) &&
|
||||
is_boundary(opposite_halfedge_handle(h2)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// the edges v0-vr and vr-v1 must not be both boundary edges
|
||||
if (!is_boundary(v1v0))
|
||||
{
|
||||
vr = to_vertex_handle(next_halfedge_handle(v1v0));
|
||||
|
||||
h1 = next_halfedge_handle(v1v0);
|
||||
h2 = next_halfedge_handle(h1);
|
||||
if (is_boundary(opposite_halfedge_handle(h1)) &&
|
||||
is_boundary(opposite_halfedge_handle(h2)))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// if vl and vr are equal or both invalid -> fail
|
||||
if (vl == vr) return false;
|
||||
|
||||
|
||||
VertexVertexIter vv_it;
|
||||
|
||||
|
||||
// test intersection of the one-rings of v0 and v1
|
||||
for (vv_it = vv_iter(v0); vv_it; ++vv_it)
|
||||
status(vv_it).set_tagged(false);
|
||||
|
||||
for (vv_it = vv_iter(v1); vv_it; ++vv_it)
|
||||
status(vv_it).set_tagged(true);
|
||||
|
||||
for (vv_it = vv_iter(v0); vv_it; ++vv_it)
|
||||
if (status(vv_it).tagged() && vv_it.handle() != vl && vv_it.handle() != vr)
|
||||
return false;
|
||||
|
||||
|
||||
|
||||
// edge between two boundary vertices should be a boundary edge
|
||||
if ( is_boundary(v0) && is_boundary(v1) &&
|
||||
!is_boundary(v0v1) && !is_boundary(v1v0))
|
||||
return false;
|
||||
|
||||
// passed all tests
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
TriConnectivity::HalfedgeHandle
|
||||
TriConnectivity::vertex_split(VertexHandle v0, VertexHandle v1,
|
||||
VertexHandle vl, VertexHandle vr)
|
||||
{
|
||||
HalfedgeHandle v1vl, vlv1, vrv1, v0v1;
|
||||
|
||||
// build loop from halfedge v1->vl
|
||||
if (vl.is_valid())
|
||||
{
|
||||
v1vl = find_halfedge(v1, vl);
|
||||
assert(v1vl.is_valid());
|
||||
vlv1 = insert_loop(v1vl);
|
||||
}
|
||||
|
||||
// build loop from halfedge vr->v1
|
||||
if (vr.is_valid())
|
||||
{
|
||||
vrv1 = find_halfedge(vr, v1);
|
||||
assert(vrv1.is_valid());
|
||||
insert_loop(vrv1);
|
||||
}
|
||||
|
||||
// handle boundary cases
|
||||
if (!vl.is_valid())
|
||||
vlv1 = prev_halfedge_handle(halfedge_handle(v1));
|
||||
if (!vr.is_valid())
|
||||
vrv1 = prev_halfedge_handle(halfedge_handle(v1));
|
||||
|
||||
|
||||
// split vertex v1 into edge v0v1
|
||||
v0v1 = insert_edge(v0, vlv1, vrv1);
|
||||
|
||||
|
||||
return v0v1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
TriConnectivity::HalfedgeHandle
|
||||
TriConnectivity::insert_loop(HalfedgeHandle _hh)
|
||||
{
|
||||
HalfedgeHandle h0(_hh);
|
||||
HalfedgeHandle o0(opposite_halfedge_handle(h0));
|
||||
|
||||
VertexHandle v0(to_vertex_handle(o0));
|
||||
VertexHandle v1(to_vertex_handle(h0));
|
||||
|
||||
HalfedgeHandle h1 = new_edge(v1, v0);
|
||||
HalfedgeHandle o1 = opposite_halfedge_handle(h1);
|
||||
|
||||
FaceHandle f0 = face_handle(h0);
|
||||
FaceHandle f1 = new_face();
|
||||
|
||||
// halfedge -> halfedge
|
||||
set_next_halfedge_handle(prev_halfedge_handle(h0), o1);
|
||||
set_next_halfedge_handle(o1, next_halfedge_handle(h0));
|
||||
set_next_halfedge_handle(h1, h0);
|
||||
set_next_halfedge_handle(h0, h1);
|
||||
|
||||
// halfedge -> face
|
||||
set_face_handle(o1, f0);
|
||||
set_face_handle(h0, f1);
|
||||
set_face_handle(h1, f1);
|
||||
|
||||
// face -> halfedge
|
||||
set_halfedge_handle(f1, h0);
|
||||
if (f0.is_valid())
|
||||
set_halfedge_handle(f0, o1);
|
||||
|
||||
|
||||
// vertex -> halfedge
|
||||
adjust_outgoing_halfedge(v0);
|
||||
adjust_outgoing_halfedge(v1);
|
||||
|
||||
return h1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
TriConnectivity::HalfedgeHandle
|
||||
TriConnectivity::insert_edge(VertexHandle _vh, HalfedgeHandle _h0, HalfedgeHandle _h1)
|
||||
{
|
||||
assert(_h0.is_valid() && _h1.is_valid());
|
||||
|
||||
VertexHandle v0 = _vh;
|
||||
VertexHandle v1 = to_vertex_handle(_h0);
|
||||
|
||||
assert( v1 == to_vertex_handle(_h1));
|
||||
|
||||
HalfedgeHandle v0v1 = new_edge(v0, v1);
|
||||
HalfedgeHandle v1v0 = opposite_halfedge_handle(v0v1);
|
||||
|
||||
|
||||
|
||||
// vertex -> halfedge
|
||||
set_halfedge_handle(v0, v0v1);
|
||||
set_halfedge_handle(v1, v1v0);
|
||||
|
||||
|
||||
// halfedge -> halfedge
|
||||
set_next_halfedge_handle(v0v1, next_halfedge_handle(_h0));
|
||||
set_next_halfedge_handle(_h0, v0v1);
|
||||
set_next_halfedge_handle(v1v0, next_halfedge_handle(_h1));
|
||||
set_next_halfedge_handle(_h1, v1v0);
|
||||
|
||||
|
||||
// halfedge -> vertex
|
||||
for (VertexIHalfedgeIter vih_it(vih_iter(v0)); vih_it; ++vih_it)
|
||||
set_vertex_handle(vih_it.handle(), v0);
|
||||
|
||||
|
||||
// halfedge -> face
|
||||
set_face_handle(v0v1, face_handle(_h0));
|
||||
set_face_handle(v1v0, face_handle(_h1));
|
||||
|
||||
|
||||
// face -> halfedge
|
||||
if (face_handle(v0v1).is_valid())
|
||||
set_halfedge_handle(face_handle(v0v1), v0v1);
|
||||
if (face_handle(v1v0).is_valid())
|
||||
set_halfedge_handle(face_handle(v1v0), v1v0);
|
||||
|
||||
|
||||
// vertex -> halfedge
|
||||
adjust_outgoing_halfedge(v0);
|
||||
adjust_outgoing_halfedge(v1);
|
||||
|
||||
|
||||
return v0v1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool TriConnectivity::is_flip_ok(EdgeHandle _eh) const
|
||||
{
|
||||
// boundary edges cannot be flipped
|
||||
if (is_boundary(_eh)) return false;
|
||||
|
||||
|
||||
HalfedgeHandle hh = halfedge_handle(_eh, 0);
|
||||
HalfedgeHandle oh = halfedge_handle(_eh, 1);
|
||||
|
||||
|
||||
// check if the flipped edge is already present
|
||||
// in the mesh
|
||||
|
||||
VertexHandle ah = to_vertex_handle(next_halfedge_handle(hh));
|
||||
VertexHandle bh = to_vertex_handle(next_halfedge_handle(oh));
|
||||
|
||||
if (ah == bh) // this is generally a bad sign !!!
|
||||
return false;
|
||||
|
||||
for (ConstVertexVertexIter vvi(*this, ah); vvi; ++vvi)
|
||||
if (vvi.handle() == bh)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void TriConnectivity::flip(EdgeHandle _eh)
|
||||
{
|
||||
// CAUTION : Flipping a halfedge may result in
|
||||
// a non-manifold mesh, hence check for yourself
|
||||
// whether this operation is allowed or not!
|
||||
assert(is_flip_ok(_eh));//let's make it sure it is actually checked
|
||||
assert(!is_boundary(_eh));
|
||||
|
||||
HalfedgeHandle a0 = halfedge_handle(_eh, 0);
|
||||
HalfedgeHandle b0 = halfedge_handle(_eh, 1);
|
||||
|
||||
HalfedgeHandle a1 = next_halfedge_handle(a0);
|
||||
HalfedgeHandle a2 = next_halfedge_handle(a1);
|
||||
|
||||
HalfedgeHandle b1 = next_halfedge_handle(b0);
|
||||
HalfedgeHandle b2 = next_halfedge_handle(b1);
|
||||
|
||||
VertexHandle va0 = to_vertex_handle(a0);
|
||||
VertexHandle va1 = to_vertex_handle(a1);
|
||||
|
||||
VertexHandle vb0 = to_vertex_handle(b0);
|
||||
VertexHandle vb1 = to_vertex_handle(b1);
|
||||
|
||||
FaceHandle fa = face_handle(a0);
|
||||
FaceHandle fb = face_handle(b0);
|
||||
|
||||
set_vertex_handle(a0, va1);
|
||||
set_vertex_handle(b0, vb1);
|
||||
|
||||
set_next_halfedge_handle(a0, a2);
|
||||
set_next_halfedge_handle(a2, b1);
|
||||
set_next_halfedge_handle(b1, a0);
|
||||
|
||||
set_next_halfedge_handle(b0, b2);
|
||||
set_next_halfedge_handle(b2, a1);
|
||||
set_next_halfedge_handle(a1, b0);
|
||||
|
||||
set_face_handle(a1, fb);
|
||||
set_face_handle(b1, fa);
|
||||
|
||||
set_halfedge_handle(fa, a0);
|
||||
set_halfedge_handle(fb, b0);
|
||||
|
||||
if (halfedge_handle(va0) == b0)
|
||||
set_halfedge_handle(va0, a1);
|
||||
if (halfedge_handle(vb0) == a0)
|
||||
set_halfedge_handle(vb0, b1);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void TriConnectivity::split(EdgeHandle _eh, VertexHandle _vh)
|
||||
{
|
||||
HalfedgeHandle h0 = halfedge_handle(_eh, 0);
|
||||
HalfedgeHandle o0 = halfedge_handle(_eh, 1);
|
||||
|
||||
VertexHandle v2 = to_vertex_handle(o0);
|
||||
|
||||
HalfedgeHandle e1 = new_edge(_vh, v2);
|
||||
HalfedgeHandle t1 = opposite_halfedge_handle(e1);
|
||||
|
||||
FaceHandle f0 = face_handle(h0);
|
||||
FaceHandle f3 = face_handle(o0);
|
||||
|
||||
set_halfedge_handle(_vh, h0);
|
||||
set_vertex_handle(o0, _vh);
|
||||
|
||||
if (!is_boundary(h0))
|
||||
{
|
||||
HalfedgeHandle h1 = next_halfedge_handle(h0);
|
||||
HalfedgeHandle h2 = next_halfedge_handle(h1);
|
||||
|
||||
VertexHandle v1 = to_vertex_handle(h1);
|
||||
|
||||
HalfedgeHandle e0 = new_edge(_vh, v1);
|
||||
HalfedgeHandle t0 = opposite_halfedge_handle(e0);
|
||||
|
||||
FaceHandle f1 = new_face();
|
||||
set_halfedge_handle(f0, h0);
|
||||
set_halfedge_handle(f1, h2);
|
||||
|
||||
set_face_handle(h1, f0);
|
||||
set_face_handle(t0, f0);
|
||||
set_face_handle(h0, f0);
|
||||
|
||||
set_face_handle(h2, f1);
|
||||
set_face_handle(t1, f1);
|
||||
set_face_handle(e0, f1);
|
||||
|
||||
set_next_halfedge_handle(h0, h1);
|
||||
set_next_halfedge_handle(h1, t0);
|
||||
set_next_halfedge_handle(t0, h0);
|
||||
|
||||
set_next_halfedge_handle(e0, h2);
|
||||
set_next_halfedge_handle(h2, t1);
|
||||
set_next_halfedge_handle(t1, e0);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_next_halfedge_handle(prev_halfedge_handle(h0), t1);
|
||||
set_next_halfedge_handle(t1, h0);
|
||||
// halfedge handle of _vh already is h0
|
||||
}
|
||||
|
||||
|
||||
if (!is_boundary(o0))
|
||||
{
|
||||
HalfedgeHandle o1 = next_halfedge_handle(o0);
|
||||
HalfedgeHandle o2 = next_halfedge_handle(o1);
|
||||
|
||||
VertexHandle v3 = to_vertex_handle(o1);
|
||||
|
||||
HalfedgeHandle e2 = new_edge(_vh, v3);
|
||||
HalfedgeHandle t2 = opposite_halfedge_handle(e2);
|
||||
|
||||
FaceHandle f2 = new_face();
|
||||
set_halfedge_handle(f2, o1);
|
||||
set_halfedge_handle(f3, o0);
|
||||
|
||||
set_face_handle(o1, f2);
|
||||
set_face_handle(t2, f2);
|
||||
set_face_handle(e1, f2);
|
||||
|
||||
set_face_handle(o2, f3);
|
||||
set_face_handle(o0, f3);
|
||||
set_face_handle(e2, f3);
|
||||
|
||||
set_next_halfedge_handle(e1, o1);
|
||||
set_next_halfedge_handle(o1, t2);
|
||||
set_next_halfedge_handle(t2, e1);
|
||||
|
||||
set_next_halfedge_handle(o0, e2);
|
||||
set_next_halfedge_handle(e2, o2);
|
||||
set_next_halfedge_handle(o2, o0);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_next_halfedge_handle(e1, next_halfedge_handle(o0));
|
||||
set_next_halfedge_handle(o0, e1);
|
||||
set_halfedge_handle(_vh, e1);
|
||||
}
|
||||
|
||||
if (halfedge_handle(v2) == h0)
|
||||
set_halfedge_handle(v2, t1);
|
||||
}
|
||||
|
||||
}// namespace OpenMesh
|
||||
130
Core/Mesh/TriConnectivity.hh
Normal file
130
Core/Mesh/TriConnectivity.hh
Normal file
@@ -0,0 +1,130 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2004 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_TRICONNECTIVITY_HH
|
||||
#define OPENMESH_TRICONNECTIVITY_HH
|
||||
|
||||
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
class TriConnectivity : public PolyConnectivity
|
||||
{
|
||||
public:
|
||||
|
||||
TriConnectivity() {}
|
||||
virtual ~TriConnectivity() {}
|
||||
|
||||
inline static bool is_triangles()
|
||||
{ return true; }
|
||||
|
||||
/** assign_connectivity() methods. See ArrayKernel::assign_connectivity()
|
||||
for more details. When the source connectivity is not triangles, in
|
||||
addition "fan" connectivity triangulation is performed*/
|
||||
inline void assign_connectivity(const TriConnectivity& _other)
|
||||
{ PolyConnectivity::assign_connectivity(_other); }
|
||||
|
||||
inline void assign_connectivity(const PolyConnectivity& _other)
|
||||
{
|
||||
PolyConnectivity::assign_connectivity(_other);
|
||||
triangulate();
|
||||
}
|
||||
|
||||
/** \name Addding items to a mesh
|
||||
*/
|
||||
//@{
|
||||
/** Override OpenMesh::Mesh::PolyMeshT::add_face(). Faces that aren't
|
||||
triangles will be triangulated and added. In this case an
|
||||
invalid face handle will be returned. */
|
||||
FaceHandle add_face(const std::vector<VertexHandle>& _vhandles)
|
||||
{ return add_face(&_vhandles.front(), _vhandles.size()); }
|
||||
|
||||
FaceHandle add_face(const VertexHandle* _vhandles, uint _vhs_size);
|
||||
|
||||
FaceHandle add_face(VertexHandle _vh0, VertexHandle _vh1, VertexHandle _vh2)
|
||||
{
|
||||
VertexHandle vhs[3] = { _vh0, _vh1, _vh2 };
|
||||
return PolyConnectivity::add_face(vhs, 3);
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
/** Returns the opposite vertex to the halfedge _heh in the face
|
||||
referenced by _heh returns InvalidVertexHandle if the _heh is
|
||||
boundary */
|
||||
inline VertexHandle opposite_vh(HalfedgeHandle _heh) const
|
||||
{
|
||||
return is_boundary(_heh) ? InvalidVertexHandle :
|
||||
to_vertex_handle(next_halfedge_handle(_heh));
|
||||
}
|
||||
|
||||
/** Returns the opposite vertex to the opposite halfedge of _heh in
|
||||
the face referenced by it returns InvalidVertexHandle if the
|
||||
opposite halfedge is boundary */
|
||||
VertexHandle opposite_he_opposite_vh(HalfedgeHandle _heh) const
|
||||
{ return opposite_vh(opposite_halfedge_handle(_heh)); }
|
||||
|
||||
/** \name Topology modifying operators
|
||||
*/
|
||||
//@{
|
||||
|
||||
|
||||
/** Returns whether collapsing halfedge _heh is ok or would lead to
|
||||
topological inconsistencies.
|
||||
\attention This method need the Attributes::Status attribute and
|
||||
changes the \em tagged bit. */
|
||||
bool is_collapse_ok(HalfedgeHandle _heh);
|
||||
|
||||
/// Vertex Split: inverse operation to collapse().
|
||||
HalfedgeHandle vertex_split(VertexHandle v0, VertexHandle v1,
|
||||
VertexHandle vl, VertexHandle vr);
|
||||
|
||||
/// Check whether flipping _eh is topologically correct.
|
||||
bool is_flip_ok(EdgeHandle _eh) const;
|
||||
|
||||
/** Flip edge _eh.
|
||||
Check for topological correctness first using is_flip_ok(). */
|
||||
void flip(EdgeHandle _eh);
|
||||
|
||||
/// Edge split (= 2-to-4 split)
|
||||
void split(EdgeHandle _eh, VertexHandle _vh);
|
||||
|
||||
/// Face split (= 1-to-3 split, calls corresponding PolyMeshT function).
|
||||
inline void split(FaceHandle _fh, VertexHandle _vh)
|
||||
{ PolyConnectivity::split(_fh, _vh); }
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
/// Helper for vertex split
|
||||
HalfedgeHandle insert_loop(HalfedgeHandle _hh);
|
||||
/// Helper for vertex split
|
||||
HalfedgeHandle insert_edge(VertexHandle _vh,
|
||||
HalfedgeHandle _h0, HalfedgeHandle _h1);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif//OPENMESH_TRICONNECTIVITY_HH
|
||||
60
Core/Mesh/TriMeshT.cc
Normal file
60
Core/Mesh/TriMeshT.cc
Normal file
@@ -0,0 +1,60 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS TriMeshT - IMPLEMENTATION
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#define OPENMESH_TRIMESH_C
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/Mesh/TriMeshT.hh>
|
||||
#include <OpenMesh/Core/System/omstream.hh>
|
||||
#include <vector>
|
||||
|
||||
|
||||
//== NAMESPACES ==============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== IMPLEMENTATION ==========================================================
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
195
Core/Mesh/TriMeshT.hh
Normal file
195
Core/Mesh/TriMeshT.hh
Normal file
@@ -0,0 +1,195 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS TriMeshT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_TRIMESH_HH
|
||||
#define OPENMESH_TRIMESH_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Mesh/PolyMeshT.hh>
|
||||
#include <vector>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \class TriMeshT TriMeshT.hh <OpenMesh/Mesh/TriMeshT.hh>
|
||||
|
||||
Base type for a triangle mesh.
|
||||
|
||||
Base type for a triangle mesh, parameterized by a mesh kernel. The
|
||||
mesh inherits all methods from the kernel class and the
|
||||
more general polygonal mesh PolyMeshT. Therefore it provides
|
||||
the same types for items, handles, iterators and so on.
|
||||
|
||||
\param Kernel: template argument for the mesh kernel
|
||||
\note You should use the predefined mesh-kernel combinations in
|
||||
\ref mesh_types_group
|
||||
\see \ref mesh_type
|
||||
\see OpenMesh::PolyMeshT
|
||||
*/
|
||||
|
||||
template <class Kernel>
|
||||
class TriMeshT : public PolyMeshT<Kernel>
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// self
|
||||
typedef TriMeshT<Kernel> This;
|
||||
typedef PolyMeshT<Kernel> PolyMesh;
|
||||
|
||||
//@{
|
||||
/// Determine whether this is a PolyMeshT or TriMeshT
|
||||
enum { IsPolyMesh = 0 };
|
||||
enum { IsTriMesh = 1 };
|
||||
static bool is_polymesh() { return false; }
|
||||
static bool is_trimesh() { return true; }
|
||||
//@}
|
||||
|
||||
//--- items ---
|
||||
|
||||
typedef typename PolyMesh::Scalar Scalar;
|
||||
typedef typename PolyMesh::Point Point;
|
||||
typedef typename PolyMesh::Normal Normal;
|
||||
typedef typename PolyMesh::Color Color;
|
||||
typedef typename PolyMesh::TexCoord1D TexCoord1D;
|
||||
typedef typename PolyMesh::TexCoord2D TexCoord2D;
|
||||
typedef typename PolyMesh::TexCoord3D TexCoord3D;
|
||||
typedef typename PolyMesh::Vertex Vertex;
|
||||
typedef typename PolyMesh::Halfedge Halfedge;
|
||||
typedef typename PolyMesh::Edge Edge;
|
||||
typedef typename PolyMesh::Face Face;
|
||||
|
||||
|
||||
//--- handles ---
|
||||
|
||||
typedef typename PolyMesh::VertexHandle VertexHandle;
|
||||
typedef typename PolyMesh::HalfedgeHandle HalfedgeHandle;
|
||||
typedef typename PolyMesh::EdgeHandle EdgeHandle;
|
||||
typedef typename PolyMesh::FaceHandle FaceHandle;
|
||||
|
||||
|
||||
//--- iterators ---
|
||||
|
||||
typedef typename PolyMesh::VertexIter VertexIter;
|
||||
typedef typename PolyMesh::ConstVertexIter ConstVertexIter;
|
||||
typedef typename PolyMesh::EdgeIter EdgeIter;
|
||||
typedef typename PolyMesh::ConstEdgeIter ConstEdgeIter;
|
||||
typedef typename PolyMesh::FaceIter FaceIter;
|
||||
typedef typename PolyMesh::ConstFaceIter ConstFaceIter;
|
||||
|
||||
|
||||
|
||||
//--- circulators ---
|
||||
|
||||
typedef typename PolyMesh::VertexVertexIter VertexVertexIter;
|
||||
typedef typename PolyMesh::VertexOHalfedgeIter VertexOHalfedgeIter;
|
||||
typedef typename PolyMesh::VertexIHalfedgeIter VertexIHalfedgeIter;
|
||||
typedef typename PolyMesh::VertexEdgeIter VertexEdgeIter;
|
||||
typedef typename PolyMesh::VertexFaceIter VertexFaceIter;
|
||||
typedef typename PolyMesh::FaceVertexIter FaceVertexIter;
|
||||
typedef typename PolyMesh::FaceHalfedgeIter FaceHalfedgeIter;
|
||||
typedef typename PolyMesh::FaceEdgeIter FaceEdgeIter;
|
||||
typedef typename PolyMesh::FaceFaceIter FaceFaceIter;
|
||||
typedef typename PolyMesh::ConstVertexVertexIter ConstVertexVertexIter;
|
||||
typedef typename PolyMesh::ConstVertexOHalfedgeIter ConstVertexOHalfedgeIter;
|
||||
typedef typename PolyMesh::ConstVertexIHalfedgeIter ConstVertexIHalfedgeIter;
|
||||
typedef typename PolyMesh::ConstVertexEdgeIter ConstVertexEdgeIter;
|
||||
typedef typename PolyMesh::ConstVertexFaceIter ConstVertexFaceIter;
|
||||
typedef typename PolyMesh::ConstFaceVertexIter ConstFaceVertexIter;
|
||||
typedef typename PolyMesh::ConstFaceHalfedgeIter ConstFaceHalfedgeIter;
|
||||
typedef typename PolyMesh::ConstFaceEdgeIter ConstFaceEdgeIter;
|
||||
typedef typename PolyMesh::ConstFaceFaceIter ConstFaceFaceIter;
|
||||
|
||||
// --- constructor/destructor
|
||||
|
||||
/// Default constructor
|
||||
TriMeshT() : PolyMesh() {}
|
||||
/// Destructor
|
||||
virtual ~TriMeshT() {}
|
||||
|
||||
//--- halfedge collapse / vertex split ---
|
||||
|
||||
/// Vertex Split: inverse operation to collapse().
|
||||
inline HalfedgeHandle vertex_split(Point _v0_point, VertexHandle _v1,
|
||||
VertexHandle _vl, VertexHandle _vr)
|
||||
{ return PolyMesh::vertex_split(add_vertex(_v0_point), _v1, _vl, _vr); }
|
||||
|
||||
inline HalfedgeHandle vertex_split(VertexHandle _v0, VertexHandle _v1,
|
||||
VertexHandle _vl, VertexHandle _vr)
|
||||
{ return PolyMesh::vertex_split(_v0, _v1, _vl, _vr); }
|
||||
|
||||
/// Edge split (= 2-to-4 split)
|
||||
inline void split(EdgeHandle _eh, const Point& _p)
|
||||
{ PolyMesh::split(_eh, add_vertex(_p)); }
|
||||
|
||||
inline void split(EdgeHandle _eh, VertexHandle _vh)
|
||||
{ PolyMesh::split(_eh, _vh); }
|
||||
|
||||
/// Face split (= 1-to-3 split, calls corresponding PolyMeshT function).
|
||||
|
||||
/// Face split (= 1-to-3 split, calls corresponding PolyMeshT function).
|
||||
inline void split(FaceHandle _fh, const Point& _p)
|
||||
{ PolyMesh::split(_fh, _p); }
|
||||
|
||||
inline void split(FaceHandle _fh, VertexHandle _vh)
|
||||
{ PolyMesh::split(_fh, _vh); }
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_TRIMESH_C)
|
||||
#define OPENMESH_TRIMESH_TEMPLATES
|
||||
#include "TriMeshT.cc"
|
||||
#endif
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_TRIMESH_HH defined
|
||||
//=============================================================================
|
||||
89
Core/Mesh/TriMesh_ArrayKernelT.hh
Normal file
89
Core/Mesh/TriMesh_ArrayKernelT.hh
Normal file
@@ -0,0 +1,89 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS TriMesh_ArrayKernelT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_TRIMESH_ARRAY_KERNEL_HH
|
||||
#define OPENMESH_TRIMESH_ARRAY_KERNEL_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Mesh/TriConnectivity.hh>
|
||||
#include <OpenMesh/Core/Mesh/Traits.hh>
|
||||
#include <OpenMesh/Core/Mesh/FinalMeshItemsT.hh>
|
||||
#include <OpenMesh/Core/Mesh/AttribKernelT.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMeshT.hh>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/// Helper class to create a TriMesh-type based on ArrayKernelT
|
||||
template <class Traits>
|
||||
struct TriMesh_ArrayKernel_GeneratorT
|
||||
{
|
||||
typedef FinalMeshItemsT<Traits, true> MeshItems;
|
||||
typedef AttribKernelT<MeshItems, TriConnectivity> AttribKernel;
|
||||
typedef TriMeshT<AttribKernel> Mesh;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** \ingroup mesh_types_group
|
||||
Triangle mesh based on the ArrayKernel.
|
||||
\see OpenMesh::TriMeshT
|
||||
\see OpenMesh::ArrayKernelT
|
||||
*/
|
||||
template <class Traits = DefaultTraits>
|
||||
class TriMesh_ArrayKernelT
|
||||
: public TriMesh_ArrayKernel_GeneratorT<Traits>::Mesh
|
||||
{};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_TRIMESH_ARRAY_KERNEL_HH
|
||||
//=============================================================================
|
||||
73
Core/Mesh/gen/circulators_header.hh
Normal file
73
Core/Mesh/gen/circulators_header.hh
Normal file
@@ -0,0 +1,73 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2001-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_CIRCULATORS_HH
|
||||
#define OPENMESH_CIRCULATORS_HH
|
||||
//=============================================================================
|
||||
//
|
||||
// Vertex and Face circulators for PolyMesh/TriMesh
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
namespace Iterators {
|
||||
|
||||
|
||||
//== FORWARD DECLARATIONS =====================================================
|
||||
|
||||
|
||||
template <class Mesh> class VertexVertexIterT;
|
||||
template <class Mesh> class VertexIHalfedgeIterT;
|
||||
template <class Mesh> class VertexOHalfedgeIterT;
|
||||
template <class Mesh> class VertexEdgeIterT;
|
||||
template <class Mesh> class VertexFaceIterT;
|
||||
|
||||
template <class Mesh> class ConstVertexVertexIterT;
|
||||
template <class Mesh> class ConstVertexIHalfedgeIterT;
|
||||
template <class Mesh> class ConstVertexOHalfedgeIterT;
|
||||
template <class Mesh> class ConstVertexEdgeIterT;
|
||||
template <class Mesh> class ConstVertexFaceIterT;
|
||||
|
||||
template <class Mesh> class FaceVertexIterT;
|
||||
template <class Mesh> class FaceHalfedgeIterT;
|
||||
template <class Mesh> class FaceEdgeIterT;
|
||||
template <class Mesh> class FaceFaceIterT;
|
||||
|
||||
template <class Mesh> class ConstFaceVertexIterT;
|
||||
template <class Mesh> class ConstFaceHalfedgeIterT;
|
||||
template <class Mesh> class ConstFaceEdgeIterT;
|
||||
template <class Mesh> class ConstFaceFaceIterT;
|
||||
|
||||
|
||||
|
||||
190
Core/Mesh/gen/circulators_template.hh
Normal file
190
Core/Mesh/gen/circulators_template.hh
Normal file
@@ -0,0 +1,190 @@
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \class CirculatorT CirculatorsT.hh <OpenMesh/Mesh/Iterators/CirculatorsT.hh>
|
||||
Circulator.
|
||||
*/
|
||||
|
||||
template <class Mesh>
|
||||
class CirculatorT
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
//--- Typedefs ---
|
||||
|
||||
typedef typename Mesh::HalfedgeHandle HalfedgeHandle;
|
||||
|
||||
typedef TargetType value_type;
|
||||
typedef TargetHandle value_handle;
|
||||
|
||||
#if IsConst
|
||||
typedef const Mesh& mesh_ref;
|
||||
typedef const Mesh* mesh_ptr;
|
||||
typedef const TargetType& reference;
|
||||
typedef const TargetType* pointer;
|
||||
#else
|
||||
typedef Mesh& mesh_ref;
|
||||
typedef Mesh* mesh_ptr;
|
||||
typedef TargetType& reference;
|
||||
typedef TargetType* pointer;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// Default constructor
|
||||
CirculatorT() : mesh_(0), active_(false) {}
|
||||
|
||||
|
||||
/// Construct with mesh and a SourceHandle
|
||||
CirculatorT(mesh_ref _mesh, SourceHandle _start) :
|
||||
mesh_(&_mesh),
|
||||
start_(_mesh.halfedge_handle(_start)),
|
||||
heh_(start_),
|
||||
active_(false)
|
||||
{ post_init; }
|
||||
|
||||
|
||||
/// Construct with mesh and start halfedge
|
||||
CirculatorT(mesh_ref _mesh, HalfedgeHandle _heh) :
|
||||
mesh_(&_mesh),
|
||||
start_(_heh),
|
||||
heh_(_heh),
|
||||
active_(false)
|
||||
{ post_init; }
|
||||
|
||||
|
||||
/// Copy constructor
|
||||
CirculatorT(const CirculatorT& _rhs) :
|
||||
mesh_(_rhs.mesh_),
|
||||
start_(_rhs.start_),
|
||||
heh_(_rhs.heh_),
|
||||
active_(_rhs.active_)
|
||||
{ post_init; }
|
||||
|
||||
|
||||
/// Assignment operator
|
||||
CirculatorT& operator=(const CirculatorT<Mesh>& _rhs)
|
||||
{
|
||||
mesh_ = _rhs.mesh_;
|
||||
start_ = _rhs.start_;
|
||||
heh_ = _rhs.heh_;
|
||||
active_ = _rhs.active_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#if IsConst
|
||||
/// construct from non-const circulator type
|
||||
CirculatorT(const NonConstCircT<Mesh>& _rhs) :
|
||||
mesh_(_rhs.mesh_),
|
||||
start_(_rhs.start_),
|
||||
heh_(_rhs.heh_),
|
||||
active_(_rhs.active_)
|
||||
{ post_init; }
|
||||
|
||||
|
||||
/// assign from non-const circulator
|
||||
CirculatorT& operator=(const NonConstCircT<Mesh>& _rhs)
|
||||
{
|
||||
mesh_ = _rhs.mesh_;
|
||||
start_ = _rhs.start_;
|
||||
heh_ = _rhs.heh_;
|
||||
active_ = _rhs.active_;
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
friend class ConstCircT<Mesh>;
|
||||
#endif
|
||||
|
||||
|
||||
/// Equal ?
|
||||
bool operator==(const CirculatorT& _rhs) const {
|
||||
return ((mesh_ == _rhs.mesh_) &&
|
||||
(start_ == _rhs.start_) &&
|
||||
(heh_ == _rhs.heh_) &&
|
||||
(active_ == _rhs.active_));
|
||||
}
|
||||
|
||||
|
||||
/// Not equal ?
|
||||
bool operator!=(const CirculatorT& _rhs) const {
|
||||
return !operator==(_rhs);
|
||||
}
|
||||
|
||||
|
||||
/// Pre-Increment (next cw target)
|
||||
CirculatorT& operator++() {
|
||||
assert(mesh_);
|
||||
active_ = true;
|
||||
increment;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/// Pre-Decrement (next ccw target)
|
||||
CirculatorT& operator--() {
|
||||
assert(mesh_);
|
||||
active_ = true;
|
||||
decrement;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/** Get the current halfedge. There are \c Vertex*Iters and \c
|
||||
Face*Iters. For both the current state is defined by the
|
||||
current halfedge. This is what this method returns.
|
||||
*/
|
||||
HalfedgeHandle current_halfedge_handle() const {
|
||||
return heh_;
|
||||
}
|
||||
|
||||
|
||||
/// Return the handle of the current target.
|
||||
TargetHandle handle() const {
|
||||
assert(mesh_);
|
||||
return get_handle;
|
||||
}
|
||||
|
||||
|
||||
/// Cast to the handle of the current target.
|
||||
operator TargetHandle() const {
|
||||
assert(mesh_);
|
||||
return get_handle;
|
||||
}
|
||||
|
||||
|
||||
/// Return a reference to the current target.
|
||||
reference operator*() const {
|
||||
assert(mesh_);
|
||||
return mesh_->deref(handle());
|
||||
}
|
||||
|
||||
|
||||
/// Return a pointer to the current target.
|
||||
pointer operator->() const {
|
||||
assert(mesh_);
|
||||
return &mesh_->deref(handle());
|
||||
}
|
||||
|
||||
|
||||
/** Returns whether the circulator is still valid.
|
||||
After one complete round around a vertex/face the circulator becomes
|
||||
invalid, i.e. this function will return \c false. Nevertheless you
|
||||
can continue circulating. This method just tells you whether you
|
||||
have completed the first round.
|
||||
*/
|
||||
operator bool() const {
|
||||
return heh_.is_valid() && ((start_ != heh_) || (!active_));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
mesh_ptr mesh_;
|
||||
HalfedgeHandle start_, heh_;
|
||||
bool active_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
6
Core/Mesh/gen/footer.hh
Normal file
6
Core/Mesh/gen/footer.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
//=============================================================================
|
||||
} // namespace Iterators
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif
|
||||
//=============================================================================
|
||||
175
Core/Mesh/gen/generate.sh
Normal file
175
Core/Mesh/gen/generate.sh
Normal file
@@ -0,0 +1,175 @@
|
||||
#!/bin/bash
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# generate_iterator( TargetType, n_elements, has_element_status )
|
||||
function generate_iterator
|
||||
{
|
||||
NonConstIter=$1"IterT"
|
||||
ConstIter="Const"$NonConstIter
|
||||
TargetType="typename Mesh::"$1
|
||||
TargetHandle="typename Mesh::"$1"Handle"
|
||||
|
||||
|
||||
cat iterators_template.hh \
|
||||
| sed -e "s/IteratorT/$NonConstIter/; s/IteratorT/$NonConstIter/;
|
||||
s/NonConstIterT/$NonConstIter/;
|
||||
s/ConstIterT/$ConstIter/;
|
||||
s/TargetType/$TargetType/;
|
||||
s/TargetHandle/$TargetHandle/;
|
||||
s/IsConst/0/;
|
||||
s/n_elements/$2/;
|
||||
s/has_element_status/$3/;"
|
||||
|
||||
|
||||
cat iterators_template.hh \
|
||||
| sed -e "s/IteratorT/$ConstIter/; s/IteratorT/$ConstIter/;
|
||||
s/NonConstIterT/$NonConstIter/;
|
||||
s/ConstIterT/$ConstIter/;
|
||||
s/TargetType/$TargetType/;
|
||||
s/TargetHandle/$TargetHandle/;
|
||||
s/IsConst/1/;
|
||||
s/n_elements/$2/;
|
||||
s/has_element_status/$3/;"
|
||||
}
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# generate_circulator( NonConstName, SourceType, TargetType,
|
||||
# post_init,
|
||||
# increment, decrement,
|
||||
# get_handle,
|
||||
# [Name] )
|
||||
function generate_circulator
|
||||
{
|
||||
NonConstCirc=$1
|
||||
ConstCirc="Const"$NonConstCirc
|
||||
SourceHandle="typename Mesh::"$2"Handle"
|
||||
TargetHandle="typename Mesh::"$3"Handle"
|
||||
TargetType="typename Mesh::"$3
|
||||
|
||||
|
||||
cat circulators_template.hh \
|
||||
| sed -e "s/CirculatorT/$NonConstCirc/; s/CirculatorT/$NonConstCirc/;
|
||||
s/NonConstCircT/$NonConstCirc/;
|
||||
s/ConstCircT/$ConstCirc/;
|
||||
s/SourceHandle/$SourceHandle/;
|
||||
s/TargetHandle/$TargetHandle/;
|
||||
s/TargetType/$TargetType/;
|
||||
s/IsConst/0/;
|
||||
s/post_init/$4/;
|
||||
s/increment/$5/;
|
||||
s/decrement/$6/;
|
||||
s/get_handle/$7/;"
|
||||
|
||||
|
||||
cat circulators_template.hh \
|
||||
| sed -e "s/CirculatorT/$ConstCirc/; s/CirculatorT/$ConstCirc/;
|
||||
s/NonConstCircT/$NonConstCirc/;
|
||||
s/ConstCircT/$ConstCirc/;
|
||||
s/SourceHandle/$SourceHandle/;
|
||||
s/TargetHandle/$TargetHandle/;
|
||||
s/TargetType/$TargetType/;
|
||||
s/IsConst/1/;
|
||||
s/post_init/$4/;
|
||||
s/increment/$5/;
|
||||
s/decrement/$6/;
|
||||
s/get_handle/$7/;"
|
||||
}
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
|
||||
### Generate IteratorsT.hh
|
||||
|
||||
cat iterators_header.hh > IteratorsT.hh
|
||||
|
||||
generate_iterator Vertex n_vertices has_vertex_status >> IteratorsT.hh
|
||||
generate_iterator Halfedge n_halfedges has_halfedge_status >> IteratorsT.hh
|
||||
generate_iterator Edge n_edges has_edge_status >> IteratorsT.hh
|
||||
generate_iterator Face n_faces has_face_status >> IteratorsT.hh
|
||||
|
||||
cat footer.hh >> IteratorsT.hh
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
|
||||
### Generate CirculatorsT.hh
|
||||
|
||||
cat circulators_header.hh > CirculatorsT.hh
|
||||
|
||||
|
||||
generate_circulator VertexVertexIterT Vertex Vertex \
|
||||
" " \
|
||||
"heh_=mesh_->cw_rotated_halfedge_handle(heh_);" \
|
||||
"heh_=mesh_->ccw_rotated_halfedge_handle(heh_);" \
|
||||
"mesh_->to_vertex_handle(heh_);" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
generate_circulator VertexOHalfedgeIterT Vertex Halfedge \
|
||||
" " \
|
||||
"heh_=mesh_->cw_rotated_halfedge_handle(heh_);" \
|
||||
"heh_=mesh_->ccw_rotated_halfedge_handle(heh_);" \
|
||||
"heh_" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
generate_circulator VertexIHalfedgeIterT Vertex Halfedge \
|
||||
" " \
|
||||
"heh_=mesh_->cw_rotated_halfedge_handle(heh_);" \
|
||||
"heh_=mesh_->ccw_rotated_halfedge_handle(heh_);" \
|
||||
"mesh_->opposite_halfedge_handle(heh_)" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
generate_circulator VertexEdgeIterT Vertex Edge \
|
||||
" " \
|
||||
"heh_=mesh_->cw_rotated_halfedge_handle(heh_);" \
|
||||
"heh_=mesh_->ccw_rotated_halfedge_handle(heh_);" \
|
||||
"mesh_->edge_handle(heh_)" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
generate_circulator VertexFaceIterT Vertex Face \
|
||||
"if (heh_.is_valid() \&\& !handle().is_valid()) operator++();" \
|
||||
"do heh_=mesh_->cw_rotated_halfedge_handle(heh_); while ((*this) \&\& (!handle().is_valid()));" \
|
||||
"do heh_=mesh_->ccw_rotated_halfedge_handle(heh_); while ((*this) \&\& (!handle().is_valid()));" \
|
||||
"mesh_->face_handle(heh_)" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
|
||||
generate_circulator FaceVertexIterT Face Vertex \
|
||||
" " \
|
||||
"heh_=mesh_->next_halfedge_handle(heh_);" \
|
||||
"heh_=mesh_->prev_halfedge_handle(heh_);" \
|
||||
"mesh_->to_vertex_handle(heh_)" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
generate_circulator FaceHalfedgeIterT Face Halfedge \
|
||||
" " \
|
||||
"heh_=mesh_->next_halfedge_handle(heh_);" \
|
||||
"heh_=mesh_->prev_halfedge_handle(heh_);" \
|
||||
"heh_" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
generate_circulator FaceEdgeIterT Face Edge \
|
||||
" " \
|
||||
"heh_=mesh_->next_halfedge_handle(heh_);" \
|
||||
"heh_=mesh_->prev_halfedge_handle(heh_);" \
|
||||
"mesh_->edge_handle(heh_)" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
generate_circulator FaceFaceIterT Face Face \
|
||||
"if (heh_.is_valid() \&\& !handle().is_valid()) operator++();" \
|
||||
"do heh_=mesh_->next_halfedge_handle(heh_); while ((*this) \&\& (!handle().is_valid()));" \
|
||||
"do heh_=mesh_->prev_halfedge_handle(heh_); while ((*this) \&\& (!handle().is_valid()));" \
|
||||
"mesh_->face_handle(mesh_->opposite_halfedge_handle(heh_))" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
|
||||
cat footer.hh >> CirculatorsT.hh
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
62
Core/Mesh/gen/iterators_header.hh
Normal file
62
Core/Mesh/gen/iterators_header.hh
Normal file
@@ -0,0 +1,62 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2001-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_ITERATORS_HH
|
||||
#define OPENMESH_ITERATORS_HH
|
||||
//=============================================================================
|
||||
//
|
||||
// Iterators for PolyMesh/TriMesh
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Attributes/Status.hh>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
namespace Iterators {
|
||||
|
||||
|
||||
//== FORWARD DECLARATIONS =====================================================
|
||||
|
||||
|
||||
template <class Mesh> class VertexIterT;
|
||||
template <class Mesh> class ConstVertexIterT;
|
||||
template <class Mesh> class HalfedgeIterT;
|
||||
template <class Mesh> class ConstHalfedgeIterT;
|
||||
template <class Mesh> class EdgeIterT;
|
||||
template <class Mesh> class ConstEdgeIterT;
|
||||
template <class Mesh> class FaceIterT;
|
||||
template <class Mesh> class ConstFaceIterT;
|
||||
|
||||
|
||||
|
||||
|
||||
162
Core/Mesh/gen/iterators_template.hh
Normal file
162
Core/Mesh/gen/iterators_template.hh
Normal file
@@ -0,0 +1,162 @@
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \class IteratorT IteratorsT.hh <OpenMesh/Mesh/Iterators/IteratorsT.hh>
|
||||
Linear iterator.
|
||||
*/
|
||||
|
||||
template <class Mesh>
|
||||
class IteratorT
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
//--- Typedefs ---
|
||||
|
||||
typedef TargetType value_type;
|
||||
typedef TargetHandle value_handle;
|
||||
|
||||
#if IsConst
|
||||
typedef const value_type& reference;
|
||||
typedef const value_type* pointer;
|
||||
typedef const Mesh* mesh_ptr;
|
||||
typedef const Mesh& mesh_ref;
|
||||
#else
|
||||
typedef value_type& reference;
|
||||
typedef value_type* pointer;
|
||||
typedef Mesh* mesh_ptr;
|
||||
typedef Mesh& mesh_ref;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/// Default constructor.
|
||||
IteratorT()
|
||||
: mesh_(0), skip_bits_(0)
|
||||
{}
|
||||
|
||||
|
||||
/// Construct with mesh and a target handle.
|
||||
IteratorT(mesh_ref _mesh, value_handle _hnd, bool _skip=false)
|
||||
: mesh_(&_mesh), hnd_(_hnd), skip_bits_(0)
|
||||
{
|
||||
if (_skip) enable_skipping();
|
||||
}
|
||||
|
||||
|
||||
/// Copy constructor
|
||||
IteratorT(const IteratorT& _rhs)
|
||||
: mesh_(_rhs.mesh_), hnd_(_rhs.hnd_), skip_bits_(_rhs.skip_bits_)
|
||||
{}
|
||||
|
||||
|
||||
/// Assignment operator
|
||||
IteratorT& operator=(const IteratorT<Mesh>& _rhs)
|
||||
{
|
||||
mesh_ = _rhs.mesh_;
|
||||
hnd_ = _rhs.hnd_;
|
||||
skip_bits_ = _rhs.skip_bits_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#if IsConst
|
||||
|
||||
/// Construct from a non-const iterator
|
||||
IteratorT(const NonConstIterT<Mesh>& _rhs)
|
||||
: mesh_(_rhs.mesh_), hnd_(_rhs.hnd_), skip_bits_(_rhs.skip_bits_)
|
||||
{}
|
||||
|
||||
|
||||
/// Assignment from non-const iterator
|
||||
IteratorT& operator=(const NonConstIterT<Mesh>& _rhs)
|
||||
{
|
||||
mesh_ = _rhs.mesh_;
|
||||
hnd_ = _rhs.hnd_;
|
||||
skip_bits_ = _rhs.skip_bits_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#else
|
||||
friend class ConstIterT<Mesh>;
|
||||
#endif
|
||||
|
||||
|
||||
/// Standard dereferencing operator.
|
||||
reference operator*() const { return mesh_->deref(hnd_); }
|
||||
|
||||
/// Standard pointer operator.
|
||||
pointer operator->() const { return &(mesh_->deref(hnd_)); }
|
||||
|
||||
/// Get the handle of the item the iterator refers to.
|
||||
value_handle handle() const { return hnd_; }
|
||||
|
||||
/// Cast to the handle of the item the iterator refers to.
|
||||
operator value_handle() const { return hnd_; }
|
||||
|
||||
/// Are two iterators equal? Only valid if they refer to the same mesh!
|
||||
bool operator==(const IteratorT& _rhs) const
|
||||
{ return ((mesh_ == _rhs.mesh_) && (hnd_ == _rhs.hnd_)); }
|
||||
|
||||
/// Not equal?
|
||||
bool operator!=(const IteratorT& _rhs) const
|
||||
{ return !operator==(_rhs); }
|
||||
|
||||
/// Standard pre-increment operator
|
||||
IteratorT& operator++()
|
||||
{ hnd_.__increment(); if (skip_bits_) skip_fwd(); return *this; }
|
||||
|
||||
/// Standard pre-decrement operator
|
||||
IteratorT& operator--()
|
||||
{ hnd_.__decrement(); if (skip_bits_) skip_bwd(); return *this; }
|
||||
|
||||
|
||||
/// Turn on skipping: automatically skip deleted/hidden elements
|
||||
void enable_skipping()
|
||||
{
|
||||
if (mesh_ && mesh_->has_element_status())
|
||||
{
|
||||
Attributes::StatusInfo status;
|
||||
status.set_deleted(true);
|
||||
status.set_hidden(true);
|
||||
skip_bits_ = status.bits();
|
||||
skip_fwd();
|
||||
}
|
||||
else skip_bits_ = 0;
|
||||
}
|
||||
|
||||
|
||||
/// Turn on skipping: automatically skip deleted/hidden elements
|
||||
void disable_skipping() { skip_bits_ = 0; }
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void skip_fwd()
|
||||
{
|
||||
assert(mesh_ && skip_bits_);
|
||||
while ((hnd_.idx() < (signed) mesh_->n_elements()) &&
|
||||
(mesh_->status(hnd_).bits() & skip_bits_))
|
||||
hnd_.__increment();
|
||||
}
|
||||
|
||||
|
||||
void skip_bwd()
|
||||
{
|
||||
assert(mesh_ && skip_bits_);
|
||||
while ((hnd_.idx() >= 0) &&
|
||||
(mesh_->status(hnd_).bits() & skip_bits_))
|
||||
hnd_.__decrement();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
mesh_ptr mesh_;
|
||||
value_handle hnd_;
|
||||
unsigned int skip_bits_;
|
||||
};
|
||||
|
||||
|
||||
578
Core/OpenMesh_Core.vcproj
Executable file
578
Core/OpenMesh_Core.vcproj
Executable file
@@ -0,0 +1,578 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Name="OpenMesh_Core"
|
||||
ProjectGUID="{ED38FC0A-3C42-4D41-B234-B2912430DE52}"
|
||||
RootNamespace="OpenMesh_Core"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="0"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="4"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\.."
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_USE_MATH_DEFINES"
|
||||
MinimalRebuild="false"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
BufferSecurityCheck="false"
|
||||
EnableFunctionLevelLinking="false"
|
||||
ForceConformanceInForLoopScope="true"
|
||||
RuntimeTypeInfo="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="1"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/OpenMesh.lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="4"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="2"
|
||||
AdditionalIncludeDirectories="..\.. "
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_USE_MATH_DEFINES"
|
||||
StringPooling="false"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="false"
|
||||
EnableFunctionLevelLinking="false"
|
||||
ForceConformanceInForLoopScope="true"
|
||||
RuntimeTypeInfo="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="0"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/OpenMesh.lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Geometry"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Geometry\Config.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Geometry\LoopSchemeMaskT.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Geometry\MathDefs.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Geometry\Plane3d.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Geometry\QuadricT.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Geometry\VectorT.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Geometry\VectorT_inc.hh"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Mesh"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Mesh\ArrayItems.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\ArrayKernel.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\ArrayKernel.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\AttribKernelT.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\Attributes.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\BaseKernel.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\BaseKernel.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\BaseMesh.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\Casts.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\CirculatorsT.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\FinalMeshItemsT.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\Handles.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\IteratorsT.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\PolyConnectivity.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\PolyConnectivity.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\PolyMesh_ArrayKernelT.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\PolyMeshT.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\PolyMeshT.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\Status.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\Traits.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\TriConnectivity.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\TriConnectivity.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\TriMesh_ArrayKernelT.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\TriMeshT.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Mesh\TriMeshT.hh"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="System"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\System\compiler.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\System\config.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\System\config.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\System\mostream.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\System\omstream.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\System\omstream.hh"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Utils"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Utils\AutoPropertyHandleT.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Utils\BaseProperty.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Utils\BaseProperty.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Utils\color_cast.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Utils\Endian.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Utils\Endian.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Utils\GenProg.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Utils\Noncopyable.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Utils\Property.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Utils\PropertyContainer.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Utils\SingletonT.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Utils\SingletonT.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Utils\vector_cast.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Utils\vector_traits.hh"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="IO"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Io\BinaryHelper.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\BinaryHelper.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\IOInstances.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\IOManager.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\IOManager.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\MeshIO.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\OFFFormat.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\OMFormat.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\OMFormat.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\Options.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\SR_binary.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\SR_binary_spec.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\SR_binary_vector_of_bool.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\SR_binary_vector_of_fundamentals.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\SR_binary_vector_of_string.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\SR_rbo.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\SR_store.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\SR_types.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\StoreRestore.hh"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="exporter"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Io\exporter\BaseExporter.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\exporter\ExporterT.hh"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="importer"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Io\importer\BaseImporter.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\importer\ImporterT.hh"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="reader"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Io\reader\BaseReader.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\reader\BaseReader.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\reader\OBJReader.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\reader\OBJReader.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\reader\OFFReader.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\reader\OFFReader.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\reader\OMReader.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\reader\OMReader.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\reader\STLReader.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\reader\STLReader.hh"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="writer"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Io\writer\BaseWriter.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\writer\BaseWriter.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\writer\OBJWriter.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\writer\OBJWriter.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\writer\OFFWriter.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\writer\OFFWriter.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\writer\OMWriter.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\writer\OMWriter.hh"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\writer\STLWriter.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Io\writer\STLWriter.hh"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
17
Core/System/ACGMakefile
Normal file
17
Core/System/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
|
||||
#==============================================================================
|
||||
161
Core/System/compiler.hh
Normal file
161
Core/System/compiler.hh
Normal file
@@ -0,0 +1,161 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_COMPILER_H
|
||||
#define OPENMESH_COMPILER_H
|
||||
|
||||
//=============================================================================
|
||||
|
||||
#if defined(ACGMAKE_STATIC_BUILD)
|
||||
# define OM_STATIC_BUILD 1
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUG)
|
||||
# define OM_DEBUG
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// Workaround for Intel Compiler with MS VC++ 6
|
||||
#if defined(_MSC_VER) && \
|
||||
( defined(__ICL) || defined(__INTEL_COMPILER) || defined(__ICC) )
|
||||
# if !defined(__INTEL_COMPILER)
|
||||
# define __INTEL_COMPILER __ICL
|
||||
# endif
|
||||
# define OM_USE_INTEL_COMPILER 1
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------- MS Visual C++ ----
|
||||
// Compiler _MSC_VER
|
||||
// .NET 2002 1300
|
||||
// .NET 2003 1310
|
||||
// .NET 2005 1400
|
||||
#if defined(_MSC_VER) && !defined(OM_USE_INTEL_COMPILER)
|
||||
# if (_MSC_VER == 1300)
|
||||
# define OM_CC_MSVC
|
||||
# define OM_TYPENAME
|
||||
# define OM_OUT_OF_CLASS_TEMPLATE 0
|
||||
# define OM_PARTIAL_SPECIALIZATION 0
|
||||
# define OM_INCLUDE_TEMPLATES 1
|
||||
# elif (_MSC_VER == 1310)
|
||||
# define OM_CC_MSVC
|
||||
# define OM_TYPENAME
|
||||
# define OM_OUT_OF_CLASS_TEMPLATE 1
|
||||
# define OM_PARTIAL_SPECIALIZATION 1
|
||||
# define OM_INCLUDE_TEMPLATES 1
|
||||
# elif (_MSC_VER >= 1400) // settings for .NET 2005 (NOTE: not fully tested)
|
||||
# pragma warning(disable : 4996)
|
||||
# define OM_TYPENAME
|
||||
# define OM_OUT_OF_CLASS_TEMPLATE 1
|
||||
# define OM_PARTIAL_SPECIALIZATION 1
|
||||
# define OM_INCLUDE_TEMPLATES 1
|
||||
# else
|
||||
# error "Version 7 (.NET 2002) or higher of the MS VC++ is required!"
|
||||
# endif
|
||||
// currently no windows dll supported
|
||||
# define OM_STATIC_BUILD 1
|
||||
# if defined(_MT)
|
||||
# define OM_REENTRANT 1
|
||||
# endif
|
||||
# define OM_CC "MSVC++"
|
||||
# define OM_CC_VERSION _MSC_VER
|
||||
// Does not work stable because the define _CPPRTTI sometimes does not exist,
|
||||
// though the option /GR is set!?
|
||||
# if defined(__cplusplus) && !defined(_CPPRTTI)
|
||||
# error "Enable Runtime Type Information (Compiler Option /GR)!"
|
||||
# endif
|
||||
# if !defined(_USE_MATH_DEFINES)
|
||||
# error "You have to define _USE_MATH_DEFINES in the compiler settings!"
|
||||
# endif
|
||||
// ------------------------------------------------------------- Borland C ----
|
||||
#elif defined(__BORLANDC__)
|
||||
# error "Borland Compiler are not supported yet!"
|
||||
// ------------------------------------------------------------- GNU C/C++ ----
|
||||
#elif defined(__GNUC__) && !defined(__ICC)
|
||||
# define OM_CC_GCC
|
||||
# define OM_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 )
|
||||
# define OM_GCC_MAJOR __GNUC__
|
||||
# define OM_GCC_MINOR __GNUC_MINOR__
|
||||
# if (OM_GCC_VERSION >= 30200)
|
||||
# define OM_TYPENAME typename
|
||||
# define OM_OUT_OF_CLASS_TEMPLATE 1
|
||||
# define OM_PARTIAL_SPECIALIZATION 1
|
||||
# define OM_INCLUDE_TEMPLATES 1
|
||||
# else
|
||||
# error "Version 3.2.0 or better of the GNU Compiler is required!"
|
||||
# endif
|
||||
# if defined(_REENTRANT)
|
||||
# define OM_REENTRANT 1
|
||||
# endif
|
||||
# define OM_CC "GCC"
|
||||
# define OM_CC_VERSION OM_GCC_VERSION
|
||||
// ------------------------------------------------------------- Intel icc ----
|
||||
#elif defined(__ICC) || defined(__INTEL_COMPILER)
|
||||
# define OM_CC_ICC
|
||||
# define OM_TYPENAME typename
|
||||
# define OM_OUT_OF_CLASS_TEMPLATE 1
|
||||
# define OM_PARTIAL_SPECIALIZATION 1
|
||||
# define OM_INCLUDE_TEMPLATES 1
|
||||
# if defined(_REENTRANT) || defined(_MT)
|
||||
# define OM_REENTRANT 1
|
||||
# endif
|
||||
# define OM_CC "ICC"
|
||||
# define OM_CC_VERSION __INTEL_COMPILER
|
||||
// currently no windows dll supported
|
||||
# if defined(_MSC_VER) || defined(WIN32)
|
||||
# define OM_STATIC_BUILD 1
|
||||
# endif
|
||||
// ------------------------------------------------------ MIPSpro Compiler ----
|
||||
#elif defined(__MIPS_ISA) || defined(__mips)
|
||||
// _MIPS_ISA
|
||||
// _COMPILER_VERSION e.g. 730, 7 major, 3 minor
|
||||
// _MIPS_FPSET 32|64
|
||||
// _MIPS_SZINT 32|64
|
||||
// _MIPS_SZLONG 32|64
|
||||
// _MIPS_SZPTR 32|64
|
||||
# define OM_CC_MIPS
|
||||
# define OM_TYPENAME typename
|
||||
# define OM_OUT_OF_CLASS_TEMPLATE 1
|
||||
# define OM_PARTIAL_SPECIALIZATION 1
|
||||
# define OM_INCLUDE_TEMPLATES 0
|
||||
# define OM_CC "MIPS"
|
||||
# define OM_CC_VERSION _COMPILER_VERSION
|
||||
// ------------------------------------------------------------------ ???? ----
|
||||
#else
|
||||
# error "You're using an unsupported compiler!"
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_COMPILER_H defined
|
||||
//=============================================================================
|
||||
|
||||
60
Core/System/config.h
Normal file
60
Core/System/config.h
Normal file
@@ -0,0 +1,60 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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: 1.2 $
|
||||
// $Date: 2007-05-18 15:17:48 $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file config.h
|
||||
* \todo Move content to config.hh and include it to be compatible with old
|
||||
* source.
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_CONFIG_H
|
||||
#define OPENMESH_CONFIG_H
|
||||
|
||||
//=============================================================================
|
||||
|
||||
#include <assert.h>
|
||||
#include <OpenMesh/Core/System/compiler.hh>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#define OM_VERSION 0x10000
|
||||
|
||||
// only defined, if it is a beta version
|
||||
#define OM_VERSION_BETA 4
|
||||
|
||||
#define OM_GET_VER ((OM_VERSION && 0xf0000) >> 16)
|
||||
#define OM_GET_MAJ ((OM_VERSION && 0x0ff00) >> 8)
|
||||
#define OM_GET_MIN (OM_VERSION && 0x000ff)
|
||||
|
||||
typedef unsigned int uint;
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_CONFIG_H defined
|
||||
//=============================================================================
|
||||
1
Core/System/config.hh
Normal file
1
Core/System/config.hh
Normal file
@@ -0,0 +1 @@
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user