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 ...@@ -45,12 +45,11 @@ enum ApproximatorType
A_TangentPredict2, A_TangentPredict2,
A_ColorNaive, A_ColorNaive,
A_ColorQEMext, A_ColorQEMext,
A_Lightfield,
// 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,
A_hQEM, A_hQEM
A_hLightfieldHalf, // A_hLightfieldHalf,
A_hLightfield
} ; } ;
template <typename PFP> template <typename PFP>
......
...@@ -48,6 +48,7 @@ public: ...@@ -48,6 +48,7 @@ public:
protected: protected:
VertexAttribute<VEC3> m_position ; VertexAttribute<VEC3> m_position ;
EdgeAttribute<VEC3> m_approxposition ; EdgeAttribute<VEC3> m_approxposition ;
VertexAttribute<VEC3> *m_color ; VertexAttribute<VEC3> *m_color ;
public: public:
...@@ -55,13 +56,6 @@ public: ...@@ -55,13 +56,6 @@ public:
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() || !"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() ~Approximator_ColorNaive()
{} {}
...@@ -73,7 +67,15 @@ public: ...@@ -73,7 +67,15 @@ public:
bool init() 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) ; void approximate(Dart d) ;
...@@ -102,6 +104,7 @@ public: ...@@ -102,6 +104,7 @@ public:
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_ColorQEMext() ~Approximator_ColorQEMext()
{} {}
......
...@@ -57,12 +57,14 @@ template <typename PFP> ...@@ -57,12 +57,14 @@ template <typename PFP>
bool Approximator_ColorQEMext<PFP>::init() bool Approximator_ColorQEMext<PFP>::init()
{ {
m_quadric = this->m_map.template getAttribute<QuadricNd<REAL,6>, VERTEX>("QEMext-quadric") ; 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) if(this->m_predictor)
{ {
return false ; return false ;
} }
return true ;
return m_position->isValid() && m_color->isValid() ;
} }
template <typename PFP> template <typename PFP>
......
...@@ -93,6 +93,7 @@ void decimate( ...@@ -93,6 +93,7 @@ void decimate(
approximators.push_back(new Approximator_QEMhalfEdge<PFP>(map, attribs)) ; approximators.push_back(new Approximator_QEMhalfEdge<PFP>(map, attribs)) ;
break ; break ;
// case A_hLightfieldHalf: // case A_hLightfieldHalf:
// {
// v_approx = new std::vector<VertexAttribute<typename PFP::VEC3>* >[3] ; // v_approx = new std::vector<VertexAttribute<typename PFP::VEC3>* >[3] ;
// //
// // pos // // pos
...@@ -110,25 +111,29 @@ void decimate( ...@@ -110,25 +111,29 @@ void decimate(
// for (unsigned int i = 0 ; i < attribs.size() - 4 ; ++i) // for (unsigned int i = 0 ; i < attribs.size() - 4 ; ++i)
// v_approx[2].push_back(attribs[i+4]) ; // v_approx[2].push_back(attribs[i+4]) ;
// approximators.push_back(new Approximator_LightfieldCoefsHalf<PFP>(map, v_approx[2])) ; // approximators.push_back(new Approximator_LightfieldCoefsHalf<PFP>(map, v_approx[2])) ;
// }
// break ; // break ;
case A_hLightfield : case A_Lightfield :
{ {
// pos + frame + hemifunction v_approx = new std::vector<VertexAttribute<typename PFP::VEC3>* >[3] ;
approximators.push_back(new Approximator_HalfCollapse<PFP>(map, attribs)) ;
}
break ;
/*
case A_LightfieldFull_deprecated :
{
approximators.push_back(new Approximator_QEMhalfEdge<PFP>(map, position)) ;
VertexAttribute<Geom::Matrix<3,3,typename PFP::REAL> > frame = map.template getAttribute<Geom::Matrix<3,3,typename PFP::REAL>, VERTEX>("frame") ; // pos
VertexAttribute<Geom::Matrix<3,6,typename PFP::REAL> > RGBfunctions = map.template getAttribute<Geom::Matrix<3,6,typename PFP::REAL>, VERTEX>("colorPTM") ; v_approx[0].push_back(attribs[0]) ;
approximators.push_back(new Approximator_Frame_deprecated<PFP>(map, frame)) ; approximators.push_back(new Approximator_QEM<PFP>(map, v_approx[0])) ;
approximators.push_back(new Approximator_RGBfunctions_deprecated<PFP>(map, RGBfunctions)) ;
break ; // 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) switch(s)
...@@ -163,8 +168,8 @@ void decimate( ...@@ -163,8 +168,8 @@ void decimate(
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_hLightfield : case S_Lightfield :
selector = new HalfEdgeSelector_Lightfield<PFP>(map, position, approximators, selected) ; selector = new EdgeSelector_Lightfield<PFP>(map, position, approximators, selected) ;
break ; break ;
} }
......
...@@ -502,6 +502,72 @@ public: ...@@ -502,6 +502,72 @@ public:
void updateAfterCollapse(Dart d2, Dart dd2) ; 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 Decimation
} // namespace Algo } // namespace Algo
......
This diff is collapsed.
...@@ -38,6 +38,7 @@ template <typename PFP> ...@@ -38,6 +38,7 @@ template <typename PFP>
bool Approximator_QEM<PFP>::init() bool Approximator_QEM<PFP>::init()
{ {
m_quadric = this->m_map.template getAttribute<Quadric<REAL>, VERTEX>("QEMquadric") ; 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) if(this->m_predictor)
{ {
......
...@@ -89,77 +89,77 @@ public: ...@@ -89,77 +89,77 @@ public:
void updateAfterCollapse(Dart d2, Dart dd2) ; void updateAfterCollapse(Dart d2, Dart dd2) ;
} ; } ;
/***************************************************************************************************************** ///*****************************************************************************************************************
* HALF-EDGE LIGHTFIELD METRIC * // * HALF-EDGE LIGHTFIELD METRIC *
*****************************************************************************************************************/ // *****************************************************************************************************************/
template <typename PFP> //template <typename PFP>
class HalfEdgeSelector_Lightfield : public EdgeSelector<PFP> //class HalfEdgeSelector_Lightfield : public EdgeSelector<PFP>
{ //{
public: //public:
typedef typename PFP::MAP MAP ; // typedef typename PFP::MAP MAP ;
typedef typename PFP::VEC3 VEC3 ; // typedef typename PFP::VEC3 VEC3 ;
typedef typename PFP::REAL REAL ; // typedef typename PFP::REAL REAL ;
//
private: //private:
typedef struct // typedef struct
{ // {
typename std::multimap<float,Dart>::iterator it ; // typename std::multimap<float,Dart>::iterator it ;
bool valid ; // bool valid ;
static std::string CGoGNnameOfType() { return "LightfieldHalfEdgeInfo" ; } // static std::string CGoGNnameOfType() { return "LightfieldHalfEdgeInfo" ; }
} QEMhalfEdgeInfo ; // } QEMhalfEdgeInfo ;
typedef NoMathIOAttribute<QEMhalfEdgeInfo> HalfEdgeInfo ; // typedef NoMathIOAttribute<QEMhalfEdgeInfo> HalfEdgeInfo ;
//
DartAttribute<HalfEdgeInfo> halfEdgeInfo ; // DartAttribute<HalfEdgeInfo> halfEdgeInfo ;
//
VertexAttribute<VEC3> m_pos, m_frameT, m_frameB, m_frameN ; // VertexAttribute<VEC3> m_pos, m_frameT, m_frameB, m_frameN ;
//VertexAttribute<VEC3> *m_HF ; // //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 ;
//
VertexAttribute<Quadric<REAL> > m_quadricGeom ; // VertexAttribute<Quadric<REAL> > m_quadricGeom ;
VertexAttribute<QuadricHF<REAL> > m_quadricHF ; // VertexAttribute<QuadricHF<REAL> > m_quadricHF ;
//
std::multimap<float,Dart> halfEdges ; // std::multimap<float,Dart> halfEdges ;
typename std::multimap<float,Dart>::iterator cur ; // typename std::multimap<float,Dart>::iterator cur ;
//
std::vector<Approximator<PFP, typename PFP::VEC3>* > m_approx ; // std::vector<Approximator<PFP, typename PFP::VEC3>* > m_approx ;
//
void initHalfEdgeInfo(Dart d) ; // void initHalfEdgeInfo(Dart d) ;
void updateHalfEdgeInfo(Dart d, bool recompute) ; // void updateHalfEdgeInfo(Dart d, bool recompute) ;
void computeHalfEdgeInfo(Dart d, HalfEdgeInfo& einfo) ; // void computeHalfEdgeInfo(Dart d, HalfEdgeInfo& einfo) ;
void recomputeQuadric(const Dart d, const bool recomputeNeighbors = false) ; // void recomputeQuadric(const Dart d, const bool recomputeNeighbors = false) ;
//
public: //public:
HalfEdgeSelector_Lightfield(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select = allDarts) : // HalfEdgeSelector_Lightfield(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select = allDarts) :
EdgeSelector<PFP>(m, pos, approx, select), // EdgeSelector<PFP>(m, pos, approx, select),
// m_positionApproximator(NULL), //// m_positionApproximator(NULL),
// m_frameApproximator(NULL), //// m_frameApproximator(NULL),
// m_hfcoefsApproximator(NULL), //// m_hfcoefsApproximator(NULL),
// m_pos(NULL), //// m_pos(NULL),
// m_frameB(NULL), //// m_frameB(NULL),
// m_frameN(NULL), //// m_frameN(NULL),
// m_frameT(NULL), //// m_frameT(NULL),
m_approxindex_pos(-1), // m_approxindex_pos(-1),
m_attrindex_pos(-1), // m_attrindex_pos(-1),
m_approxindex_FN(-1), // m_approxindex_FN(-1),
m_attrindex_FN(-1) // m_attrindex_FN(-1)
{ // {
halfEdgeInfo = m.template addAttribute<HalfEdgeInfo, DART>("halfEdgeInfo") ; // halfEdgeInfo = m.template addAttribute<HalfEdgeInfo, DART>("halfEdgeInfo") ;
m_quadricGeom = m.template addAttribute<Quadric<REAL>, VERTEX>("QEMquadric") ; // m_quadricGeom = m.template addAttribute<Quadric<REAL>, VERTEX>("QEMquadric") ;
m_quadricHF = m.template addAttribute<QuadricHF<REAL>, VERTEX>("HFquadric") ; // m_quadricHF = m.template addAttribute<QuadricHF<REAL>, VERTEX>("HFquadric") ;
} // }
~HalfEdgeSelector_Lightfield() // ~HalfEdgeSelector_Lightfield()
{ // {
this->m_map.removeAttribute(halfEdgeInfo) ; // this->m_map.removeAttribute(halfEdgeInfo) ;
this->m_map.removeAttribute(m_quadricGeom) ; // this->m_map.removeAttribute(m_quadricGeom) ;
this->m_map.removeAttribute(m_quadricHF) ; // this->m_map.removeAttribute(m_quadricHF) ;
} // }
SelectorType getType() { return S_hLightfield ; } // SelectorType getType() { return S_hLightfield ; }
bool init() ; // bool init() ;
bool nextEdge(Dart& d) ; // bool nextEdge(Dart& d) ;
void updateBeforeCollapse(Dart d) ; // void updateBeforeCollapse(Dart d) ;
void updateAfterCollapse(Dart d2, Dart dd2) ; // void updateAfterCollapse(Dart d2, Dart dd2) ;
} ; //} ;
/*template <typename PFP> /*template <typename PFP>
class HalfEdgeSelector_Lightfield_deprecated : public EdgeSelector<PFP> class HalfEdgeSelector_Lightfield_deprecated : public EdgeSelector<PFP>
......
...@@ -37,9 +37,8 @@ namespace Algo ...@@ -37,9 +37,8 @@ namespace Algo
namespace Decimation namespace Decimation
{ {
/*
template <typename PFP> template <typename PFP>
class Approximator_FrameHalf : public Approximator<PFP, typename PFP::VEC3> class Approximator_FrameInterpolation : public Approximator<PFP, typename PFP::VEC3>
{ {
public: public:
typedef typename PFP::MAP MAP ; typedef typename PFP::MAP MAP ;
...@@ -47,67 +46,181 @@ public: ...@@ -47,67 +46,181 @@ public:
typedef typename PFP::REAL REAL ; typedef typename PFP::REAL REAL ;
protected: protected:
VertexAttribute<VEC3> m_position ;
EdgeAttribute<VEC3> m_approxposition ;
VertexAttribute<VEC3> *m_frameT ; VertexAttribute<VEC3> *m_frameT ;
VertexAttribute<VEC3> *m_frameB ; VertexAttribute<VEC3> *m_frameB ;
VertexAttribute<VEC3> *m_frameN ; VertexAttribute<VEC3> *m_frameN ;
public: public:
Approximator_FrameHalf(MAP& m, std::vector<VertexAttribute<VEC3>* >& attr, Predictor<PFP, VEC3>* pred = NULL) : Approximator_FrameInterpolation(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_frameT(NULL),
m_frameB(NULL),
m_frameN(NULL)
{ {
if (this->m_attrV.size() < 3) if (this->m_attrV.size() < 3)
std::cerr << "Approximator_Frame: not enough attributes provided (only " << this->m_attrV.size() << " instead of 3)" << std::endl ; std::cerr << "Approximator_FrameInterpolation: not enough attributes provided (only " << this->m_attrV.size() << " instead of 3)" << std::endl ;
m_frameT = this->m_attrV[0] ; m_frameT = this->m_attrV[0] ;
m_frameB = this->m_attrV[1] ; m_frameB = this->m_attrV[1] ;
m_frameN = this->m_attrV[2] ; m_frameN = this->m_attrV[2] ;
assert(m_frameT->isValid() || !"Approximator_FrameHalf: the first approximated attribute is not valid") ;
assert(m_frameB->isValid() || !"Approximator_FrameHalf: the second approximated attribute is not valid") ;
assert(m_frameN->isValid() || !"Approximator_FrameHalf: the third approximated attribute is not valid") ;
} }
~Approximator_FrameHalf()
~Approximator_FrameInterpolation()
{} {}
ApproximatorType getType() const ApproximatorType getType() const
{ {
return A_hLightfieldHalf ; return A_Lightfield ;
} }
bool init() bool init()
{ {
return true ; assert(m_frameT->isValid() || !"Approximator_FrameInterpolation: the first approximated attribute is not valid") ;
assert(m_frameB->isValid() || !"Approximator_FrameInterpolation: the second approximated attribute is not valid") ;
assert(m_frameN->isValid() || !"Approximator_FrameInterpolation: the third approximated attribute is not valid") ;
m_position = this->m_map.template getAttribute<VEC3, VERTEX>("position") ;
assert(m_position.isValid() || !"Approximator_FrameInterpolation::init: the position attribute is not valid") ;
m_approxposition = this->m_map.template getAttribute<VEC3, EDGE>("approx_position") ;
assert(m_approxposition.isValid() || !"Approximator_FrameInterpolation::init: the approx_position attribute is not valid") ;
return m_frameT->isValid() && m_frameB->isValid() && m_frameN->isValid() && m_position.isValid() && m_approxposition.isValid() ;
} }
void approximate(Dart d) ; void approximate(Dart d) ;
} ; } ;
template <typename PFP> template <typename PFP>
class Approximator_LightfieldCoefsHalf : public Approximator<PFP, typename PFP::VEC3> class Approximator_HemiFuncCoefs: 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::VEC3 VEC3 ;
typedef typename PFP::REAL REAL ; typedef typename PFP::REAL REAL ;
unsigned int m_nbCoefs ;
unsigned int m_HFtype ;
VertexAttribute<VEC3 > m_frameT ;
VertexAttribute<VEC3 > m_frameB ;
VertexAttribute<VEC3 > m_frameN ;
EdgeAttribute<VEC3 > m_newFrameT ;
EdgeAttribute<VEC3 > m_newFrameB ;
EdgeAttribute<VEC3 > m_newFrameN ;
std::vector<VertexAttribute<VEC3>* > m_coefs ;
VertexAttribute<QuadricHF<REAL> > m_quadricHF ;
public: public:
Approximator_LightfieldCoefsHalf(MAP& m, std::vector<VertexAttribute<VEC3> >& attr, Predictor<PFP, VEC3>* pred = NULL) : Approximator_HemiFuncCoefs(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_nbCoefs(0),
~Approximator_LightfieldCoefsHalf() m_HFtype(0) // SH = 0
{
// check name of number 0
if (this->m_attrV[0]->name().find("SH") != std::string::npos)
m_HFtype = 1 ;
unsigned int i ;
for (i = 1 ; i < 200 ; ++i)
{
// check if number i is present
if ((this->m_attrV.size() <= i) || this->m_attrV[i]->name().find("coefs") == std::string::npos)
break ;
m_coefs.push_back(this->m_attrV[i]) ;
}
m_nbCoefs = i - 1 ;
}
~Approximator_HemiFuncCoefs()
{} {}
ApproximatorType getType() const ApproximatorType getType() const
{ {
return A_hLightfieldHalf ; return A_Lightfield ;
} }
bool init() bool init() ;
{
return true ;
}
void approximate(Dart d) ; void approximate(Dart d) ;
} ;*/ } ;
//template <typename PFP>
//class Approximator_FrameHalf : public Approximator<PFP, typename PFP::VEC3>
//{
//public:
// typedef typename PFP::MAP MAP ;
// typedef typename PFP::VEC3 VEC3 ;
// typedef typename PFP::REAL REAL ;
//
//protected:
// VertexAttribute<VEC3> *m_frameT ;
// VertexAttribute<VEC3> *m_frameB ;
// VertexAttribute<VEC3> *m_frameN ;
//
//public:
// Approximator_FrameHalf(MAP& m, std::vector<VertexAttribute<VEC3>* >& attr, Predictor<PFP, VEC3>* pred = NULL) :
// Approximator<PFP, VEC3>(m, attr, pred)
// {
// if (this->m_attrV.size() < 3)