Commit 62aec045 authored by Kenneth Vanhoey's avatar Kenneth Vanhoey

big commit sur selectors/approximator (non fini pour la partie champ de lumière)

parent 0d36fdf8
......@@ -45,12 +45,11 @@ enum ApproximatorType
A_TangentPredict2,
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,
A_hLightfield
A_hQEM
// A_hLightfieldHalf,
} ;
template <typename PFP>
......
......@@ -48,6 +48,7 @@ public:
protected:
VertexAttribute<VEC3> m_position ;
EdgeAttribute<VEC3> m_approxposition ;
VertexAttribute<VEC3> *m_color ;
public:
......@@ -55,13 +56,6 @@ public:
Approximator<PFP, VEC3>(m, attr, pred)
{
m_color = this->m_attrV[0] ;
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_ColorNaive()
{}
......@@ -73,7 +67,15 @@ public:
bool init()
{
return true ;
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::init: the position attribute is not valid") ;
m_approxposition = this->m_map.template getAttribute<VEC3, EDGE>("approx_position") ;
assert(m_approxposition.isValid() || !"Approximator_ColorNaive::init: the approx_position attribute is not valid") ;
return m_color->isValid() && m_position.isValid() && m_approxposition.isValid() ;
}
void approximate(Dart d) ;
......@@ -102,6 +104,7 @@ public:
m_position = this->m_attrV[0] ;
m_color = this->m_attrV[1] ;
}
~Approximator_ColorQEMext()
{}
......
......@@ -57,12 +57,14 @@ template <typename PFP>
bool Approximator_ColorQEMext<PFP>::init()
{
m_quadric = this->m_map.template getAttribute<QuadricNd<REAL,6>, VERTEX>("QEMext-quadric") ;
// Does not require to be valid (if it is not, altenatives will be used).
if(this->m_predictor)
{
return false ;
}
return true ;
return m_position->isValid() && m_color->isValid() ;
}
template <typename PFP>
......
......@@ -93,6 +93,7 @@ void decimate(
approximators.push_back(new Approximator_QEMhalfEdge<PFP>(map, attribs)) ;
break ;
// case A_hLightfieldHalf:
// {
// v_approx = new std::vector<VertexAttribute<typename PFP::VEC3>* >[3] ;
//
// // pos
......@@ -110,25 +111,29 @@ void decimate(
// for (unsigned int i = 0 ; i < attribs.size() - 4 ; ++i)
// v_approx[2].push_back(attribs[i+4]) ;
// approximators.push_back(new Approximator_LightfieldCoefsHalf<PFP>(map, v_approx[2])) ;
// }
// break ;
case A_hLightfield :
case A_Lightfield :
{
// pos + frame + hemifunction
approximators.push_back(new Approximator_HalfCollapse<PFP>(map, attribs)) ;
}
break ;
/*
case A_LightfieldFull_deprecated :
{
approximators.push_back(new Approximator_QEMhalfEdge<PFP>(map, position)) ;
v_approx = new std::vector<VertexAttribute<typename PFP::VEC3>* >[3] ;
VertexAttribute<Geom::Matrix<3,3,typename PFP::REAL> > frame = map.template getAttribute<Geom::Matrix<3,3,typename PFP::REAL>, VERTEX>("frame") ;
VertexAttribute<Geom::Matrix<3,6,typename PFP::REAL> > RGBfunctions = map.template getAttribute<Geom::Matrix<3,6,typename PFP::REAL>, VERTEX>("colorPTM") ;
approximators.push_back(new Approximator_Frame_deprecated<PFP>(map, frame)) ;
approximators.push_back(new Approximator_RGBfunctions_deprecated<PFP>(map, RGBfunctions)) ;
break ;
// pos
v_approx[0].push_back(attribs[0]) ;
approximators.push_back(new Approximator_QEM<PFP>(map, v_approx[0])) ;
// frame
assert(attribs.size() >= 4 || !"Decimate: A_Lightfield --> not enough attribs provided") ;
for (unsigned int i = 0 ; i < 3 ; ++i)
v_approx[1].push_back(attribs[i+1]) ;
approximators.push_back(new Approximator_FrameInterpolation<PFP>(map, v_approx[1])) ;
// hemifunction
assert(attribs.size() >= 5 || !"Decimate: A_Lightfield --> not enough attribs provided") ;
for (unsigned int i = 0 ; i < attribs.size() - 4 ; ++i)
v_approx[2].push_back(attribs[i+4]) ;
approximators.push_back(new Approximator_HemiFuncCoefs<PFP>(map, v_approx[2])) ;
}
*/
break ;
}
switch(s)
......@@ -163,8 +168,8 @@ void decimate(
case S_hQEMml :
selector = new HalfEdgeSelector_QEMml<PFP>(map, position, approximators, selected) ;
break ;
case S_hLightfield :
selector = new HalfEdgeSelector_Lightfield<PFP>(map, position, approximators, selected) ;
case S_Lightfield :
selector = new EdgeSelector_Lightfield<PFP>(map, position, approximators, selected) ;
break ;
}
......
......@@ -502,6 +502,72 @@ public:
void updateAfterCollapse(Dart d2, Dart dd2) ;
} ;
/*****************************************************************************************************************
* LIGHTFIELD QUADRIC ERROR METRIC *
*****************************************************************************************************************/
template <typename PFP>
class EdgeSelector_Lightfield : public EdgeSelector<PFP>
{
public:
typedef typename PFP::MAP MAP ;
typedef typename PFP::REAL REAL ;
typedef typename PFP::VEC3 VEC3 ;
typedef typename Geom::Vector<6,REAL> VEC6 ;
private:
typedef struct
{
typename std::multimap<float,Dart>::iterator it ;
bool valid ;
static std::string CGoGNnameOfType() { return "QEMextColorEdgeInfo" ; }
} QEMextColorEdgeInfo ;
typedef NoMathIOAttribute<QEMextColorEdgeInfo> EdgeInfo ;
EdgeAttribute<EdgeInfo> edgeInfo ;
VertexAttribute<VEC3> m_pos, m_frameT, m_frameB, m_frameN ;
//VertexAttribute<VEC3> *m_HF ;
int m_approxindex_pos, m_attrindex_pos ;
int m_approxindex_FN, m_attrindex_FN ;
VertexAttribute<Quadric<REAL> > m_quadricGeom ;
VertexAttribute<QuadricHF<REAL> > m_quadricHF ;
std::vector<Approximator<PFP, typename PFP::VEC3>* > m_approx ;
std::multimap<float,Dart> edges ;
typename std::multimap<float,Dart>::iterator cur ;
void initEdgeInfo(Dart d) ;
void updateEdgeInfo(Dart d, bool recompute) ;
void computeEdgeInfo(Dart d,EdgeInfo& einfo) ;
void recomputeQuadric(const Dart d, const bool recomputeNeighbors = false) ;
public:
EdgeSelector_Lightfield(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select = allDarts) :
EdgeSelector<PFP>(m, pos, approx, select),
m_approxindex_pos(-1),
m_attrindex_pos(-1),
m_approxindex_FN(-1),
m_attrindex_FN(-1)
{
edgeInfo = m.template addAttribute<EdgeInfo, EDGE>("edgeInfo") ;
m_quadricGeom = m.template addAttribute<Quadric<REAL>, VERTEX>("QEMquadric") ;
m_quadricHF = m.template addAttribute<QuadricHF<REAL>, VERTEX>("HFquadric") ;
}
~EdgeSelector_Lightfield()
{
this->m_map.removeAttribute(edgeInfo) ;
this->m_map.removeAttribute(m_quadricGeom) ;
this->m_map.removeAttribute(m_quadricHF) ;
}
SelectorType getType() { return S_Lightfield ; }
bool init() ;
bool nextEdge(Dart& d) ;
void updateBeforeCollapse(Dart d) ;
void updateAfterCollapse(Dart d2, Dart dd2) ;
} ;
} // namespace Decimation
} // namespace Algo
......
......@@ -1106,7 +1106,7 @@ bool EdgeSelector_ColorNaive<PFP>::init()
assert(this->m_approximators[0]->getType() != A_hQEM || !"Approximator(hQEM) and selector (ColorNaive) are not compatible") ;
assert(this->m_approximators[0]->getType() != A_hHalfCollapse || !"Approximator(hHalfCollapse) and selector (ColorNaive) are not compatible") ;
assert(this->m_approximators[0]->getType() != A_hLightfieldHalf || !"Approximator(hLightfieldHalf) and selector (ColorNaive) are not compatible") ;
assert(this->m_approximators[0]->getType() != A_Lightfield || !"Approximator(hLightfield) and selector (ColorNaive) are not compatible") ;
// Verify availability of required approximators
unsigned int ok = 0 ;
......@@ -1373,7 +1373,6 @@ bool EdgeSelector_QEMextColor<PFP>::init()
assert(this->m_approximators[0]->getType() != A_hQEM || !"Approximator(hQEM) and selector (ColorNaive) are not compatible") ;
assert(this->m_approximators[0]->getType() != A_hHalfCollapse || !"Approximator(hHalfCollapse) and selector (ColorNaive) are not compatible") ;
assert(this->m_approximators[0]->getType() != A_hLightfieldHalf || !"Approximator(hLightfieldHalf) and selector (ColorNaive) are not compatible") ;
// Verify availability of required approximators
unsigned int ok = 0 ;
......@@ -1660,6 +1659,326 @@ void EdgeSelector_QEMextColor<PFP>::computeEdgeInfo(Dart d, EdgeInfo& einfo)
}
}
/*****************************************************************************************************************
* LIGHTFIELD QUADRIC ERROR METRIC *
*****************************************************************************************************************/
template <typename PFP>
bool EdgeSelector_Lightfield<PFP>::init()
{
MAP& m = this->m_map ;
assert(this->m_approximators[0]->getType() != A_hQEM || !"Approximator(hQEM) and selector (ColorNaive) are not compatible") ;
assert(this->m_approximators[0]->getType() != A_hHalfCollapse || !"Approximator(hHalfCollapse) and selector (ColorNaive) are not compatible") ;
// Verify availability of required approximators
unsigned int ok = 0 ;
for (unsigned int approxindex = 0 ; approxindex < this->m_approximators.size() ; ++approxindex)
{
bool saved = false ;
for (unsigned int attrindex = 0 ; attrindex < this->m_approximators[approxindex]->getNbApproximated() ; ++ attrindex)
{
// constraint : 2 approximators in specific order
if(ok == 0 && this->m_approximators[approxindex]->getApproximatedAttributeName(attrindex) == "position")
{
++ok ;
m_approxindex_pos = approxindex ;
m_attrindex_pos = attrindex ;
m_pos = this->m_position ;
if (!saved)
{
m_approx.push_back(reinterpret_cast<Approximator<PFP, VEC3>* >(this->m_approximators[approxindex])) ;
saved = true ;
}
}
else if(ok == 1 && this->m_approximators[approxindex]->getApproximatedAttributeName(attrindex) == "frameT")
{
++ok ;
// m_approxindex_FT = approxindex ;
// m_attrindex_FT = attrindex ;
m_frameT = m.template getAttribute<typename PFP::VEC3, VERTEX>("frameT") ;
if (!saved)
{
m_approx.push_back(reinterpret_cast<Approximator<PFP, VEC3>* >(this->m_approximators[approxindex])) ;
assert(m_frameT.isValid() || !"EdgeSelector_QEMextColor: frameT attribute is not valid") ;
saved = true ;
}
}
else if(ok == 2 && this->m_approximators[approxindex]->getApproximatedAttributeName(attrindex) == "frameB")
{
++ok ;
// m_approxindex_FB = approxindex ;
// m_attrindex_FB = attrindex ;
m_frameB = m.template getAttribute<typename PFP::VEC3, VERTEX>("frameB") ;
assert(m_frameB.isValid() || !"EdgeSelector_QEMextColor: frameB attribute is not valid") ;
if (!saved)
{
m_approx.push_back(reinterpret_cast<Approximator<PFP, VEC3>* >(this->m_approximators[approxindex])) ;
saved = true ;
}
}
else if(ok == 3 && this->m_approximators[approxindex]->getApproximatedAttributeName(attrindex) == "frameN")
{
++ok ;
m_approxindex_FN = approxindex ;
m_attrindex_FN = attrindex ;
m_frameN = m.template getAttribute<typename PFP::VEC3, VERTEX>("frameN") ;
assert(m_frameN.isValid() || !"EdgeSelector_QEMextColor: frameN attribute is not valid") ;
if (!saved)
{
m_approx.push_back(reinterpret_cast<Approximator<PFP, VEC3>* >(this->m_approximators[approxindex])) ;
saved = true ;
}
}
}
}
if(ok != 4)
return false ;
TraversorV<MAP> travV(m);
for(Dart dit = travV.begin() ; dit != travV.end() ; dit = travV.next())
{
Quadric<REAL> q ; // create one quadric
m_quadricGeom[dit] = q ; // per vertex
}
// Compute quadric per vertex
TraversorF<MAP> travF(m) ;
for(Dart dit = travF.begin() ; dit != travF.end() ; dit = travF.next()) // init QEM quadrics
{
Dart d1 = m.phi1(dit) ; // for each triangle,
Dart d_1 = m.phi_1(dit) ; // initialize the quadric of the triangle
Quadric<REAL> q(this->m_position[dit], this->m_position[d1], this->m_position[d_1]) ;
m_quadricGeom[dit] += q ; // and add the contribution of
m_quadricGeom[d1] += q ; // this quadric to the ones
m_quadricGeom[d_1] += q ; // of the 3 incident vertices
}
TraversorE<MAP> travE(m);
for(Dart dit = travE.begin() ; dit != travE.end() ; dit = travE.next())
{
initEdgeInfo(dit) ; // init the edges with their optimal position
// and insert them in the multimap according to their error
}
cur = edges.begin() ; // init the current edge to the first one
return true ;
}
template <typename PFP>
bool EdgeSelector_Lightfield<PFP>::nextEdge(Dart& d)
{
if(cur == edges.end() || edges.empty())
return false ;
d = (*cur).second ;
return true ;
}
template <typename PFP>
void EdgeSelector_Lightfield<PFP>::updateBeforeCollapse(Dart d)
{
MAP& m = this->m_map ;
EdgeInfo& edgeE = edgeInfo[d] ;
if(edgeE.valid)
edges.erase(edgeE.it) ;
edgeE = edgeInfo[m.phi1(d)] ;
if(edgeE.valid) // remove all
edges.erase(edgeE.it) ;
edgeE = edgeInfo[m.phi_1(d)] ; // the edges that will disappear
if(edgeE.valid)
edges.erase(edgeE.it) ;
// from the multimap
Dart dd = m.phi2(d) ;
if(dd != d)
{
edgeE = edgeInfo[m.phi1(dd)] ;
if(edgeE.valid)
edges.erase(edgeE.it) ;
edgeE = edgeInfo[m.phi_1(dd)] ;
if(edgeE.valid)
edges.erase(edgeE.it) ;
}
}
/**
* Update quadric of a vertex
* Discards quadrics of d and assigns freshly calculated
* quadrics depending on the actual planes surrounding d
* @param dart d
*/
template <typename PFP>
void EdgeSelector_Lightfield<PFP>::recomputeQuadric(const Dart d, const bool recomputeNeighbors)
{
Dart dFront,dBack ;
Dart dInit = d ;
//todo
// Init Front
dFront = dInit ;
m_quadricGeom[d].zero() ;
do
{
// Make step
dBack = this->m_map.phi2(dFront) ;
dFront = this->m_map.phi2_1(dFront) ;
if (dBack != dFront)
{ // if dFront is no border
m_quadricGeom[d] += Quadric<REAL>(m_pos[d],m_pos[this->m_map.phi1(dFront)],m_pos[dBack]) ;
}
if (recomputeNeighbors)
recomputeQuadric(dBack, false) ;
} while(dFront != dInit) ;
}
template <typename PFP>
void EdgeSelector_Lightfield<PFP>::updateAfterCollapse(Dart d2, Dart dd2)
{
MAP& m = this->m_map ;
//todo
recomputeQuadric(d2, true) ;
Dart vit = d2 ;
do
{
updateEdgeInfo(m.phi1(vit), true) ; // must recompute some edge infos in the
if(vit == d2 || vit == dd2) // neighborhood of the collapsed edge
initEdgeInfo(vit) ; // various optimizations are applied here by
else // treating differently :
updateEdgeInfo(vit, true) ;
Dart vit2 = m.phi12(m.phi1(vit)) ; // - edges for which the criteria must be recomputed
Dart stop = m.phi2(vit) ; // - edges that must be re-embedded
do // - edges for which only the collapsibility must be re-tested
{
updateEdgeInfo(vit2, true) ;
updateEdgeInfo(m.phi1(vit2), false) ;
vit2 = m.phi12(vit2) ;
} while(vit2 != stop) ;
vit = m.phi2_1(vit) ;
} while(vit != d2) ;
cur = edges.begin() ; // set the current edge to the first one
}
template <typename PFP>
void EdgeSelector_Lightfield<PFP>::initEdgeInfo(Dart d)
{
MAP& m = this->m_map ;
EdgeInfo einfo ;
if(m.edgeCanCollapse(d))
computeEdgeInfo(d, einfo) ;
else
einfo.valid = false ;
edgeInfo[d] = einfo ;
}
template <typename PFP>
void EdgeSelector_Lightfield<PFP>::updateEdgeInfo(Dart d, bool recompute)
{
MAP& m = this->m_map ;
EdgeInfo& einfo = edgeInfo[d] ;
if(recompute)
{
if(einfo.valid)
edges.erase(einfo.it) ; // remove the edge from the multimap
if(m.edgeCanCollapse(d))
computeEdgeInfo(d, einfo) ;
else
einfo.valid = false ;
}
else
{
if(m.edgeCanCollapse(d))
{ // if the edge can be collapsed now
if(!einfo.valid) // but it was not before
computeEdgeInfo(d, einfo) ;
}
else
{ // if the edge cannot be collapsed now
if(einfo.valid) // and it was before
{
edges.erase(einfo.it) ;
einfo.valid = false ;
}
}
}
}
template <typename PFP>
void EdgeSelector_Lightfield<PFP>::computeEdgeInfo(Dart d, EdgeInfo& einfo)
{
MAP& m = this->m_map ;
Dart dd = m.phi1(d) ;
// New position
Quadric<REAL> quad ;
quad += m_quadricGeom[d] ; // compute the sum of the
quad += m_quadricGeom[dd] ; // two vertices quadrics
// compute all approximated attributes
for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = this->m_approximators.begin() ;
it != this->m_approximators.end() ;
++it)
{
(*it)->approximate(d) ;
}
// Get all approximated attributes
// New position
const VEC3& newPos = this->m_approx[m_approxindex_pos]->getApprox(d,m_attrindex_pos) ; // get newPos
// New normal
const VEC3& newFN = this->m_approx[m_approxindex_FN]->getApprox(d,m_attrindex_FN) ; // get new frameN
// New function
// todo const VEC3& hfcoefs0 = this->m_approximators[m_approxindex_hf]->getApprox(d,m_attrindex_hf[0]) ; // get newHFcoefs0
// todo const VEC3& hfcoefs1 = this->m_approximators[m_approxindex_hf]->getApprox(d,m_attrindex_hf[1]) ; // get newHFcoefs1
// todo const VEC3& hfcoefs2 = this->m_approximators[m_approxindex_hf]->getApprox(d,m_attrindex_hf[2]) ; // get newHFcoefs2
// ...
// todo const VEC3& hfcoefsK = this->m_approximators[m_approxindex_hf]->getApprox(d,m_attrindex_hf[K]) ; // get newHFcoefsK
// Compute errors
// Position
Quadric<REAL> quadGeom ;
quadGeom += m_quadricGeom[d] ; // compute the sum of the
quadGeom += m_quadricGeom[dd] ; // two vertices quadrics
// hemisphere difference error
double scal1 = abs(double(m_frameN[d] * newFN)) ;
scal1 = std::min(scal1, double(1)) ; // for epsilon normalization of newFN errors
// angle 2
double scal2 = abs(double(m_frameN[dd] * newFN)) ;
scal2 = std::min(scal2, double(1)) ;
// Important: sum of abs values works only if newFN is in-between the two old ones (interpolated).
// This avoids computation of the sign of alpha1 and alpha2.
double alpha = acos(scal1 + scal2) ;
std::cout << quadGeom(newPos) << " vs " << alpha/M_PI << std::endl ;
// sum of QEM metric and frame orientation difference
const REAL& err =
quadGeom(newPos) // geom
+ alpha / M_PI // frame
// todo+ quadHF(newHF) // function coefficients
;
// Check if errated values appear
if (err < -1e-6)
einfo.valid = false ;
else
{
einfo.it = edges.insert(std::make_pair(std::max(err,REAL(0)), d)) ;
einfo.valid = true ;
}
}
} // namespace Decimation
......
......@@ -38,6 +38,7 @@ template <typename PFP>
bool Approximator_QEM<PFP>::init()
{
m_quadric = this->m_map.template getAttribute<Quadric<REAL>, VERTEX>("QEMquadric") ;
// Does not require to be valid (if it is not, altenatives will be used).
if(this->m_predictor)
{
......
......@@ -89,77 +89,77 @@ public:
void updateAfterCollapse(Dart d2, Dart dd2) ;
} ;
/*****************************************************************************************************************
* HALF-EDGE LIGHTFIELD METRIC *
*****************************************************************************************************************/
template <typename PFP>
class HalfEdgeSelector_Lightfield : 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>::iterator it ;
bool valid ;
static std::string CGoGNnameOfType() { return "LightfieldHalfEdgeInfo" ; }
} QEMhalfEdgeInfo ;
typedef NoMathIOAttribute<QEMhalfEdgeInfo> HalfEdgeInfo ;
DartAttribute<HalfEdgeInfo> halfEdgeInfo ;
VertexAttribute<VEC3> m_pos, m_frameT, m_frameB, m_frameN ;
//VertexAttribute<VEC3> *m_HF ;
int m_approxindex_pos, m_attrindex_pos ;
int m_approxindex_FN, m_attrindex_FN ;
VertexAttribute<Quadric<REAL> > m_quadricGeom ;
VertexAttribute<QuadricHF<REAL> > m_quadricHF ;
std::multimap<float,Dart> halfEdges ;
typename std::multimap<float,Dart>::iterator cur ;
std::vector<Approximator<PFP, typename PFP::VEC3>* > m_approx ;
void initHalfEdgeInfo(Dart d) ;
void updateHalfEdgeInfo(Dart d, bool recompute) ;
void computeHalfEdgeInfo(Dart d, HalfEdgeInfo& einfo) ;
void recomputeQuadric(const Dart d, const bool recomputeNeighbors = false) ;