// // Apply filter // bool FilterTopoPlugin::applyFilter(QAction *filter, MeshModel &m, RichParameterSet & par, vcg::CallBackPos *cb) { // To run the retopology algorithm an istance of RetopoMeshBuilder is needed RetopMeshBuilder rm; // Load topology mesh MeshModel *userMesh = par.getMesh("userMesh"); // Load (input) original mesh MeshModel *inMesh = par.getMesh("inMesh"); // Load iterations value int it = par.getInt("it"); // Load distance value float dist = par.getAbsPerc("dist"); // Destination meshmodel: retopology mesh will replace flat topology mesh MeshModel * outM = par.getMesh("userMesh"); // Prepare mesh inMesh->updateDataMask(MeshModel::MM_FACEMARK); tri::UpdateNormals<CMeshO>::PerFaceNormalized(inMesh->cm); tri::UpdateFlags<CMeshO>::FaceProjection(inMesh->cm); // Init the retopology builder with original input mesh and distance value rm.init(inMesh, dist); // Apply the algorithm return rm.applyTopoMesh(*userMesh, *inMesh, it, dist, *outM); }
// The Real Core Function doing the actual mesh processing. bool FilterAutoalign::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb) { vcg::tri::FourPCS<CMeshO> *fpcs ; switch(ID(filter)) { case FP_AUTOALIGN : { MeshModel *firstMesh= par.getMesh("FirstMesh"); MeshModel *secondMesh= par.getMesh("SecondMesh"); vcg::tri::FourPCS<CMeshO> fpcs; fpcs.par.Default(); fpcs.par.f = par.getFloat("overlapping"); firstMesh->updateDataMask(MeshModel::MM_VERTMARK); secondMesh->updateDataMask(MeshModel::MM_VERTMARK); fpcs.Init(firstMesh->cm,secondMesh->cm); bool res = fpcs.Align(0,firstMesh->cm.Tr,cb); firstMesh->clearDataMask(MeshModel::MM_VERTMARK); secondMesh->clearDataMask(MeshModel::MM_VERTMARK); if(res) Log("Automatic Rough Alignment Done"); else Log("Automatic Rough Alignment Failed"); } break; case FP_BEST_ROTATION : { MeshModel *firstMesh= par.getMesh("FirstMesh"); MeshModel *secondMesh= par.getMesh("SecondMesh"); tri::Guess GG; GG.pp.MatrixNum = 100; GG.GenRotMatrix(); GG.Init<CMeshO>(firstMesh->cm, secondMesh->cm); static int counterMV=0; static int step=0; //for(int i=0;i<GG.MV.size();++i) int i=counterMV; step = (step +1)%4; // if(step==0) counterMV++; qDebug("Counter %i step %i",counterMV,step); { Point3f baseTran = GG.InitBaseTranslation(GG.MV[i]); Point3f bestTran; int res = GG.SearchBestTranslation(GG.u[0],GG.MV[i],4,1,baseTran,bestTran); if(step==0) firstMesh->cm.Tr.SetIdentity(); if(step==1) firstMesh->cm.Tr = GG.MV[i]; if(step==2) firstMesh->cm.Tr = GG.BuildTransformation(GG.MV[i],baseTran); if(step==3) firstMesh->cm.Tr = GG.BuildTransformation(GG.MV[i],bestTran); } //Log(0,(res)?" Automatic Rough Alignment Done":"Automatic Rough Alignment Failed"); } break; default: assert (0); } return true; }
bool FilterFractal::applyFilter(QAction* filter, MeshDocument &md, RichParameterSet &par, vcg::CallBackPos* cb) { if(this->getClass(filter) == MeshFilterInterface::MeshCreation) md.addNewMesh("",this->filterName(ID(filter))); switch(ID(filter)) { case CR_FRACTAL_TERRAIN: case FP_FRACTAL_MESH: { MeshModel* mm = md.mm(); float maxHeight = .0; int smoothingSteps = 0; if(ID(filter) == CR_FRACTAL_TERRAIN) { int steps = par.getInt("steps"); steps = ((steps<2)? 2: steps); float gridSide = .0; FractalUtils<CMeshO>::GenerateGrid(mm->cm, steps, gridSide); maxHeight = par.getDynamicFloat("maxHeight") * gridSide; } else { maxHeight = par.getAbsPerc("maxHeight"); smoothingSteps = par.getInt("smoothingSteps"); } FractalUtils<CMeshO>::FractalArgs args (mm, par.getEnum("algorithm"),par.getFloat("seed"), par.getFloat("octaves"), par.getFloat("lacunarity"), par.getFloat("fractalIncrement"), par.getFloat("offset"), par.getFloat("gain"), maxHeight, par.getDynamicFloat("scale"), smoothingSteps, par.getBool("saveAsQuality")); if(args.saveAsQuality) mm->updateDataMask(MeshModel::MM_VERTQUALITY); return FractalUtils<CMeshO>::ComputeFractalPerturbation(mm->cm, args, cb); } break; case FP_CRATERS: { if (md.meshList.size() < 2) { errorMessage = "There must be at least two layers to apply the craters generation filter."; return false; } CMeshO* samples = &(par.getMesh("samples_mesh")->cm); if (samples->face.size() > 0) { errorMessage = "The sample layer selected should be a points cloud."; return false; } CMeshO* target = &(par.getMesh("target_mesh")->cm); if (samples == target) { errorMessage = "The sample layer and the target layer must be different."; return false; } float minRadius = par.getDynamicFloat("min_radius"); float maxRadius = par.getDynamicFloat("max_radius"); if (maxRadius <= minRadius) { errorMessage = "Min radius is greater than max radius."; return false; } float minDepth = par.getDynamicFloat("min_depth"); float maxDepth = par.getDynamicFloat("max_depth"); if (maxDepth <= minDepth) { errorMessage = "Min depth is greater than max depth."; return false; } // reads parameters CratersUtils<CMeshO>::CratersArgs args(par.getMesh("target_mesh"), par.getMesh("samples_mesh"), par.getEnum("rbf"), par.getInt("seed"), minRadius, maxRadius, minDepth, maxDepth, par.getInt("smoothingSteps"), par.getBool("save_as_quality"), par.getBool("invert"), par.getBool("ppNoise"), par.getBool("successiveImpacts"), par.getDynamicFloat("elevation"), par.getEnum("blend"), par.getDynamicFloat("blendThreshold")); return CratersUtils<CMeshO>::GenerateCraters(args, cb); } break; } return false; }
bool FilterCSG::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb) { switch(ID(filter)) { case FP_CSG: { MeshModel *firstMesh = par.getMesh("FirstMesh"); MeshModel *secondMesh = par.getMesh("SecondMesh"); firstMesh->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACENORMAL | MeshModel::MM_FACEQUALITY); secondMesh->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACENORMAL | MeshModel::MM_FACEQUALITY); if (!isValid (firstMesh->cm, this->errorMessage) || !isValid (secondMesh->cm, this->errorMessage)) return false; firstMesh->updateDataMask(MeshModel::MM_FACENORMAL | MeshModel::MM_FACEQUALITY); secondMesh->updateDataMask(MeshModel::MM_FACENORMAL | MeshModel::MM_FACEQUALITY); typedef CMeshO::ScalarType scalar; typedef Intercept<mpq_class,scalar> intercept; const scalar d = par.getFloat("Delta"); const Point3f delta(d, d, d); const int subFreq = par.getInt("SubDelta"); Log(0, "Rasterizing first volume..."); InterceptVolume<intercept> v = InterceptSet3<intercept>(firstMesh->cm, delta, subFreq, cb); Log(0, "Rasterizing second volume..."); InterceptVolume<intercept> tmp = InterceptSet3<intercept>(secondMesh->cm, delta, subFreq, cb); MeshModel *mesh; switch(par.getEnum("Operator")){ case CSG_OPERATION_INTERSECTION: Log(0, "Intersection..."); v &= tmp; mesh = md.addNewMesh("","intersection"); break; case CSG_OPERATION_UNION: Log(0, "Union..."); v |= tmp; mesh = md.addNewMesh("","union"); break; case CSG_OPERATION_DIFFERENCE: Log(0, "Difference..."); v -= tmp; mesh = md.addNewMesh("","difference"); break; default: assert(0); return true; } Log(0, "Building mesh..."); typedef vcg::intercept::Walker<CMeshO, intercept> MyWalker; MyWalker walker; if (par.getBool("Extended")) { mesh->updateDataMask(MeshModel::MM_FACEFACETOPO); typedef vcg::tri::ExtendedMarchingCubes<CMeshO, MyWalker> MyExtendedMarchingCubes; MyExtendedMarchingCubes mc(mesh->cm, walker); walker.BuildMesh<MyExtendedMarchingCubes>(mesh->cm, v, mc, cb); } else { typedef vcg::tri::MarchingCubes<CMeshO, MyWalker> MyMarchingCubes; MyWalker walker; MyMarchingCubes mc(mesh->cm, walker); walker.BuildMesh<MyMarchingCubes>(mesh->cm, v, mc, cb); } Log(0, "Done"); vcg::tri::UpdateBounding<CMeshO>::Box(mesh->cm); vcg::tri::UpdateNormal<CMeshO>::PerFaceFromCurrentVertexNormal(mesh->cm); } return true; default: assert (0); } return true; }
bool AlignTools::setupThenAlign(MeshModel &/*mm*/, RichParameterSet & par) { //mesh that wont move MeshModel *stuckModel = par.getMesh(StuckMesh); PickedPoints *stuckPickedPoints = 0; //mesh that will move MeshModel *modelToMove = par.getMesh(MeshToMove); PickedPoints *modelToMovePickedPoints = 0; bool useMarkers = par.getBool(UseMarkers); if(NULL == stuckModel || NULL == modelToMove) { qDebug() << "one of the input meshes to filter align was null"; return false; } //if we are going to use the markers try to load them if(useMarkers){ //first try to get points from memory if(vcg::tri::HasPerMeshAttribute(stuckModel->cm, PickedPoints::Key) ) { CMeshO::PerMeshAttributeHandle<PickedPoints*> ppHandle = vcg::tri::Allocator<CMeshO>::GetPerMeshAttribute<PickedPoints*>(stuckModel->cm, PickedPoints::Key); stuckPickedPoints = ppHandle(); if(NULL == stuckPickedPoints){ qDebug() << "problem casting to picked points"; return false; } } else { //now try to load them from a file QString ppFileName = PickedPoints::getSuggestedPickedPointsFileName(*stuckModel); QFileInfo file(ppFileName); if(file.exists()) { stuckPickedPoints = new PickedPoints(); bool success = stuckPickedPoints->open(ppFileName); if(!success){ qDebug() << "problem loading stuck picked points from a file"; return false; } } else { qDebug() << "stuck points file didnt exist: " << ppFileName; //Log(GLLogStream::WARNING, "No points were found for the Stuck mesh."); return false; } } if(vcg::tri::HasPerMeshAttribute(modelToMove->cm, PickedPoints::Key) ) { CMeshO::PerMeshAttributeHandle<PickedPoints*> ppHandle = vcg::tri::Allocator<CMeshO>::GetPerMeshAttribute<PickedPoints*>(modelToMove->cm, PickedPoints::Key); modelToMovePickedPoints = ppHandle(); if(NULL == modelToMovePickedPoints){ qDebug() << "problem casting to picked poitns"; return false; } } else { QString ppFileName = PickedPoints::getSuggestedPickedPointsFileName(*modelToMove); QFileInfo file(ppFileName); if(file.exists()) { modelToMovePickedPoints = new PickedPoints(); bool success = modelToMovePickedPoints->open(ppFileName); if(!success){ qDebug() << "failed to load modelToMove pick points"; return false; } } else { qDebug() << "model to move points file didnt exist: " << ppFileName; //Log(GLLogStream::WARNING, "No points were found for the mesh to move."); return false; } } } bool result = AlignTools::align(stuckModel, stuckPickedPoints, modelToMove, modelToMovePickedPoints, 0, par); return result; }
// The Real Core Function doing the actual mesh processing. bool FilterAutoalign::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb) { switch(ID(filter)) { case FP_ALIGN_4PCS : { MeshModel *fixMesh= par.getMesh("fixMesh"); MeshModel *movMesh= par.getMesh("movMesh"); MeshModel *sampleMesh= 0; bool showSample = par.getBool("showSample"); if(showSample) sampleMesh = md.addOrGetMesh("sample","sample",false, RenderMode(vcg::GLW::DMPoints)); tri::UpdateNormal<CMeshO>::NormalizePerVertex(fixMesh->cm); tri::UpdateNormal<CMeshO>::NormalizePerVertex(movMesh->cm); tri::Clean<CMeshO>::RemoveUnreferencedVertex(fixMesh->cm); tri::Clean<CMeshO>::RemoveUnreferencedVertex(movMesh->cm); tri::Allocator<CMeshO>::CompactEveryVector(fixMesh->cm); tri::Allocator<CMeshO>::CompactEveryVector(movMesh->cm); fixMesh->updateDataMask(MeshModel::MM_VERTMARK); movMesh->updateDataMask(MeshModel::MM_VERTMARK); vcg::tri::FourPCS<CMeshO> fpcs; fpcs.par.Default(); fpcs.par.overlap = par.getFloat("overlap"); fpcs.par.sampleNumP = par.getInt("sampleNum"); fpcs.par.deltaPerc = par.getFloat("tolerance"); fpcs.par.seed = par.getInt("randSeed"); fpcs.Init(movMesh->cm,fixMesh->cm); Matrix44m Tr; bool res = fpcs.Align(Tr,cb); if(res) { Log("4PCS Completed, radius %f",fpcs.par.samplingRadius); Log("Tested %i candidate, best score was %i\n",fpcs.U.size(),fpcs.U[fpcs.iwinner].score); Log("Estimated overlap is now %f \n",fpcs.par.overlap); Log("Init %5.0f Coplanar Search %5.0f",fpcs.stat.init(),fpcs.stat.select()); Log("findCongruent %5.0f testAlignment %5.0f",fpcs.stat.findCongruent(),fpcs.stat.testAlignment()); movMesh->cm.Tr = Tr; if(showSample) { sampleMesh->cm.Clear(); for(size_t i=0;i<fpcs.subsetQ.size();++i) tri::Allocator<CMeshO>::AddVertex(sampleMesh->cm, fpcs.subsetQ[i]->P(), fpcs.subsetQ[i]->N()); tri::UpdateBounding<CMeshO>::Box(sampleMesh->cm); } } else Log("4PCS Failed"); } break; case FP_BEST_ROTATION : { MeshModel *fixMesh= par.getMesh("fixMesh"); MeshModel *movMesh= par.getMesh("movMesh"); int searchRange = par.getInt("searchRange"); int rotNum = par.getInt("RotationNumber"); int gridSize = par.getInt("gridSize"); int sampleSize = par.getInt("sampleSize"); MeshModel *sample=md.addOrGetMesh("sample", "sample",false); MeshModel *occ=md.addOrGetMesh("occ", "occ",false); tri::Guess<Scalarm> GG; std::vector<tri::Guess<Scalarm>::Result> ResultVec; GG.pp.MatrixNum = rotNum; GG.pp.GridSize =gridSize; GG.pp.SampleNum = sampleSize; GG.Init<CMeshO>(fixMesh->cm, movMesh->cm); for(size_t i=0;i<GG.RotMVec.size();++i) { Point3m baseTran = GG.ComputeBaseTranslation(GG.RotMVec[i]); Point3m bestTran; int res = GG.SearchBestTranslation(GG.u[0],GG.RotMVec[i],searchRange,baseTran,bestTran); ResultVec.push_back(tri::Guess<Scalarm>::Result(GG.BuildResult(GG.RotMVec[i],baseTran,bestTran), res, i, bestTran)); } sort(ResultVec.begin(),ResultVec.end()); movMesh->cm.Tr.Import(ResultVec.back().m); tri::Build(sample->cm,GG.movVertBase); sample->cm.Tr.Import(ResultVec.back().m); qDebug("Result %i",ResultVec.back().score); GG.GenerateOccupancyMesh(occ->cm,0,ResultVec.back().m); occ->UpdateBoxAndNormals(); Log("Automatic Rough Alignment Tested %i rotations, best err was %i",GG.RotMVec.size(), ResultVec.back().score); } break; default: assert (0); } return true; }
bool RandomFillFilter::applyFilter(QAction*, MeshDocument &md, RichParameterSet& par, vcg::CallBackPos* cb){ if(parametersAreNotCorrect(md, par)) return false; MeshSubFilter::initialize(md, par, cb); if(cb != 0) (*cb)(0, "Physics renderization of the scene started..."); MeshModel* container = par.getMesh("container"); MeshModel* filler = par.getMesh("filler"); int fillOffset = md.size(); float gravity[3] = {0.0f, par.getBool("useRandomVertices") ? 0.0f : -9.8f, 0.0f}; if(par.getBool("flipNormal")){ vcg::tri::Clean<CMeshO>::FlipMesh(container->cm); tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(container->cm); container->clearDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER); } m_engine.clear(); m_engine.setGlobalForce(gravity); m_engine.setIterations(par.getInt("iterations")); m_engine.setMaxContacts(par.getInt("contacts")); m_engine.setBounciness(par.getFloat("bounciness")); m_engine.setFriction(par.getFloat("friction")); m_engine.registerTriMesh(*container, true); srand((unsigned)time(0)); vcg::tri::UpdatePosition<CMeshO>::Matrix(filler->cm, filler->cm.Tr); filler->cm.Tr.SetIdentity(); tri::Inertia<CMeshO> inertiaContainer, inertiaFiller; inertiaContainer.Compute(par.getMesh("container")->cm); inertiaFiller.Compute(par.getMesh("filler")->cm); int objects = abs(inertiaContainer.Mass()/inertiaFiller.Mass())*par.getFloat("factor"); filler->cm.Tr.SetColumn(3, - inertiaFiller.CenterOfMass()); //Restore old generated meshes int restoredMeshes = 0; for(int i = 0; i < md.size(); i++){ if(md.getMesh(i)->fileName.find("randomFillMesh") == 0){ m_engine.registerTriMesh(*md.getMesh(i)); restoredMeshes++; m_engine.integrate(1.0f/par.getInt("fps")); } } int frequency = 1 / par.getFloat("updateFrequency"); // To refactor when the right algorithm has be found if(par.getBool("useRandomVertices")){ for(int i = 0; i < objects; i++){ if(cb != 0) (*cb)(50.f*i/objects, "Computing..."); addRandomObject(md, filler, getRandomOrigin(par), restoredMeshes + i); m_engine.registerTriMesh(*md.getMesh(fillOffset++)); } for(int j = 0; j < par.getFloat("seconds") * par.getInt("fps"); j++){ if(cb != 0) (*cb)(50 + 48.f*j/(par.getFloat("seconds") * par.getInt("fps")), "Computing..."); m_engine.integrate(1.0f/par.getInt("fps")); } }else{ for(int i = 0; i < objects; i++){ if(cb != 0) (*cb)(98.f*i/objects, "Computing..."); addRandomObject(md, filler, inertiaContainer.CenterOfMass(), i); m_engine.registerTriMesh(*md.getMesh(fillOffset++)); if(i % frequency == 0) for(int j = 0; j < par.getFloat("seconds") * par.getInt("fps"); j++) m_engine.integrate(1.0f/par.getInt("fps")); } } m_engine.updateTransform(); filler->cm.Tr.SetIdentity(); m_currentFilterType = m_filterType; if(par.getBool("flipNormal")){ vcg::tri::Clean<CMeshO>::FlipMesh(container->cm); tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(container->cm); container->clearDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER); } if(cb != 0) (*cb)(99, "Physics renderization of the scene completed..."); return true; }
vcg::Point3<float> RandomFillFilter::getRandomOrigin(RichParameterSet& par){ int randomVertex = float(rand())/RAND_MAX*(par.getMesh("container")->cm.vert.size() - 1); CVertexO& vertex = par.getMesh("container")->cm.vert[randomVertex]; return vertex.P() + (vertex.N() * par.getMesh("filler")->cm.bbox.Diag()); }
bool RandomFillFilter::parametersAreNotCorrect(MeshDocument& md, RichParameterSet& par){ return md.size() < 2 || par.getMesh("container") == 0 || par.getMesh("container") == par.getMesh("filler") || par.getInt("fps") <= 0 || par.getInt("iterations") <= 0 || par.getInt("contacts") <= 0 || par.getFloat("bounciness") < 0.f || par.getFloat("bounciness") > 1.f || par.getFloat("factor") < 0.f || par.getFloat("factor") > 1.f; }
bool FilterIsoParametrization::applyFilter(QAction *filter, MeshDocument& md, RichParameterSet & par, vcg::CallBackPos *cb) { MeshModel* m = md.mm(); //get current mesh from document CMeshO *mesh=&m->cm; switch(ID(filter)) { case ISOP_PARAM : { int targetAbstractMinFaceNum = par.getInt("targetAbstractMinFaceNum"); int targetAbstractMaxFaceNum = par.getInt("targetAbstractMaxFaceNum"); int convergenceSpeed = par.getInt("convergenceSpeed"); int stopCriteria=par.getEnum("stopCriteria"); bool doublestep=par.getBool("DoubleStep"); IsoParametrizator Parametrizator; m->updateDataMask(MeshModel::MM_FACEFACETOPO); m->updateDataMask(MeshModel::MM_VERTQUALITY); // needed to store patch index bool isTXTenabled=m->hasDataMask(MeshModel::MM_VERTTEXCOORD); if (!isTXTenabled) m->updateDataMask(MeshModel::MM_VERTTEXCOORD); bool isVMarkenabled=m->hasDataMask(MeshModel::MM_VERTMARK); if (!isVMarkenabled) m->updateDataMask(MeshModel::MM_VERTMARK); bool isFMarkenabled=m->hasDataMask(MeshModel::MM_FACEMARK); if (!isFMarkenabled) m->updateDataMask(MeshModel::MM_FACEMARK); bool isVColorenabled=m->hasDataMask(MeshModel::MM_VERTCOLOR); if (!isVColorenabled) m->updateDataMask(MeshModel::MM_VERTCOLOR); bool isFColorenabled=m->hasDataMask(MeshModel::MM_FACECOLOR); if (!isFColorenabled) m->updateDataMask(MeshModel::MM_FACECOLOR); int tolerance = targetAbstractMaxFaceNum-targetAbstractMinFaceNum; switch (stopCriteria) { case 0: Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Euristic,convergenceSpeed); break; case 1: Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Corr,convergenceSpeed); break; case 2: Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Reg,convergenceSpeed); break; case 3: Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_L2,convergenceSpeed); break; default: Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Euristic,convergenceSpeed); break; } tri::ParamEdgeCollapseParameter pecp; IsoParametrizator::ReturnCode ret=Parametrizator.Parametrize<CMeshO>(mesh,pecp,doublestep); if (ret==IsoParametrizator::Done) { Parametrizator.PrintAttributes(); float aggregate,L2; int n_faces; Parametrizator.getValues(aggregate,L2,n_faces); Log("Num Faces of Abstract Domain: %d, One way stretch efficiency: %.4f, Area+Angle Distorsion %.4f ",n_faces,L2,aggregate*100.f); } else { if (!isTXTenabled) m->clearDataMask(MeshModel::MM_VERTTEXCOORD); if (!isFMarkenabled) m->clearDataMask(MeshModel::MM_FACEMARK); if (!isVMarkenabled) m->clearDataMask(MeshModel::MM_VERTMARK); if (!isVColorenabled) m->clearDataMask(MeshModel::MM_VERTCOLOR); if (!isFColorenabled) m->clearDataMask(MeshModel::MM_FACECOLOR); switch(ret) { case IsoParametrizator::MultiComponent: this->errorMessage="non possible parameterization because of multi componet mesh"; return false; case IsoParametrizator::NonSizeCons: this->errorMessage="non possible parameterization because of non size consistent mesh"; return false; case IsoParametrizator::NonManifoldE: this->errorMessage="non possible parameterization because of non manifold edges"; return false; case IsoParametrizator::NonManifoldV: this->errorMessage="non possible parameterization because of non manifold vertices"; return false; case IsoParametrizator::NonWatertigh: this->errorMessage="non possible parameterization because of non watertight mesh"; return false; case IsoParametrizator::FailParam: this->errorMessage="non possible parameterization cause one of the following reasons:\n Topologycal noise \n Too Low resolution mesh \n Too Bad triangulation \n"; return false; default: this->errorMessage="unknown error"; return false; } } // At this point we are sure that everithing went ok so we can allocate surely the abstract AbstractMesh *abs_mesh = new AbstractMesh(); ParamMesh *para_mesh = new ParamMesh(); Parametrizator.ExportMeshes(*para_mesh,*abs_mesh); CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle; isoPHandle=tri::Allocator<CMeshO>::AddPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); bool isOK=isoPHandle().Init(abs_mesh,para_mesh); ///copy back to original mesh isoPHandle().CopyParametrization<CMeshO>(mesh); if (!isOK) { this->errorMessage="Problems gathering parameterization \n"; return false; } if (!isVMarkenabled) m->clearDataMask(MeshModel::MM_VERTMARK); if (!isFMarkenabled) m->clearDataMask(MeshModel::MM_FACEMARK); return true; } case ISOP_REMESHING : { CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle = tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); bool b=tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle); if (!b) { this->errorMessage="You must compute the Base domain before remeshing. Use the Isoparametrization command."; return false; } int SamplingRate=par.getInt("SamplingRate"); if (!SamplingRate>2) { this->errorMessage="Sampling rate must be >1"; return false; } MeshModel* mm=md.addNewMesh("","Re-meshed"); CMeshO *rem=&mm->cm; DiamSampler DiamSampl; DiamSampl.Init(&isoPHandle()); bool done=DiamSampl.SamplePos(SamplingRate); assert(done); DiamSampl.GetMesh<CMeshO>(*rem); int n_diamonds,inFace,inEdge,inStar,n_merged; DiamSampl.getResData(n_diamonds,inFace,inEdge,inStar,n_merged); Log("INTERPOLATION DOMAINS"); Log("In Face: %d \n",inFace); Log("In Diamond: %d \n",inEdge); Log("In Star: %d \n",inStar); Log("Merged %d vertices\n",n_merged); mm->updateDataMask(MeshModel::MM_FACEFACETOPO); mm->updateDataMask(MeshModel::MM_VERTFACETOPO); PrintStats(rem); tri::UpdateNormal<CMeshO>::PerFace(*rem); return true; } case ISOP_DIAMPARAM : { CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle = tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); bool b=tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle); if (!b) { this->errorMessage="You must compute the Base domain before remeshing. Use the Isoparametrization command."; return false; } float border_size=par.getDynamicFloat("BorderSize"); MeshModel* mm=md.addNewMesh("","Diam-Parameterized"); mm->updateDataMask(MeshModel::MM_WEDGTEXCOORD); mm->updateDataMask(MeshModel::MM_VERTCOLOR); CMeshO *rem=&mm->cm; DiamondParametrizator DiaPara; DiaPara.Init(&isoPHandle()); DiaPara.SetCoordinates<CMeshO>(*rem,border_size); tri::UpdateNormal<CMeshO>::PerFace(*rem); return true; } case ISOP_LOAD : { QString AbsName = par.getString("AbsName"); m->updateDataMask(MeshModel::MM_WEDGTEXCOORD); m->updateDataMask(MeshModel::MM_VERTTEXCOORD); m->updateDataMask(MeshModel::MM_FACECOLOR); m->updateDataMask(MeshModel::MM_VERTQUALITY); m->updateDataMask(MeshModel::MM_FACEMARK); if(!QFile(m->fullName()).exists()) { this->errorMessage="File not exists"; return false; } CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle = tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); bool b=tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle); if (!b) isoPHandle=tri::Allocator<CMeshO>::AddPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); QByteArray ba = AbsName.toLatin1(); char *path=ba.data(); AbstractMesh *abs_mesh = new AbstractMesh(); ParamMesh *para_mesh = new ParamMesh(); bool Done=isoPHandle().LoadBaseDomain<CMeshO>(path,mesh,para_mesh,abs_mesh,true); if (!Done) { this->errorMessage="Abstract domain doesnt fit well with the parametrized mesh"; delete para_mesh; delete abs_mesh; return false; } return true; } case ISOP_SAVE : { m->updateDataMask(MeshModel::MM_VERTQUALITY); CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle = tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); bool b=tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle); if (!b) { this->errorMessage="You must compute the Base domain before remeshing. Use the Isoparametrization command."; return false; } /*QString Qpath=m->fullName();*/ QString AbsName = par.getString("AbsName"); QByteArray ba = AbsName.toLatin1(); char *path=ba.data(); isoPHandle().SaveBaseDomain(path); return true; } case ISOP_TRANSFER: { MeshModel *mmtrg = par.getMesh("targetMesh"); MeshModel *mmsrc = par.getMesh("targetMesh"); CMeshO *trgMesh=&mmtrg->cm; CMeshO *srcMesh=&mmsrc->cm; CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle = tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); bool b=tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*srcMesh,isoPHandle); if (!b) { this->errorMessage="Your source mesh must have the abstract isoparametrization. Use the Isoparametrization command."; return false; } IsoTransfer IsoTr; AbstractMesh *abs_mesh = isoPHandle().AbsMesh(); ParamMesh *para_mesh = isoPHandle().ParaMesh(); mmtrg->updateDataMask(MeshModel::MM_WEDGTEXCOORD); mmtrg->updateDataMask(MeshModel::MM_VERTTEXCOORD); mmtrg->updateDataMask(MeshModel::MM_FACECOLOR); mmtrg->updateDataMask(MeshModel::MM_VERTQUALITY); mmtrg->updateDataMask(MeshModel::MM_FACEMARK); IsoTr.Transfer<CMeshO>(isoPHandle(),*trgMesh); isoPHandle().Clear(); tri::Allocator<CMeshO>::DeletePerMeshAttribute(*srcMesh,isoPHandle); isoPHandle=tri::Allocator<CMeshO>::AddPerMeshAttribute<IsoParametrization>(*trgMesh,"isoparametrization"); isoPHandle().AbsMesh()=abs_mesh; isoPHandle().SetParamMesh<CMeshO>(trgMesh,para_mesh); return true; } } return false; }