Commit 49e7e333 authored by Kenneth Vanhoey's avatar Kenneth Vanhoey

passed to new container format for plyptm : good for glsl (only vec3)

parent 195e3fc5
......@@ -44,6 +44,7 @@ enum ApproximatorType
A_CornerCutting,
A_TangentPredict1,
A_TangentPredict2,
A_LightfieldHalf,
A_LightfieldFull
} ;
......
......@@ -71,11 +71,11 @@ void decimate(
}
case A_LightfieldHalf :
{
approximators.push_back(new Approximator_QEM<PFP>(map, position)) ;
approximators.push_back(new Approximator_HalfCollapse<PFP>(map, position)) ;
AttributeHandler<Geom::Matrix<3,3,typename PFP::REAL> > frame = map.template getAttribute<Geom::Matrix<3,3,typename PFP::REAL> >(VERTEX_ORBIT, "frame") ;
AttributeHandler<Geom::Matrix<3,6,typename PFP::REAL> > RGBfunctions = map.template getAttribute<Geom::Matrix<3,6,typename PFP::REAL> >(VERTEX_ORBIT, "colorPTM") ;
approximators.push_back(new Approximator_FrameHalf<PFP>(map, frame)) ;
approximators.push_back(new Approximator_RGBfunctions<PFP>(map, RGBfunctions)) ;
approximators.push_back(new Approximator_RGBfunctionsHalf<PFP>(map, RGBfunctions)) ;
break ;
}
}
......@@ -91,12 +91,18 @@ void decimate(
case S_EdgeLength :
selector = new EdgeSelector_Length<PFP>(map, position, approximators) ;
break ;
case S_QEMml :
selector = new EdgeSelector_QEMml<PFP>(map, position, approximators) ;
break ;
case S_QEM :
selector = new EdgeSelector_QEM<PFP>(map, position, approximators) ;
break ;
case S_Lightfield :
selector = new EdgeSelector_Lightfield<PFP>(map, position, approximators) ;
break ;
case S_LightfieldHalf :
selector = new HalfEdgeSelector_Lightfield<PFP>(map, position, approximators) ;
break ;
case S_Curvature :
selector = new EdgeSelector_Curvature<PFP>(map, position, approximators) ;
break ;
......
......@@ -36,6 +36,55 @@ namespace Algo
namespace Decimation
{
template <typename PFP>
class Approximator_FrameHalf : public Approximator<PFP, typename Geom::Matrix<3,3,typename PFP::REAL> >
{
public:
typedef typename PFP::MAP MAP ;
typedef typename PFP::VEC3 VEC3 ;
typedef typename PFP::REAL REAL ;
typedef Geom::Matrix<3,3,REAL> MATRIX33 ;
typedef Geom::Matrix<3,6,REAL> MATRIX36 ;
public:
Approximator_FrameHalf(MAP& m, AttributeHandler<MATRIX33>& frame, Predictor<PFP, MATRIX33>* pred = NULL) :
Approximator<PFP, MATRIX33>(m, frame, EDGE_ORBIT, pred)
{}
~Approximator_FrameHalf()
{}
ApproximatorType getType() const { return A_LightfieldHalf ; }
bool init() { return true ; } ;
void approximate(Dart d) ;
} ;
template <typename PFP>
class Approximator_RGBfunctionsHalf : public Approximator<PFP, typename Geom::Matrix<3,6,typename PFP::REAL> >
{
public:
typedef typename PFP::MAP MAP ;
typedef typename PFP::VEC3 VEC3 ;
typedef typename PFP::REAL REAL ;
typedef Geom::Matrix<3,3,REAL> MATRIX33 ;
typedef Geom::Matrix<3,6,REAL> MATRIX36 ;
protected:
AttributeHandler<MATRIX33> m_frame ;
AttributeHandler<MATRIX33> m_approxFrame ;
AttributeHandler<QuadricRGBfunctions<REAL> > m_quadricRGBfunctions ;
public:
Approximator_RGBfunctionsHalf(MAP& m, AttributeHandler<MATRIX36>& rgbfunctions, Predictor<PFP, MATRIX36>* pred = NULL) :
Approximator<PFP, MATRIX36>(m, rgbfunctions, EDGE_ORBIT, pred)
{ }
~Approximator_RGBfunctionsHalf ()
{}
ApproximatorType getType() const { return A_LightfieldHalf ; }
bool init() ;
void approximate(Dart d) ;
} ;
template <typename PFP>
class Approximator_Frame : public Approximator<PFP, typename Geom::Matrix<3,3,typename PFP::REAL> >
{
......
......@@ -31,6 +31,96 @@ namespace Algo
namespace Decimation
{
/************************************************************************************
* LIGHTFIELD QUADRIC METRIC : frame *
************************************************************************************/
template <typename PFP>
void Approximator_FrameHalf<PFP>::approximate(Dart d)
{
this->m_approx[d] = this->m_attrV[d] ;
}
/************************************************************************************
* LIGHTFIELD QUADRIC METRIC : functions *
************************************************************************************/
template <typename PFP>
bool Approximator_RGBfunctionsHalf<PFP>::init()
{
// get actual frames and hypothetical approximated frames
m_frame = this->m_map.template getAttribute<MATRIX33>(VERTEX_ORBIT, "frame") ;
m_approxFrame = this->m_map.template getAttribute<MATRIX33>(EDGE_ORBIT, "approx_frame") ;
m_quadricRGBfunctions = this->m_map.template getAttribute<QuadricRGBfunctions<REAL> >(EDGE_ORBIT, "quadricRGBfunctions") ;
MapBrowserLinkedAuto<typename PFP::MAP> mb(this->m_map) ;
this->m_map.foreach_orbit(EDGE_ORBIT, mb) ;
// create quadric embedding for computing and set them to 0
for (Dart d = mb.begin() ; d != mb.end() ; mb.next(d))
m_quadricRGBfunctions[d].zero() ;
// Check on embeddings
if (!m_frame.isValid() || !m_approxFrame.isValid() || !m_quadricRGBfunctions.isValid())
{
std::cerr << "Approximator_RGBfunctions::init() --> No approxPosition or no quadricRGBfunctions specified" << std::endl ;
return false ;
}
return true ;
}
template <typename PFP>
void Approximator_RGBfunctionsHalf<PFP>::approximate(Dart d)
{
MAP& m = this->m_map ;
Dart dd = m.phi2(d) ; // get the two vertices
// Approximation
this->m_approx[d] = this->m_attrV[d] ;
// Compute quadrics for error evaluation
// get hypothetical local frames
VEC3 i,n ;
m_approxFrame[d].getSubVectorH(0,0,i) ;
m_approxFrame[d].getSubVectorH(2,0,n) ;
// Get previous local frames
VEC3 n1,n2,i1,i2,j1,j2 ;
m_frame[d].getSubVectorH(0,0,i1) ;
m_frame[dd].getSubVectorH(0,0,i2) ;
m_frame[d].getSubVectorH(1,0,j1) ;
m_frame[dd].getSubVectorH(1,0,j2) ;
m_frame[d].getSubVectorH(2,0,n1) ;
m_frame[dd].getSubVectorH(2,0,n2) ;
// Compute j1' and j2'
VEC3 j1pr = n1 ^ i ;
j1pr.normalize() ;
VEC3 j2pr = n2 ^ i ;
j2pr.normalize() ;
// Rotation dans sens trigo dans le plan tangent autour de n (i1->i)
// REAL gamma1 = ((j1 * i) > 0 ? 1 : -1) * acos( std::max(std::min(1.0f, i1 * i ), -1.0f)) ; // angle positif ssi
REAL gamma2 = ((j2 * i) > 0 ? 1 : -1) * acos( std::max(std::min(1.0f, i2 * i ), -1.0f)) ; // -PI/2 < angle(i,j1) < PI/2 ssi i*j1 > 0
// Rotation dans le sens trigo autour de l'axe i (n1->n)
// REAL alpha1 = ((n * j1pr) > 0 ? -1 : 1) * acos( std::max(std::min(1.0f, n * n1), -1.0f) ) ; // angle positif ssi
REAL alpha2 = ((n * j2pr) > 0 ? -1 : 1) * acos( std::max(std::min(1.0f, n * n2), -1.0f) ) ; // PI/2 < angle(j1',n) < -PI/2 ssi j1'*n < 0
// assert (-0.01 < gamma1 && gamma1 < 0.01) ;
// assert (-0.01 < alpha1 && alpha1 < 0.01) ;
REAL gamma1 = REAL(0) ;
REAL alpha1 = REAL(0) ;
// Create and sum quadrics
m_quadricRGBfunctions[d] += QuadricRGBfunctions<REAL>(this->m_attrV[d], gamma1, alpha1) ;
m_quadricRGBfunctions[d] += QuadricRGBfunctions<REAL>(this->m_attrV[dd], gamma2, alpha2) ;
}
/************************************************************************************
* LIGHTFIELD QUADRIC METRIC : frame *
************************************************************************************/
......@@ -106,8 +196,11 @@ bool Approximator_RGBfunctions<PFP>::init()
m_approxFrame = this->m_map.template getAttribute<MATRIX33>(EDGE_ORBIT, "approx_frame") ;
m_quadricRGBfunctions = this->m_map.template getAttribute<QuadricRGBfunctions<REAL> >(EDGE_ORBIT, "quadricRGBfunctions") ;
MapBrowserLinkedAuto<typename PFP::MAP> mb(this->m_map) ;
this->m_map.foreach_orbit(EDGE_ORBIT, mb) ;
// create quadric embedding for computing and set them to 0
for (Dart d = this->m_map.begin() ; d != this->m_map.end() ; this->m_map.next(d))
for (Dart d = mb.begin() ; d != mb.end() ; mb.next(d))
m_quadricRGBfunctions[d].zero() ;
// Check on embeddings
......
......@@ -46,9 +46,11 @@ enum SelectorType
S_Random,
S_EdgeLength,
S_QEM,
S_QEMml,
S_MinDetail,
S_Curvature,
S_Lightfield
S_Lightfield,
S_LightfieldHalf
} ;
......@@ -228,6 +230,120 @@ public:
void updateAfterCollapse(Dart d2, Dart dd2) ;
} ;
template <typename PFP>
class EdgeSelector_QEMml : 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 "QEMedgeInfo" ; }
} QEMedgeInfo ;
typedef NoMathIOAttribute<QEMedgeInfo> EdgeInfo ;
AttributeHandler<EdgeInfo> edgeInfo ;
AttributeHandler<Quadric<REAL> > quadric ;
std::multimap<float,Dart> edges ;
typename std::multimap<float,Dart>::iterator cur ;
Approximator<PFP, typename PFP::VEC3>* m_positionApproximator ;
void initEdgeInfo(Dart d) ;
void updateEdgeInfo(Dart d, bool recompute) ;
void computeEdgeInfo(Dart d, EdgeInfo& einfo) ;
void recomputeQuadric(const Dart d, const bool neighbours = false) ;
Dart rewind(const Dart d) ;
public:
EdgeSelector_QEMml(MAP& m, typename PFP::TVEC3& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select = SelectorTrue()) :
EdgeSelector<PFP>(m, pos, approx, select)
{
edgeInfo = m.template addAttribute<EdgeInfo>(EDGE_ORBIT, "edgeInfo") ;
quadric = m.template addAttribute<Quadric<REAL> >(VERTEX_ORBIT, "QEMquadric") ;
}
~EdgeSelector_QEMml()
{
this->m_map.removeAttribute(quadric) ;
this->m_map.removeAttribute(edgeInfo) ;
}
SelectorType getType() { return S_QEM ; }
bool init() ;
bool nextEdge(Dart& d) ;
void updateBeforeCollapse(Dart d) ;
void updateAfterCollapse(Dart d2, Dart dd2) ;
} ;
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 ;
typedef Geom::Matrix<3,3,REAL> MATRIX33 ;
typedef MATRIX33 FRAME ;
typedef Geom::Matrix<3,6,REAL> MATRIX36 ;
typedef MATRIX36 RGBFUNCTIONS ;
private:
typedef struct
{
typename std::multimap<float,Dart>::iterator it ;
bool valid ;
static std::string CGoGNnameOfType() { return "LightfieldHalfEdgeInfo" ; }
} LightfieldHalfEdgeInfo ;
typedef NoMathIOAttribute<LightfieldHalfEdgeInfo> HalfEdgeInfo ;
AttributeHandler<FRAME > m_frame ;
AttributeHandler<HalfEdgeInfo> halfEdgeInfo ;
AttributeHandler<Quadric<REAL> > quadric ;
AttributeHandler<QuadricRGBfunctions<REAL> > quadricRGBfunctions ;
std::multimap<float,Dart> halfEdges ;
typename std::multimap<float,Dart>::iterator cur ;
Approximator<PFP, VEC3>* m_positionApproximator ;
Approximator<PFP, FRAME >* m_frameApproximator ;
Approximator<PFP, RGBFUNCTIONS >* m_RGBfunctionsApproximator ;
void initHalfEdgeInfo(Dart d) ;
void updateHalfEdgeInfo(Dart d, bool recompute) ;
void computeHalfEdgeInfo(Dart d, HalfEdgeInfo& einfo) ;
void recomputeQuadric(const Dart d, const bool neighbors) ;
Dart rewind(const Dart d) ;
public:
HalfEdgeSelector_Lightfield(MAP& m, typename PFP::TVEC3& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select = SelectorTrue()) :
EdgeSelector<PFP>(m, pos, approx, select)
{
m_frame = m.template getAttribute<FRAME>(VERTEX_ORBIT, "frame") ;
halfEdgeInfo = m.template addAttribute<HalfEdgeInfo>(DART_ORBIT, "halfEdgeInfo") ;
quadric = m.template addAttribute<Quadric<REAL> >(VERTEX_ORBIT, "QEMquadric") ;
quadricRGBfunctions = m.template addAttribute<QuadricRGBfunctions<REAL> >(EDGE_ORBIT, "quadricRGBfunctions") ;
}
~HalfEdgeSelector_Lightfield()
{
this->m_map.removeAttribute(quadric) ;
this->m_map.removeAttribute(quadricRGBfunctions) ;
this->m_map.removeAttribute(halfEdgeInfo) ;
}
SelectorType getType() { return S_Lightfield ; }
bool init() ;
bool nextEdge(Dart& d) ;
void updateBeforeCollapse(Dart d) ;
void updateAfterCollapse(Dart d2, Dart dd2) ;
} ;
template <typename PFP>
class EdgeSelector_Lightfield : public EdgeSelector<PFP>
{
......
......@@ -404,9 +404,9 @@ void EdgeSelector_QEM<PFP>::updateAfterCollapse(Dart d2, Dart dd2)
do // - edges for which only the collapsibility must be re-tested
{
updateEdgeInfo(vit2, false) ;
updateEdgeInfo(m.phi1(vit2), false) ;
updateEdgeInfo(m.phi1(vit2), false) ; // OPTIM POSSIBLE : ne pas faire le 1er phi1(vit2) (car sera fait dans prochaine itération) ?
vit2 = m.alpha_1(vit2) ;
} while(vit2 != stop) ;
} while(vit2 != stop) ; // OPTIM POSSIBLE : ne pas faire vit2 == stop (car déjà fait dans initEdgeInfo(vit)) ?
}
else
updateEdgeInfo(vit, true) ;
......@@ -478,6 +478,537 @@ void EdgeSelector_QEM<PFP>::computeEdgeInfo(Dart d, EdgeInfo& einfo)
einfo.valid = true ;
}
/************************************************************************************
* QUADRIC ERROR METRIC (Memoryless version) *
************************************************************************************/
template <typename PFP>
bool EdgeSelector_QEMml<PFP>::init()
{
MAP& m = this->m_map ;
bool ok = false ;
for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = this->m_approximators.begin();
it != this->m_approximators.end() && !ok;
++it)
{
if((*it)->getApproximatedAttributeName() == "position")
{
m_positionApproximator = reinterpret_cast<Approximator<PFP, VEC3>* >(*it) ;
ok = true ;
}
}
if(!ok)
return false ;
edges.clear() ;
CellMarker vMark(m, VERTEX_CELL) ;
for(Dart d = m.begin(); d != m.end(); m.next(d))
{
if(!vMark.isMarked(d))
{
Quadric<REAL> q ; // create one quadric
quadric[d] = q ; // per vertex
vMark.mark(d) ;
}
}
DartMarker mark(m) ;
for(Dart d = m.begin(); d != m.end(); m.next(d))
{
if(!mark.isMarked(d))
{
Dart d1 = m.phi1(d) ; // for each triangle,
Dart d_1 = m.phi_1(d) ; // initialize the quadric of the triangle
Quadric<REAL> q(this->m_position[d], this->m_position[d1], this->m_position[d_1]) ;
quadric[d] += q ; // and add the contribution of
quadric[d1] += q ; // this quadric to the ones
quadric[d_1] += q ; // of the 3 incident vertices
mark.markOrbit(FACE_ORBIT, d) ;
}
}
CellMarker eMark(m, EDGE_CELL) ;
for(Dart d = m.begin(); d != m.end(); m.next(d))
{
if(!eMark.isMarked(d))
{
initEdgeInfo(d) ; // init the edges with their optimal position
eMark.mark(d) ; // 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_QEMml<PFP>::nextEdge(Dart& d)
{
if(cur == edges.end() || edges.empty())
return false ;
d = (*cur).second ;
return true ;
}
template <typename PFP>
void EdgeSelector_QEMml<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 concerned edges
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) ;
}
}
/**
* rewind until border (if any)
*/
// TODO : check & optimize
template <typename PFP>
Dart EdgeSelector_QEMml<PFP>::rewind(const Dart d) {
Dart dInit = d ;
do {
if (dInit == this->m_map.phi2(dInit)) // if border
break ; // stop
dInit = this->m_map.alpha_1(dInit) ;
} while (dInit != d) ;
return dInit ;
}
/**
* 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_QEMml<PFP>::recomputeQuadric(const Dart d, const bool neighbours) {
Dart dFront,dBack;
Dart dInit = rewind(d) ; // rewind until border (if any)
// Init Front
dFront = dInit;
quadric[d].zero();
do {
// Make step
dBack = dFront ;
dFront = this->m_map.alpha1(dFront);
if (neighbours)
recomputeQuadric(this->m_map.phi2(dFront), false) ;
if (dFront == this->m_map.phi2(dFront))
break ;
quadric[d] += Quadric<REAL>(this->m_position[d],this->m_position[this->m_map.phi2(dFront)],this->m_position[this->m_map.phi2(dBack)]);
} while(dFront != dInit);
}
template <typename PFP>
void EdgeSelector_QEMml<PFP>::updateAfterCollapse(Dart d2, Dart dd2)
{
MAP& m = this->m_map ;
// for local vertex and neighbors
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.alpha_1(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.alpha_1(vit2) ; // OPTIM POSSIBLE : ne pas faire vit2 == stop car déjà fait dans init/updateEdgeInfo(vit)
} while(vit2 != stop) ;
vit = m.alpha1(vit) ;
} while(vit != d2) ;
cur = edges.begin() ; // set the current edge to the first one
}
template <typename PFP>
void EdgeSelector_QEMml<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_QEMml<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_QEMml<PFP>::computeEdgeInfo(Dart d, EdgeInfo& einfo)
{
MAP& m = this->m_map ;
Dart dd = m.phi2(d) ;
Quadric<REAL> quad ;
quad += quadric[d] ; // compute the sum of the
quad += quadric[dd] ; // two vertices quadrics
m_positionApproximator->approximate(d) ;
REAL err = quad(m_positionApproximator->getApprox(d)) ;
einfo.it = edges.insert(std::make_pair(err, d)) ;
einfo.valid = true ;
}
/************************************************************************************
* HALFEDGESELECTOR LIGHTFIELD *
************************************************************************************/
template <typename PFP>
bool HalfEdgeSelector_Lightfield<PFP>::init()
{