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 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); 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; } IsoParametrizator::ReturnCode ret=Parametrizator.Parametrize<CMeshO>(mesh,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); if (ret==IsoParametrizator::NonPrecondition) this->errorMessage="non possible parameterization because of violated preconditions"; else if (ret==IsoParametrizator::FailParam) this->errorMessage="non possible parameterization cause because missing the intepolation for some triangle of original the mesh (maybe due to topologycal noise)"; return false; } Parametrizator.ExportMeshes(para_mesh,abs_mesh); isoPHandle=vcg::tri::Allocator<CMeshO>::AddPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); bool isOK=isoPHandle().Init(&abs_mesh,¶_mesh); ///copy back to original mesh isoPHandle().CopyParametrization<CMeshO>(mesh); if (!isOK) { Log("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 : { bool b=vcg::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"); MeshModel* mm=md.addNewMesh("Re-meshed"); CMeshO *rem=&mm->cm; DiamSampl.Init(&isoPHandle()); DiamSampl.SamplePos(SamplingRate); 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); vcg::tri::UpdateNormals<CMeshO>::PerFace(*rem); return true; } case ISOP_DIAMPARAM : { bool b=vcg::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); vcg::tri::UpdateNormals<CMeshO>::PerFace(*rem); return true; } case ISOP_LOAD : { QString AbsName = par.getString("AbsName"); bool isTXTenabled=m->hasDataMask(MeshModel::MM_VERTTEXCOORD); if (!isTXTenabled) { this->errorMessage="Per Vertex Text Coordinates are not enabled"; return false; } if(!QFile(m->fullName()).exists()) { this->errorMessage="File not exists"; return false; } bool b=vcg::tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle); if (!b) isoPHandle=vcg::tri::Allocator<CMeshO>::AddPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); QByteArray ba = AbsName.toLatin1(); char *path=ba.data(); bool Done=isoPHandle().LoadBaseDomain<CMeshO>(path,mesh,¶_mesh,true); if (!Done) { this->errorMessage="Abstract domain doesnt fit well with the parametrized mesh"; return false; } return true; } case ISOP_SAVE : { bool b=vcg::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; } } return false; }
bool ExtraMeshColorizePlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb){ MeshModel &m=*(md.mm()); switch(ID(filter)) { case CP_SATURATE_QUALITY:{ m.updateDataMask(MeshModel::MM_VERTFACETOPO); tri::UpdateQuality<CMeshO>::VertexSaturate(m.cm, par.getFloat("gradientThr")); if(par.getBool("updateColor")) { Histogramf H; tri::Stat<CMeshO>::ComputePerVertexQualityHistogram(m.cm,H); m.updateDataMask(MeshModel::MM_VERTCOLOR); tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,H.Percentile(0.1f),H.Percentile(0.9f)); } Log("Saturated "); } break; case CP_MAP_VQUALITY_INTO_COLOR: m.updateDataMask(MeshModel::MM_VERTCOLOR); case CP_CLAMP_QUALITY: { float RangeMin = par.getFloat("minVal"); float RangeMax = par.getFloat("maxVal"); bool usePerc = par.getDynamicFloat("perc")>0; Histogramf H; tri::Stat<CMeshO>::ComputePerVertexQualityHistogram(m.cm,H); float PercLo = H.Percentile(par.getDynamicFloat("perc")/100.f); float PercHi = H.Percentile(1.0-par.getDynamicFloat("perc")/100.f); if(par.getBool("zeroSym")) { RangeMin = min(RangeMin, -math::Abs(RangeMax)); RangeMax = max(math::Abs(RangeMin), RangeMax); PercLo = min(PercLo, -math::Abs(PercHi)); PercHi = max(math::Abs(PercLo), PercHi); } if(usePerc) { if(ID(filter)==CP_CLAMP_QUALITY) tri::UpdateQuality<CMeshO>::VertexClamp(m.cm,PercLo,PercHi); else tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,PercLo,PercHi); Log("Quality Range: %f %f; Used (%f %f) percentile (%f %f) ",H.MinV(),H.MaxV(),PercLo,PercHi,par.getDynamicFloat("perc"),100-par.getDynamicFloat("perc")); } else { if(ID(filter)==CP_CLAMP_QUALITY) tri::UpdateQuality<CMeshO>::VertexClamp(m.cm,RangeMin,RangeMax); else tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,RangeMin,RangeMax); Log("Quality Range: %f %f; Used (%f %f)",H.MinV(),H.MaxV(),RangeMin,RangeMax); } break; } case CP_MAP_FQUALITY_INTO_COLOR: { m.updateDataMask(MeshModel::MM_FACECOLOR); float RangeMin = par.getFloat("minVal"); float RangeMax = par.getFloat("maxVal"); float perc = par.getDynamicFloat("perc"); Histogramf H; tri::Stat<CMeshO>::ComputePerFaceQualityHistogram(m.cm,H); float PercLo = H.Percentile(perc/100.f); float PercHi = H.Percentile(1.0-perc/100.f); // Make the range and percentile symmetric w.r.t. zero, so that // the value zero is always colored in yellow if(par.getBool("zeroSym")){ RangeMin = min(RangeMin, -math::Abs(RangeMax)); RangeMax = max(math::Abs(RangeMin), RangeMax); PercLo = min(PercLo, -math::Abs(PercHi)); PercHi = max(math::Abs(PercLo), PercHi); } tri::UpdateColor<CMeshO>::FaceQualityRamp(m.cm,PercLo,PercHi); Log("Quality Range: %f %f; Used (%f %f) percentile (%f %f) ", H.MinV(), H.MaxV(), PercLo, PercHi, perc, 100-perc); break; } case CP_DISCRETE_CURVATURE: { m.updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTCURV); m.updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY); tri::UpdateFlags<CMeshO>::FaceBorderFromFF(m.cm); if ( tri::Clean<CMeshO>::CountNonManifoldEdgeFF(m.cm) > 0) { errorMessage = "Mesh has some not 2-manifold faces, Curvature computation requires manifoldness"; // text return false; // can't continue, mesh can't be processed } int delvert=tri::Clean<CMeshO>::RemoveUnreferencedVertex(m.cm); if(delvert) Log("Pre-Curvature Cleaning: Removed %d unreferenced vertices",delvert); tri::Allocator<CMeshO>::CompactVertexVector(m.cm); tri::UpdateCurvature<CMeshO>::MeanAndGaussian(m.cm); int curvType = par.getEnum("CurvatureType"); switch(curvType){ case 0: tri::UpdateQuality<CMeshO>::VertexFromMeanCurvature(m.cm); Log( "Computed Mean Curvature"); break; case 1: tri::UpdateQuality<CMeshO>::VertexFromGaussianCurvature(m.cm); Log( "Computed Gaussian Curvature"); break; case 2: tri::UpdateQuality<CMeshO>::VertexFromRMSCurvature(m.cm); Log( "Computed RMS Curvature"); break; case 3: tri::UpdateQuality<CMeshO>::VertexFromAbsoluteCurvature(m.cm); Log( "Computed ABS Curvature"); break; default : assert(0); } Histogramf H; tri::Stat<CMeshO>::ComputePerVertexQualityHistogram(m.cm,H); tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,H.Percentile(0.1f),H.Percentile(0.9f)); Log( "Curvature Range: %f %f (Used 90 percentile %f %f) ",H.MinV(),H.MaxV(),H.Percentile(0.1f),H.Percentile(0.9f)); break; } case CP_TRIANGLE_QUALITY: { m.updateDataMask(MeshModel::MM_FACECOLOR | MeshModel::MM_FACEQUALITY); CMeshO::FaceIterator fi; Distribution<float> distrib; float minV = 0; float maxV = 1.0; int metric = par.getEnum("Metric"); if(metric ==4 || metric ==5 ) { if(!m.hasDataMask(MeshModel::MM_VERTTEXCOORD) && !m.hasDataMask(MeshModel::MM_WEDGTEXCOORD)) { this->errorMessage = "This metric need Texture Coordinate"; return false; } } switch(metric){ case 0: { //area / max edge minV = 0; maxV = sqrt(3.0f)/2.0f; for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = vcg::Quality((*fi).P(0), (*fi).P(1),(*fi).P(2)); } break; case 1: { //inradius / circumradius for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = vcg::QualityRadii((*fi).P(0), (*fi).P(1), (*fi).P(2)); } break; case 2: { //mean ratio for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = vcg::QualityMeanRatio((*fi).P(0), (*fi).P(1), (*fi).P(2)); } break; case 3: { // AREA for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = vcg::DoubleArea((*fi))*0.5f; tri::Stat<CMeshO>::ComputePerFaceQualityMinMax(m.cm,minV,maxV); } break; case 4: { //TEXTURE Angle Distortion if(m.hasDataMask(MeshModel::MM_WEDGTEXCOORD)) { for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = Distortion<CMeshO,true>::AngleDistortion(&*fi); } else { for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = Distortion<CMeshO,false>::AngleDistortion(&*fi); } tri::Stat<CMeshO>::ComputePerFaceQualityDistribution(m.cm,distrib); minV = distrib.Percentile(0.05); maxV = distrib.Percentile(0.95); } break; case 5: { //TEXTURE Area Distortion float areaScaleVal, edgeScaleVal; if(m.hasDataMask(MeshModel::MM_WEDGTEXCOORD)) { Distortion<CMeshO,true>::MeshScalingFactor(m.cm, areaScaleVal,edgeScaleVal); for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = Distortion<CMeshO,true>::AreaDistortion(&*fi,areaScaleVal); } else { Distortion<CMeshO,false>::MeshScalingFactor(m.cm, areaScaleVal,edgeScaleVal); for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = Distortion<CMeshO,false>::AreaDistortion(&*fi,areaScaleVal); } tri::Stat<CMeshO>::ComputePerFaceQualityDistribution(m.cm,distrib); minV = distrib.Percentile(0.05); maxV = distrib.Percentile(0.95); } break; default: assert(0); } tri::UpdateColor<CMeshO>::FaceQualityRamp(m.cm,minV,maxV,false); break; } case CP_RANDOM_CONNECTED_COMPONENT: m.updateDataMask(MeshModel::MM_FACEFACETOPO); m.updateDataMask(MeshModel::MM_FACEMARK | MeshModel::MM_FACECOLOR); vcg::tri::UpdateColor<CMeshO>::FaceRandomConnectedComponent(m.cm); break; case CP_RANDOM_FACE: m.updateDataMask(MeshModel::MM_FACEFACETOPO); m.updateDataMask(MeshModel::MM_FACEMARK | MeshModel::MM_FACECOLOR); vcg::tri::UpdateColor<CMeshO>::MultiFaceRandom(m.cm); break; case CP_VERTEX_SMOOTH: { int iteration = par.getInt("iteration"); tri::Smooth<CMeshO>::VertexColorLaplacian(m.cm,iteration,false,cb); } break; case CP_FACE_SMOOTH: { m.updateDataMask(MeshModel::MM_FACEFACETOPO); int iteration = par.getInt("iteration"); tri::Smooth<CMeshO>::FaceColorLaplacian(m.cm,iteration,false,cb); } break; case CP_FACE_TO_VERTEX: m.updateDataMask(MeshModel::MM_VERTCOLOR); tri::UpdateColor<CMeshO>::VertexFromFace(m.cm); break; case CP_VERTEX_TO_FACE: m.updateDataMask(MeshModel::MM_FACECOLOR); tri::UpdateColor<CMeshO>::FaceFromVertex(m.cm); break; case CP_TEXTURE_TO_VERTEX: { m.updateDataMask(MeshModel::MM_VERTCOLOR); if(!HasPerWedgeTexCoord(m.cm)) break; CMeshO::FaceIterator fi; QImage tex(m.cm.textures[0].c_str()); for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) { for (int i=0; i<3; i++) { // note the trick for getting only the fractional part of the uv with the correct wrapping (e.g. 1.5 -> 0.5 and -0.3 -> 0.7) vcg::Point2f newcoord((*fi).WT(i).P().X()-floor((*fi).WT(i).P().X()),(*fi).WT(i).P().Y()-floor((*fi).WT(i).P().Y())); QRgb val = tex.pixel(newcoord[0]*tex.width(),(1-newcoord[1])*tex.height()-1); (*fi).V(i)->C().SetRGB(qRed(val),qGreen(val),qBlue(val)); } } } break; } return true; }
// The Real Core Function doing the actual mesh processing. // Move Vertex of a random quantity bool ExtraSamplePlugin::applyFilter(QAction *action, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb) { switch(ID(action)) { case FP_DECOMPOSER : { CMeshO &m = md.mm()->cm; CutMesh cm; vcg::tri::Append<CutMesh,CMeshO>::MeshCopy(cm,m); vcg::tri::Allocator<CutMesh>::CompactEveryVector(cm); vcg::tri::UpdateTopology<CutMesh>::FaceFace(cm); vcg::tri::UpdateTopology<CutMesh>::VertexFace(cm); vcg::tri::UpdateNormal<CutMesh>::PerFace(cm); //Get Parameters vcg::Point3f upperPoint = par.getPoint3f("upperPoint"); vcg::Point3f lowerPoint = par.getPoint3f("lowerPoint"); float dihedral = par.getDynamicFloat("dihedral"); float ambient = par.getDynamicFloat("ambient"); float geodesic = par.getDynamicFloat("geodesic"); float geomin = par.getDynamicFloat("geo-factor-min"); float geomax = par.getDynamicFloat("geo-factor-max"); float elength = par.getDynamicFloat("e-length"); CutMesh::FacePointer startFace = NULL; CutMesh::FacePointer endFace = NULL; //getting the closest faces to the passed point parameters TriMeshGrid grid; grid.Set(cm.face.begin(),cm.face.end()); vcg::Point3<CutMesh::ScalarType> closest; float maxDist = cm.bbox.Diag(); float minDist; startFace = vcg::tri::GetClosestFaceBase(cm, grid, upperPoint, maxDist, minDist, closest); endFace = vcg::tri::GetClosestFaceBase(cm, grid, lowerPoint, maxDist, minDist, closest); assert(startFace!=NULL && endFace!=NULL); std::vector<CutVertex::VertexPointer> seedVec; for(int i=0; i<3; i++) seedVec.push_back(startFace->V(i)); //getting the geodesic distance from the start/end face and some other data //that will be used in the weight computation typename CutMesh::template PerFaceAttributeHandle <float> gfH1 = vcg::tri::Allocator<CutMesh>::template AddPerFaceAttribute<float>(cm, std::string("GeoDis1")); vcg::tri::Geodesic<CutMesh>::Compute(cm, seedVec); float max1=0.0f; float maxq=0.0f; //getting also the maximum perFaceQuality value for(CutMesh::FaceIterator fit= cm.face.begin(); fit!=cm.face.end(); fit++){ if(fit->Q()>=maxq) maxq=fit->Q(); gfH1[fit] = (fit->V(0)->Q()+fit->V(1)->Q()+fit->V(2)->Q())/3.0f; if(gfH1[fit]>=max1) max1=gfH1[fit]; } //this functor will be used to compute edge weights on the dual graph WeightFunctor<CutMesh> wf(ambient, dihedral, geodesic, elength, startFace, endFace, gfH1, max1, geomin, geomax, maxq); //start actual computation vcg::tri::GraphBuilder<CutMesh, WeightFunctor<CutMesh> >::Compute(cm, wf, startFace, endFace); vcg::tri::Allocator<CutMesh>::DeletePerFaceAttribute(cm,gfH1); vcg::tri::Append<CMeshO,CutMesh>::MeshCopy(m,cm); return true; } } return false; }
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; }