// given a RichParameterSet get back the alignment parameter  (dual of the buildParemeterSet)
void AlignParameter::buildAlignParameters(RichParameterSet &fps , AlignPair::Param &app)
{
	app.SampleNum=fps.getInt("SampleNum");
  app.MinDistAbs=fps.getFloat("MinDistAbs");
	app.TrgDistAbs=fps.getFloat("TrgDistAbs");
	app.MaxIterNum=fps.getInt("MaxIterNum");
	app.SampleMode= fps.getBool("SampleMode")?AlignPair::Param::SMNormalEqualized  : AlignPair::Param::SMRandom;
  app.ReduceFactorPerc=fps.getFloat("ReduceFactorPerc");
  app.PassHiFilter=fps.getFloat("PassHiFilter");
	app.MatchMode=fps.getBool("MatchMode")? AlignPair::Param::MMRigid : AlignPair::Param::MMClassic;
}
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 IOMPlugin::save(const QString &formatName, const QString &fileName, MeshModel &m, const int mask,const RichParameterSet & par,  vcg::CallBackPos *cb, QWidget *parent)
{
	QString errorMsgFormat = "Error encountered while exportering file %1:\n%2";
    m.updateDataMask(MeshModel::MM_FACEFACETOPO);
    int result = vcg::tri::io::ExporterM<CMeshO>::Save(m.cm,qPrintable(fileName),mask);
    if(par.getBool("HtmlSnippet"))
    {
        vcg::tri::io::ExporterM<CMeshO>::WriteHtmlSnippet(qPrintable(fileName),qPrintable(QString(fileName)+".html"));
    }
	if(result!=0)
	{
        QMessageBox::warning(parent, tr("Saving Error"), errorMsgFormat.arg(qPrintable(fileName), vcg::tri::io::ExporterM<CMeshO>::ErrorMsg(result)));
		return false;
	}
	return true;
}
Example #4
0
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;
}
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 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;
}
Example #7
0
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;
}
Example #8
0
// The Real Core Function doing the actual mesh processing.
// Move Vertex of a random quantity
bool FilterMutualInfoPlugin::applyFilter(QAction *action, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
	QTime filterTime;
	filterTime.start();

	float thresDiff=par.getFloat("Threshold for refinement convergence");

	std::vector<vcg::Point3f> myVec;
	int leap=(int)((float)md.mm()->cm.vn/1000.0f);
	CMeshO::VertexIterator vi;
	for(int i=0;i<=md.mm()->cm.vn;i=i+leap) 
	{
		myVec.push_back(md.mm()->cm.vert[i].P());
	}
	std::vector<vcg::Shotf> oldShots;
	for (int r=0; r<md.rasterList.size();r++)
	{
		oldShots.push_back(md.rasterList[r]->shot);
	}

	Log(0,"Sampled has %i vertices",myVec.size());
	
	std::vector<SubGraph> Graphs;
	/// Preliminary singular alignment using classic MI
	switch(ID(action))	 {
		case FP_IMAGE_GLOBALIGN :  
			/// Building of the graph of images
			if (md.rasterList.size()==0)
			{
				 Log(0, "You need a Raster Model to apply this filter!");
				 return false;
				 
			}

			this->glContext->makeCurrent();

			this->initGL();

			if (par.getBool("Pre-alignment"))
			{
				preAlignment(md, par, cb);
			}

			if (par.getInt("Max number of refinement steps")!=0)
			{
				
				Graphs=buildGraph(md);
				Log(0, "BuildGraph completed");
				for (int i=0; i<par.getInt("Max number of refinement steps"); i++)
				{
					AlignGlobal(md, Graphs);
					float diff=calcShotsDifference(md,oldShots,myVec);
					Log(0, "AlignGlobal %d of %d completed, average improvement %f pixels",i+1,par.getInt("Max number of refinement steps"),diff);
					if (diff<thresDiff)
						break;
					oldShots.clear();
					for (int r=0; r<md.rasterList.size();r++)
					{
						oldShots.push_back(md.rasterList[r]->shot);
					}
				}
			}
			
			this->glContext->doneCurrent();
			Log(0, "Done!");
			break;
		
		default : assert(0); 
	}

	Log(0,"Filter completed in %i sec",(int)((float)filterTime.elapsed()/1000.0f));

		return true;



}
Example #9
0
//write to an opened file the attribute of object entity
QString IORenderman::convertObject(int currentFrame, QString destDir, MeshModel* m,const RichParameterSet &par, QStringList* textureList)//, ObjValues* dummyValues)
{	
	QString name = "meshF" + QString::number(currentFrame) + "O" + QString::number(numberOfDummies) + ".rib";
  numberOfDummies++;
  FILE *fout = fopen(qPrintable(destDir + QDir::separator() + name),"wb");
  if(fout == NULL) {
    this->errorMessage = "Impossible to create the file: " + destDir + QDir::separator() + name;
    return "";
  }
  fprintf(fout,"AttributeBegin\n");
	//name
	fprintf(fout,"Attribute \"identifier\" \"string name\" [ \"meshlabMesh\" ]\n");
	//modify the transformation matrix
	vcg::Matrix44f scaleMatrix = vcg::Matrix44f::Identity();
	float dummyX = objectBound[1] - objectBound[0];
	float dummyY = objectBound[3] - objectBound[2];
	float dummyZ = objectBound[5] - objectBound[4];
				
	//autoscale
	float scale = 1.0;
	if(par.getBool("Autoscale")) {
		float ratioX = dummyX / m->cm.trBB().DimX();
		float ratioY = dummyY / m->cm.trBB().DimY();
		float ratioZ = dummyZ / m->cm.trBB().DimZ();
		scale = std::min<float>(ratioX, std::min<float>(ratioY, ratioZ)); //scale factor is min ratio
		scaleMatrix.SetScale(scale,scale,scale);
	}

	//center mesh
	vcg::Point3f c = m->cm.trBB().Center();
	vcg::Matrix44f translateBBMatrix;
	translateBBMatrix.SetTranslate(-c[0],-c[1],-c[2]);
			
	//align
	float dx = 0.0, dy = 0.0, dz = 0.0;				
	switch(par.getEnum("AlignX")) {
		case IORenderman::TOP:
			dx = (dummyX - m->cm.trBB().DimX() * scale) / 2;	break;
        case IORenderman::BOTTOM:
			dx = -(dummyX - m->cm.trBB().DimX() * scale) / 2; break;
        case IORenderman::CENTER: break; //is already center
	}
	switch(par.getEnum("AlignY")) {
		case IORenderman::TOP:
			dy = (dummyY - m->cm.trBB().DimY() * scale) / 2; break;
        case IORenderman::BOTTOM:
			dy = -(dummyY - m->cm.trBB().DimY() * scale) / 2; break;
        case IORenderman::CENTER: break; //is already center
	}			
	switch(par.getEnum("AlignZ")) {
		case IORenderman::TOP:
			dz = (dummyZ - m->cm.trBB().DimZ() * scale) / 2; break;
        case IORenderman::BOTTOM:
			dz = -(dummyZ - m->cm.trBB().DimZ() * scale) / 2; break;
        case IORenderman::CENTER: break; //is already center
	}
	vcg::Matrix44f alignMatrix;
	alignMatrix = alignMatrix.SetTranslate(dx,dy,dz);
	vcg::Matrix44f templateMatrix = transfMatrixStack.top(); //by default is identity
	
	vcg::Matrix44f result = templateMatrix * alignMatrix * scaleMatrix * translateBBMatrix;
	//write transformation matrix (after transpose it)
	writeMatrix(fout, &result);
	//write bounding box
	fprintf(fout,"Bound %g %g %g %g %g %g\n",
		m->cm.trBB().min.X(), m->cm.trBB().max.X(),
		m->cm.trBB().min.Y(), m->cm.trBB().max.Y(),
		m->cm.trBB().min.Z(), m->cm.trBB().max.Z());

	//force the shading interpolation to smooth
  fprintf(fout,"ShadingInterpolation \"smooth\"\n");
	//shader
	fprintf(fout,"%s\n",qPrintable(surfaceShaderStack.top()));
	//texture mapping (are TexCoord needed for texture mapping?)
	if(!textureList->empty() > 0 && (m->cm.HasPerWedgeTexCoord() || m->cHasPerVertexTexCoord(m))) {
		//multi-texture don't work!I need ad-hoc shader and to read the texture index for vertex..
		//foreach(QString textureName, *textureList) {

		//read only the first texture
		QString textureName = QFileInfo(textureList->first()).completeBaseName();
    fprintf(fout,"Surface \"paintedplastic\" \"Kd\" 1.0 \"Ks\" 0.0 \"texturename\" [\"%s.tx\"]\n", qPrintable(textureName));								
	}
	//geometry
	QString filename = "geometry.rib";
	fprintf(fout,"ReadArchive \"%s\"\n", qPrintable(filename));
	if(!convertedGeometry) {
		//make the conversion only once
		convertedGeometry = true;
		QString geometryDest = destDir + QDir::separator() + filename;			
		int res = vcg::tri::io::ExporterRIB<CMeshO>::Save(m->cm, qPrintable(geometryDest), vcg::tri::io::Mask::IOM_ALL, false, cb);
    if(res != vcg::tri::io::ExporterRIB<CMeshO>::E_NOERROR) {
      fclose(fout);
	    this->errorMessage = QString(vcg::tri::io::ExporterRIB<CMeshO>::ErrorMsg(res));
      return "";
    }
    else
		  Log(GLLogStream::FILTER,"Successfully converted mesh");
	}
	fprintf(fout,"AttributeEnd\n");
  fclose(fout);
	return name;
}
Example #10
0
// The Real Core Function doing the actual mesh processing.
bool FilterFunctionPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
  if(this->getClass(filter) == MeshFilterInterface::MeshCreation)
       md.addNewMesh("",this->filterName(ID(filter)));
  MeshModel &m=*(md.mm());
	Q_UNUSED(cb);
	switch(ID(filter)) {
		case FF_VERT_SELECTION :
			{
				std::string expr = par.getString("condSelect").toStdString();
			
				// muparser initialization and explicitely define parser variables
				Parser p;
        setPerVertexVariables(p,m.cm);

				// set expression inserted by user as string (required by muparser)
				p.SetExpr(expr);

				int numvert = 0;
				time_t start = clock();

				// every parser variables is related to vertex coord and attributes.
				CMeshO::VertexIterator vi;
				for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)if(!(*vi).IsD())
				{
					setAttributes(vi,m.cm);

					bool selected = false;

					// use parser to evaluate boolean function specified above
					// in case of fail, error dialog contains details of parser's error
					try { 
						selected = p.Eval();
					} catch(Parser::exception_type &e) {
						errorMessage = e.GetMsg().c_str();
  						return false;
					}

					// set vertex as selected or clear selection
					if(selected) { 
						(*vi).SetS();
						numvert++;
					} else (*vi).ClearS();
				}

				// strict face selection
				if(par.getBool("strictSelect"))
						tri::UpdateSelection<CMeshO>::FaceFromVertexStrict(m.cm); 
				else  
						tri::UpdateSelection<CMeshO>::FaceFromVertexLoose(m.cm); 
		
				// if succeded log stream contains number of vertices and time elapsed
				Log( "selected %d vertices in %.2f sec.", numvert, (clock() - start) / (float) CLOCKS_PER_SEC);
					
				return true;
			}
		break;

		case FF_FACE_SELECTION :
			{
				QString select = par.getString("condSelect");
			
				// muparser initialization and explicitely define parser variables
				Parser p;
        setPerFaceVariables(p,m.cm);

				// set expression inserted by user as string (required by muparser)
				p.SetExpr(select.toStdString());

				int numface = 0;
				time_t start = clock();

				// every parser variables is related to face attributes.
				CMeshO::FaceIterator fi;
				for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)if(!(*fi).IsD())
				{
					setAttributes(fi,m.cm);

					bool selected = false;

					// use parser to evaluate boolean function specified above
					// in case of fail, error dialog contains details of parser's error
					try { 
						selected = p.Eval();
					} catch(Parser::exception_type &e) {
						errorMessage = e.GetMsg().c_str();
  						return false;
					}

					// set face as selected or clear selection
					if(selected) { 
						(*fi).SetS();
						numface++;
					} else (*fi).ClearS();
				}

				// if succeded log stream contains number of vertices and time elapsed
				Log( "selected %d faces in %.2f sec.", numface, (clock() - start) / (float) CLOCKS_PER_SEC);
					
				return true;
			}
		break;

		case FF_GEOM_FUNC :
		case FF_VERT_COLOR:
    case FF_VERT_NORMAL:
			{
        std::string func_x,func_y,func_z,func_a;
				// FF_VERT_COLOR : x = r, y = g, z = b
        // FF_VERT_NORMAL : x = r, y = g, z = b
        func_x = par.getString("x").toStdString();
        func_y = par.getString("y").toStdString();
        func_z = par.getString("z").toStdString();
        if(ID(filter) == FF_VERT_COLOR) func_a = par.getString("a").toStdString();

				// muparser initialization and explicitely define parser variables
				// function for x,y and z must use different parser and variables
        Parser p1,p2,p3,p4;

        setPerVertexVariables(p1,m.cm);
        setPerVertexVariables(p2,m.cm);
        setPerVertexVariables(p3,m.cm);
        setPerVertexVariables(p4,m.cm);

				p1.SetExpr(func_x);
				p2.SetExpr(func_y);
				p3.SetExpr(func_z);
        p4.SetExpr(func_a);

        double newx=0,newy=0,newz=0,newa=255;
				errorMessage = "";

				time_t start = clock();

				// every parser variables is related to vertex coord and attributes.
				CMeshO::VertexIterator vi;
				for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)if(!(*vi).IsD())
				{
					setAttributes(vi,m.cm);

					// every function is evaluated by different parser.
					// errorMessage dialog contains errors for func x, func y and func z
          try { newx = p1.Eval(); }  catch(Parser::exception_type &e) { showParserError("1st func : ",e); }
          try { newy = p2.Eval(); }  catch(Parser::exception_type &e) { showParserError("2nd func : ",e); }
          try { newz = p3.Eval(); }  catch(Parser::exception_type &e) { showParserError("3rd func : ",e); }
          if(ID(filter) == FF_VERT_COLOR)
          {
            try { newa = p4.Eval(); } catch(Parser::exception_type &e) { showParserError("4th func : ",e); }
          }
          if(errorMessage != "") return false;

          if(ID(filter) == FF_GEOM_FUNC)  // set new vertex coord for this iteration
						(*vi).P() = Point3f(newx,newy,newz); 
          if(ID(filter) == FF_VERT_COLOR) // set new color for this iteration
            (*vi).C() = Color4b(newx,newy,newz,newa);
          if(ID(filter) == FF_VERT_NORMAL) // set new color for this iteration
            (*vi).N() = Point3f(newx,newy,newz);
          }

				if(ID(filter) == FF_GEOM_FUNC) {
					// update bounding box, normalize normals
					tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m.cm);
					tri::UpdateNormals<CMeshO>::NormalizeFace(m.cm);
					tri::UpdateBounding<CMeshO>::Box(m.cm);
				}

				// if succeded log stream contains number of vertices processed and time elapsed
				Log( "%d vertices processed in %.2f sec.", m.cm.vn, (clock() - start) / (float) CLOCKS_PER_SEC);

				return true;
			}
		break;
		
		case FF_VERT_QUALITY:
			{
				std::string func_q = par.getString("q").toStdString();
				m.updateDataMask(MeshModel::MM_VERTQUALITY);
				
				// muparser initialization and define custom variables
				Parser p;
        setPerVertexVariables(p,m.cm);

				// set expression to calc with parser
				p.SetExpr(func_q);

				// every parser variables is related to vertex coord and attributes.
				time_t start = clock();
				CMeshO::VertexIterator vi;
        for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)
        if(!(*vi).IsD())
				{
					setAttributes(vi,m.cm);

					// use parser to evaluate function specified above
					// in case of fail, errorMessage dialog contains details of parser's error
					try { 
						(*vi).Q() = p.Eval();
					} catch(Parser::exception_type &e) {
						errorMessage = e.GetMsg().c_str();
  						return false;
					}
				}

				// normalize quality with values in [0..1] 
        if(par.getBool("normalize")) tri::UpdateQuality<CMeshO>::VertexNormalize(m.cm);
				
				// map quality into per-vertex color
        if(par.getBool("map")) tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm);

				// if succeded log stream contains number of vertices and time elapsed
				Log( "%d vertices processed in %.2f sec.", m.cm.vn, (clock() - start) / (float) CLOCKS_PER_SEC);

				return true;
			}
		break;

		case FF_FACE_COLOR:
			{
				std::string func_r = par.getString("r").toStdString();
				std::string func_g = par.getString("g").toStdString();
				std::string func_b = par.getString("b").toStdString();
        std::string func_a = par.getString("a").toStdString();

				// muparser initialization and explicitely define parser variables
				// every function must uses own parser and variables
        Parser p1,p2,p3,p4;

        setPerFaceVariables(p1,m.cm);
        setPerFaceVariables(p2,m.cm);
        setPerFaceVariables(p3,m.cm);
        setPerFaceVariables(p4,m.cm);

				p1.SetExpr(func_r);
				p2.SetExpr(func_g);
				p3.SetExpr(func_b);
        p4.SetExpr(func_a);

				// RGB is related to every face
				CMeshO::FaceIterator fi;
        double newr=0,newg=0,newb=0,newa=255;
				errorMessage = "";

				time_t start = clock();

				// every parser variables is related to face attributes.
				for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)if(!(*fi).IsD())
				{
					setAttributes(fi,m.cm);

					// evaluate functions to generate new color
					// in case of fail, error dialog contains details of parser's error
          try { newr = p1.Eval(); } catch(Parser::exception_type &e) { showParserError("func r: ",e); }
          try { newg = p2.Eval(); } catch(Parser::exception_type &e) { showParserError("func g: ",e); }
          try { newb = p3.Eval(); } catch(Parser::exception_type &e) { showParserError("func b: ",e); 	}
          try { newa = p4.Eval(); } catch(Parser::exception_type &e) { showParserError("func a: ",e); 	}

					if(errorMessage != "") return false;

					// set new color for this iteration
          (*fi).C() = Color4b(newr,newg,newb,newa);
				}

				// if succeded log stream contains number of vertices processed and time elapsed
				Log( "%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC);

				return true;

			}
		break;

		case FF_FACE_QUALITY:
			{
				std::string func_q = par.getString("q").toStdString();
				m.updateDataMask(MeshModel::MM_FACEQUALITY);

				// muparser initialization and define custom variables
				Parser pf;
        setPerFaceVariables(pf,m.cm);
					
				// set expression to calc with parser
          pf.SetExpr(func_q);

				time_t start = clock();
				errorMessage = "";

				// every parser variables is related to face attributes.
				CMeshO::FaceIterator fi;
				for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)if(!(*fi).IsD())
				{
					setAttributes(fi,m.cm);

					// evaluate functions to generate new quality
					// in case of fail, error dialog contains details of parser's error
					try { (*fi).Q() = pf.Eval(); }
					catch(Parser::exception_type &e) {
						showParserError("func q: ",e);
					}
					if(errorMessage != "") return false;
				}

				// normalize quality with values in [0..1]
        if(par.getBool("normalize")) tri::UpdateQuality<CMeshO>::FaceNormalize(m.cm);

				// map quality into per-vertex color
        if(par.getBool("map")) tri::UpdateColor<CMeshO>::FaceQualityRamp(m.cm);

				// if succeded log stream contains number of faces processed and time elapsed
				Log( "%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC);

				return true;
			}
		break;

		case FF_DEF_VERT_ATTRIB :
			{
				std::string name = par.getString("name").toStdString();
				std::string expr = par.getString("expr").toStdString();

				// add per-vertex attribute with type float and name specified by user
        CMeshO::PerVertexAttributeHandle<float> h;
        if(tri::HasPerVertexAttribute(m.cm,name))
				{
          h = tri::Allocator<CMeshO>::GetPerVertexAttribute<float>(m.cm, name);
              if(!tri::Allocator<CMeshO>::IsValidHandle<float>(m.cm,h))
          {
          errorMessage = "attribute already exists with a different type";
					return false;
          }
				}
        else
          h = tri::Allocator<CMeshO>::AddPerVertexAttribute<float> (m.cm,name);

        std::vector<std::string> AllVertexAttribName;
        tri::Allocator<CMeshO>::GetAllPerVertexAttribute< float >(m.cm,AllVertexAttribName);
        qDebug("Now mesh has %i vertex float attribute",AllVertexAttribName.size());
				Parser p;
        setPerVertexVariables(p,m.cm);
				p.SetExpr(expr);

				time_t start = clock();

				// perform calculation of attribute's value with function specified by user
				CMeshO::VertexIterator vi;
				for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)if(!(*vi).IsD())
				{
					setAttributes(vi,m.cm);

					// add new user-defined attribute
					try {
						h[vi] = p.Eval();
					} catch(Parser::exception_type &e) {
						errorMessage = e.GetMsg().c_str();
  						return false;
					}
				}

				// add string, double and handler to vector.
				// vectors keep tracks of new attributes and let muparser use explicit variables
				// it's possibile to use custom attributes in other filters
				v_attrNames.push_back(name);
				v_attrValue.push_back(0);
        v_handlers.push_back(h);

				// if succeded log stream contains number of vertices processed and time elapsed
				Log( "%d vertices processed in %.2f sec.", m.cm.vn, (clock() - start) / (float) CLOCKS_PER_SEC);

				return true;
			}
		break;

		case FF_DEF_FACE_ATTRIB :
			{
				std::string name = par.getString("name").toStdString();
				std::string expr = par.getString("expr").toStdString();
				
				// add per-face attribute with type float and name specified by user
        // add per-vertex attribute with type float and name specified by user
        CMeshO::PerFaceAttributeHandle<float> h;
        if(tri::HasPerFaceAttribute(m.cm,name))
        {
          h = tri::Allocator<CMeshO>::GetPerFaceAttribute<float>(m.cm, name);
          if(!tri::Allocator<CMeshO>::IsValidHandle<float>(m.cm,h))
          {
          errorMessage = "attribute already exists with a different type";
          return false;
          }
        }
        else
          h = tri::Allocator<CMeshO>::AddPerFaceAttribute<float> (m.cm,name);
				Parser p;
        setPerFaceVariables(p,m.cm);
				p.SetExpr(expr);

				time_t start = clock();

				// every parser variables is related to face attributes.
				CMeshO::FaceIterator fi;
				for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)if(!(*fi).IsD())
				{
					setAttributes(fi,m.cm);

					// add new user-defined attribute
					try {
						h[fi] = p.Eval();
					} catch(Parser::exception_type &e) {
						errorMessage = e.GetMsg().c_str();
  						return false;
					}
				}

