Commit e149301a authored by Sylvain Thery's avatar Sylvain Thery

Merge cgogn:~vanhoey/CGoGN

Conflicts:
	src/Utils/textureSticker.cpp
parents 4883f7a5 7ee9134c
......@@ -104,7 +104,7 @@ ENDIF (WITH_ZINRI)
IF (WITH_QT)
add_definitions(-DWITH_QT)
find_package(Qt4 REQUIRED)
find_package(Qt REQUIRED)
SET(QT_USE_QTCORE TRUE)
SET(QT_USE_QTOPENGL TRUE)
SET(QT_USE_QTSVG TRUE)
......
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg *
* Copyright (C) 2009-2013, IGG Team, ICube, University of Strasbourg *
* *
* 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 *
......@@ -41,21 +41,32 @@ namespace Decimation
enum ApproximatorType
{
A_QEM,
A_MidEdge,
A_CornerCutting,
A_TangentPredict1,
A_TangentPredict2,
A_NormalArea,
A_ColorNaive,
A_ColorQEMext,
A_Lightfield,
// note: the following "h" prefix means that half-edges are prioritized instead of edges.
A_hHalfCollapse,
A_hQEM,
A_hLightfieldHalf
// One approx per edge
// Geometry approximators
A_QEM = 0, /**< Approximates the geometry of an edge collapse by quadric error metric minimization [GH97]. */
A_MidEdge = 1, /**< Approximates the geometry of an edge collapse by placing the resulting vertex in its middle. */
A_CornerCutting = 2,
A_TangentPredict1 = 3,
A_TangentPredict2 = 4,
A_NormalArea = 5, /**< EXPERIMENTAL Approximates the geometry of an edge collapse by minimization of its normal times area measure [Sauvage] */
// Geometry + color approximators
A_ColorNaive = 6, /**< Approximates the color of the resulting vertex by linear interpolation (based on the approximated position) of its two predecessors. */
A_ColorQEMext = 7, /**< Approximates both geometry and color of the resulting vertex by minimization of the extended (R^6) quadric error metric [GH98]. */
A_GeomColorOpt = 8, /**< EXPERIMENTAL. */
// One approx per half-edge
// Generic (considers all provided attributes) approximator
A_hHalfCollapse = 9, /**< Approximates all provided attributes of a half-edge collapse by keeping the attributes of the first of two vertices. */
// Geometry approximator
A_hQEM = 10, /**< Approximates the geometry of a full-edge collapse by quadric error metric minimization [GH97]. Compatible version for half-edge selectors. */
A_OTHER /**< Can be used for extensions. */
} ;
/*!
* \class ApproximatorGen
* \brief Generic class holder for approximators
*/
template <typename PFP>
class ApproximatorGen
{
......@@ -73,7 +84,6 @@ public:
virtual ~ApproximatorGen()
{}
virtual const std::string& getApproximatedAttributeName(unsigned int index = 0) const = 0 ;
// virtual std::vector<std::string> getApproximatedAttributeNames() const = 0 ;
virtual ApproximatorType getType() const = 0 ;
virtual unsigned int getNbApproximated() const = 0 ;
virtual bool init() = 0 ;
......@@ -86,6 +96,10 @@ public:
} ;
/*!
* \class Approximator
* \brief Generic class for approximators
*/
template <typename PFP, typename T, unsigned int ORBIT>
class Approximator : public ApproximatorGen<PFP>
{
......@@ -103,163 +117,33 @@ protected:
std::vector<T> m_app ;
public:
Approximator(MAP& m, std::vector<VertexAttribute<T>* > va, Predictor<PFP, T> * predictor) :
ApproximatorGen<PFP>(m), m_predictor(predictor), m_attrV(va)
{
const unsigned int& size = m_attrV.size() ;
assert(size > 0 || !"Approximator: no attributes provided") ;
m_approx.resize(size) ;
m_detail.resize(size) ;
m_app.resize(size) ;
for (unsigned int i = 0 ; i < size ; ++i)
{
if (!m_attrV[i]->isValid())
std::cerr << "Approximator Warning: attribute number " << i << " is not valid" << std::endl ;
std::stringstream aname ;
aname << "approx_" << m_attrV[i]->name() ;
m_approx[i] = this->m_map.template addAttribute<T, ORBIT>(aname.str()) ;
if(m_predictor) // if predictors are associated to the approximator
{ // create attributes to store the details needed for reconstruction
std::stringstream dname ;
dname << "detail_" << m_attrV[i]->name() ;
m_detail[i] = this->m_map.template addAttribute<T, ORBIT>(dname.str()) ;
}
}
}
virtual ~Approximator()
{
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
{
this->m_map.template removeAttribute(m_approx[i]) ;
if(m_predictor)
this->m_map.template removeAttribute(m_detail[i]) ;
}
}
const std::string& getApproximatedAttributeName(unsigned int index = 0) const
{
return m_attrV[index]->name() ;
}
// std::vector<std::string> getApproximatedAttributeNames() const
// {
// std::vector<std::string> names ;
// names.resize(m_attrV.size()) ;
// for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
// names[i] = m_attrV[i]->name() ;
//
// return names ;
// }
unsigned int getNbApproximated() const
{
return m_attrV.size() ;
}
void saveApprox(Dart d)
{
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
m_app[i] = m_approx[i][d] ;
}
void affectApprox(Dart d)
{
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
m_attrV[i]->operator[](d) = m_app[i] ;
}
const T& getApprox(Dart d, unsigned int index = 0) const
{
return m_approx[index][d] ;
}
const VertexAttribute<T>& getAttr(unsigned int index = 0) const
{
return *(m_attrV[index]) ;
}
std::vector<T> getAllApprox(Dart d) const
{
std::vector<T> res ;
res.resize(m_attrV.size()) ;
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
res[i] = m_approx[i][d] ;
return res ;
}
const Predictor<PFP, T>* getPredictor() const
{
return m_predictor ;
}
const T& getDetail(Dart d, unsigned int index = 0) const
{
assert(m_predictor || !"Trying to get detail on a non-predictive scheme") ;
return m_detail[index][d] ;
}
std::vector<T> getAllDetail(Dart d) const
{
assert(m_predictor || !"Trying to get detail on a non-predictive scheme") ;
std::vector<T> res ;
res.resize(m_attrV.size()) ;
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
res[i] = m_detail[i][d] ;
return res ;
}
void setDetail(Dart d, unsigned int index, T& val)
{
assert(m_predictor || !"Trying to set detail on a non-predictive scheme") ;
m_detail[index][d] = val ;
}
void setDetail(Dart d, std::vector<T>& val)
{
assert(m_predictor || !"Trying to set detail on a non-predictive scheme") ;
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
m_detail[index][d] = val[i] ;
}
// // TODO works only for vector types !!
// REAL detailMagnitude(Dart d)
// {
// assert(m_predictor || !"Trying to get detail magnitude on a non-predictive scheme") ;
// return m_detail[d].norm2() ;
// }
void addDetail(Dart d, double amount, bool sign, typename PFP::MATRIX33* detailTransform)
{
assert(m_predictor || !"Trying to add detail on a non-predictive scheme") ;
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
{
T det = m_detail[i][d] ;
if(detailTransform)
det = (*detailTransform) * det ;
det *= amount ;
if(!sign)
det *= REAL(-1) ;
m_attrV[i]->operator[](d) += det ;
}
}
Approximator(MAP& m, std::vector<VertexAttribute<T>* > va, Predictor<PFP, T> * predictor) ;
virtual ~Approximator() ;
const std::string& getApproximatedAttributeName(unsigned int index = 0) const ;
unsigned int getNbApproximated() const ;
void saveApprox(Dart d) ;
void affectApprox(Dart d) ;
const T& getApprox(Dart d, unsigned int index = 0) const ;
const VertexAttribute<T>& getAttr(unsigned int index = 0) const ;
VertexAttribute<T>& getAttr(unsigned int index = 0) ;
std::vector<T> getAllApprox(Dart d) const ;
const Predictor<PFP, T>* getPredictor() const ;
const T& getDetail(Dart d, unsigned int index = 0) const ;
std::vector<T> getAllDetail(Dart d) const ;
void setDetail(Dart d, unsigned int index, T& val) ;
void setDetail(Dart d, std::vector<T>& val) ;
// REAL detailMagnitude(Dart d) ; // TODO works only for vector types !!
void addDetail(Dart d, double amount, bool sign, typename PFP::MATRIX33* detailTransform) ;
} ;
} //namespace Decimation
} // namespace Decimation
} // namespace surface
} // surface
} // namespace Algo
} //namespace Algo
} // namespace CGoGN
} //namespace CGoGN
#include "Algo/Decimation/approximator.hpp"
#endif
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2013, IGG Team, ICube, University of Strasbourg *
* *
* 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; either version 2.1 of the License, or (at your *
* option) any later version. *
* *
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* Web site: http://cgogn.unistra.fr/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
namespace CGoGN
{
namespace Algo
{
namespace Surface
{
namespace Decimation
{
template <typename PFP, typename T, unsigned int ORBIT>
Approximator<PFP,T,ORBIT>::Approximator(MAP& m, std::vector<VertexAttribute<T>* > va, Predictor<PFP, T> * predictor) :
ApproximatorGen<PFP>(m), m_predictor(predictor), m_attrV(va)
{
const unsigned int& size = m_attrV.size() ;
assert(size > 0 || !"Approximator: no attributes provided") ;
m_approx.resize(size) ;
m_detail.resize(size) ;
m_app.resize(size) ;
for (unsigned int i = 0 ; i < size ; ++i)
{
if (!m_attrV[i]->isValid())
std::cerr << "Approximator Warning: attribute number " << i << " is not valid" << std::endl ;
std::stringstream aname ;
aname << "approx_" << m_attrV[i]->name() ;
m_approx[i] = this->m_map.template addAttribute<T, ORBIT>(aname.str()) ;
if(m_predictor) // if predictors are associated to the approximator
{ // create attributes to store the details needed for reconstruction
std::stringstream dname ;
dname << "detail_" << m_attrV[i]->name() ;
m_detail[i] = this->m_map.template addAttribute<T, ORBIT>(dname.str()) ;
}
}
}
template <typename PFP, typename T, unsigned int ORBIT>
Approximator<PFP,T,ORBIT>::~Approximator()
{
std::cout << "Approximator<PFP,T,ORBIT>::~Approximator()" << std::endl ;
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
{
this->m_map.template removeAttribute(m_approx[i]) ;
if(m_predictor)
this->m_map.template removeAttribute(m_detail[i]) ;
}
}
template <typename PFP, typename T, unsigned int ORBIT>
const std::string&
Approximator<PFP,T,ORBIT>::getApproximatedAttributeName(unsigned int index) const
{
return m_attrV[index]->name() ;
}
template <typename PFP, typename T, unsigned int ORBIT>
unsigned int
Approximator<PFP,T,ORBIT>::getNbApproximated() const
{
return m_attrV.size() ;
}
template <typename PFP, typename T, unsigned int ORBIT>
void
Approximator<PFP,T,ORBIT>::saveApprox(Dart d)
{
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
{
m_app[i] = m_approx[i][d] ;
}
}
template <typename PFP, typename T, unsigned int ORBIT>
void
Approximator<PFP,T,ORBIT>::affectApprox(Dart d)
{
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
{
m_attrV[i]->operator[](d) = m_app[i] ;
}
}
template <typename PFP, typename T, unsigned int ORBIT>
const T&
Approximator<PFP,T,ORBIT>::getApprox(Dart d, unsigned int index) const
{
return m_approx[index][d] ;
}
template <typename PFP, typename T, unsigned int ORBIT>
const VertexAttribute<T>&
Approximator<PFP,T,ORBIT>::getAttr(unsigned int index) const
{
return *(m_attrV[index]) ;
}
template <typename PFP, typename T, unsigned int ORBIT>
VertexAttribute<T>&
Approximator<PFP,T,ORBIT>::getAttr(unsigned int index)
{
return *(m_attrV[index]) ;
}
template <typename PFP, typename T, unsigned int ORBIT>
std::vector<T>
Approximator<PFP,T,ORBIT>::getAllApprox(Dart d) const
{
std::vector<T> res ;
res.resize(m_attrV.size()) ;
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
res[i] = m_approx[i][d] ;
return res ;
}
template <typename PFP, typename T, unsigned int ORBIT>
const Predictor<PFP, T>*
Approximator<PFP,T,ORBIT>::getPredictor() const
{
return m_predictor ;
}
template <typename PFP, typename T, unsigned int ORBIT>
const T&
Approximator<PFP,T,ORBIT>::getDetail(Dart d, unsigned int index) const
{
assert(m_predictor || !"Trying to get detail on a non-predictive scheme") ;
return m_detail[index][d] ;
}
template <typename PFP, typename T, unsigned int ORBIT>
std::vector<T>
Approximator<PFP,T,ORBIT>::getAllDetail(Dart d) const
{
assert(m_predictor || !"Trying to get detail on a non-predictive scheme") ;
std::vector<T> res ;
res.resize(m_attrV.size()) ;
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
res[i] = m_detail[i][d] ;
return res ;
}
template <typename PFP, typename T, unsigned int ORBIT>
void
Approximator<PFP,T,ORBIT>::setDetail(Dart d, unsigned int index, T& val)
{
assert(m_predictor || !"Trying to set detail on a non-predictive scheme") ;
m_detail[index][d] = val ;
}
template <typename PFP, typename T, unsigned int ORBIT>
void
Approximator<PFP,T,ORBIT>::setDetail(Dart d, std::vector<T>& val)
{
assert(m_predictor || !"Trying to set detail on a non-predictive scheme") ;
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
m_detail[index][d] = val[i] ;
}
// // TODO works only for vector types !!
// REAL detailMagnitude(Dart d)
// {
// assert(m_predictor || !"Trying to get detail magnitude on a non-predictive scheme") ;
// return m_detail[d].norm2() ;
// }
template <typename PFP, typename T, unsigned int ORBIT>
void
Approximator<PFP,T,ORBIT>::addDetail(Dart d, double amount, bool sign, typename PFP::MATRIX33* detailTransform)
{
assert(m_predictor || !"Trying to add detail on a non-predictive scheme") ;
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
{
T det = m_detail[i][d] ;
if(detailTransform)
det = (*detailTransform) * det ;
det *= amount ;
if(!sign)
det *= REAL(-1) ;
m_attrV[i]->operator[](d) += det ;
}
}
} //namespace Decimation
} // namespace surface
} //namespace Algo
} //namespace CGoGN
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg *
* Copyright (C) 2009-2013, IGG Team, ICube, University of Strasbourg *
* *
* 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 *
......@@ -121,48 +121,46 @@ public:
void approximate(Dart d) ;
} ;
/*
template <typename PFP>
class Approximator_ColorQEMextHalfCollapse : public Approximator<PFP, typename PFP::VEC3>
class Approximator_GeomColOpt : public Approximator<PFP, typename PFP::VEC3, EDGE>
{
public:
typedef typename PFP::MAP MAP ;
typedef typename PFP::REAL REAL ;
typedef typename PFP::VEC3 VEC3 ;
typedef Geom::Vector<6,REAL> VEC6 ;
protected:
VertexAttribute<Utils::QuadricNd<REAL,6> > m_quadric ;
VertexAttribute<Utils::Quadric<REAL> > m_quadric ;
VertexAttribute<VEC3> *m_position ;
VertexAttribute<VEC3> *m_color ;
public:
Approximator_ColorQEMextHalfCollapse(MAP& m, std::vector<VertexAttribute<VEC3>* >& attr, Predictor<PFP, VEC3>* pred = NULL) :
Approximator<PFP, VEC3>(m, attr, pred)
Approximator_GeomColOpt(MAP& m, std::vector<VertexAttribute<VEC3>* >& attr, Predictor<PFP, VEC3>* pred = NULL) :
Approximator<PFP, VEC3, EDGE>(m, attr, pred)
{
assert(attr.size() > 1 || !"Approximator_ColorQEMext_HalfCollapse: there are not sufficient attributes provided") ;
assert(attr.size() > 1 || !"Approximator_GeomColOpt: there are not sufficient attributes provided") ;
m_position = this->m_attrV[0] ;
m_color = this->m_attrV[1] ;
}
~Approximator_ColorQEMextHalfCollapse()
~Approximator_GeomColOpt()
{}
ApproximatorType getType() const
{
return A_ColorQEMextHalfCollapse ;
return A_GeomColorOpt ;
}
bool init() ;
void approximate(Dart d) ;
} ;
*/
} //namespace Decimation
}
} // namespace Surface
} //namespace Algo
......
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg *
* Copyright (C) 2009-2013, IGG Team, ICube, University of Strasbourg *
* *
* 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 *
......@@ -165,6 +165,102 @@ void Approximator_ColorQEMext<PFP>::approximate(Dart d)
}
}
/************************************************************************************
* GEOM + COLOR OPTIMIZED ERROR METRIC *
************************************************************************************/
template <typename PFP>
bool Approximator_GeomColOpt<PFP>::init()
{
m_quadric = this->m_map.template getAttribute<Utils::Quadric<REAL>, VERTEX>("QEMquadric") ;
// Does not require to be valid (if it is not, altenatives will be used).
if(this->m_predictor)
{
return false ;
}
return m_position->isValid() && m_color->isValid() ;
}
template <typename PFP>
void Approximator_GeomColOpt<PFP>::approximate(Dart d)
{
MAP& m = this->m_map ;
// get some darts
Dart dd = m.phi2(d) ;
// POSITION
Utils::Quadric<REAL> q1, q2 ;
if(!m_quadric.isValid()) // if the selector is not QEM, compute local error quadrics
{
// compute the error quadric associated to v1
Dart it = d ;
do
{
Utils::Quadric<REAL> q(this->m_attrV[0]->operator[](it), this->m_attrV[0]->operator[](m.phi1(it)), this->m_attrV[0]->operator[](m.phi_1(it))) ;
q1 += q ;
it = m.phi2_1(it) ;
} while(it != d) ;
// compute the error quadric associated to v2
it = dd ;
do
{
Utils::Quadric<REAL> q(this->m_attrV[0]->operator[](it), this->m_attrV[0]->operator[](m.phi1(it)), this->m_attrV[0]->operator[](m.phi_1(it))) ;
q2 += q ;
it = m.phi2_1(it) ;
} while(it != dd) ;
}
else // if the selector is QEM, use the error quadrics computed by the selector
{
q1 = m_quadric[d] ;
q2 = m_quadric[dd] ;
}
Utils::Quadric<REAL> quad ;
quad += q1 ; // compute the sum of the
quad += q2 ; // two vertices quadrics
VEC3 res ;
bool opt = quad.findOptimizedPos(res) ; // try to compute an optimized position for the contraction of this edge
const VEC3& p0 = this->m_attrV[0]->operator[](d) ; // let the new vertex lie
const VEC3& p1 = this->m_attrV[0]->operator[](dd) ; // on either one of the two endpoints
if(false && !opt)
{
VEC3 p12 = (p0 + p1) / 2.0f ; // or the middle of the edge
REAL e1 = quad(p0) ;
REAL e2 = quad(p1) ;
REAL e12 = quad(p12) ;
REAL minerr = std::min(std::min(e1, e2), e12) ; // consider only the one for
if(minerr == e12) this->m_approx[0][d] = p12 ; // which the error is minimal
else if(minerr == e1) this->m_approx[0][d] = p0 ;
else this->m_approx[0][d] = p1 ;
}
// copy res into m_approx
else
{
this->m_approx[0][d] = res ;
}
const VEC3& p = this->m_approx[0][d] ;