Commit 27a0566f authored by Kenneth Vanhoey's avatar Kenneth Vanhoey

Add decimation with color attributes ('Naive' version works, rest is todo)

parent 282195db
...@@ -39,14 +39,16 @@ namespace Decimation ...@@ -39,14 +39,16 @@ namespace Decimation
enum ApproximatorType enum ApproximatorType
{ {
A_QEM, A_QEM,
A_hQEM,
A_MidEdge, A_MidEdge,
A_HalfCollapse,
A_CornerCutting, A_CornerCutting,
A_TangentPredict1, A_TangentPredict1,
A_TangentPredict2, A_TangentPredict2,
A_hColor A_ColorNaive,
/*A_LightfieldHalf, A_ColorQEMext,
// note: the following "h" prefix means that half-edges are prioritized instead of edges.
A_hHalfCollapse,
A_hQEM,
A_hLightfieldHalf/*,
A_LightfieldHalf_deprecated, A_LightfieldHalf_deprecated,
A_LightfieldFull_deprecated*/ A_LightfieldFull_deprecated*/
} ; } ;
...@@ -99,15 +101,17 @@ public: ...@@ -99,15 +101,17 @@ public:
Approximator(MAP& m, std::vector<VertexAttribute<T>* > va, Predictor<PFP, T> * predictor) : Approximator(MAP& m, std::vector<VertexAttribute<T>* > va, Predictor<PFP, T> * predictor) :
ApproximatorGen<PFP>(m), m_predictor(predictor), m_attrV(va) ApproximatorGen<PFP>(m), m_predictor(predictor), m_attrV(va)
{ {
assert(m_attrV.size() > 0 || !"Approximator: no attributes provided") ;
m_approx.resize(m_attrV.size()) ; m_approx.resize(m_attrV.size()) ;
m_detail.resize(m_attrV.size()) ; m_detail.resize(m_attrV.size()) ;
m_app.resize(m_attrV.size()) ; m_app.resize(m_attrV.size()) ;
if (m_attrV.size() < 1)
std::cerr << "Approximator: no attributes provided" << std::endl ;
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i) for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
{ {
if (!m_attrV[i]->isValid())
std::cerr << "Approximator Warning: attribute number " << i << " is not valid" << std::endl ;
std::stringstream aname ; std::stringstream aname ;
aname << "approx_" << m_attrV[i]->name() ; aname << "approx_" << m_attrV[i]->name() ;
m_approx[i] = this->m_map.template addAttribute<T, EDGE>(aname.str()) ; m_approx[i] = this->m_map.template addAttribute<T, EDGE>(aname.str()) ;
......
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
* * * *
*******************************************************************************/ *******************************************************************************/
#ifndef __LIGHTFIELD_APPROXIMATOR_H__ #ifndef __COLOR_APPROXIMATOR_H__
#define __LIGHTFIELD_APPROXIMATOR_H__ #define __COLOR_APPROXIMATOR_H__
#include "Algo/Decimation/approximator.h" #include "Algo/Decimation/approximator.h"
#include "Topology/generic/mapBrowser.h" #include "Topology/generic/mapBrowser.h"
...@@ -38,7 +38,7 @@ namespace Decimation ...@@ -38,7 +38,7 @@ namespace Decimation
{ {
template <typename PFP> template <typename PFP>
class Approximator_Color : public Approximator<PFP, typename PFP::VEC3> class Approximator_ColorNaive : public Approximator<PFP, typename PFP::VEC3>
{ {
public: public:
typedef typename PFP::MAP MAP ; typedef typename PFP::MAP MAP ;
...@@ -46,21 +46,29 @@ public: ...@@ -46,21 +46,29 @@ public:
typedef typename PFP::REAL REAL ; typedef typename PFP::REAL REAL ;
protected: protected:
VertexAttribute<VEC3> m_position ;
EdgeAttribute<VEC3> m_approxposition ;
VertexAttribute<VEC3> *m_color ; VertexAttribute<VEC3> *m_color ;
public: public:
Approximator_Color(MAP& m, std::vector<VertexAttribute<VEC3>* >& attr, Predictor<PFP, VEC3>* pred = NULL) : Approximator_ColorNaive(MAP& m, std::vector<VertexAttribute<VEC3>* >& attr, Predictor<PFP, VEC3>* pred = NULL) :
Approximator<PFP, VEC3>(m, attr, pred) Approximator<PFP, VEC3>(m, attr, pred)
{ {
m_color = this->m_attrV[0] ; m_color = this->m_attrV[0] ;
assert((m_color->isValid() && m_color->name() == "color") || !"Approximator_Color: the approximated attribute is not valid or not named 'color'") ; assert(m_color->isValid() || !"Approximator_ColorNaive: the approximated attribute is not valid") ;
m_position = this->m_map.template getAttribute<VEC3, VERTEX>("position") ;
assert(m_position.isValid() || !"Approximator_ColorNaive: the position attribute is not valid") ;
m_approxposition = this->m_map.template getAttribute<VEC3, EDGE>("approx_position") ;
assert(m_approxposition.isValid() || !"Approximator_ColorNaive: the approx_position attribute is not valid") ;
} }
~Approximator_Color() ~Approximator_ColorNaive()
{} {}
ApproximatorType getType() const ApproximatorType getType() const
{ {
return A_hColor ; return A_ColorNaive ;
} }
bool init() bool init()
...@@ -71,63 +79,42 @@ public: ...@@ -71,63 +79,42 @@ public:
void approximate(Dart d) ; void approximate(Dart d) ;
} ; } ;
/*
template <typename PFP> template <typename PFP>
class Approximator_FrameHalf : public Approximator<PFP, typename PFP::VEC3> class Approximator_ColorQEMext : public Approximator<PFP, typename PFP::VEC3>
{ {
public: public:
typedef typename PFP::MAP MAP ; typedef typename PFP::MAP MAP ;
typedef typename PFP::VEC3 VEC3 ;
typedef typename PFP::REAL REAL ; typedef typename PFP::REAL REAL ;
typedef typename PFP::VEC3 VEC3 ;
typedef Geom::Vector<6,REAL> VEC6 ;
protected:
VertexAttribute<QuadricNd<REAL,6> > m_quadric ;
VertexAttribute<VEC3> *m_position ;
VertexAttribute<VEC3> *m_color ;
public: public:
Approximator_FrameHalf(MAP& m, std::vector<VertexAttribute<VEC3> >& attr, Predictor<PFP, VEC3>* pred = NULL) : Approximator_ColorQEMext(MAP& m, std::vector<VertexAttribute<VEC3>* >& attr, Predictor<PFP, VEC3>* pred = NULL) :
Approximator<PFP, VEC3>(m, attr, pred) Approximator<PFP, VEC3>(m, attr, pred)
{}
~Approximator_FrameHalf()
{}
ApproximatorType getType() const
{ {
return A_LightfieldHalf ; assert(attr.size() > 1 || !"Approximator_ColorQEMext: there are not sufficient attributes provided") ;
}
bool init() m_position = this->m_attrV[0] ;
{ m_color = this->m_attrV[1] ;
return true ;
} }
~Approximator_ColorQEMext()
void approximate(Dart d) ;
} ;
template <typename PFP>
class Approximator_LightfieldCoefsHalf : public Approximator<PFP, typename PFP::VEC3>
{
public:
typedef typename PFP::MAP MAP ;
typedef typename PFP::VEC3 VEC3 ;
typedef typename PFP::REAL REAL ;
public:
Approximator_LightfieldCoefsHalf(MAP& m, std::vector<VertexAttribute<VEC3> >& attr, Predictor<PFP, VEC3>* pred = NULL) :
Approximator<PFP, VEC3>(m, attr, pred)
{}
~Approximator_LightfieldCoefsHalf()
{} {}
ApproximatorType getType() const ApproximatorType getType() const
{ {
return A_LightfieldHalf ; return A_ColorQEMext ;
} }
bool init() bool init() ;
{
return true ;
}
void approximate(Dart d) ; void approximate(Dart d) ;
} ; } ;
*/
} //namespace Decimation } //namespace Decimation
} //namespace Algo } //namespace Algo
......
...@@ -32,17 +32,132 @@ namespace Decimation ...@@ -32,17 +32,132 @@ namespace Decimation
{ {
/************************************************************************************ /************************************************************************************
* COLOR METRIC * * NAIVE COLOR METRIC *
************************************************************************************/ ************************************************************************************/
template <typename PFP> template <typename PFP>
void Approximator_Color<PFP>::approximate(Dart d) void Approximator_ColorNaive<PFP>::approximate(Dart d)
{ {
Dart dd = this->m_map.phi1(d) ; Dart dd = this->m_map.phi1(d) ;
this->m_approx[0][d] = m_color->operator[](d) ; const VEC3& p1 = m_position.operator[](d) ;
this->m_approx[0][d] += m_color->operator[](dd) ; const VEC3& p2 = m_position.operator[](dd) ;
this->m_approx[0][d] /= 2 ; const VEC3& p = m_approxposition.operator[](d) ;
const VEC3& edge = p2 - p1 ;
const REAL& ratio = std::max(std::min(((p - p1) * edge) / edge.norm2(),REAL(1)),REAL(0)) ;
this->m_approx[0][d] = m_color->operator[](d)*ratio + m_color->operator[](dd)*(1-ratio) ;
}
/************************************************************************************
* EXTENDED QUADRIC ERROR METRIC *
************************************************************************************/
template <typename PFP>
bool Approximator_ColorQEMext<PFP>::init()
{
m_quadric = this->m_map.template getAttribute<QuadricNd<REAL,6>, VERTEX>("QEMext-quadric") ;
if(this->m_predictor)
{
return false ;
}
return true ;
}
template <typename PFP>
void Approximator_ColorQEMext<PFP>::approximate(Dart d)
{
MAP& m = this->m_map ;
// get some darts
Dart dd = m.phi2(d) ;
QuadricNd<REAL,6> 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
{
VEC6 p0,p1,p2 ;
for (unsigned int i = 0 ; i < 3 ; ++i)
{
p0[i] = this->m_attrV[0]->operator[](it)[i] ;
p0[i+3] = this->m_attrV[1]->operator[](it)[i] ;
p1[i] = this->m_attrV[0]->operator[](m.phi1(it))[i] ;
p1[i+3] = this->m_attrV[1]->operator[](m.phi1(it))[i] ;
p2[i] = this->m_attrV[0]->operator[](m.phi_1(it))[i] ;
p2[i+3] = this->m_attrV[1]->operator[](m.phi_1(it))[i] ;
}
QuadricNd<REAL,6> q(p0,p1,p2) ;
q1 += q ;
it = m.phi2_1(it) ;
} while(it != d) ;
// compute the error quadric associated to v2
it = dd ;
do
{
VEC6 p0,p1,p2 ;
for (unsigned int i = 0 ; i < 3 ; ++i)
{
p0[i] = this->m_attrV[0]->operator[](it)[i] ;
p0[i+3] = this->m_attrV[1]->operator[](it)[i] ;
p1[i] = this->m_attrV[0]->operator[](m.phi1(it))[i] ;
p1[i+3] = this->m_attrV[1]->operator[](m.phi1(it))[i] ;
p2[i] = this->m_attrV[0]->operator[](m.phi_1(it))[i] ;
p2[i+3] = this->m_attrV[1]->operator[](m.phi_1(it))[i] ;
}
QuadricNd<REAL,6> q(p0,p1,p2) ;
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] ;
}
QuadricNd<REAL,6> quad ;
quad += q1 ; // compute the sum of the
quad += q2 ; // two vertices quadrics
VEC6 res ;
bool opt = quad.findOptimizedPos(res) ; // try to compute an optimized position for the contraction of this edge
if(!opt)
{
VEC6 p1, p2 ;
for (unsigned int i = 0 ; i < 3; ++i)
{
p1[i] = this->m_attrV[0]->operator[](d)[i] ; // let the new vertex lie
p1[i+3] = this->m_attrV[1]->operator[](d)[i] ; // on either one
p2[i] = this->m_attrV[0]->operator[](dd)[i] ; // of the two
p2[i+3] = this->m_attrV[1]->operator[](dd)[i] ; // endpoints
}
VEC6 p12 = (p1 + p2) / 2.0f ; // or the middle of the edge
REAL e1 = quad(p1) ;
REAL e2 = quad(p2) ;
REAL e12 = quad(p12) ;
REAL minerr = std::min(std::min(e1, e2), e12) ; // consider only the one for
if(minerr == e12)
res = p12 ; // which the error is minimal
else if(minerr == e1)
res = p1 ;
else
res = p2 ;
}
// copy res into m_approx
for (unsigned int i = 0 ; i < 3 ; ++i)
{
this->m_approx[0][d] = res[i] ;
this->m_approx[1][d] = res[i+3] ;
}
} }
} //namespace Decimation } //namespace Decimation
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include "Algo/Decimation/halfEdgeSelector.h" #include "Algo/Decimation/halfEdgeSelector.h"
#include "Algo/Decimation/geometryApproximator.h" #include "Algo/Decimation/geometryApproximator.h"
#include "Algo/Decimation/colorPerVertexApproximator.h" #include "Algo/Decimation/colorPerVertexApproximator.h"
//#include "Algo/Decimation/lightfieldApproximator_deprecated.h" #include "Algo/Decimation/lightfieldApproximator.h"
namespace CGoGN namespace CGoGN
{ {
......
...@@ -48,9 +48,6 @@ void decimate( ...@@ -48,9 +48,6 @@ void decimate(
case A_QEM : case A_QEM :
approximators.push_back(new Approximator_QEM<PFP>(map, v_pos)) ; approximators.push_back(new Approximator_QEM<PFP>(map, v_pos)) ;
break ; break ;
case A_hQEM :
approximators.push_back(new Approximator_QEMhalfEdge<PFP>(map, v_pos)) ;
break ;
case A_MidEdge : case A_MidEdge :
approximators.push_back(new Approximator_MidEdge<PFP>(map, v_pos)) ; approximators.push_back(new Approximator_MidEdge<PFP>(map, v_pos)) ;
break ; break ;
...@@ -63,19 +60,57 @@ void decimate( ...@@ -63,19 +60,57 @@ void decimate(
case A_TangentPredict2 : case A_TangentPredict2 :
approximators.push_back(new Approximator_MidEdge<PFP>(map, v_pos)) ; approximators.push_back(new Approximator_MidEdge<PFP>(map, v_pos)) ;
break ; break ;
case A_HalfCollapse : case A_hHalfCollapse :
approximators.push_back(new Approximator_HalfCollapse<PFP>(map, v_pos)) ; approximators.push_back(new Approximator_HalfCollapse<PFP>(map, v_pos)) ;
break ; break ;
case A_hColor : case A_ColorNaive :
{
// pos // pos
approximators.push_back(new Approximator_HalfCollapse<PFP>(map, v_pos)) ; approximators.push_back(new Approximator_QEM<PFP>(map, v_pos)) ;
// col // col
std::vector<VertexAttribute<typename PFP::VEC3>* > v_col ; std::vector<VertexAttribute<typename PFP::VEC3>* > v_col ;
VertexAttribute<typename PFP::VEC3> colors = map.template getAttribute<typename PFP::VEC3, VERTEX>("color") ; VertexAttribute<typename PFP::VEC3> colors = map.template getAttribute<typename PFP::VEC3, VERTEX>("color") ;
v_col.push_back(&colors) ; v_col.push_back(&colors) ;
approximators.push_back(new Approximator_Color<PFP>(map, v_col)) ; approximators.push_back(new Approximator_ColorNaive<PFP>(map, v_col)) ;
break ; }
break ;
case A_ColorQEMext :
{
// pos+col
std::vector<VertexAttribute<typename PFP::VEC3>* > v_poscol ;
v_poscol.push_back(&position) ; // pos
VertexAttribute<typename PFP::VEC3> colors = map.template getAttribute<typename PFP::VEC3, VERTEX>("color") ;
v_poscol.push_back(&colors) ; // col
approximators.push_back(new Approximator_ColorQEMext<PFP>(map, v_poscol)) ;
}
break;
case A_hQEM :
approximators.push_back(new Approximator_QEMhalfEdge<PFP>(map, v_pos)) ;
break ;
case A_hLightfieldHalf :
{
// pos
approximators.push_back(new Approximator_HalfCollapse<PFP>(map, v_pos)) ;
// frame
std::vector<VertexAttribute<typename PFP::VEC3>* > v_frame ;
VertexAttribute<typename PFP::VEC3> FT = map.template getAttribute<typename PFP::VEC3, VERTEX>("frameT") ;
VertexAttribute<typename PFP::VEC3> FB = map.template getAttribute<typename PFP::VEC3, VERTEX>("frameB") ;
VertexAttribute<typename PFP::VEC3> FN = map.template getAttribute<typename PFP::VEC3, VERTEX>("frameN") ;
v_frame.push_back(&FT) ;
v_frame.push_back(&FB) ;
v_frame.push_back(&FN) ;
approximators.push_back(new Approximator_FrameHalf<PFP>(map, v_frame)) ;
// TODO
// // function coefs
// std::vector<VertexAttribute<typename PFP::VEC3>* > v_coefs ;
// VertexAttribute<typename PFP::VEC3> coefs = map.template getAttribute<typename PFP::VEC3, VERTEX>("SLFcoefs_0") ;
// v_frame.push_back(&coefs) ;
// approximators.push_back(new Approximator_LFcoefs<PFP>(map, v_coefs)) ;
}
break ;
/*case A_LightfieldHalf: /*case A_LightfieldHalf:
approximators.push_back(new Approximator_HalfCollapse<PFP>(map, position)) ; approximators.push_back(new Approximator_HalfCollapse<PFP>(map, position)) ;
...@@ -177,14 +212,14 @@ void decimate( ...@@ -177,14 +212,14 @@ void decimate(
case S_MinDetail : case S_MinDetail :
selector = new EdgeSelector_MinDetail<PFP>(map, position, approximators, selected) ; selector = new EdgeSelector_MinDetail<PFP>(map, position, approximators, selected) ;
break ; break ;
/*case S_hLightfield_deprecated : case S_ColorNaive :
selector = new HalfEdgeSelector_Lightfield_deprecated<PFP>(map, position, approximators, selected) ; selector = new EdgeSelector_ColorNaive<PFP>(map, position, approximators, selected) ;
break ;*/ break ;
case S_hQEMml : case S_hQEMml :
selector = new HalfEdgeSelector_QEMml<PFP>(map, position, approximators, selected) ; selector = new HalfEdgeSelector_QEMml<PFP>(map, position, approximators, selected) ;
break ; break ;
case S_hColor : case S_hLightfield :
selector = new HalfEdgeSelector_Color<PFP>(map, position, approximators, selected) ; selector = new HalfEdgeSelector_Lightfield<PFP>(map, position, approximators, selected) ;
break ; break ;
} }
......
...@@ -169,7 +169,8 @@ private: ...@@ -169,7 +169,8 @@ private:
public: public:
EdgeSelector_QEM(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select) : EdgeSelector_QEM(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select) :
EdgeSelector<PFP>(m, pos, approx, select) EdgeSelector<PFP>(m, pos, approx, select),
m_positionApproximator(NULL)
{ {
edgeInfo = m.template addAttribute<EdgeInfo, EDGE>("edgeInfo") ; edgeInfo = m.template addAttribute<EdgeInfo, EDGE>("edgeInfo") ;
quadric = m.template addAttribute<Quadric<REAL>, VERTEX>("QEMquadric") ; quadric = m.template addAttribute<Quadric<REAL>, VERTEX>("QEMquadric") ;
...@@ -218,7 +219,8 @@ private: ...@@ -218,7 +219,8 @@ private:
public: public:
EdgeSelector_QEMml(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select) : EdgeSelector_QEMml(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select) :
EdgeSelector<PFP>(m, pos, approx, select) EdgeSelector<PFP>(m, pos, approx, select),
m_positionApproximator(NULL)
{ {
edgeInfo = m.template addAttribute<EdgeInfo, EDGE>("edgeInfo") ; edgeInfo = m.template addAttribute<EdgeInfo, EDGE>("edgeInfo") ;
quadric = m.template addAttribute<Quadric<REAL>, VERTEX>("QEMquadric") ; quadric = m.template addAttribute<Quadric<REAL>, VERTEX>("QEMquadric") ;
...@@ -275,7 +277,8 @@ private: ...@@ -275,7 +277,8 @@ private:
public: public:
EdgeSelector_Curvature(MAP& m, VertexAttribute<VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select) : EdgeSelector_Curvature(MAP& m, VertexAttribute<VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select) :
EdgeSelector<PFP>(m, pos, approx, select) EdgeSelector<PFP>(m, pos, approx, select),
m_positionApproximator(NULL)
{ {
bb = Algo::Geometry::computeBoundingBox<PFP>(m, pos) ; bb = Algo::Geometry::computeBoundingBox<PFP>(m, pos) ;
radius = bb.diagSize() * 0.003 ; radius = bb.diagSize() * 0.003 ;
...@@ -360,7 +363,8 @@ private: ...@@ -360,7 +363,8 @@ private:
public: public:
EdgeSelector_MinDetail(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select) : EdgeSelector_MinDetail(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select) :
EdgeSelector<PFP>(m, pos, approx, select) EdgeSelector<PFP>(m, pos, approx, select),
m_positionApproximator(NULL)
{ {
edgeInfo = m.template addAttribute<EdgeInfo, EDGE>("edgeInfo") ; edgeInfo = m.template addAttribute<EdgeInfo, EDGE>("edgeInfo") ;
} }
...@@ -375,6 +379,66 @@ public: ...@@ -375,6 +379,66 @@ public:
void updateAfterCollapse(Dart d2, Dart dd2) ; void updateAfterCollapse(Dart d2, Dart dd2) ;
} ; } ;
/*****************************************************************************************************************
* HALF-EDGE NAIVE COLOR METRIC (using QEMml) *
*****************************************************************************************************************/
template <typename PFP>
class EdgeSelector_ColorNaive : public EdgeSelector<PFP>
{
public:
typedef typename PFP::MAP MAP ;
typedef typename PFP::VEC3 VEC3 ;
typedef typename PFP::REAL REAL ;
private:
typedef struct
{
typename std::multimap<float,Dart>::iterat