Commit e4a13e90 authored by Kenneth Vanhoey's avatar Kenneth Vanhoey
Browse files

Begin of decim with colors grad+opt

parent 3a4315bb
...@@ -41,19 +41,20 @@ namespace Decimation ...@@ -41,19 +41,20 @@ namespace Decimation
enum ApproximatorType enum ApproximatorType
{ {
A_QEM, A_QEM = 0,
A_MidEdge, A_MidEdge = 1,
A_CornerCutting, A_CornerCutting = 2,
A_TangentPredict1, A_TangentPredict1 = 3,
A_TangentPredict2, A_TangentPredict2 = 4,
A_NormalArea, A_NormalArea = 5,
A_ColorNaive, A_ColorNaive = 6,
A_ColorQEMext, A_ColorQEMext = 7,
A_Lightfield, A_GeomColorOpt = 8,
A_Lightfield = 9,
// note: the following "h" prefix means that half-edges are prioritized instead of edges. // note: the following "h" prefix means that half-edges are prioritized instead of edges.
A_hHalfCollapse, A_hHalfCollapse = 10,
A_hQEM, A_hQEM = 11,
A_hLightfieldHalf A_hLightfieldHalf = 12
} ; } ;
template <typename PFP> template <typename PFP>
...@@ -164,13 +165,17 @@ public: ...@@ -164,13 +165,17 @@ public:
void saveApprox(Dart d) void saveApprox(Dart d)
{ {
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i) for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
{
m_app[i] = m_approx[i][d] ; m_app[i] = m_approx[i][d] ;
}
} }
void affectApprox(Dart d) void affectApprox(Dart d)
{ {
for (unsigned int i = 0 ; i < m_attrV.size() ; ++i) for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
{
m_attrV[i]->operator[](d) = m_app[i] ; m_attrV[i]->operator[](d) = m_app[i] ;
}
} }
const T& getApprox(Dart d, unsigned int index = 0) const const T& getApprox(Dart d, unsigned int index = 0) const
......
...@@ -121,44 +121,43 @@ public: ...@@ -121,44 +121,43 @@ public:
void approximate(Dart d) ; void approximate(Dart d) ;
} ; } ;
/*
template <typename PFP> template <typename PFP>
class Approximator_ColorQEMextHalfCollapse : public Approximator<PFP, typename PFP::VEC3> class Approximator_GeomColOpt : public Approximator<PFP, typename PFP::VEC3, EDGE>
{ {
public: public:
typedef typename PFP::MAP MAP ; typedef typename PFP::MAP MAP ;
typedef typename PFP::REAL REAL ; typedef typename PFP::REAL REAL ;
typedef typename PFP::VEC3 VEC3 ; typedef typename PFP::VEC3 VEC3 ;
typedef Geom::Vector<6,REAL> VEC6 ;
protected: protected:
VertexAttribute<Utils::QuadricNd<REAL,6> > m_quadric ; VertexAttribute<Utils::Quadric<REAL> > m_quadric ;
VertexAttribute<VEC3> *m_position ; VertexAttribute<VEC3> *m_position ;
VertexAttribute<VEC3> *m_color ; VertexAttribute<VEC3> *m_color ;
public: public:
Approximator_ColorQEMextHalfCollapse(MAP& m, std::vector<VertexAttribute<VEC3>* >& attr, Predictor<PFP, VEC3>* pred = NULL) : Approximator_GeomColOpt(MAP& m, std::vector<VertexAttribute<VEC3>* >& attr, Predictor<PFP, VEC3>* pred = NULL) :
Approximator<PFP, VEC3>(m, attr, pred) 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_position = this->m_attrV[0] ;
m_color = this->m_attrV[1] ; m_color = this->m_attrV[1] ;
} }
~Approximator_ColorQEMextHalfCollapse() ~Approximator_GeomColOpt()
{} {}
ApproximatorType getType() const ApproximatorType getType() const
{ {
return A_ColorQEMextHalfCollapse ; return A_GeomColorOpt ;
} }
bool init() ; bool init() ;
void approximate(Dart d) ; void approximate(Dart d) ;
} ; } ;
*/
} //namespace Decimation } //namespace Decimation
......
...@@ -165,6 +165,102 @@ void Approximator_ColorQEMext<PFP>::approximate(Dart d) ...@@ -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(!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] ;
// COLOR
const VEC3& c1 = this->m_attrV[1]->operator[](d) ; // let the new vertex lie
const VEC3& c2 = this->m_attrV[1]->operator[](dd) ; // on either one of the two endpoints
VEC3 e = p1 - p0 ;
VEC3 e1 = p - p0 ;
const REAL normE1 = e1.normalize() ;
const REAL normE = e.normalize() ;
REAL ratio = (e * e1)*normE1/normE ;
ratio = std::max(REAL(0),std::min(REAL(1),ratio)) ;
this->m_approx[1][d] = ratio*c1 + (1-ratio)*c2 ;
}
} //namespace Decimation } //namespace Decimation
} }
......
...@@ -62,7 +62,7 @@ void decimate( ...@@ -62,7 +62,7 @@ void decimate(
typename PFP::MAP& map, typename PFP::MAP& map,
SelectorType s, SelectorType s,
ApproximatorType a, ApproximatorType a,
std::vector<VertexAttribute<typename PFP::VEC3> *>& position, std::vector<VertexAttribute<typename PFP::VEC3> *>& attribs,
unsigned int nbWantedVertices, unsigned int nbWantedVertices,
EdgeAttribute<typename PFP::REAL> *edgeErrors = NULL, EdgeAttribute<typename PFP::REAL> *edgeErrors = NULL,
void (*callback_wrapper)(void*, const void*) = NULL, void *callback_object = NULL void (*callback_wrapper)(void*, const void*) = NULL, void *callback_object = NULL
......
...@@ -95,6 +95,13 @@ void decimate( ...@@ -95,6 +95,13 @@ void decimate(
approximators.push_back(new Approximator_ColorQEMext<PFP>(map, attribs)) ; approximators.push_back(new Approximator_ColorQEMext<PFP>(map, attribs)) ;
} }
break; break;
case A_GeomColorOpt :
{
// pos + col
assert(attribs.size() >= 2 || !"Decimate: A_GeomColorOpt --> not enough attribs provided") ;
approximators.push_back(new Approximator_GeomColOpt<PFP>(map, attribs)) ;
}
break ;
case A_hQEM : case A_hQEM :
// pos // pos
approximators.push_back(new Approximator_QEMhalfEdge<PFP>(map, attribs)) ; approximators.push_back(new Approximator_QEMhalfEdge<PFP>(map, attribs)) ;
...@@ -190,23 +197,29 @@ void decimate( ...@@ -190,23 +197,29 @@ void decimate(
case S_hLightfield : case S_hLightfield :
selector = new HalfEdgeSelector_Lightfield<PFP>(map, position, approximators) ; selector = new HalfEdgeSelector_Lightfield<PFP>(map, position, approximators) ;
break ; break ;
case S_hLightfieldExp : case S_hLightfieldAvgColor :
selector = new HalfEdgeSelector_LightfieldExp<PFP>(map, position, approximators) ; selector = new HalfEdgeSelector_LightfieldAvgColor<PFP>(map, position, approximators) ;
break ; break ;
case S_hLightfieldKCL : case S_hLightfieldKCL :
selector = new HalfEdgeSelector_LightfieldKCL<PFP>(map, position, approximators) ; selector = new HalfEdgeSelector_LightfieldKCL<PFP>(map, position, approximators) ;
break ; break ;
case S_hColorExperimental: case S_hColorExperimental:
selector = new HalfEdgeSelector_ColorExperimental<PFP>(map, position, approximators, selected) ; selector = new HalfEdgeSelector_ColorExperimental<PFP>(map, position, approximators) ;
break ;
case S_hColorGradient:
selector = new HalfEdgeSelector_ColorGradient<PFP>(map, position, approximators) ;
break ; break ;
case S_hLFexperimental: case S_hLFexperimental:
selector = new HalfEdgeSelector_LFexperimental<PFP>(map, position, approximators, selected) ; selector = new HalfEdgeSelector_LFexperimental<PFP>(map, position, approximators) ;
break ;
case S_hLFgradient:
selector = new HalfEdgeSelector_LFgradient<PFP>(map, position, approximators) ;
break ; break ;
case S_hColorPerFace: case S_hColorPerFace:
selector = new HalfEdgeSelector_ColorPerFace<PFP>(map, position, approximators, selected) ; selector = new HalfEdgeSelector_ColorPerFace<PFP>(map, position, approximators) ;
break ; break ;
case S_hLFperFace: case S_hLFperFace:
selector = new HalfEdgeSelector_LFperFace<PFP>(map, position, approximators, selected) ; selector = new HalfEdgeSelector_LFperFace<PFP>(map, position, approximators) ;
break ; break ;
} }
......
...@@ -701,7 +701,7 @@ private: ...@@ -701,7 +701,7 @@ private:
EdgeAttribute<EdgeInfo> edgeInfo ; EdgeAttribute<EdgeInfo> edgeInfo ;
VertexAttribute<VEC3> m_pos, m_frameT, m_frameB, m_frameN ; VertexAttribute<VEC3> m_pos, m_frameT, m_frameB, m_frameN, m_avgColor ;
std::vector<VertexAttribute<VEC3> > m_HF ; std::vector<VertexAttribute<VEC3> > m_HF ;
int m_approxindex_pos, m_attrindex_pos ; int m_approxindex_pos, m_attrindex_pos ;
int m_approxindex_FN, m_attrindex_FN ; int m_approxindex_FN, m_attrindex_FN ;
...@@ -733,6 +733,8 @@ public: ...@@ -733,6 +733,8 @@ public:
edgeInfo = m.template addAttribute<EdgeInfo, EDGE>("edgeInfo") ; edgeInfo = m.template addAttribute<EdgeInfo, EDGE>("edgeInfo") ;
m_quadricGeom = m.template addAttribute<Utils::Quadric<REAL>, VERTEX>("QEMquadric") ; m_quadricGeom = m.template addAttribute<Utils::Quadric<REAL>, VERTEX>("QEMquadric") ;
m_quadricHF = m.template getAttribute<Utils::QuadricHF<REAL>, EDGE>("HFquadric") ; m_quadricHF = m.template getAttribute<Utils::QuadricHF<REAL>, EDGE>("HFquadric") ;
m_avgColor = m.template getAttribute<typename PFP::VEC3, VERTEX>("color") ;
assert(m_avgColor.isValid()) ;
} }
~EdgeSelector_Lightfield() ~EdgeSelector_Lightfield()
{ {
......
...@@ -2533,10 +2533,15 @@ void EdgeSelector_Lightfield<PFP>::computeEdgeInfo(Dart d, EdgeInfo& einfo) ...@@ -2533,10 +2533,15 @@ void EdgeSelector_Lightfield<PFP>::computeEdgeInfo(Dart d, EdgeInfo& einfo)
assert(m_quadricHF.isValid() | !"EdgeSelector_Lightfield<PFP>::computeEdgeInfo: quadricHF is not valid") ; assert(m_quadricHF.isValid() | !"EdgeSelector_Lightfield<PFP>::computeEdgeInfo: quadricHF is not valid") ;
Utils::QuadricHF<REAL> quadHF = m_quadricHF[d] ; Utils::QuadricHF<REAL> quadHF = m_quadricHF[d] ;
assert(m_avgColor.isValid()) ;
VEC3 avgColDiff = m_avgColor[d] ;
avgColDiff -= m_avgColor[dd] ;
//std::cout << quadGeom(newPos) << " vs " << alpha/M_PI << " vs " << quadHF(newHF) << std::endl ; //std::cout << quadGeom(newPos) << " vs " << alpha/M_PI << " vs " << quadHF(newHF) << std::endl ;
// sum of QEM metric and frame orientation difference // sum of QEM metric and frame orientation difference
const REAL& errG = quadGeom(newPos) ; // geom const REAL& errG = quadGeom(newPos) ; // geom
const REAL& errAngle = alpha / M_PI ; // frame //const REAL& errAngle = alpha / M_PI ; // frame
const REAL& errAngle = (alpha / M_PI) * avgColDiff.norm2() / 3. ; // avg color times covering area
const REAL& errLF = quadHF(newHF) ; // function coefficients const REAL& errLF = quadHF(newHF) ; // function coefficients
// Check if errated values appear // Check if errated values appear
...@@ -2544,7 +2549,8 @@ void EdgeSelector_Lightfield<PFP>::computeEdgeInfo(Dart d, EdgeInfo& einfo) ...@@ -2544,7 +2549,8 @@ void EdgeSelector_Lightfield<PFP>::computeEdgeInfo(Dart d, EdgeInfo& einfo)
einfo.valid = false ; einfo.valid = false ;
else else
{ {
einfo.it = edges.insert(std::make_pair(std::max(errG + errAngle + errLF, REAL(0)), d)) ; einfo.it = edges.insert(std::make_pair(std::max(errG, REAL(0)) + 10*(errAngle + errLF), d)) ;
//einfo.it = edges.insert(std::make_pair(errG+errLF+errAngle, d)) ;
einfo.valid = true ; einfo.valid = true ;
} }
} }
......
...@@ -166,16 +166,18 @@ public: ...@@ -166,16 +166,18 @@ public:
TraversorE<typename PFP::MAP> travE(this->m_map) ; TraversorE<typename PFP::MAP> travE(this->m_map) ;
for(Dart d = travE.begin() ; d != travE.end() ; d = travE.next()) for(Dart d = travE.begin() ; d != travE.end() ; d = travE.next())
{ {
(*errors)[d] = -1 ; Dart dd = this->m_map.phi2(d) ;
if (halfEdgeInfo[d].valid) if (halfEdgeInfo[d].valid)
{ {
(*errors)[d] = halfEdgeInfo[d].it->first ; (*errors)[d] = halfEdgeInfo[d].it->first ;
} }
Dart dd = this->m_map.phi2(d) ;
if (halfEdgeInfo[dd].valid && halfEdgeInfo[dd].it->first < (*errors)[d]) if (halfEdgeInfo[dd].valid && halfEdgeInfo[dd].it->first < (*errors)[d])
{ {
(*errors)[d] = halfEdgeInfo[dd].it->first ; (*errors)[d] = halfEdgeInfo[dd].it->first ;
} }
if (!(halfEdgeInfo[d].valid || halfEdgeInfo[dd].valid))
(*errors)[d] = -1 ;
} }
} }
} ; } ;
...@@ -259,16 +261,18 @@ public: ...@@ -259,16 +261,18 @@ public:
TraversorE<typename PFP::MAP> travE(this->m_map) ; TraversorE<typename PFP::MAP> travE(this->m_map) ;
for(Dart d = travE.begin() ; d != travE.end() ; d = travE.next()) for(Dart d = travE.begin() ; d != travE.end() ; d = travE.next())
{ {
(*errors)[d] = -1 ; Dart dd = this->m_map.phi2(d) ;
if (halfEdgeInfo[d].valid) if (halfEdgeInfo[d].valid)
{ {
(*errors)[d] = halfEdgeInfo[d].it->first ; (*errors)[d] = halfEdgeInfo[d].it->first ;
} }
Dart dd = this->m_map.phi2(d) ;
if (halfEdgeInfo[dd].valid && halfEdgeInfo[dd].it->first < (*errors)[d]) if (halfEdgeInfo[dd].valid && halfEdgeInfo[dd].it->first < (*errors)[d])
{ {
(*errors)[d] = halfEdgeInfo[dd].it->first ; (*errors)[d] = halfEdgeInfo[dd].it->first ;
} }
if (!(halfEdgeInfo[d].valid || halfEdgeInfo[dd].valid))
(*errors)[d] = -1 ;
} }
} }
} ; } ;
...@@ -277,7 +281,7 @@ public: ...@@ -277,7 +281,7 @@ public:
* HALF-EDGE LIGHTFIELD METRIC experimental * * HALF-EDGE LIGHTFIELD METRIC experimental *
*****************************************************************************************************************/ *****************************************************************************************************************/
template <typename PFP> template <typename PFP>
class HalfEdgeSelector_LightfieldExp : public EdgeSelector<PFP> class HalfEdgeSelector_LightfieldAvgColor : public EdgeSelector<PFP>
{ {
public: public:
typedef typename PFP::MAP MAP ; typedef typename PFP::MAP MAP ;
...@@ -317,7 +321,7 @@ private: ...@@ -317,7 +321,7 @@ private:
void recomputeQuadric(const Dart d, const bool recomputeNeighbors = false) ; void recomputeQuadric(const Dart d, const bool recomputeNeighbors = false) ;
public: public:
HalfEdgeSelector_LightfieldExp(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx) : HalfEdgeSelector_LightfieldAvgColor(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx) :
EdgeSelector<PFP>(m, pos, approx), EdgeSelector<PFP>(m, pos, approx),
m_approxindex_pos(-1), m_approxindex_pos(-1),
m_attrindex_pos(-1), m_attrindex_pos(-1),
...@@ -331,12 +335,12 @@ public: ...@@ -331,12 +335,12 @@ public:
m_avgColor = m.template getAttribute<typename PFP::VEC3, VERTEX>("color") ; m_avgColor = m.template getAttribute<typename PFP::VEC3, VERTEX>("color") ;
assert(m_avgColor.isValid()) ; assert(m_avgColor.isValid()) ;
} }
~HalfEdgeSelector_LightfieldExp() ~HalfEdgeSelector_LightfieldAvgColor()
{ {
this->m_map.removeAttribute(m_quadricGeom) ; this->m_map.removeAttribute(m_quadricGeom) ;
this->m_map.removeAttribute(halfEdgeInfo) ; this->m_map.removeAttribute(halfEdgeInfo) ;
} }
SelectorType getType() { return S_hLightfieldExp ; } SelectorType getType() { return S_hLightfieldAvgColor ; }
bool init() ; bool init() ;
bool nextEdge(Dart& d) ; bool nextEdge(Dart& d) ;
void updateBeforeCollapse(Dart d) ; void updateBeforeCollapse(Dart d) ;
...@@ -354,16 +358,18 @@ public: ...@@ -354,16 +358,18 @@ public:
TraversorE<typename PFP::MAP> travE(this->m_map) ; TraversorE<typename PFP::MAP> travE(this->m_map) ;
for(Dart d = travE.begin() ; d != travE.end() ; d = travE.next()) for(Dart d = travE.begin() ; d != travE.end() ; d = travE.next())
{ {
(*errors)[d] = -1 ; Dart dd = this->m_map.phi2(d) ;
if (halfEdgeInfo[d].valid) if (halfEdgeInfo[d].valid)
{ {
(*errors)[d] = halfEdgeInfo[d].it->first ; (*errors)[d] = halfEdgeInfo[d].it->first ;
} }
Dart dd = this->m_map.phi2(d) ;
if (halfEdgeInfo[dd].valid && halfEdgeInfo[dd].it->first < (*errors)[d]) if (halfEdgeInfo[dd].valid && halfEdgeInfo[dd].it->first < (*errors)[d])
{ {
(*errors)[d] = halfEdgeInfo[dd].it->first ; (*errors)[d] = halfEdgeInfo[dd].it->first ;
} }
if (!(halfEdgeInfo[d].valid || halfEdgeInfo[dd].valid))
(*errors)[d] = -1 ;
} }
} }
} ; } ;
...@@ -460,17 +466,18 @@ public: ...@@ -460,17 +466,18 @@ public:
TraversorE<typename PFP::MAP> travE(this->m_map) ; TraversorE<typename PFP::MAP> travE(this->m_map) ;
for(Dart d = travE.begin() ; d != travE.end() ; d = travE.next()) for(Dart d = travE.begin() ; d != travE.end() ; d = travE.next())
{ {
(*errors)[d] = -1 ; Dart dd = this->m_map.phi2(d) ;
if (halfEdgeInfo[d].valid) if (halfEdgeInfo[d].valid)
{ {
(*errors)[d] = halfEdgeInfo[d].it->first ; (*errors)[d] = halfEdgeInfo[d].it->first ;
} }
Dart dd = this->m_map.phi2(d) ;
if (halfEdgeInfo[dd].valid && halfEdgeInfo[dd].it->first < (*errors)[d]) if (halfEdgeInfo[dd].valid && halfEdgeInfo[dd].it->first < (*errors)[d])
{ {
(*errors)[dd] = halfEdgeInfo[dd].it->first ; (*errors)[d] = halfEdgeInfo[dd].it->first ;
} }
//m_avgColor[d] = VEC3(m_visualImportance[d]/6.,m_visualImportance[d]/6.,m_visualImportance[d]/6.) ; if (!(halfEdgeInfo[d].valid || halfEdgeInfo[dd].valid))
(*errors)[d] = -1 ;
} }
}