Example #1
0
//
// 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);
}
Example #2
0
// The Real Core Function doing the actual mesh processing.
// Move Vertex of a random quantity
bool ExtraSamplePlugin::applyFilter(QAction */*filter*/, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
	CMeshO &m = md.mm()->cm;
	srand(time(NULL)); 
	const float max_displacement =par.getAbsPerc("Displacement");

	for(unsigned int i = 0; i< m.vert.size(); i++){
		 // Typical usage of the callback for showing a nice progress bar in the bottom. 
		 // First parameter is a 0..100 number indicating percentage of completion, the second is an info string.
		  cb(100*i/m.vert.size(), "Randomly Displacing...");

		float rndax = (float(2.0f*rand())/RAND_MAX - 1.0f ) *max_displacement;
		float rnday = (float(2.0f*rand())/RAND_MAX - 1.0f ) *max_displacement;
		float rndaz = (float(2.0f*rand())/RAND_MAX - 1.0f ) *max_displacement;
		m.vert[i].P() += vcg::Point3f(rndax,rnday,rndaz);
	}
	
	// Log function dump textual info in the lower part of the MeshLab screen. 
	Log("Successfully displaced %i vertices",m.vn);
	
	// to access to the parameters of the filter dialog simply use the getXXXX function of the FilterParameter Class
	if(par.getBool("UpdateNormals"))	
			vcg::tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFace(m);
	
	vcg::tri::UpdateBounding<CMeshO>::Box(m);
  
	return true;
}
Example #3
0
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;
}
Example #4
0
/* The Real Core Function doing the actual mesh processing */
bool GeometryAgingPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet &params, vcg::CallBackPos *cb)
{	
    MeshModel &m=*(md.mm());
    if( ID(filter) != FP_ERODE)
	{
		assert (0);
		return false;
	}

	m.updateDataMask(MeshModel::MM_VERTQUALITY);
	
	bool curvature = params.getBool("ComputeCurvature");
	if(curvature)	computeMeanCurvature(m.cm);
		
	// other plugin parameters
	bool smoothQ = params.getBool("SmoothQuality");
	float qualityTh = params.getAbsPerc("QualityThreshold");
	float edgeLenTh = params.getAbsPerc("EdgeLenThreshold");
	float chipDepth = params.getAbsPerc("ChipDepth");
	int octaves = params.getInt("Octaves");
	float noiseScale = params.getAbsPerc("NoiseFreqScale");
	float noiseClamp = params.getFloat("NoiseClamp");
	int dispSteps = (int)params.getFloat("DisplacementSteps");
	bool selected = params.getBool("Selected");
	bool storeDispl = params.getBool("StoreDisplacement");
	
	// error checking on parameters values
	if(edgeLenTh == 0.0) edgeLenTh = m.cm.bbox.Diag()*0.02;
	if(chipDepth == 0.0) chipDepth = m.cm.bbox.Diag()*0.05;
	noiseClamp = math::Clamp<float>(noiseClamp, 0.0, 1.0);
	
			// quality threshold percentage value
			std::pair<float, float> qRange = tri::Stat<CMeshO>::ComputePerVertexQualityMinMax(m.cm);
			float qperc = (qualityTh-qRange.first) / (qRange.second-qRange.first);
			
			// compute mesh quality, if requested
			if(curvature) {
				if(cb) (*cb)(0, "Computing quality values...");
				computeMeanCurvature(m.cm);
			}
			
			// eventually, smooth quality values
			if(smoothQ) tri::Smooth<CMeshO>::VertexQualityLaplacian(m.cm);
			
			// if quality values have been recomputed quality threshold may not 
			// be valid, so we recompute its absolute value using the percentage
			// value chosen by the user
			if(curvature || smoothQ) {
				qRange = tri::Stat<CMeshO>::ComputePerVertexQualityMinMax(m.cm);
				qualityTh = qRange.first + (qRange.second-qRange.first) * qperc;
			}
			
			// edge predicate
			QualityEdgePred ep = QualityEdgePred(selected, edgeLenTh, qualityTh);
			
			// refine needed edges
			refineMesh(m.cm, ep, selected, cb);
			
			// if requested, add erosion attribute to vertexes and initialize it
			if(storeDispl) {
				CMeshO::PerVertexAttributeHandle<Point3f> vah = 
						(tri::HasPerVertexAttribute(m.cm, "Erosion") ?
						 tri::Allocator<CMeshO>::GetPerVertexAttribute<Point3f>(m.cm, "Erosion") :
						 tri::Allocator<CMeshO>::AddPerVertexAttribute<Point3f>(m.cm, std::string("Erosion")));
				for(CMeshO::VertexIterator vi=m.cm.vert.begin(); vi!=m.cm.vert.end(); vi++)
					vah[vi] = Point3f(0.0, 0.0, 0.0);
			}
			CMeshO::PerVertexAttributeHandle<Point3f> vah = vcg::tri::Allocator<CMeshO>::GetPerVertexAttribute<Point3f>(m.cm, "Erosion");
			
			// vertexes along selection border will not be displaced 
			if(selected) tri::UpdateSelection<CMeshO>::VertexFromFaceStrict(m.cm);
			
			// clear vertexes V bit (will be used to mark the vertexes as displaced) 
			tri::UpdateFlags<CMeshO>::VertexClearV(m.cm);
			
			// displace vertexes
			for(int i=0; i<dispSteps; i++) {
				GridStaticPtr<CFaceO, CMeshO::ScalarType> gM;
				gM.Set(m.cm.face.begin(), m.cm.face.end());
				
				if(cb) (*cb)( (i+1)*100/dispSteps, "Aging...");
				
				// blend toghether face normals and recompute vertex normal from these normals 
				// to get smoother offest directions
				tri::Smooth<CMeshO>::FaceNormalLaplacianFF(m.cm, 3); 
				tri::UpdateNormals<CMeshO>::PerVertexFromCurrentFaceNormal(m.cm);
				tri::UpdateNormals<CMeshO>::NormalizeVertex(m.cm);
				
				for(CMeshO::FaceIterator fi=m.cm.face.begin(); fi!=m.cm.face.end(); fi++) {
					if((*fi).IsD()) continue;
					for(int j=0; j<3; j++) {
						if(ep.qVertTest(face::Pos<CMeshO::FaceType>(&*fi,j))  &&
						   !(*fi).V(j)->IsV() &&		
						   (!selected || ((*fi).IsS() && (*fi).FFp(j)->IsS())) ) {
								double noise;						// noise value
								Point3f dispDir = (*fi).V(j)->N();	// displacement direction
								
								Point3f p = (*fi).V(j)->P() / noiseScale;
								noise = generateNoiseValue(octaves, p);
								// only values bigger than noiseClamp will be considered
								noise = (noise<noiseClamp?0.0:(noise-noiseClamp));
								
								// displacement offset
								Point3f offset = -(dispDir * chipDepth * noise) / dispSteps;
								
								(*fi).V(j)->P() += offset;
								if(faceIntersections(m.cm, face::Pos<CMeshO::FaceType>(&*fi,j), gM))
									(*fi).V(j)->P() -= offset;
								else if(storeDispl)	// store displacement
									vah[(*fi).V(j)] = vah[(*fi).V(j)] + offset;
								
								// mark as visited (displaced)
								(*fi).V(j)->SetV();
							}
					}
				}
				// clear vertexes V bit again
				tri::UpdateFlags<CMeshO>::VertexClearV(m.cm);
			}
			
			// update normals
			vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m.cm);
			
			smoothPeaks(m.cm, selected, storeDispl);
			
			// readjust selection
			if(selected) tri::UpdateSelection<CMeshO>::VertexFromFaceLoose(m.cm);
						
			return true;
}
Example #5
0
bool CleanFilter::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos * cb)
{
    MeshModel &m=*(md.mm());
    switch(ID(filter))
  {
    case FP_BALL_PIVOTING:
    {
      float Radius = par.getAbsPerc("BallRadius");
      float Clustering = par.getFloat("Clustering") / 100.0f;
      float CreaseThr = math::ToRad(par.getFloat("CreaseThr"));
      bool DeleteFaces = par.getBool("DeleteFaces");
      if(DeleteFaces) {
        m.cm.fn=0;
        m.cm.face.resize(0);
      }
      m.updateDataMask(MeshModel::MM_VERTFACETOPO);
      int startingFn=m.cm.fn;
      tri::BallPivoting<CMeshO> pivot(m.cm, Radius, Clustering, CreaseThr);
      // the main processing
      pivot.BuildMesh(cb);
      m.clearDataMask(MeshModel::MM_FACEFACETOPO);
      Log("Reconstructed surface. Added %i faces",m.cm.fn-startingFn);
    } break;
    case FP_REMOVE_ISOLATED_DIAMETER:
    {
      float minCC= par.getAbsPerc("MinComponentDiag");
      std::pair<int,int> delInfo= tri::Clean<CMeshO>::RemoveSmallConnectedComponentsDiameter(m.cm,minCC);
      Log("Removed %2 connected components out of %1", delInfo.second, delInfo.first);
    }break;
    case FP_REMOVE_ISOLATED_COMPLEXITY:
	  {
      float minCC= par.getInt("MinComponentSize");		
      std::pair<int,int> delInfo=tri::Clean<CMeshO>::RemoveSmallConnectedComponentsSize(m.cm,minCC);
			Log("Removed %i connected components out of %i", delInfo.second, delInfo.first); 		
	  }break;
    case FP_REMOVE_WRT_Q:
	  {
			int deletedFN=0;
			int deletedVN=0;
      float val=par.getAbsPerc("MaxQualityThr");		
      CMeshO::VertexIterator vi;
      for(vi=m.cm.vert.begin();vi!=m.cm.vert.end();++vi)
						if(!(*vi).IsD() && (*vi).Q()<val)
						{
							tri::Allocator<CMeshO>::DeleteVertex(m.cm, *vi);
							deletedVN++;
						}
        
      CMeshO::FaceIterator fi;
      for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
				 if((*fi).V(0)->IsD() ||(*fi).V(1)->IsD() ||(*fi).V(2)->IsD() ) 
						 {
								tri::Allocator<CMeshO>::DeleteFace(m.cm, *fi);
								deletedFN++;
						 }
								 
	  m.clearDataMask(MeshModel::MM_FACEFACETOPO);
			Log("Deleted %i vertices and %i faces with a quality lower than %f", deletedVN,deletedFN,val); 		

	  }break;

    case FP_REMOVE_TVERTEX_COLLAPSE :
    {
        float threshold = par.getFloat("Threshold");
        bool repeat = par.getBool("Repeat");

        int total = tri::Clean<CMeshO>::RemoveTVertexByCollapse(m.cm, threshold, repeat);
        Log("Successfully removed %d t-vertices", total);
    }
        break;
    case FP_REMOVE_TVERTEX_FLIP :
    {
        float threshold = par.getFloat("Threshold");
        bool repeat = par.getBool("Repeat");
        int total = tri::Clean<CMeshO>::RemoveTVertexByFlip(m.cm, threshold, repeat);
        Log("Successfully removed %d t-vertices", total);
    }
    break;
   case FP_MERGE_CLOSE_VERTEX :
    {
        float threshold = par.getAbsPerc("Threshold");
        int total = tri::Clean<CMeshO>::MergeCloseVertex(m.cm, threshold);
        Log("Successfully merged %d vertices", total);
    }
    break;
  case FP_REMOVE_DUPLICATE_FACE :
   {
       int total = tri::Clean<CMeshO>::RemoveDuplicateFace(m.cm);
       Log("Successfully deleted %d duplicated faces", total);
   }
   break;
  case FP_REMOVE_FOLD_FACE:
    {
      m.updateDataMask(MeshModel::MM_FACECOLOR);
      int total = tri::Clean<CMeshO>::RemoveFaceFoldByFlip(m.cm);
      m.UpdateBoxAndNormals();
      Log("Successfully flipped %d folded faces", total);
    }
      break;
  case FP_REMOVE_NON_MANIF_EDGE :
  {
      int total = tri::Clean<CMeshO>::RemoveNonManifoldFace(m.cm);
      Log("Successfully removed %d folded faces", total);
  }
  break;
  case FP_REMOVE_NON_MANIF_VERT :
  {
      float threshold = par.getFloat("VertDispRatio");

      int total = tri::Clean<CMeshO>::SplitNonManifoldVertex(m.cm,threshold);
      Log("Successfully split %d non manifold vertices faces", total);
  }
  break;
  case FP_SNAP_MISMATCHED_BORDER :
    {
      float threshold = par.getFloat("EdgeDistRatio");
      int total = SnapVertexBorder(m.cm, threshold,cb);
      Log("Successfully Splitted %d faces to snap", total);
    } break;
	
  case FP_COMPACT_FACE :
	  {
		  vcg::tri::Allocator<CMeshO>::CompactFaceVector(m.cm);
		  break;
	  }
  case FP_COMPACT_VERT :
	  {
		  vcg::tri::Allocator<CMeshO>::CompactVertexVector(m.cm);
		  break;
	  }
  default : assert(0); // unknown filter;
	}
	return true;
}
Example #6
0
bool FilterGeodesic::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos * /*cb*/)
{
    MeshModel &m=*(md.mm());
    CMeshO::FaceIterator fi;
    CMeshO::VertexIterator vi;
    switch (ID(filter)) {
        case FP_QUALITY_POINT_GEODESIC:
            {
                m.updateDataMask(MeshModel::MM_VERTFACETOPO);
                m.updateDataMask(MeshModel::MM_VERTMARK);
                m.updateDataMask(MeshModel::MM_VERTQUALITY);
                m.updateDataMask(MeshModel::MM_VERTCOLOR);
                tri::UpdateFlags<CMeshO>::FaceBorderFromVF(m.cm);
                tri::UpdateFlags<CMeshO>::VertexBorderFromFace(m.cm);
                Point3f startPoint = par.getPoint3f("startPoint");
                // first search the closest point on the surface;
                CMeshO::VertexPointer startVertex=0;
                float minDist= std::numeric_limits<float>::max();

                for(vi=m.cm.vert.begin();vi!=m.cm.vert.end();++vi) if(!(*vi).IsD())
                    if(SquaredDistance(startPoint,(*vi).P()) < minDist) {
                        startVertex=&*vi;
                        minDist=SquaredDistance(startPoint,(*vi).P());
                        }


                Log("Input point is %f %f %f Closest on surf is %f %f %f",startPoint[0],startPoint[1],startPoint[2],startVertex->P()[0],startVertex->P()[1],startVertex->P()[2]);

                // Now actually compute the geodesic distnace from the closest point
                float dist_thr = par.getAbsPerc("maxDistance");
                tri::EuclideanDistance<CMeshO> dd;
                tri::Geodesic<CMeshO>::Compute(m.cm, vector<CVertexO*>(1,startVertex),dd,dist_thr);

                // Cleaning Quality value of the unrefernced vertices
                // Unreached vertexes has a quality that is maxfloat
                int unreachedCnt=0;
                float unreached  = std::numeric_limits<float>::max();
                for(vi=m.cm.vert.begin();vi!=m.cm.vert.end();++vi) if(!(*vi).IsD())
                    if((*vi).Q() == unreached) {
                            unreachedCnt++;
                            (*vi).Q()=0;
                        }
                if(unreachedCnt >0 )
                        Log("Warning: %i vertices were unreacheable from the borders, probably your mesh has unreferenced vertices",unreachedCnt);

                tri::UpdateColor<CMeshO>::PerVertexQualityRamp(m.cm);

            }
            break;
        case FP_QUALITY_BORDER_GEODESIC:
            {
                m.updateDataMask(MeshModel::MM_VERTFACETOPO);
                m.updateDataMask(MeshModel::MM_VERTMARK);
                m.updateDataMask(MeshModel::MM_VERTQUALITY);
                m.updateDataMask(MeshModel::MM_VERTCOLOR);
                tri::UpdateFlags<CMeshO>::FaceBorderFromVF(m.cm);
                tri::UpdateFlags<CMeshO>::VertexBorderFromFace(m.cm);

                bool ret = tri::Geodesic<CMeshO>::DistanceFromBorder(m.cm);

                // Cleaning Quality value of the unrefernced vertices
                // Unreached vertexes has a quality that is maxfloat
                int unreachedCnt=0;
                float unreached  = std::numeric_limits<float>::max();
                for(vi=m.cm.vert.begin();vi!=m.cm.vert.end();++vi) if(!(*vi).IsD())
                    if((*vi).Q() == unreached) {
                            unreachedCnt++;
                            (*vi).Q()=0;
                        }
                if(unreachedCnt >0 )
                        Log("Warning: %i vertices were unreacheable from the borders, probably your mesh has unreferenced vertices",unreachedCnt);

                if(!ret) Log("Mesh Has no borders. No geodesic distance computed");
                    else tri::UpdateColor<CMeshO>::PerVertexQualityRamp(m.cm);
                }

            break;
        default: assert(0);
            break;
    }
return true;
}