Example #1
0
//
// Apply filter
//
bool FilterTopoPlugin::applyFilter(QAction *filter, MeshModel &m, RichParameterSet & par, vcg::CallBackPos *cb)
{
	// To run the retopology algorithm an istance of RetopoMeshBuilder is needed
	RetopMeshBuilder rm;

	// Load topology mesh
	MeshModel *userMesh = par.getMesh("userMesh");
	// Load (input) original mesh
	MeshModel *inMesh = par.getMesh("inMesh");
	// Load iterations value
	int it = par.getInt("it");
	// Load distance value
	float dist = par.getAbsPerc("dist");

	// Destination meshmodel: retopology mesh will replace flat topology mesh
	MeshModel * outM = par.getMesh("userMesh");

	// Prepare mesh
	inMesh->updateDataMask(MeshModel::MM_FACEMARK);
	tri::UpdateNormals<CMeshO>::PerFaceNormalized(inMesh->cm);
	tri::UpdateFlags<CMeshO>::FaceProjection(inMesh->cm);

	// Init the retopology builder with original input mesh and distance value
	rm.init(inMesh, dist);
	// Apply the algorithm
	return rm.applyTopoMesh(*userMesh, *inMesh, it, dist, *outM);
}
Example #2
0
// The Real Core Function doing the actual mesh processing.
bool FilterAutoalign::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
  vcg::tri::FourPCS<CMeshO> *fpcs ;
  switch(ID(filter)) {
    case FP_AUTOALIGN :
    {

      MeshModel *firstMesh= par.getMesh("FirstMesh");
      MeshModel *secondMesh= par.getMesh("SecondMesh");
      vcg::tri::FourPCS<CMeshO> fpcs;
      fpcs.par.Default();
      fpcs.par.f =  par.getFloat("overlapping");
      firstMesh->updateDataMask(MeshModel::MM_VERTMARK);
      secondMesh->updateDataMask(MeshModel::MM_VERTMARK);
      fpcs.Init(firstMesh->cm,secondMesh->cm);
      bool res = fpcs.Align(0,firstMesh->cm.Tr,cb);
      firstMesh->clearDataMask(MeshModel::MM_VERTMARK);
      secondMesh->clearDataMask(MeshModel::MM_VERTMARK);

      if(res) Log("Automatic Rough Alignment Done");
         else Log("Automatic Rough Alignment Failed");
    } break;



    case FP_BEST_ROTATION :
    {
      MeshModel *firstMesh= par.getMesh("FirstMesh");
      MeshModel *secondMesh= par.getMesh("SecondMesh");
      tri::Guess GG;
      GG.pp.MatrixNum = 100;
      GG.GenRotMatrix();
      GG.Init<CMeshO>(firstMesh->cm, secondMesh->cm);
      static int counterMV=0;
      static int step=0;
      //for(int i=0;i<GG.MV.size();++i)
      int i=counterMV;
      step = (step +1)%4;
//			if(step==0) counterMV++;

      qDebug("Counter %i step %i",counterMV,step);
        {
            Point3f baseTran =  GG.InitBaseTranslation(GG.MV[i]);
            Point3f bestTran;

            int res = GG.SearchBestTranslation(GG.u[0],GG.MV[i],4,1,baseTran,bestTran);
            if(step==0) firstMesh->cm.Tr.SetIdentity();
            if(step==1) firstMesh->cm.Tr = GG.MV[i];
            if(step==2) firstMesh->cm.Tr = GG.BuildTransformation(GG.MV[i],baseTran);
            if(step==3) firstMesh->cm.Tr = GG.BuildTransformation(GG.MV[i],bestTran);
        }
      //Log(0,(res)?" Automatic Rough Alignment Done":"Automatic Rough Alignment Failed");
    } break;
    default: assert (0);
  }
  return true;
}
Example #3
0
bool FilterFractal::applyFilter(QAction* filter, MeshDocument &md, RichParameterSet &par, vcg::CallBackPos* cb)
{
  if(this->getClass(filter) == MeshFilterInterface::MeshCreation)
       md.addNewMesh("",this->filterName(ID(filter)));
  switch(ID(filter))
    {
    case CR_FRACTAL_TERRAIN:
    case FP_FRACTAL_MESH:
        {
            MeshModel* mm = md.mm();
            float maxHeight = .0;
            int smoothingSteps = 0;

            if(ID(filter) == CR_FRACTAL_TERRAIN)
            {
                int steps = par.getInt("steps");
                steps = ((steps<2)? 2: steps);
                float gridSide = .0;
                FractalUtils<CMeshO>::GenerateGrid(mm->cm, steps, gridSide);
                maxHeight = par.getDynamicFloat("maxHeight") * gridSide;
            } else {
                maxHeight = par.getAbsPerc("maxHeight");
                smoothingSteps = par.getInt("smoothingSteps");
            }

            FractalUtils<CMeshO>::FractalArgs args
               (mm, par.getEnum("algorithm"),par.getFloat("seed"),
                par.getFloat("octaves"), par.getFloat("lacunarity"),
                par.getFloat("fractalIncrement"), par.getFloat("offset"), par.getFloat("gain"),
                maxHeight, par.getDynamicFloat("scale"), smoothingSteps, par.getBool("saveAsQuality"));

            if(args.saveAsQuality)
                mm->updateDataMask(MeshModel::MM_VERTQUALITY);
            return FractalUtils<CMeshO>::ComputeFractalPerturbation(mm->cm, args, cb);
        }
        break;
    case FP_CRATERS:
        {
            if (md.meshList.size() < 2) {
                errorMessage = "There must be at least two layers to apply the craters generation filter.";
                return false;
            }

            CMeshO* samples = &(par.getMesh("samples_mesh")->cm);
            if (samples->face.size() > 0) {
                errorMessage = "The sample layer selected should be a points cloud.";
                return false;
            }
            CMeshO* target = &(par.getMesh("target_mesh")->cm);
            if (samples == target) {
                errorMessage = "The sample layer and the target layer must be different.";
                return false;
            }

            float minRadius = par.getDynamicFloat("min_radius");
            float maxRadius = par.getDynamicFloat("max_radius");
            if (maxRadius <= minRadius)  {
                errorMessage =  "Min radius is greater than max radius.";
                return false;
            }

            float minDepth = par.getDynamicFloat("min_depth");
            float maxDepth = par.getDynamicFloat("max_depth");
            if (maxDepth <= minDepth) {
                errorMessage = "Min depth is greater than max depth.";
                return false;
            }

            // reads parameters
            CratersUtils<CMeshO>::CratersArgs args(par.getMesh("target_mesh"), par.getMesh("samples_mesh"), par.getEnum("rbf"),
                                    par.getInt("seed"), minRadius, maxRadius, minDepth, maxDepth,
                                    par.getInt("smoothingSteps"), par.getBool("save_as_quality"), par.getBool("invert"),
                                    par.getBool("ppNoise"), par.getBool("successiveImpacts"),
                                    par.getDynamicFloat("elevation"), par.getEnum("blend"),
                                    par.getDynamicFloat("blendThreshold"));

            return CratersUtils<CMeshO>::GenerateCraters(args, cb);
        }
        break;
    }
    return false;
}
Example #4
0
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 AlignTools::setupThenAlign(MeshModel &/*mm*/, RichParameterSet & par)
{
	//mesh that wont move
	MeshModel *stuckModel = par.getMesh(StuckMesh);
	PickedPoints *stuckPickedPoints = 0;

	//mesh that will move
	MeshModel *modelToMove = par.getMesh(MeshToMove);
	PickedPoints *modelToMovePickedPoints = 0;

	bool useMarkers = par.getBool(UseMarkers);
	
	if(NULL == stuckModel || NULL == modelToMove)
	{
		qDebug() << "one of the input meshes to filter align was null";
		return false;
	}

	//if we are going to use the markers try to load them
	if(useMarkers){
		//first try to get points from memory
		if(vcg::tri::HasPerMeshAttribute(stuckModel->cm, PickedPoints::Key) )
		{
			CMeshO::PerMeshAttributeHandle<PickedPoints*> ppHandle =
					vcg::tri::Allocator<CMeshO>::GetPerMeshAttribute<PickedPoints*>(stuckModel->cm, PickedPoints::Key);
	
			stuckPickedPoints = ppHandle();
	
			if(NULL == stuckPickedPoints){
				qDebug() << "problem casting to picked points";
				return false;
			}
		} else
		{
			//now try to load them from a file
			QString ppFileName = PickedPoints::getSuggestedPickedPointsFileName(*stuckModel);
			QFileInfo file(ppFileName);
			if(file.exists())
			{
				stuckPickedPoints = new PickedPoints();
				bool success = stuckPickedPoints->open(ppFileName);
	
				if(!success){
					qDebug() << "problem loading stuck picked points from a file";
					return false;
				}
			} else
			{
				qDebug() << "stuck points file didnt exist: " << ppFileName;
				//Log(GLLogStream::WARNING, "No points were found for the Stuck mesh.");
				return false;
			}
		}
	
		if(vcg::tri::HasPerMeshAttribute(modelToMove->cm, PickedPoints::Key) )
		{
			CMeshO::PerMeshAttributeHandle<PickedPoints*> ppHandle =
					vcg::tri::Allocator<CMeshO>::GetPerMeshAttribute<PickedPoints*>(modelToMove->cm, PickedPoints::Key);
	
			modelToMovePickedPoints = ppHandle();
	
			if(NULL == modelToMovePickedPoints){
				qDebug() << "problem casting to picked poitns";
				return false;
			}
		} else
		{
			QString ppFileName = PickedPoints::getSuggestedPickedPointsFileName(*modelToMove);
			QFileInfo file(ppFileName);
			if(file.exists())
			{
				modelToMovePickedPoints = new PickedPoints();
				bool success = modelToMovePickedPoints->open(ppFileName);
				if(!success){
					qDebug() << "failed to load modelToMove pick points";
					return false;
				}
			} else
			{
				qDebug() << "model to move points file didnt exist: " << ppFileName;
				//Log(GLLogStream::WARNING, "No points were found for the mesh to move.");
				return false;
			}
		}
	}
	
	bool result = AlignTools::align(stuckModel, stuckPickedPoints,
			modelToMove, modelToMovePickedPoints,
			0, par);
	
	return result;
}
// The Real Core Function doing the actual mesh processing.
bool FilterAutoalign::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
  switch(ID(filter)) {
    case FP_ALIGN_4PCS :
    {
      MeshModel *fixMesh= par.getMesh("fixMesh");
      MeshModel *movMesh= par.getMesh("movMesh");
      MeshModel *sampleMesh= 0;
      bool showSample = par.getBool("showSample");
      if(showSample) sampleMesh = md.addOrGetMesh("sample","sample",false, RenderMode(vcg::GLW::DMPoints));
      tri::UpdateNormal<CMeshO>::NormalizePerVertex(fixMesh->cm);
      tri::UpdateNormal<CMeshO>::NormalizePerVertex(movMesh->cm);
      tri::Clean<CMeshO>::RemoveUnreferencedVertex(fixMesh->cm);
      tri::Clean<CMeshO>::RemoveUnreferencedVertex(movMesh->cm);
      tri::Allocator<CMeshO>::CompactEveryVector(fixMesh->cm);
      tri::Allocator<CMeshO>::CompactEveryVector(movMesh->cm);
      fixMesh->updateDataMask(MeshModel::MM_VERTMARK);
      movMesh->updateDataMask(MeshModel::MM_VERTMARK);

      vcg::tri::FourPCS<CMeshO> fpcs;
      fpcs.par.Default();
      fpcs.par.overlap    =  par.getFloat("overlap");
      fpcs.par.sampleNumP =  par.getInt("sampleNum");
      fpcs.par.deltaPerc  =  par.getFloat("tolerance");
      fpcs.par.seed       = par.getInt("randSeed");
      fpcs.Init(movMesh->cm,fixMesh->cm);
      Matrix44m Tr;
      bool res = fpcs.Align(Tr,cb);

      if(res)
      {
        Log("4PCS Completed, radius %f",fpcs.par.samplingRadius);
        Log("Tested %i candidate, best score was %i\n",fpcs.U.size(),fpcs.U[fpcs.iwinner].score);

        Log("Estimated overlap is now %f \n",fpcs.par.overlap);
        Log("Init %5.0f Coplanar Search %5.0f",fpcs.stat.init(),fpcs.stat.select());
        Log("findCongruent %5.0f testAlignment %5.0f",fpcs.stat.findCongruent(),fpcs.stat.testAlignment());
        movMesh->cm.Tr = Tr;
        if(showSample)
        {
          sampleMesh->cm.Clear();
          for(size_t i=0;i<fpcs.subsetQ.size();++i)
            tri::Allocator<CMeshO>::AddVertex(sampleMesh->cm, fpcs.subsetQ[i]->P(), fpcs.subsetQ[i]->N());
          tri::UpdateBounding<CMeshO>::Box(sampleMesh->cm);
        }
      }
      else Log("4PCS Failed");
    } break;



    case FP_BEST_ROTATION :
    {
      MeshModel *fixMesh= par.getMesh("fixMesh");
      MeshModel *movMesh= par.getMesh("movMesh");
      int searchRange = par.getInt("searchRange");
      int rotNum = par.getInt("RotationNumber");
      int gridSize = par.getInt("gridSize");
      int sampleSize = par.getInt("sampleSize");
      MeshModel *sample=md.addOrGetMesh("sample", "sample",false);
      MeshModel *occ=md.addOrGetMesh("occ", "occ",false);

      tri::Guess<Scalarm> GG;
      std::vector<tri::Guess<Scalarm>::Result> ResultVec;
      GG.pp.MatrixNum = rotNum;
      GG.pp.GridSize =gridSize;
      GG.pp.SampleNum = sampleSize;
      GG.Init<CMeshO>(fixMesh->cm, movMesh->cm);

      for(size_t i=0;i<GG.RotMVec.size();++i)
      {
        Point3m baseTran =  GG.ComputeBaseTranslation(GG.RotMVec[i]);
        Point3m bestTran;
        int res = GG.SearchBestTranslation(GG.u[0],GG.RotMVec[i],searchRange,baseTran,bestTran);
        ResultVec.push_back(tri::Guess<Scalarm>::Result(GG.BuildResult(GG.RotMVec[i],baseTran,bestTran), res, i, bestTran));
      }
      sort(ResultVec.begin(),ResultVec.end());
      movMesh->cm.Tr.Import(ResultVec.back().m);

      tri::Build(sample->cm,GG.movVertBase);
      sample->cm.Tr.Import(ResultVec.back().m);

      qDebug("Result %i",ResultVec.back().score);
      GG.GenerateOccupancyMesh(occ->cm,0,ResultVec.back().m);
      occ->UpdateBoxAndNormals();

      Log("Automatic Rough Alignment Tested %i rotations, best err was %i",GG.RotMVec.size(), ResultVec.back().score);
    } break;
    default: assert (0);
  }
  return true;
}
Example #7
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;
}
Example #8
0
vcg::Point3<float> RandomFillFilter::getRandomOrigin(RichParameterSet& par){
    int randomVertex = float(rand())/RAND_MAX*(par.getMesh("container")->cm.vert.size() - 1);
    CVertexO& vertex = par.getMesh("container")->cm.vert[randomVertex];
    return vertex.P() + (vertex.N() * par.getMesh("filler")->cm.bbox.Diag());
}
Example #9
0
bool RandomFillFilter::parametersAreNotCorrect(MeshDocument& md, RichParameterSet& par){
    return md.size() < 2 || par.getMesh("container") == 0 || par.getMesh("container") == par.getMesh("filler") || par.getInt("fps") <= 0 || par.getInt("iterations") <= 0 || par.getInt("contacts") <= 0 || par.getFloat("bounciness") < 0.f || par.getFloat("bounciness") > 1.f || par.getFloat("factor") < 0.f || par.getFloat("factor") > 1.f;
}
Example #10
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;
}