void SimplifTrian<PFP>::simplifUntil(unsigned int nbWantedTriangles) { m_nbWanted = nbWantedTriangles; bool notFinished = true; while (notFinished) { // TODO optimiser la calcul de diff int diff = (m_nbTriangles - m_nbWanted) / 8; if (diff < 128) diff = 128; int collapsed = 0; CRIT_IT it = m_edgeCrit.begin(); // traverse the criteria map until diff collapse & enough triangles while ( (it != m_edgeCrit.end()) /*&& (collapsed < diff)*/ && (m_nbWanted < m_nbTriangles) ) { // get the criteria CRIT* cr = it->second; // if criteria invalid then remove it and step to next if (cr->isDirty()) { CRIT_IT jt = it++; delete jt->second; m_edgeCrit.erase(jt); } else { Dart d = cr->getDart(); if (cr->removingAllowed()) { if (edgeIsCollapsible(d)) { // compute new position typename PFP::VEC3 np = cr->newPosition(m_map, m_positions); // and collapse edge Dart dd = edgeCollapse(d, np); // update criterias updateCriterias(dd); m_nbTriangles -= 2; ++collapsed; } } ++it; } } // test finish condition if ((collapsed == 0) || (m_nbWanted >= m_nbTriangles)) notFinished = false; m_protectMarker.unmarkAll(); } }
void VolumetricProgressiveMesh<PFP>::coarsen() { if(m_cur == m_splits.size()) return ; VSplit<PFP>* vs = m_splits[m_cur] ; // get the split node ++m_cur ; Dart d = vs->getEdge() ; Dart dd = m_map.phi2(d) ; // get some darts Dart d2 = vs->getLeftEdge() ; Dart dd2 = vs->getRightEdge() ; edgeCollapse(vs) ; // collapse edge m_map.template setOrbitEmbedding<VERTEX>(d2, vs->getApproxV()) ; m_map.template setOrbitEmbedding<EDGE>(d2, vs->getApproxE1()) ; m_map.template setOrbitEmbedding<EDGE>(dd2, vs->getApproxE2()) ; }
bool BuilderTerrain::simplifyTriangle(runnel::Triangle* triangle, Terrain* ter){ assert(("Triangle to simplify was not part of the terrain",ter->struct_triangle.find(triangle) != ter->struct_triangle.end())); runnel::Edge* shortestEdge = triangle->getShortestEdge(); bool edgeWasCollapsed = edgeCollapse(shortestEdge, ter); return edgeWasCollapsed; }
void Mesh<VertData, TriData>::remesh() { //std::cout << "remesh initial tri count: " << tris.size() << std::endl; if(verts.size() == 0) return; // pathology guard /*{ // dump out mesh before performing re-mesh Files::FileMesh filemesh; filemesh = transduce<Files::FileVertex, Files::FileTriangle, VertData, TriData> (raw(), [](Files::FileVertex &out, const VertData &in) { out.pos = in.pos; }, [](Files::FileTriangle &out, const TriData &in) { out.a = in.a; out.b = in.b; out.c = in.c; }); if(Files::writeTriMesh("remesh_in.off", &filemesh) > 0) { CORK_ERROR("Unable to write out remesh input to remesh_in.off"); } }*/ // create a scratchpad and set it up RemeshScratchpad scratchpad(this); // compute which vertices are boundary or not for(VertData &v : verts) { v.manifold = true; } scratchpad.cache.edges.for_each([this, &scratchpad](Eptr edge) { if(edge->tris.size() != 2) { verts[edge->verts[0]->ref].manifold = false; verts[edge->verts[1]->ref].manifold = false; } }); // Then, we set up the priority queue // (allocating auxiliary data as we go) scratchpad.cache.edges.for_each([this, &scratchpad](Eptr edge) { edge->data = scratchpad.edge_data.alloc(); scoreAndEnqueue(scratchpad.queue, edge); }); int cutoff = 10000; // now let's go into a loop pulling work off of the queue while(scratchpad.queue.size() > 0) { // pop the end of the queue auto it_top = scratchpad.queue.end(); it_top--; //double top_score = it_top->first; Eptr top_edge = it_top->second; scratchpad.queue.erase(it_top); // Which operation should be performed to this edge? EdgeRemeshOperation op = reinterpret_cast<RemeshEdgeAuxiliary*>(top_edge->data)->op; if(op == EDGE_SPLIT) { //std::cout << "edge split" << std::endl; edgeSplit(scratchpad, top_edge); } else if (op == EDGE_COLLAPSE) { //std::cout << "edge collapse" << std::endl; edgeCollapse(scratchpad, top_edge, true); } // else do nothing (should have score <= 0.0 then...) cutoff--; if(cutoff < 0) break; } //std::cout << " cache.tris is " // << scratchpad.cache.tris.size() << std::endl; //std::cout << "prefinalize tri count: " << tris.size() << std::endl; // finally, we commit all of the results of this remeshing operation // causing the data storage to defrag and clean out dead items scratchpad.cache.commit(); //std::cout << "remesh final tri count: " << tris.size() << std::endl; }
void VolumetricProgressiveMesh<PFP>::createPM(unsigned int percentWantedVertices) { unsigned int nbVertices = m_map.template getNbOrbits<VERTEX>() ; unsigned int nbWantedVertices = nbVertices * percentWantedVertices / 100 ; CGoGNout << " creating PM (" << nbVertices << " vertices).." << /* flush */ CGoGNendl ; bool finished = false ; Dart d ; while(!finished) { if(!m_selector->nextEdge(d)) break ; --nbVertices ; Dart d2 = m_map.phi2(m_map.phi_1(d)) ; Dart dd2 = m_map.phi2(m_map.phi_1(m_map.phi2(d))) ; VSplit<PFP>* vs = new VSplit<PFP>(m_map, d, dd2, d2) ; // create new VSplit node m_splits.push_back(vs) ; // and store it for(typename std::vector<Algo::Decimation::ApproximatorGen<PFP>*>::iterator it = m_approximators.begin(); it != m_approximators.end(); ++it) { (*it)->approximate(d) ; // compute approximated attributes with its associated detail (*it)->saveApprox(d) ; } m_selector->updateBeforeCollapse(d) ; // update selector edgeCollapse(vs) ; // collapse edge unsigned int newV = m_map.template setOrbitEmbeddingOnNewCell<VERTEX>(d2) ; unsigned int newE1 = m_map.template setOrbitEmbeddingOnNewCell<EDGE>(d2) ; unsigned int newE2 = m_map.template setOrbitEmbeddingOnNewCell<EDGE>(dd2) ; vs->setApproxV(newV) ; vs->setApproxE1(newE1) ; vs->setApproxE2(newE2) ; for(typename std::vector<Algo::Decimation::ApproximatorGen<PFP>*>::iterator it = m_approximators.begin(); it != m_approximators.end(); ++it) (*it)->affectApprox(d2); // affect data to the resulting vertex m_selector->updateAfterCollapse(d2, dd2) ; // update selector if(nbVertices <= nbWantedVertices) finished = true ; } delete m_selector ; m_selector = NULL ; m_cur = m_splits.size() ; CGoGNout << "..done (" << nbVertices << " vertices)" << CGoGNendl ; // unsigned int nbVertices = m_map.template getNbOrbits<VERTEX>() ; // unsigned int nbWantedVertices = nbVertices * percentWantedVertices / 100 ; // CGoGNout << " creating PM (" << nbVertices << " vertices).." << /* flush */ CGoGNendl ; // // bool finished = false ; // Dart d ; // while(!finished) // { // //Next Operator to perform // Algo::DecimationVolumes::Operator<PFP> *op; // // if((op = m_selector->nextOperator()) == NULL) // break; // // m_nodes->add(op); // // for(typename std::vector<Algo::DecimationVolumes::ApproximatorGen<PFP>*>::iterator it = m_approximators.begin(); it != m_approximators.end(); ++it) // { // (*it)->approximate(op) ; // compute approximated attributes with its associated detail // (*it)->saveApprox(op) ; // } // // //Update the selector before performing operation // if(!m_selector->updateBeforeOperation(op)) // break; // // nbVertices -= op->collapse(m_map, positionsTable); // // for(typename std::vector<Algo::DecimationVolumes::ApproximatorGen<PFP>*>::iterator it = m_approximators.begin(); it != m_approximators.end(); ++it) // (*it)->affectApprox(op); // affect data to the resulting vertex // // m_selector->updateAfterOperation(op) ; // update selector // // if(nbVertices <= 3) //<= nbWantedVertices) // finished = true ; // } // // m_selector->finish() ; // // delete m_selector ; // m_selector = NULL ; // // m_level = m_nodes->size() ; // CGoGNout << "..done (" << nbVertices << " vertices)" << CGoGNendl ; }