First checkin for OpenMesh 2.0

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

19
Core/ACGMakefile Normal file
View 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
View 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
View File

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

56
Core/Geometry/Config.hh Normal file
View 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
//=============================================================================

View 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
View 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
View 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
View 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
View 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
//=============================================================================

View 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
View File

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

View File

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

View File

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

View File

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

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

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

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

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

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

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

View File

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

View File

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

View File

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

17
Core/Mesh/ACGMakefile Normal file
View File

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

112
Core/Mesh/ArrayItems.hh Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View 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
View File

@@ -0,0 +1,134 @@
//=============================================================================
//
// OpenMesh
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
// www.openmesh.org
//
//-----------------------------------------------------------------------------
//
// License
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, version 2.1.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// $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

File diff suppressed because it is too large Load Diff

View 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

View 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
View 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
View 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
//=============================================================================

View 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
View 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
View 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
//=============================================================================

View 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

View 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
View 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
View 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
//=============================================================================

View 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
//=============================================================================

View 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;

View 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
View File

@@ -0,0 +1,6 @@
//=============================================================================
} // namespace Iterators
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

175
Core/Mesh/gen/generate.sh Normal file
View 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
#------------------------------------------------------------------------------

View 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;

View 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
View 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
View File

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

161
Core/System/compiler.hh Normal file
View 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
View 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
View 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