//				// add string, double and handler to vector.
//				// vectors keep tracks of new attributes and let muparser use explicit variables
//				// it's possibile to use custom attributes in other filters
//				f_attrNames.push_back(name);
//				f_attrValue.push_back(0);
//				fhandlers.push_back(h);

				// if succeded log stream contains number of vertices processed and time elapsed
				Log( "%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC);

				return true;
			}
		break;

		case FF_GRID : 
			{
				// obtain parameters to generate 2D Grid
				int w = par.getInt("numVertX");		 
				int h = par.getInt("numVertY");		 
				float wl = par.getFloat("absScaleX");	 
				float hl = par.getFloat("absScaleY");

				if(w <= 0 || h <= 0) {
					errorMessage = "number of vertices must be positive";
					return false;
				}

				// use Grid function to generate Grid
				std::vector<float> data(w*h,0);
				tri::Grid<CMeshO>(m.cm, w, h, wl, hl, &data[0]);

				// if "centered on origin" is checked than move generated Grid in (0,0,0)
				if(par.getBool("center")) 
				{
					// move x and y
					double halfw = double(w-1)/2;
					double halfh = double(h-1)/2;
					double wld = wl/double(w);
					double hld = hl/float(h);

					CMeshO::VertexIterator vi;
					for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)
					{
						(*vi).P()[0] = (*vi).P()[0] - (wld * halfw);
						(*vi).P()[1] = (*vi).P()[1] - (hld * halfh);
					}
				}
				// update bounding box, normals
        Matrix44f rot; rot.SetRotateDeg(180,Point3f(0,1,0));
        tri::UpdatePosition<CMeshO>::Matrix(m.cm,rot,false);
				tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m.cm);	
				tri::UpdateNormals<CMeshO>::NormalizeFace(m.cm);
				tri::UpdateBounding<CMeshO>::Box(m.cm);
				
				return true;
			}
		break;
		case FF_ISOSURFACE :
			{
					SimpleVolume<SimpleVoxel> 	volume;
		
					typedef vcg::tri::TrivialWalker<CMeshO, SimpleVolume<SimpleVoxel> >	MyWalker;
					typedef vcg::tri::MarchingCubes<CMeshO, MyWalker>	MyMarchingCubes;
					MyWalker walker;
		
					Box3d rbb;
					rbb.min[0]=par.getFloat("minX");
					rbb.min[1]=par.getFloat("minY");
					rbb.min[2]=par.getFloat("minZ");
					rbb.max[0]=par.getFloat("maxX");
					rbb.max[1]=par.getFloat("maxY");
					rbb.max[2]=par.getFloat("maxZ");
					double step=par.getFloat("voxelSize");
					Point3i siz= Point3i::Construct((rbb.max-rbb.min)*(1.0/step));
					
					Parser p;
					double x,y,z;
					p.DefineVar("x", &x);
					p.DefineVar("y", &y);
					p.DefineVar("z", &z);
					std::string expr = par.getString("expr").toStdString();
					p.SetExpr(expr);
					Log("Filling a Volume of %i %i %i",siz[0],siz[1],siz[2]);
					volume.Init(siz);
					for(double i=0;i<siz[0];i++)
						for(double j=0;j<siz[1];j++)
							for(double k=0;k<siz[2];k++)
							{
							 x = rbb.min[0]+step*i;
							 y = rbb.min[1]+step*j;
							 z = rbb.min[2]+step*k;
							 	try {
										volume.Val(i,j,k)=p.Eval();
										} catch(Parser::exception_type &e) {
												errorMessage = e.GetMsg().c_str();
												return false;
											}
							}
		
		// MARCHING CUBES
		Log("[MARCHING CUBES] Building mesh...");
		MyMarchingCubes					mc(m.cm, walker);
		walker.BuildMesh<MyMarchingCubes>(m.cm, volume, mc, 0);
		Matrix44f tr; tr.SetIdentity(); tr.SetTranslate(rbb.min[0],rbb.min[1],rbb.min[2]);
		Matrix44f sc; sc.SetIdentity(); sc.SetScale(step,step,step);
		tr=tr*sc;
		
		tri::UpdatePosition<CMeshO>::Matrix(m.cm,tr);
		tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m.cm);																																			 
		tri::UpdateBounding<CMeshO>::Box(m.cm);					// updates bounding box		
		return true;

			}
		break;

		case FF_REFINE :
			{
				std::string condSelect = par.getString("condSelect").toStdString();
				
				std::string expr1 = par.getString("x").toStdString();
				std::string expr2 = par.getString("y").toStdString();
				std::string expr3 = par.getString("z").toStdString();

				bool errorMidPoint = false;
				bool errorEdgePred = false;
				std::string msg = "";

				// check parsing errors while creating two func obj
				// display error message
				MidPointCustom<CMeshO> mid = MidPointCustom<CMeshO>(m.cm,expr1,expr2,expr3,errorMidPoint,msg);
				CustomEdge<CMeshO> edge = CustomEdge<CMeshO>(condSelect,errorEdgePred,msg);
				if(errorMidPoint || errorEdgePred) 
				{
					errorMessage = msg.c_str();
					return false;
				}

				// Refine current mesh.
				// Only edge specified with CustomEdge pred are selected
				//  and the new vertex is choosen with MidPointCustom created above
				RefineE<CMeshO, MidPointCustom<CMeshO>, CustomEdge<CMeshO> >
					(m.cm, mid, edge, false, cb);

				m.clearDataMask( MeshModel::MM_VERTMARK);
				vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m.cm);

				return true;
			}
		break;

		default : assert (0);
	}
	return false;
}
Example #11
0
// The Real Core Function doing the actual mesh processing.
// Run mesh optimization
bool TriOptimizePlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
    MeshModel &m=*(md.mm());
    float limit = -std::numeric_limits<float>::epsilon();
	
	if (ID(filter) == FP_CURVATURE_EDGE_FLIP) {		
		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::Allocator<CMeshO>::CompactFaceVector(m.cm);
		m.updateDataMask(MeshModel::MM_FACEFACETOPO);
		vcg::tri::UpdateFlags<CMeshO>::FaceBorderFromFF(m.cm);
		
    if ( tri::Clean<CMeshO>::CountNonManifoldEdgeFF(m.cm) >0) {
			errorMessage = "Mesh has some not 2-manifold faces, edge flips requires manifoldness";
			return false; // can't continue, mesh can't be processed
		}
    vcg::tri::PlanarEdgeFlipParameter pp;

    vcg::LocalOptimization<CMeshO> optimiz(m.cm,&pp);
		float pthr = par.getFloat("pthreshold");
		time_t start = clock();

		if (par.getBool("selection")) {
			// Mark not writable un-selected faces
			for (CMeshO::FaceIterator fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi) {
					if (!(*fi).IsS()) (*fi).ClearW();
					else (*fi).SetW();
				}

			// select vertices with at least one incident face selected
			tri::UpdateSelection<CMeshO>::VertexFromFaceLoose(m.cm);

			// Mark not writable un-selected vertices
			for (CMeshO::VertexIterator vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi){
					if (!(*vi).IsS()) (*vi).ClearW();
					else (*vi).SetW();
				}
		}

			// VF adjacency needed for edge flips based on vertex curvature 
			vcg::tri::UpdateTopology<CMeshO>::VertexFace(m.cm);
			vcg::tri::UpdateTopology<CMeshO>::TestVertexFace(m.cm);

			int metric = par.getEnum("curvtype");
      pp.CoplanarAngleThresholdDeg = pthr;
			switch (metric) {
        case 0: optimiz.Init<MeanCEFlip>(); break;
        case 1: optimiz.Init<NSMCEFlip>();  break;
        case 2: optimiz.Init<AbsCEFlip>();  break;
			}
			
			// stop when flips become harmful
			optimiz.SetTargetMetric(limit);
			//optimiz.SetTargetOperations(10);
			optimiz.DoOptimization();
			optimiz.h.clear();

			Log( "%d curvature edge flips performed in %.2f sec.",  optimiz.nPerfmormedOps, (clock() - start) / (float) CLOCKS_PER_SEC);
		}
	if (ID(filter) == FP_PLANAR_EDGE_FLIP) {
    if ( tri::Clean<CMeshO>::CountNonManifoldEdgeFF(m.cm) >0) {
					errorMessage = "Mesh has some not 2-manifold faces, edge flips requires manifoldness";
					return false; // can't continue, mesh can't be processed
				}
		
		bool selection = par.getBool("selection");
		
		tri::Allocator<CMeshO>::CompactVertexVector(m.cm);
		tri::Allocator<CMeshO>::CompactFaceVector(m.cm);
		vcg::tri::UpdateTopology<CMeshO>::FaceFace(m.cm);
		vcg::tri::UpdateFlags<CMeshO>::FaceBorderFromFF(m.cm);
    vcg::tri::PlanarEdgeFlipParameter pp;
    vcg::LocalOptimization<CMeshO> optimiz(m.cm,&pp);
		float pthr = par.getFloat("pthreshold");
    pp.CoplanarAngleThresholdDeg=pthr;
    time_t	start = clock();
		
		
			int metric = par.getEnum("planartype");
			switch (metric) {
        case 0: optimiz.Init<QEFlip>(); break;
        case 1: optimiz.Init<QRadiiEFlip>(); break;
        case 2: optimiz.Init<QMeanRatioEFlip>(); break;
        case 3: optimiz.Init<MyTriEFlip>(); break;
        case 4: optimiz.Init<MyTopoEFlip>(); 	break;
			}
			// stop when flips become harmful
			optimiz.SetTargetMetric(limit);
			optimiz.DoOptimization();
			optimiz.h.clear();

			Log( "%d planar edge flips performed in %.2f sec.", optimiz.nPerfmormedOps, (clock() - start) / (float) CLOCKS_PER_SEC);
			int iternum = par.getInt("iterations");
			
			tri::Smooth<CMeshO>::VertexCoordPlanarLaplacian(m.cm, iternum, 0.0001f, selection,cb);
			
		
		vcg::tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFace(m.cm);

		if (par.getBool("selection")) {
			// Clear Writable flags (faces)
			CMeshO::FaceIterator fi;
			for (fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)
				if (!(*fi).IsD())
					(*fi).SetW();

			// Clear Writable flags (vertices)
			CMeshO::VertexIterator vi;
			for (vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)
				if (!(*vi).IsD())
					(*vi).SetW();
			
			// restore "default" selection  for vertices
			vcg::tri::UpdateSelection<CMeshO>::VertexFromFaceStrict(m.cm);
		}
	}

	if (ID(filter) == FP_NEAR_LAPLACIAN_SMOOTH) {
		bool selection = par.getBool("selection");
		if (selection)
			vcg::tri::UpdateSelection<CMeshO>::VertexFromFaceStrict(m.cm);

		int iternum = par.getInt("iterations");
		float dthreshold = par.getFloat("AngleDeg");
		tri::Smooth<CMeshO>::VertexCoordPlanarLaplacian(m.cm, iternum, math::ToRad(dthreshold), selection,cb);
		tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFace(m.cm);
	}

	return true;
}
// 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;
}
Example #13
0
// The Real Core Function doing the actual mesh processing.
bool FilterCreate::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, CallBackPos * /*cb*/)
{
	MeshModel & currM = *md.mm();
	MeshModel* m;

	switch(ID(filter))	 
	{
	case CR_TETRAHEDRON :
		m = md.addNewMesh("", this->filterName(ID(filter)));
		tri::Tetrahedron<CMeshO>(m->cm);
		break;
    case CR_ICOSAHEDRON:
		m = md.addNewMesh("", this->filterName(ID(filter)));
		tri::Icosahedron<CMeshO>(m->cm);
		break;
	case CR_DODECAHEDRON:
		m = md.addNewMesh("", this->filterName(ID(filter)));
		tri::Dodecahedron<CMeshO>(m->cm);
		m->updateDataMask(MeshModel::MM_POLYGONAL);
		break;
	case CR_OCTAHEDRON:
		m = md.addNewMesh("", this->filterName(ID(filter)));
		tri::Octahedron<CMeshO>(m->cm);
		break;
	case CR_ANNULUS:
		m = md.addNewMesh("", this->filterName(ID(filter)));
		tri::Annulus<CMeshO>(m->cm,par.getFloat("internalRadius"), par.getFloat("externalRadius"), par.getInt("sides"));
      break;

	case CR_TORUS:
    {
		m = md.addNewMesh("", this->filterName(ID(filter)));
		float hRadius=par.getFloat("hRadius");
		float vRadius=par.getFloat("vRadius");
		int hSubdiv=par.getInt("hSubdiv");
		int vSubdiv=par.getInt("vSubdiv");
		tri::Torus(m->cm,hRadius,vRadius,hSubdiv,vSubdiv);
	} break;

	case CR_FITPLANE:
	{
		Box3m selBox; //boundingbox of the selected vertices
		std::vector< Point3m > selected_pts; //copy of selected vertices, for plane fitting

		if (&currM == NULL)
		{
			errorMessage = "No mesh layer selected"; 
			return false;
		}

		if (currM.cm.svn == 0 && currM.cm.sfn == 0) // if no selection, fail
		{
			errorMessage = "No selection";
			return false;
		}

		m = md.addNewMesh("", "Fitted Plane");

		if (currM.cm.svn == 0 || currM.cm.sfn != 0)
		{
			tri::UpdateSelection<CMeshO>::VertexClear(currM.cm);
			tri::UpdateSelection<CMeshO>::VertexFromFaceLoose(currM.cm);
		}

		Point3m Naccum = Point3m(0.0, 0.0, 0.0);
		for (CMeshO::VertexIterator vi = currM.cm.vert.begin(); vi != currM.cm.vert.end(); ++vi)
		if (!(*vi).IsD() && (*vi).IsS())
		{
			Point3m p = (*vi).P();
			selBox.Add(p);
			selected_pts.push_back(p);
			Naccum = Naccum + (*vi).N();
		}
		Log("Using %i vertexes to build a fitting  plane", int(selected_pts.size()));
		Plane3m plane;
		FitPlaneToPointSet(selected_pts, plane);
		plane.Normalize();
		// check if normal of the interpolated plane is coherent with average normal of the used points, otherwise, flip
		// i do this because plane fitter does not take in account source noramls, and a fliped fit is terrible to see
		Naccum = (Naccum / (CMeshO::ScalarType)selected_pts.size()).Normalize();
		if ((plane.Direction() * Naccum) < 0.0)
			plane.Set(-plane.Direction(), -plane.Offset());

		float errorSum = 0;
		for (size_t i = 0; i < selected_pts.size(); ++i)
			errorSum += fabs(SignedDistancePlanePoint(plane, selected_pts[i]));
		Log("Fitting Plane avg error is %f", errorSum / float(selected_pts.size()));
		Log("Fitting Plane normal is [%f, %f, %f]", plane.Direction().X(), plane.Direction().Y(), plane.Direction().Z());
		Log("Fitting Plane offset is %f", plane.Offset());

		// find center of selection on plane
		Point3m centerP;
		for (size_t i = 0; i < selected_pts.size(); ++i)
		{
			centerP += plane.Projection(selected_pts[i]);
		}
		centerP /= selected_pts.size();
		Log("center [%f, %f, %f]", centerP.X(), centerP.Y(), centerP.Z());

		// find horizontal and vertical axis
		Point3m dirH, dirV;

		int orientation = par.getEnum("orientation");

		if (orientation == 0)
		{
			if ((plane.Direction().X() <= plane.Direction().Y()) && (plane.Direction().X() <= plane.Direction().Z()))
			dirH = Point3m(1.0, 0.0, 0.0) ^ plane.Direction();
			else if ((plane.Direction().Y() <= plane.Direction().X()) && (plane.Direction().Y() <= plane.Direction().Z()))
				dirH = Point3m(0.0, 1.0, 0.0) ^ plane.Direction();
			else
				dirH = Point3m(0.0, 0.0, 1.0) ^ plane.Direction();

			dirH.Normalize();
			dirV = dirH ^ plane.Direction();
			dirV.Normalize();
		}
		else
		{
			Matrix33m cov;
			vector<Point3m> PtVec;
			for (size_t i = 0; i < selected_pts.size(); ++i)
				PtVec.push_back(plane.Projection(selected_pts[i]));

			cov.Covariance(PtVec, centerP);
			Matrix33f eigenvecMatrix;
			Point3f eigenvecVector;
			Eigen::Matrix3d em;
			cov.ToEigenMatrix(em);
			Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eig(em);
			Eigen::Vector3d c_val = eig.eigenvalues();
			Eigen::Matrix3d c_vec = eig.eigenvectors();

			eigenvecMatrix.FromEigenMatrix(c_vec);
			eigenvecVector.FromEigenVector(c_val);

			// max eigenvector is best horizontal axis, but is not guarantee is orthogonal to plane normal, so
			// I use eigenvector ^ plane direction and assign it to vertical plane axis
			if ((eigenvecVector[0]<=eigenvecVector[1]) && (eigenvecVector[0]<=eigenvecVector[2]))
				dirV = Point3m(eigenvecMatrix[0][0], eigenvecMatrix[0][1], eigenvecMatrix[0][2]) ^ plane.Direction();
			if ((eigenvecVector[1]<=eigenvecVector[0]) && (eigenvecVector[1]<=eigenvecVector[2]))
				dirV = Point3m(eigenvecMatrix[1][0], eigenvecMatrix[1][1], eigenvecMatrix[1][2]) ^ plane.Direction();
			else
				dirV = Point3m(eigenvecMatrix[2][0], eigenvecMatrix[2][1], eigenvecMatrix[2][2]) ^ plane.Direction();

			dirV.Normalize();
			dirH = plane.Direction() ^ dirV;
			dirH.Normalize();
		}

		Log("H [%f, %f, %f]", dirH.X(), dirH.Y(), dirH.Z());
		Log("V [%f, %f, %f]", dirV.X(), dirV.Y(), dirV.Z());


		// find extent
		float dimH = -1000000;
		float dimV = -1000000;
		for (size_t i = 0; i < selected_pts.size(); ++i)
		{
			Point3m pp = plane.Projection(selected_pts[i]);
			float distH = fabs(((pp - centerP) * dirH));
			float distV = fabs(((pp - centerP) * dirV));

			if (distH > dimH)
				dimH = distH;
			if (distV > dimV)
				dimV = distV;
		}
		float exScale = par.getFloat("extent");
		dimV = dimV * exScale;
		dimH = dimH * exScale;
		Log("extent on plane [%f, %f]", dimV, dimH);

		int vertNum = par.getInt("subdiv") + 1;
		if (vertNum <= 1) vertNum = 2;
		int numV, numH;
		numV = numH = vertNum;

		// UV vector, just in case
		float *UUs, *VVs;
		UUs = new float[numH*numV];
		VVs = new float[numH*numV];

		int vind = 0;
		for (int ir = 0; ir < numV; ir++)
		for (int ic = 0; ic < numH; ic++)
			{
				Point3m newP = (centerP + (dirV * -dimV) + (dirH * -dimH)); 
				newP = newP + (dirH * ic * (2.0 * dimH / (numH-1))) + (dirV * ir * (2.0 * dimV / (numV-1)));
				tri::Allocator<CMeshO>::AddVertex(m->cm, newP, plane.Direction());
				UUs[vind] = ic * (1.0 / (numH - 1));
				VVs[vind] = ir * (1.0 / (numV - 1));
				vind++;
			}
		
		FaceGrid(m->cm, numH, numV);

		bool hasUV = par.getBool("hasuv");
		if (hasUV)
		{
			m->updateDataMask(MeshModel::MM_WEDGTEXCOORD);

			CMeshO::FaceIterator fi;
			for (fi = m->cm.face.begin(); fi != m->cm.face.end(); ++fi)
			{
				for (int i = 0; i<3; ++i)
				{
					int vind = (*fi).V(i)->Index();
					(*fi).WT(i).U() = UUs[vind];
					(*fi).WT(i).V() = VVs[vind];
				}
			}
		}
		delete[] UUs;	// delete temporary UV storage
		delete[] VVs;

	} break;

	case CR_RANDOM_SPHERE:
	{
		int pointNum = par.getInt("pointNum");
		int sphereGenTech = par.getEnum("sphereGenTech");
		math::MarsenneTwisterRNG rng;
		m = md.addNewMesh("", this->filterName(ID(filter)));
		m->cm.Clear();
		std::vector<Point3m> sampleVec;


		switch(sphereGenTech)
		{
			case 0: // Montecarlo
			{
				for(int i=0;i<pointNum;++i)
					sampleVec.push_back(math::GeneratePointOnUnitSphereUniform<CMeshO::ScalarType>(rng));
			} break;
			case 1: // Poisson Disk
			{
				int oversamplingFactor =100;
				if(pointNum <= 100) oversamplingFactor = 1000;
				if(pointNum >= 10000) oversamplingFactor = 50;
				if(pointNum >= 100000) oversamplingFactor = 20;
				CMeshO tt;
				tri::Allocator<CMeshO>::AddVertices(tt,pointNum*oversamplingFactor);
				for(CMeshO::VertexIterator vi=tt.vert.begin();vi!=tt.vert.end();++vi)
					vi->P()=math::GeneratePointOnUnitSphereUniform<CMeshO::ScalarType>(rng);
				tri::UpdateBounding<CMeshO>::Box(tt);

				const float SphereArea = 4*M_PI;
				float poissonRadius = 2.0*sqrt((SphereArea / float(pointNum*2))/M_PI);

				std::vector<Point3m> sampleVec;
				tri::TrivialSampler<CMeshO> pdSampler(sampleVec);
				tri::SurfaceSampling<CMeshO, tri::TrivialSampler<CMeshO> >::PoissonDiskParam pp;
				tri::SurfaceSampling<CMeshO,tri::TrivialSampler<CMeshO> >::PoissonDiskPruning(pdSampler, tt, poissonRadius, pp);
			} break;
			case 2: // Disco Ball
				GenNormal<CMeshO::ScalarType>::DiscoBall(pointNum,sampleVec);
				break;
			case 3: // Recursive Oct
				GenNormal<CMeshO::ScalarType>::RecursiveOctahedron(pointNum,sampleVec);
				break;
			case 4: // Fibonacci
				GenNormal<CMeshO::ScalarType>::Fibonacci(pointNum,sampleVec);
				break;
		}
		for(size_t i=0;i<sampleVec.size();++i)
			tri::Allocator<CMeshO>::AddVertex(m->cm,sampleVec[i],sampleVec[i]);
	} break;

	case CR_SPHERE_CAP:
	{
		int rec = par.getInt("subdiv");
		const float angleDeg = par.getFloat("angle");
		m = md.addNewMesh("", this->filterName(ID(filter)));
		m->updateDataMask(MeshModel::MM_FACEFACETOPO);
		tri::UpdateTopology<CMeshO>::FaceFace(m->cm);
		tri::SphericalCap(m->cm,math::ToRad(angleDeg),rec);
	} break;

	case CR_SPHERE:
    {
		int rec = par.getInt("subdiv");
		float radius = par.getFloat("radius");
		m = md.addNewMesh("", this->filterName(ID(filter)));
		m->cm.face.EnableFFAdjacency();
		m->updateDataMask(MeshModel::MM_FACEFACETOPO);
		assert(tri::HasPerVertexTexCoord(m->cm) == false);
		tri::Sphere<CMeshO>(m->cm,rec);
		tri::UpdatePosition<CMeshO>::Scale(m->cm,radius);
	} break;

    case CR_BOX:
    {
      float sz=par.getFloat("size");
      Box3m b(Point3m(1,1,1)*(-sz/2),Point3m(1,1,1)*(sz/2));
	  m = md.addNewMesh("", this->filterName(ID(filter)));
      tri::Box<CMeshO>(m->cm,b);
            m->updateDataMask(MeshModel::MM_POLYGONAL);
	} break;

	case CR_CONE:
	{
		float r0 = par.getFloat("r0");
		float r1 = par.getFloat("r1");
		float h = par.getFloat("h");
		int subdiv = par.getInt("subdiv");
		m = md.addNewMesh("", this->filterName(ID(filter)));
		tri::Cone<CMeshO>(m->cm, r0, r1, h, subdiv);
	} break;

	}//CASE FILTER

	tri::UpdateBounding<CMeshO>::Box(m->cm);
	tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFaceNormalized(m->cm);
    return true;
}
Example #14
0
bool AmbientOcclusionPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
    MeshModel &m=*(md.mm());
    if(ID(filter)==FP_FACE_AMBIENT_OCCLUSION ) perFace=true;
	else perFace = false;
	
	useGPU = par.getBool("useGPU");
	useVBO = par.getBool("useVBO");
	depthTexSize = par.getInt("depthTexSize");
	depthTexArea = depthTexSize*depthTexSize;
	numViews = par.getInt("reqViews");
	errInit = false;
	float dirBias = par.getFloat("dirBias");
	Point3f coneDir = par.getPoint3f("coneDir");
	float coneAngle = par.getFloat("coneAngle");
	
	if(perFace) 
	  m.updateDataMask(MeshModel::MM_FACEQUALITY | MeshModel::MM_FACECOLOR);
	else 
		m.updateDataMask(MeshModel::MM_VERTQUALITY | MeshModel::MM_VERTCOLOR);

	
	std::vector<Point3f> unifDirVec;
	GenNormal<float>::Uniform(numViews,unifDirVec);
	
	std::vector<Point3f> coneDirVec;
	GenNormal<float>::UniformCone(numViews, coneDirVec, math::ToRad(coneAngle), coneDir);
	
	std::random_shuffle(unifDirVec.begin(),unifDirVec.end());
	std::random_shuffle(coneDirVec.begin(),coneDirVec.end());

	int unifNum = floor(unifDirVec.size() * (1.0 - dirBias ));
	int coneNum = floor(coneDirVec.size() * (dirBias ));
									
	
	viewDirVec.clear();
	viewDirVec.insert(viewDirVec.end(),unifDirVec.begin(),unifDirVec.begin()+unifNum);
	viewDirVec.insert(viewDirVec.end(),coneDirVec.begin(),coneDirVec.begin()+coneNum);
	
	numViews = viewDirVec.size();


	this->glContext->makeCurrent();
	this->initGL(cb,m.cm.vn);
	unsigned int widgetSize = std::min(maxTexSize, depthTexSize);
	QSize fbosize(widgetSize,widgetSize);
	QGLFramebufferObjectFormat frmt;
	frmt.setInternalTextureFormat(GL_RGBA);
	frmt.setAttachment(QGLFramebufferObject::Depth);
	QGLFramebufferObject fbo(fbosize,frmt);
	qDebug("Start Painting window size %i %i", fbo.width(), fbo.height());
	GLenum err = glGetError();
	fbo.bind();
	processGL(m,viewDirVec);
	fbo.release();
	err = glGetError();
	const GLubyte* errname = gluErrorString(err);
	qDebug("End Painting");
	this->glContext->doneCurrent();
	return !errInit;
}
Example #15
0
bool ExtraFilter_SlicePlugin::applyFilter(QAction *filter, MeshDocument &m, RichParameterSet &parlst, vcg::CallBackPos *cb)
{
    vcg::tri::UpdateBounding<CMeshO>::Box(m.mm()->cm);

    switch(ID(filter))
    {
        case FP_WAFFLE_SLICE :
        {
            MeshModel* base = m.mm();
            CMeshO &cmBase = base->cm;
            Box3f &bbox = m.mm()->cm.bbox;

            if (tri::Clean<CMeshO>::CountNonManifoldEdgeFF(cmBase)>0 || (tri::Clean<CMeshO>::CountNonManifoldVertexFF(cmBase,false) != 0))
            {
                Log("Mesh is not two manifold, cannot apply filter");
                return false;
            }
            if(parlst.getFloat("spacing") >= 1)
            {
                Log("the selected distance between the planes is greater than 1. The filter had no effect");
                return false;
            }

            Point3f planeAxis(0,0,0);
            Axis axis = (Axis) parlst.getEnum("planeAxis");
            planeAxis[axis] = 1.0f;

            float length = parlst.getFloat("length");

            bool hideBase = parlst.getBool("hideBase");
            bool hideEdge = parlst.getBool("hideEdge");
            bool hidePlanes = parlst.getBool("hidePlanes");
            bool hideExtrudes = parlst.getBool("hideExtrudes");

            // set common SVG Properties
            const float maxdim=m.mm()->cm.bbox.Dim()[m.mm()->cm.bbox.MaxDim()];

            Point3f sizeCm=m.mm()->cm.bbox.Dim()*(length/maxdim);
            // to check for dimensions with custom axis
            Axis axisOrthog, axisJoint;
            Point2f sizeCmOrth;
            switch(axis)
            {
            case X:
                {
                    axisOrthog = (Axis) Succ<X>::value;
                    axisJoint = (Axis) Succ<Succ<X>::value>::value;
                    pr.sizeCm = Point2f(sizeCm[1],sizeCm[2]);
                    sizeCmOrth.X()=sizeCm[0];
                    sizeCmOrth.Y()=sizeCm[2];
                }
                break;
            case Y:
                {
                    axisOrthog = (Axis) Succ<Y>::value;
                    axisJoint = (Axis) Succ<Succ<Y>::value>::value;
                    pr.sizeCm = Point2f(sizeCm[0],sizeCm[2]);
                    sizeCmOrth.X()=sizeCm[0];
                    sizeCmOrth.Y()=sizeCm[1];
                }
                break;
            case Z:
                {
                    axisOrthog = (Axis) Succ<Z>::value;
                    axisJoint = (Axis) Succ<Succ<Z>::value>::value;
                    pr.sizeCm = Point2f(sizeCm[0],sizeCm[1]);
                    sizeCmOrth.X()=sizeCm[1];
                    sizeCmOrth.Y()=sizeCm[2];
                }
                break;
            }

            Log("sizecm %fx%f",pr.sizeCm[0],pr.sizeCm[1]);

            vector<CMeshO*> ev;

            const float planeDist = maxdim * parlst.getFloat("spacing");
            const int planeNum = (planeDist == 0) ? 1 : ( ((bbox.Dim()*planeAxis)/planeDist)+1 ); //evito la divisione per 0
            const float lengthDiag = bbox.Diag()/2.0;

            Segment2f lati[3]; //the rectangle is made up of three segments, the fourth side is ignored, so I never use it

            const float eps =planeDist*parlst.getFloat("eps");
            float epsTmp;
            float start;
            int rectNum;
            if(parlst.getFloat("eps") < 1)
            {
                start = - (planeNum/2) * planeDist;   //I have to go back from the center of half the length
                epsTmp = eps/2.0;
                generateRectSeg(0, epsTmp, bbox.Diag()*2, lati);
                rectNum = planeNum;
            }
            else
            {
                start = 0;
                epsTmp = bbox.Diag();
                generateRectSeg(0, bbox.Diag()*2, bbox.Diag()*2, lati);
                rectNum = 1;
                Log("thickness is greater than 1: the extrusions will overlap");
            }

            float planeOffset = parlst.getFloat("planeOffset");

            pr.lineWidthPt=200;
            pr.scale=2/maxdim;
            pr.numCol=(int)(max((int)sqrt(planeNum*1.0f),2)+1);
            pr.numRow=(int)(planeNum*1.0f/pr.numCol)+1;
            pr.projDir = planeAxis;
            pr.projCenter =  m.mm()->cm.bbox.Center();
            pr.enumeration = true;

            MeshModel* cap, *cap2, *extr;
            QString layername;


            for(int pl = 0; pl < 2; ++pl)
            {
//                Log("################## PLANE %i", pl);
                Plane3f slicingPlane;
                Point3f planeCenter = bbox.Center() + planeAxis*planeOffset*lengthDiag;
                int numAdd = 0;

//                int i=4;  //if I want to apply only the plan number i I decomment this variable and comment the cycle
                for(int i = 0; i < planeNum; ++i)   //cropping the plans
                {
//                    Log("######## LAYER %i", i);
                    planeCenter[axis] = start + planeDist*i;;

                    slicingPlane.Init(planeCenter,planeAxis);

                    layername.sprintf("EdgeMesh_%d_%d",pl,numAdd);
                    cap= m.addNewMesh("",qPrintable(layername));
                    vcg::IntersectionPlaneMesh<CMeshO, CMeshO, float>(base->cm, slicingPlane, cap->cm );

                    tri::Clean<CMeshO>::RemoveDuplicateVertex(cap->cm);
                    if(cap->cm.edge.size()>= 3)
                    {
                        Incastri temp;

//                        int j=1;      //if I want to apply only the rectangle number j I decomment this variable and comment the cycle
                        for(int j = 0; j <rectNum ; ++j)   //clipping the rectangles
                        {
//                            Log("#### RECTANGLE %i", j);
                            float newDist = start + planeDist*j;
                            modifyOnY(lati, newDist+epsTmp, newDist-epsTmp);

                            temp = subtraction(cap->cm, lati, axis, axisOrthog, axisJoint, planeCenter[axis]);

                            if(temp == NOT_PLANE) {Log("ATTENTION! The IntersectionPlaneMesh did not return a plane silhouette in the current plane!"); m.delMesh(cap); break;}
                            if(temp== NOT_SAGOME) {Log("ATTENTION! The IntersectionPlaneMesh did not return a simple closed silhouette for the plane %i, on axis %i",i, pl); m.delMesh(cap); break;}
                        }
                        if(temp > NOT_SAGOME)
                        {
                            ev.push_back(&(cap->cm));   //add the silhouette to those for export to SVG

                            layername.sprintf("CappedSlice_%d_%d",pl,numAdd);   //add the silhouettes converted in mesh
                            cap2= m.addNewMesh("",qPrintable(layername));
                            tri::CapEdgeMesh(cap->cm, cap2->cm);

                            layername.sprintf("Extruded_%d_%d",pl,numAdd++);      //add the mesh extruded
                            extr= m.addNewMesh("",qPrintable(layername));
                            cap2->updateDataMask(MeshModel::MM_FACEFACETOPO);
                            extr->updateDataMask(MeshModel::MM_FACEFACETOPO);
                            tri::UpdateTopology<CMeshO>::FaceFace(cap2->cm);
                            tri::ExtrudeBoundary<CMeshO>(cap2->cm,extr->cm,eps,planeAxis);

                            if(hideEdge) cap->visible =false;
                            if(hidePlanes) cap2->visible =false;
                            if(hideExtrudes) extr->visible =false;
                        }
                    }else m.delMesh(cap);   //if the intersection does not exist I reject the result
                }

                QString fname;//= parlst.getSaveFileName("filename");
                if(fname=="") fname.sprintf("Slice_%d.svg",pl);
                if (!fname.endsWith(".svg")) fname+=".svg";
                tri::io::ExporterSVG<CMeshO>::Save(ev, fname.toStdString().c_str(), pr);

                ev.clear();

                planeAxis[axis] = 0.0f;
                planeAxis[axisOrthog] = 1.0f;

                flipOnX(lati);

                pr.sizeCm = sizeCmOrth;
                pr.projDir = planeAxis;

                Axis aSwap = axis;
                axis = axisOrthog;
                axisOrthog = aSwap;
            }


            if(hideEdge) cap->visible =false;
            if(hidePlanes) cap2->visible =false;
            if(hideExtrudes) extr->visible =false;

            if(hideBase) base->visible =false;
            if(hideBase) base->visible =false;

        }
        break;
    }
    return true;
}
Example #16
0
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;
}
bool FilterOutputOpticalFlowPlugin::applyFilter( QAction *act,
                                                 MeshDocument &md,
                                                 RichParameterSet &par,
                                                 vcg::CallBackPos * /*cb*/ )
{
    if( glewInit() != GLEW_OK )
        return false;


    bool retValue = true;
    m_Mesh = &md.mm()->cm;


    QList<OOCRaster> rasters;
    if( md.rasterList.isEmpty() )
    {
        QString filename = QFileDialog::getOpenFileName( NULL, "Select a MeshLab project file", QString(), "MeshLab project (*.mlp)" );
        if( filename.isNull() || !loadRasterList(filename,rasters) )
            return false;
    }
    else
    {
        foreach( RasterModel *rm, md.rasterList )
            rasters.push_back( OOCRaster(rm) );
    }


    std::list<vcg::Shotf> initialShots;
    for( QList<OOCRaster>::iterator r=rasters.begin(); r!=rasters.end(); ++r )
    {
        initialShots.push_back( r->shot );
        r->shot.ApplyRigidTransformation( vcg::Inverse(m_Mesh->Tr) );
    }


    switch( ID(act) )
    {
		case FP_OUTPUT_OPTICAL_FLOW:
		{
            for( CMeshO::FaceIterator f=m_Mesh->face.begin(); f!=m_Mesh->face.end(); ++f )
                f->ClearV();

            int weightMask = 0;
            if( par.getBool("useDistanceWeight") )
                weightMask |= DominancyClassifier::W_DISTANCE;
            if( par.getBool("useImgBorderWeight") )
                weightMask |= DominancyClassifier::W_IMG_BORDER;
            if( par.getBool("useSilhouetteWeight") )
                weightMask |= DominancyClassifier::W_SILHOUETTE;
            if( par.getBool("useOrientationWeight") )
                weightMask |= DominancyClassifier::W_ORIENTATION;

            DominancyClassifier *set = new DominancyClassifier( *m_Mesh, rasters, weightMask );

            if( par.getBool("colorFromDominancy") )
            {
                md.mm()->updateDataMask( MeshModel::MM_VERTCOLOR );

                for( CMeshO::VertexIterator v=m_Mesh->vert.begin(); v!=m_Mesh->vert.end(); ++v )
                    if( (*set)[v].isOnBoundary() )
                    {
                        unsigned char c = (unsigned char)( 255.0f*(*set)[v].borderWeight() );
                        v->C() = vcg::Color4b( 255-c, 255-c, 255-c, 255 );
                    }
                    else
                        v->C() = vcg::Color4b( 0, 0, 255, 255 );

                delete set;
            }
            else
            {
                RasterFaceMap facesByDomImg;
                set->dominancyCoverage( facesByDomImg );
                delete set;

                //if( int n = par.getInt("dominantAreaExpansion") )
                //{
                //    md.mm()->updateDataMask( MeshModel::MM_FACEFACETOPO );
                //    md.mm()->updateDataMask( MeshModel::MM_VERTFACETOPO );

                //    for( RasterFaceMap::iterator rm=facesByDomImg.begin(); rm!=facesByDomImg.end(); ++rm )
                //        expands( rm.value(), n );
                //}

                QMap<int,QVector<int>> validPairs;
                retroProjection( facesByDomImg, 0.01f*par.getFloat("minCoverage"), validPairs );
                saveXMLProject( par.getString("xmlFileName"), md.mm(), facesByDomImg, validPairs );
            }

            break;
		}
	}


    return retValue;
}
Example #18
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 #19
0
bool BaseMeshIOPlugin::open(const QString &formatName, const QString &fileName, MeshModel &m, int& mask, const RichParameterSet &parlst, CallBackPos *cb, QWidget * /*parent*/)
{
	bool normalsUpdated = false;

	// initializing mask
  mask = 0;
	
	// initializing progress bar status
	if (cb != NULL)		(*cb)(0, "Loading...");

	QString errorMsgFormat = "Error encountered while loading file:\n\"%1\"\n\nError details: %2";

	//string filename = fileName.toUtf8().data();
	string filename = QFile::encodeName(fileName).constData ();
  
  if (formatName.toUpper() == tr("PLY"))
	{
		tri::io::ImporterPLY<CMeshO>::LoadMask(filename.c_str(), mask); 
		// small patch to allow the loading of per wedge color into faces.  
		if(mask & tri::io::Mask::IOM_WEDGCOLOR) mask |= tri::io::Mask::IOM_FACECOLOR;
		m.Enable(mask);

		 
		int result = tri::io::ImporterPLY<CMeshO>::Open(m.cm, filename.c_str(), mask, cb);
		if (result != 0) // all the importers return 0 on success
		{
			if(tri::io::ImporterPLY<CMeshO>::ErrorCritical(result) )
			{
				errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterPLY<CMeshO>::ErrorMsg(result));
				return false;
			}
		}
	}
	else if (formatName.toUpper() == tr("STL"))
	{
		int result = tri::io::ImporterSTL<CMeshO>::Open(m.cm, filename.c_str(), cb);
		if (result != 0) // all the importers return 0 on success
		{
			errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterSTL<CMeshO>::ErrorMsg(result));
			return false;
		}
	}
  else	if( (formatName.toUpper() == tr("OBJ")) || (formatName.toUpper() == tr("QOBJ")) )
	{
    tri::io::ImporterOBJ<CMeshO>::Info oi;	
		oi.cb = cb;
		if (!tri::io::ImporterOBJ<CMeshO>::LoadMask(filename.c_str(), oi))
			return false;
    m.Enable(oi.mask);
		
		int result = tri::io::ImporterOBJ<CMeshO>::Open(m.cm, filename.c_str(), oi);
		if (result != tri::io::ImporterOBJ<CMeshO>::E_NOERROR)
		{
			if (result & tri::io::ImporterOBJ<CMeshO>::E_NON_CRITICAL_ERROR)
					errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterOBJ<CMeshO>::ErrorMsg(result));
			else
			{
				errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterOBJ<CMeshO>::ErrorMsg(result));
				return false;
			}
		}

		if(oi.mask & tri::io::Mask::IOM_WEDGNORMAL)
			normalsUpdated = true;
        m.Enable(oi.mask);
        if(m.hasDataMask(MeshModel::MM_POLYGONAL)) qDebug("Mesh is Polygonal!");
		mask = oi.mask;
	}
	else if (formatName.toUpper() == tr("PTX"))
	{
		tri::io::ImporterPTX<CMeshO>::Info importparams;

    importparams.meshnum = parlst.getInt("meshindex");
    importparams.anglecull =parlst.getBool("anglecull");
    importparams.angle = parlst.getFloat("angle");
    importparams.savecolor = parlst.getBool("usecolor");
    importparams.pointcull = parlst.getBool("pointcull");
    importparams.pointsonly = parlst.getBool("pointsonly");
    importparams.switchside = parlst.getBool("switchside");
    importparams.flipfaces = parlst.getBool("flipfaces");

		// if color, add to mesh
		if(importparams.savecolor)
			importparams.mask |= tri::io::Mask::IOM_VERTCOLOR;
    if(importparams.pointsonly)
      importparams.mask |= tri::io::Mask::IOM_VERTRADIUS;

		// reflectance is stored in quality
		importparams.mask |= tri::io::Mask::IOM_VERTQUALITY;

		m.Enable(importparams.mask);

		int result = tri::io::ImporterPTX<CMeshO>::Open(m.cm, filename.c_str(), importparams, cb);
		if (result == 1)
		{
			errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterPTX<CMeshO>::ErrorMsg(result));
			return false;
		}

		// update mask
		mask = importparams.mask;
	}
    else if (formatName.toUpper() == tr("OFF"))
    {
        int loadMask;
        if (!tri::io::ImporterOFF<CMeshO>::LoadMask(filename.c_str(),loadMask))
            return false;
    m.Enable(loadMask);

        int result = tri::io::ImporterOFF<CMeshO>::Open(m.cm, filename.c_str(), mask, cb);
        if (result != 0)  // OFFCodes enum is protected
        {
            errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterOFF<CMeshO>::ErrorMsg(result));
            return false;
        }
    }
    else if (formatName.toUpper() == tr("VMI"))
    {
        int loadMask;
        if (!tri::io::ImporterVMI<CMeshO>::LoadMask(filename.c_str(),loadMask))
            return false;
        m.Enable(loadMask);

        int result = tri::io::ImporterVMI<CMeshO>::Open(m.cm, filename.c_str(), mask, cb);
        if (result != 0)
        {
            errorMessage = errorMsgFormat.arg(fileName, tri::io::ImporterOFF<CMeshO>::ErrorMsg(result));
            return false;
        }
    }
    else
  {
    assert(0); // Unknown File type
    return false;
  }

	// verify if texture files are present
	QString missingTextureFilesMsg = "The following texture files were not found:\n";
	bool someTextureNotFound = false;
	for ( unsigned textureIdx = 0; textureIdx < m.cm.textures.size(); ++textureIdx)
	{
    if (!QFile::exists(m.cm.textures[textureIdx].c_str()))
		{
			missingTextureFilesMsg.append("\n");
			missingTextureFilesMsg.append(m.cm.textures[textureIdx].c_str());
			someTextureNotFound = true;
		}
	}
	if (someTextureNotFound)
		Log("Missing texture files: %s", qPrintable(missingTextureFilesMsg));
	
	if (cb != NULL)	(*cb)(99, "Done");

	return true;
}
Example #20
0
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,&para_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,&para_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;
}
Example #21
0
bool SdfGpuPlugin::applyFilter(QAction */*filter*/, MeshDocument &md, RichParameterSet & pars, vcg::CallBackPos *cb)
{
  MeshModel* mm = md.mm();

  //RETRIEVE PARAMETERS
  mOnPrimitive  = (ONPRIMITIVE) pars.getEnum("onPrimitive");
 // assert( mOnPrimitive==ON_VERTICES && "Face mode not supported yet" );
  unsigned int numViews     = pars.getInt("numberRays");
  int          peel         = pars.getInt("peelingIteration");
  mTolerance                = pars.getFloat("peelingTolerance");
  mPeelingTextureSize       = pars.getInt("DepthTextureSize");
  mUseVBO                   = pars.getBool("useVBO");

  if(mAction != SDF_DEPTH_COMPLEXITY)
    mMinCos                 = vcg::math::Cos(math::ToRad(pars.getFloat("coneAngle")/2.0));

  std::vector<Point3f> coneDirVec;

  if(mAction == SDF_OBSCURANCE)
    mTau = pars.getFloat("obscuranceExponent");
  else if(mAction==SDF_SDF)
  {
      mRemoveFalse     = pars.getBool("removeFalse");
      mRemoveOutliers  = pars.getBool("removeOutliers");


   }
   //MESH CLEAN UP
   setupMesh( md, mOnPrimitive );

   //GL INIT
   if(!initGL(*mm)) return false;

   //
   if(mOnPrimitive==ON_VERTICES)
        vertexDataToTexture(*mm);
   else
       faceDataToTexture(*mm);

  //Uniform sampling of directions over a sphere
  std::vector<Point3f> unifDirVec;
  GenNormal<float>::Uniform(numViews,unifDirVec);


  Log(0, "Number of rays: %i ", unifDirVec.size() );
  Log(0, "Number of rays for GPU outliers removal: %i ", coneDirVec.size() );

  coneDirVec.clear();

  vector<int>  mDepthDistrib(peel,0);
  //Do the actual calculation of sdf or obscurance for each ray
  unsigned int tracedRays = 0;
  for(vector<vcg::Point3f>::iterator vi = unifDirVec.begin(); vi != unifDirVec.end(); vi++)
  {
       (*vi).Normalize();
        TraceRay(peel, (*vi), md.mm());
        cb(100*((float)tracedRays/(float)unifDirVec.size()), "Tracing rays...");

        this->glContext->makeCurrent();

        ++tracedRays;
        mDepthComplexity = std::max(mDepthComplexity, mTempDepthComplexity);

        mDepthDistrib[mTempDepthComplexity]++;
        mTempDepthComplexity = 0;
  }

  //read back the result texture and store result in the mesh
  if(mAction == SDF_OBSCURANCE)
  {
      if(mOnPrimitive == ON_VERTICES)
        applyObscurancePerVertex(*mm,unifDirVec.size());
    else
        applyObscurancePerFace(*mm,unifDirVec.size());
  }
  else if(mAction == SDF_SDF)
  {
      if(mOnPrimitive == ON_VERTICES)
            applySdfPerVertex(*mm);
      else
          applySdfPerFace(*mm);

  }



  Log(0, "Mesh depth complexity %i (The accuracy of the result depends on the value you provided for the max number of peeling iterations, \n if you get warnings try increasing"
                                    " the peeling iteration parameter)\n", mDepthComplexity );

  //Depth complexity distribution log. Useful to know which is the probability to find a number of layers looking at the mesh or scene.
  Log(0, "Depth complexity             NumberOfViews\n", mDepthComplexity );
  for(int j = 0; j < peel; j++)
  {
     Log(0, "   %i                             %i\n", j, mDepthDistrib[j] );
  }

  //Clean & Exit
  releaseGL(*mm);

  mDepthComplexity = 0;

  return true;
}
Example #22
0
bool FilterMutualInfoPlugin::preAlignment(MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
	Solver solver;
	MutualInfo mutual;
	if (md.rasterList.size()==0)
	{
		 Log(0, "You need a Raster Model to apply this filter!");
		 return false;
	}
	else {

	align.mesh=&md.mm()->cm;
	
	solver.optimize_focal=par.getBool("Estimate Focal");
	solver.fine_alignment=par.getBool("Fine");

	int rendmode= par.getEnum("RenderingMode");
			
			switch(rendmode){ 
				case 0: 
					align.mode=AlignSet::COMBINE;
					break;
				case 1: 
					align.mode=AlignSet::NORMALMAP;
					break;
				case 2: 
					align.mode=AlignSet::COLOR;
					break;
				case 3: 
					align.mode=AlignSet::SPECULAR;
					break;
				case 4: 
					align.mode=AlignSet::SILHOUETTE;
					break;
				case 5: 
					align.mode=AlignSet::SPECAMB;
					break;
				default:
					align.mode=AlignSet::COMBINE;
					break;
			}

	vcg::Point3f *vertices = new vcg::Point3f[align.mesh->vn];
  vcg::Point3f *normals = new vcg::Point3f[align.mesh->vn];
  vcg::Color4b *colors = new vcg::Color4b[align.mesh->vn];
  unsigned int *indices = new unsigned int[align.mesh->fn*3];

  for(int i = 0; i < align.mesh->vn; i++) {
    vertices[i] = align.mesh->vert[i].P();
    normals[i] = align.mesh->vert[i].N();
    colors[i] = align.mesh->vert[i].C();
  }

  for(int i = 0; i < align.mesh->fn; i++) 
    for(int k = 0; k < 3; k++) 
      indices[k+i*3] = align.mesh->face[i].V(k) - &*align.mesh->vert.begin();

  glBindBufferARB(GL_ARRAY_BUFFER_ARB, align.vbo);
  glBufferDataARB(GL_ARRAY_BUFFER_ARB, align.mesh->vn*sizeof(vcg::Point3f), 
                  vertices, GL_STATIC_DRAW_ARB);
  glBindBufferARB(GL_ARRAY_BUFFER_ARB, align.nbo);
  glBufferDataARB(GL_ARRAY_BUFFER_ARB, align.mesh->vn*sizeof(vcg::Point3f), 
                  normals, GL_STATIC_DRAW_ARB);
  glBindBufferARB(GL_ARRAY_BUFFER_ARB, align.cbo);
  glBufferDataARB(GL_ARRAY_BUFFER_ARB, align.mesh->vn*sizeof(vcg::Color4b), 
                  colors, GL_STATIC_DRAW_ARB);
  glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

  glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, align.ibo);
  glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, align.mesh->fn*3*sizeof(unsigned int), 
                  indices, GL_STATIC_DRAW_ARB);
  glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);


  // it is safe to delete after copying data to VBO
  delete []vertices;
  delete []normals;
  delete []colors;
  delete []indices;

	for (int r=0; r<md.rasterList.size();r++)
	{
		if(md.rasterList[r]->visible)
		{
				align.image=&md.rasterList[r]->currentPlane->image;
				align.shot=md.rasterList[r]->shot;
				
				align.resize(800);

				align.shot.Intrinsics.ViewportPx[0]=int((double)align.shot.Intrinsics.ViewportPx[1]*align.image->width()/align.image->height());
				align.shot.Intrinsics.CenterPx[0]=(int)(align.shot.Intrinsics.ViewportPx[0]/2);

				if (solver.fine_alignment)
				solver.optimize(&align, &mutual, align.shot);
				else
				{
				solver.iterative(&align, &mutual, align.shot);
				Log(0, "Vado di rough",r);
				}
				
				md.rasterList[r]->shot=align.shot;
				float ratio=(float)md.rasterList[r]->currentPlane->image.height()/(float)align.shot.Intrinsics.ViewportPx[1];
				md.rasterList[r]->shot.Intrinsics.ViewportPx[0]=md.rasterList[r]->currentPlane->image.width();
				md.rasterList[r]->shot.Intrinsics.ViewportPx[1]=md.rasterList[r]->currentPlane->image.height();
				md.rasterList[r]->shot.Intrinsics.PixelSizeMm[1]/=ratio;
				md.rasterList[r]->shot.Intrinsics.PixelSizeMm[0]/=ratio;
				md.rasterList[r]->shot.Intrinsics.CenterPx[0]=(int)((float)md.rasterList[r]->shot.Intrinsics.ViewportPx[0]/2.0);
				md.rasterList[r]->shot.Intrinsics.CenterPx[1]=(int)((float)md.rasterList[r]->shot.Intrinsics.ViewportPx[1]/2.0);

				Log(0, "Image %d completed",r);
				
		}
		else
			Log(0, "Image %d skipped",r);
		}
	}
	
	return true;
}
Example #23
0
// The Real Core Function doing the actual mesh processing.
bool FilterHarmonicPlugin::applyFilter(QAction * action, MeshDocument & md, RichParameterSet & par, vcg::CallBackPos * cb)
{
	switch(ID(action))
	{
	case FP_SCALAR_HARMONIC_FIELD :
	{
		typedef vcg::GridStaticPtr<CMeshO::VertexType, CMeshO::ScalarType> VertexGrid;

		typedef double                           CoeffScalar; // TODO, when moving the code to a class make it a template (CoeffScalar = double)

		typedef CMeshO::ScalarType               ScalarType;
		typedef CMeshO::CoordType                CoordType;
		typedef CMeshO::VertexType               VertexType;
		typedef CMeshO::FaceType                 FaceType;

		typedef Eigen::Triplet<CoeffScalar>      T;
		typedef Eigen::SparseMatrix<CoeffScalar> SpMat; //sparse matrix type of double


		CMeshO & m = md.mm()->cm;

		vcg::tri::Allocator<CMeshO>::CompactFaceVector(m);
		vcg::tri::Allocator<CMeshO>::CompactVertexVector(m);

		md.mm()->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTMARK);
		vcg::tri::UpdateBounding<CMeshO>::Box(m);
		vcg::tri::UpdateTopology<CMeshO>::FaceFace(m);

		int n  = m.VN();
		int fn = m.FN();

		std::vector<T>             coeffs; // coefficients of the system
		std::map<size_t,CoeffScalar> sums; // row sum of the coefficient

		SpMat laplaceMat; // the system to be solved
		laplaceMat.resize(n, n);

		Log("Generating coefficients.`");
		cb(0, "Generating coefficients...");
		vcg::tri::UpdateFlags<CMeshO>::FaceClearV(m);
		// Iterate over the faces
		for (size_t i = 0; i < m.face.size(); ++i)
		{
			CMeshO::FaceType & f = m.face[i];

			if (f.IsD())
			{
				assert(int(i) == fn);
				break; // TODO FIX the indexing of vertices
			}

			assert(!f.IsV());
			f.SetV();

			// Generate coefficients for each edge
			for (int idx = 0; idx < 3; ++idx)
			{
				CoeffScalar weight;
				WeightInfo res = ComputeWeight<FaceType, CoeffScalar>(f, idx, weight);

				switch (res)
				{
				case EdgeAlreadyVisited : continue;
				case Success            : break;
				case BorderEdge         :
					this->errorMessage = "Mesh not closed, cannot compute harmonic field on mesh containing holes or borders";
					return false;
				default: assert(0);
				}

//				if (weight < 0) weight = 0; // TODO check if negative weight may be an issue

				// Add the weight to the coefficients vector for both the vertices of the considered edge
				size_t v0_idx = vcg::tri::Index(m, f.V0(idx));
				size_t v1_idx = vcg::tri::Index(m, f.V1(idx));

				coeffs.push_back(T(v0_idx, v1_idx, -weight));
				coeffs.push_back(T(v1_idx, v0_idx, -weight));

				// Add the weight to the row sum
				sums[v0_idx] += weight;
				sums[v1_idx] += weight;
			}

			f.SetV();
		}

		// Fill the system matrix
		Log("Fill the system matrix");
		cb(10, "Filling the system matrix...");
		laplaceMat.reserve(coeffs.size());
		for (std::map<size_t,CoeffScalar>::const_iterator it = sums.begin(); it != sums.end(); ++it)
		{
			coeffs.push_back(T(it->first, it->first, it->second));
		}
		laplaceMat.setFromTriplets(coeffs.begin(), coeffs.end());

		// Get the two vertices with value set
		VertexGrid vg;
		vg.Set(m.vert.begin(), m.vert.end());

		vcg::vertex::PointDistanceFunctor<ScalarType> pd;
		vcg::tri::Tmark<CMeshO, VertexType> mv;
		mv.SetMesh(&m);
		mv.UnMarkAll();
		CoordType  closestP;
		ScalarType minDist = 0;
		VertexType * vp0 = vcg::GridClosest(vg, pd, mv, par.getPoint3f("point1"), m.bbox.Diag(), minDist, closestP);
		VertexType * vp1 = vcg::GridClosest(vg, pd, mv, par.getPoint3f("point2"), m.bbox.Diag(), minDist, closestP);
		if (vp0 == NULL || vp1 == NULL || vp0 == vp1)
		{
			this->errorMessage = "Error occurred for selected points.";
			return false;
		}

		size_t v0_idx = vcg::tri::Index(m, vp0);
		size_t v1_idx = vcg::tri::Index(m, vp1);

		// Add penalty factor alpha
		Log("Setting up the system matrix");
		const CoeffScalar alpha = pow(10, 8);

		Eigen::Matrix<CoeffScalar, Eigen::Dynamic, 1> b, x; // Unknown and known terms vectors
		b.setZero(n);
		b(v0_idx) = alpha * par.getFloat("value1");
		b(v1_idx) = alpha * par.getFloat("value2");

		laplaceMat.coeffRef(v0_idx, v0_idx) += alpha;
		laplaceMat.coeffRef(v1_idx, v1_idx) += alpha;

		// Solve system laplacianMat x = b
		Log("System matrix decomposition...");
		cb(20, "System matrix decomposition...");
		Eigen::SimplicialLDLT<Eigen::SparseMatrix<CoeffScalar> > solver; // TODO eventually use another solver
		solver.compute(laplaceMat);
		if(solver.info() != Eigen::Success)
		{
			// decomposition failed
			this->errorMessage = "System matrix decomposition failed: ";
			if (solver.info() == Eigen::NumericalIssue)
				this->errorMessage += "numerical issue.";
			else if (solver.info() == Eigen::NoConvergence)
				this->errorMessage += "no convergence.";
			else if (solver.info() == Eigen::InvalidInput)
				this->errorMessage += "invalid input.";

			return false;
		}

		Log("Solving the system...");
		cb(85, "Solving the system...");
		x = solver.solve(b);
		if(solver.info() != Eigen::Success)
		{
			// solving failed
			this->errorMessage = "System solving failed.";
			return false;
		}

		// Colorize bands for the 0-1 interval
		if (par.getBool("colorize"))
		{
			float steps = 20.0f;
			for (size_t i = 0; int(i) < n; ++i)
			{
				bool on = (int)(x[i]*steps)%2 == 1;
				if (on)
				{
					m.vert[i].C() = vcg::Color4b::ColorRamp(0,2,x[i]);
				}
				else
				{
					m.vert[i].C() = vcg::Color4b::White;
				}
			}
		}

		// Set field value into vertex quality attribute
		for (size_t i = 0; int(i) < n; ++i)
		{
			m.vert[i].Q() = x[i];
		}

		cb(100, "Done.");

		return true;
	}
	default : assert(0);
	}
	return false;
}
Example #24
0
bool AlignTools::align(MeshModel *stuckModel, PickedPoints *stuckPickedPoints,
		MeshModel *modelToMove, PickedPoints *modelToMovePickedPoints,
		GLArea *modelToMoveGLArea,
		RichParameterSet &filterParameters,
		QWidget *parentWidget, bool confirm)
{
	vcg::Matrix44f result;

	bool useMarkers = filterParameters.getBool(UseMarkers);
	bool allowScaling = filterParameters.getBool(AllowScaling);
	bool useICP = filterParameters.getBool(UseICP);

	if(useMarkers){
		//get the picked points
		std::vector<vcg::Point3f> *stuckPoints = stuckPickedPoints->getPoint3fVector();
		std::vector<vcg::Point3f> *meshToMovePoints = modelToMovePickedPoints->getPoint3fVector();
		
		//number of points are not the same so return false
		if(stuckPoints->size() != meshToMovePoints->size())	return false;

		//this will calculate the transform for the destination mesh model which we will be moving
		//into alignment with the source
		if(allowScaling)
		{
			qDebug() << "Scaling allowed";
			vcg::PointMatching<float>::ComputeSimilarityMatchMatrix(result, *stuckPoints, *meshToMovePoints);
		} else
			vcg::PointMatching<float>::ComputeRigidMatchMatrix(result, *stuckPoints, *meshToMovePoints);

		//set the transform
		modelToMove->cm.Tr = result;

		if(NULL != modelToMoveGLArea)
			modelToMoveGLArea->update();
	}

	if(useICP)
	{
		qDebug("Now on to ICP");

		//create a meshtree
		MeshTree meshTree;
		//put both meshes in it
		meshTree.nodeList.push_back(new MeshNode(stuckModel, 0));
		meshTree.nodeList.push_back(new MeshNode(modelToMove, 1));

		//set both to glued
		foreach(MeshNode *mn, meshTree.nodeList)
			mn->glued=true;

		vcg::AlignPair::Param ICPParameters;

		//get the parameter values
		AlignParameter::buildAlignParameters(filterParameters, ICPParameters);

		meshTree.Process(ICPParameters);

		qDebug() << "done with process for ICP";

		if(NULL != modelToMoveGLArea)
				modelToMoveGLArea->update();

	}

	if(useMarkers || useICP)
	{

		if(confirm && NULL != modelToMoveGLArea)
		{
			bool removeMeshAddedForQuestion = false;

			vcg::Color4b oldStuckColor;
			vcg::Color4b oldToMoveColor;
			vcg::GLW::ColorMode	oldColorMode;
			//if the stuck model is not displayed next to the model to move,
			//then temporarily display it
			if(!modelToMoveGLArea->md()->meshList.contains(stuckModel))
			{
				removeMeshAddedForQuestion = true;
				modelToMoveGLArea->md()->meshList.push_back(stuckModel);

				//save the old colors
				oldStuckColor = stuckModel->cm.C();
				oldToMoveColor = modelToMove->cm.C();
				//set the color of the objects
				stuckModel->cm.C() = vcg::Color4b::LightBlue;
				modelToMove->cm.C() = vcg::Color4b::LightGray;

				//save the old colorMode
				oldColorMode = modelToMoveGLArea->rm.colorMode;
				//set the new colorMode
				modelToMoveGLArea->rm.colorMode = GLW::CMPerMesh;

				modelToMoveGLArea->update();
			}

			int returnValue = QMessageBox::question(parentWidget,
					"MeshLab", "Do you want accept this alignment?",
					QMessageBox::Yes|QMessageBox::No, QMessageBox::No);

			//if we added the other model in for comparing
			if(removeMeshAddedForQuestion)
			{
				//remove the mesh that was added
				modelToMoveGLArea->md()->meshList.pop_back();

				//set back to how things were before
				stuckModel->cm.C() = oldStuckColor;
				modelToMove->cm.C() = oldToMoveColor;
				modelToMoveGLArea->rm.colorMode = oldColorMode;

				modelToMoveGLArea->update();
			}

			if(returnValue == QMessageBox::No)
			{
				modelToMove->cm.Tr.SetIdentity();

				modelToMoveGLArea->update();

				return false;
			}
		}

		//if there are points (may not be if you just used ICP
		if(NULL != modelToMovePickedPoints)
		{
			//now translate the picked points points
			modelToMovePickedPoints->translatePoints(modelToMove->cm.Tr);

			//update the metadata
			CMeshO::PerMeshAttributeHandle<PickedPoints*> ppHandle =
				(vcg::tri::HasPerMeshAttribute(modelToMove->cm, PickedPoints::Key) ?
					vcg::tri::Allocator<CMeshO>::GetPerMeshAttribute<PickedPoints*> (modelToMove->cm, PickedPoints::Key) :
					vcg::tri::Allocator<CMeshO>::AddPerMeshAttribute<PickedPoints*> (modelToMove->cm, PickedPoints::Key) );

			ppHandle() = modelToMovePickedPoints;
		}
		
		//now save the transform as perMeshData so that we can undo it in the future
		CMeshO::PerMeshAttributeHandle<vcg::Matrix44f> transformHandle =
			(vcg::tri::HasPerMeshAttribute(modelToMove->cm, getKey()) ?
				vcg::tri::Allocator<CMeshO>::GetPerMeshAttribute<vcg::Matrix44f> (modelToMove->cm, getKey()) :
				vcg::tri::Allocator<CMeshO>::AddPerMeshAttribute<vcg::Matrix44f> (modelToMove->cm, getKey()) );
		transformHandle() = modelToMove->cm.Tr;
		
		//now translate all the points in the mesh
		//TODO probably should call a function to do this so if meshlab changes we dont have to
		//taken from meshlab/src/meshlabplugins/meshfilter/meshfilter.cpp
		//if (ID(filter) == (FP_FREEZE_TRANSFORM) ) {
		vcg::tri::UpdatePosition<CMeshO>::Matrix(modelToMove->cm, modelToMove->cm.Tr);
		vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(modelToMove->cm);
		vcg::tri::UpdateBounding<CMeshO>::Box(modelToMove->cm);
		modelToMove->cm.Tr.SetIdentity();

		return true;
	} else
	{
		qDebug() << "you ran align without choosing a method";
	}

	return false;
}
Example #25
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 #26
0
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;
}