diff --git a/include/Algo/Decimation/approximator.h b/include/Algo/Decimation/approximator.h index 320d2b8b71d55bb553cbe7fcaf67b7091e5c2d57..5a533562f944f7f48640b1ed37d3ed97b3c5f2c4 100644 --- a/include/Algo/Decimation/approximator.h +++ b/include/Algo/Decimation/approximator.h @@ -39,6 +39,7 @@ namespace Decimation enum ApproximatorType { A_QEM, + A_QEMhalf, A_MidEdge, A_HalfCollapse, A_CornerCutting, diff --git a/include/Algo/Decimation/decimation.hpp b/include/Algo/Decimation/decimation.hpp index ece16239ac5c50a72f2699dce8c7281d510a91ec..21f8fdb03ca535f5d2929224639b2be69550fe72 100644 --- a/include/Algo/Decimation/decimation.hpp +++ b/include/Algo/Decimation/decimation.hpp @@ -45,6 +45,9 @@ void decimate( case A_QEM : approximators.push_back(new Approximator_QEM(map, position)) ; break ; + case A_QEMhalf : + approximators.push_back(new Approximator_QEMhalf(map, position)) ; + break ; case A_MidEdge : approximators.push_back(new Approximator_MidEdge(map, position)) ; break ; @@ -62,7 +65,7 @@ void decimate( break ; case A_LightfieldFull : { - approximators.push_back(new Approximator_QEM(map, position)) ; + approximators.push_back(new Approximator_QEMhalf(map, position)) ; /* PFP::TVEC3 frame[3] ; frame[0] = map.template getAttribute(VERTEX_ORBIT, "frame_T") ; // Tangent @@ -94,28 +97,6 @@ void decimate( case A_LightfieldHalf : { approximators.push_back(new Approximator_HalfCollapse(map, position)) ; - /* - PFP::TVEC3 frame[3] ; - frame[0] = map.template getAttribute(VERTEX_ORBIT, "frame_T") ; // Tangent - frame[1] = map.template getAttribute(VERTEX_ORBIT, "frame_B") ; // Bitangent - frame[2] = map.template getAttribute(VERTEX_ORBIT, "frame_N") ; // Normal - for (unsigned int i = 0 ; i < 3 ; ++i) - if (!frame[i].isValid()) { - std::cerr << "In function decimate : frame[" << i << "] is not valid" << std::endl ; - } - - AttributeHandler colorPTM[6] ; - colorPTM[0] = map.template getAttribute(VERTEX_ORBIT, "colorPTM_a") ; - colorPTM[1] = map.template getAttribute(VERTEX_ORBIT, "colorPTM_b") ; - colorPTM[2] = map.template getAttribute(VERTEX_ORBIT, "colorPTM_c") ; - colorPTM[3] = map.template getAttribute(VERTEX_ORBIT, "colorPTM_d") ; - colorPTM[4] = map.template getAttribute(VERTEX_ORBIT, "colorPTM_e") ; - colorPTM[5] = map.template getAttribute(VERTEX_ORBIT, "colorPTM_f") ; - for (unsigned int i = 0 ; i < 6 ; ++i) - if (!colorPTM[i].isValid()) { - std::cerr << "In function decimate : colorPTM[" << i << "] is not valid" << std::endl ; - } - */ AttributeHandler > frame = map.template getAttribute >(VERTEX_ORBIT, "frame") ; AttributeHandler > RGBfunctions = map.template getAttribute >(VERTEX_ORBIT, "colorPTM") ; approximators.push_back(new Approximator_FrameHalf(map, frame)) ; diff --git a/include/Algo/Decimation/geometryApproximator.h b/include/Algo/Decimation/geometryApproximator.h index 3aaabd3958464a8aeb82d82243821d7796fe7283..4b7218da93d08fc54350b1a6196af4d7bc883045 100644 --- a/include/Algo/Decimation/geometryApproximator.h +++ b/include/Algo/Decimation/geometryApproximator.h @@ -58,6 +58,28 @@ public: void approximate(Dart d) ; } ; +template +class Approximator_QEMhalf : public Approximator +{ +public: + typedef typename PFP::MAP MAP ; + typedef typename PFP::VEC3 VEC3 ; + typedef typename PFP::REAL REAL ; + +protected: + AttributeHandler > m_quadric ; + +public: + Approximator_QEMhalf(MAP& m, AttributeHandler& pos, Predictor* pred = NULL) : + Approximator(m, pos, EDGE_ORBIT, pred) + {} + ~Approximator_QEMhalf() + {} + ApproximatorType getType() const { return A_QEMhalf ; } + bool init() ; + void approximate(Dart d) ; +} ; + template class Approximator_MidEdge : public Approximator { diff --git a/include/Algo/Decimation/geometryApproximator.hpp b/include/Algo/Decimation/geometryApproximator.hpp index 442cbe40c47a0554bcf913ce59fde11edbc18d31..d929e142a039c38ee0bd8d0fe15167c73e0938e6 100644 --- a/include/Algo/Decimation/geometryApproximator.hpp +++ b/include/Algo/Decimation/geometryApproximator.hpp @@ -105,6 +105,69 @@ void Approximator_QEM::approximate(Dart d) this->m_approx[d] = res ; } +/************************************************************************************ + * QUADRIC ERROR METRIC (for half-edge criteria) * + ************************************************************************************/ + +template +bool Approximator_QEMhalf::init() +{ + m_quadric = this->m_map.template getAttribute >(VERTEX_ORBIT, "QEMquadric") ; + + if(this->m_predictor) + { + return false ; + } + return true ; +} + +template +void Approximator_QEMhalf::approximate(Dart d) +{ + MAP& m = this->m_map ; + + // get some darts + Dart dd = m.phi2(d) ; + + Quadric 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 + { + Quadric q(this->m_attrV[it], this->m_attrV[m.phi1(it)], this->m_attrV[m.phi_1(it)]) ; + q1 += q ; + it = m.alpha1(it) ; + } while(it != d) ; + + // compute the error quadric associated to v2 + it = dd ; + do + { + Quadric q(this->m_attrV[it], this->m_attrV[m.phi1(it)], this->m_attrV[m.phi_1(it)]) ; + q2 += q ; + it = m.alpha1(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] ; + } + + Quadric 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 + if(!opt) + this->m_approx[d] = this->m_attrV[d] ; + else + this->m_approx[d] = res ; +} + /************************************************************************************ * MID EDGE * ************************************************************************************/ diff --git a/include/Algo/Decimation/selector.hpp b/include/Algo/Decimation/selector.hpp index f3a747ac7ab6f9b480e29d0a6e3964f166a70e23..a4f0bc708ed61673a5b5b39af67eaecd1491579a 100644 --- a/include/Algo/Decimation/selector.hpp +++ b/include/Algo/Decimation/selector.hpp @@ -404,9 +404,9 @@ void EdgeSelector_QEM::updateAfterCollapse(Dart d2, Dart dd2) do // - edges for which only the collapsibility must be re-tested { updateEdgeInfo(vit2, false) ; - updateEdgeInfo(m.phi1(vit2), false) ; // OPTIM POSSIBLE : ne pas faire le 1er phi1(vit2) (car sera fait dans prochaine itération) ? + updateEdgeInfo(m.phi1(vit2), false) ; vit2 = m.alpha_1(vit2) ; - } while(vit2 != stop) ; // OPTIM POSSIBLE : ne pas faire vit2 == stop (car déjà fait dans initEdgeInfo(vit)) ? + } while(vit2 != stop) ; } else updateEdgeInfo(vit, true) ; @@ -473,7 +473,8 @@ void EdgeSelector_QEM::computeEdgeInfo(Dart d, EdgeInfo& einfo) m_positionApproximator->approximate(d) ; - REAL err = quad(m_positionApproximator->getApprox(d)) ; + REAL err = std::max(REAL(0),REAL(quad(m_positionApproximator->getApprox(d)))) ; + einfo.it = edges.insert(std::make_pair(err, d)) ; einfo.valid = true ; } @@ -609,7 +610,7 @@ void EdgeSelector_QEMml::recomputeQuadric(const Dart d, const bool recomput quadric[d] += Quadric(this->m_position[d],this->m_position[this->m_map.phi2(dFront)],this->m_position[dBack]) ; } if (recomputeNeighbors) - recomputeQuadric(this->m_map.phi2(dFront), false) ; + recomputeQuadric(dBack, false) ; } while(dFront != dInit) ; } @@ -638,7 +639,7 @@ void EdgeSelector_QEMml::updateAfterCollapse(Dart d2, Dart dd2) { 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) + vit2 = m.alpha_1(vit2) ; } while(vit2 != stop) ; vit = m.alpha1(vit) ; @@ -728,6 +729,7 @@ bool HalfEdgeSelector_Lightfield::init() if(ok == 0 && (*it)->getApproximatedAttributeName() == "position") { m_positionApproximator = reinterpret_cast* >(*it) ; // 1) position + assert(m_positionApproximator->getType() != A_QEM) ; // A_QEM is not compatible for half-edge crit ++ok ; } else if( ok == 1 && (*it)->getApproximatedAttributeName() == "frame") @@ -855,7 +857,7 @@ void HalfEdgeSelector_Lightfield::recomputeQuadric(const Dart d, const bool quadric[d] += Quadric(this->m_position[d],this->m_position[this->m_map.phi2(dFront)],this->m_position[dBack]) ; } if (recomputeNeighbors) - recomputeQuadric(this->m_map.phi2(dFront), false) ; + recomputeQuadric(dBack, false) ; } while(dFront != dInit) ; } @@ -872,7 +874,9 @@ void HalfEdgeSelector_Lightfield::updateAfterCollapse(Dart d2, Dart dd2) do { updateHalfEdgeInfo(vit, true) ; + updateHalfEdgeInfo(m.phi2(vit), true) ; updateHalfEdgeInfo(m.phi1(vit), true) ; + updateHalfEdgeInfo(m.phi2(m.phi1(vit)), true) ; Dart stop = m.phi2(vit) ; Dart vit2 = m.alpha_1(m.phi1(vit)) ;