Esempio n. 1
0
void LandmarkCapturePlugin::drawFace(CMeshO::FacePointer fp, MeshModel &m, GLArea *gla, QPainter *p)
{

  //glDepthMask(GL_FALSE);
  //glDisable(GL_DEPTH_TEST);
  //p->endNativePainting();
  //p->save();
  //p->setRenderHint(QPainter::TextAntialiasing);
  //p->setPen(Qt::white);
  //QFont qFont;
  //qFont.setStyleStrategy(QFont::NoAntialias);
  //qFont.setFamily("Helvetica");
  //qFont.setPixelSize(12);
  //p->setFont(qFont);
  QString buf = QString("f%1\n (%3 %4 %5)").arg(tri::Index(m.cm,fp)).arg(tri::Index(m.cm,fp->V(0))).arg(tri::Index(m.cm,fp->V(1))).arg(tri::Index(m.cm,fp->V(2)));
  Point3f c=Barycenter(*fp);
  vcg::glLabel::render(p,c,buf);
  for(int i=0;i<3;++i)
    {
       buf =QString("\nv%1:%2 (%3 %4 %5)").arg(i).arg(fp->V(i) - &m.cm.vert[0]).arg(fp->P(i)[0]).arg(fp->P(i)[1]).arg(fp->P(i)[2]);
      if( m.hasDataMask(MeshModel::MM_VERTQUALITY) )
        buf +=QString(" - Q(%1)").arg(fp->V(i)->Q());
      if( m.hasDataMask(MeshModel::MM_WEDGTEXCOORD) )
          buf +=QString("- uv(%1 %2) id:%3").arg(fp->WT(i).U()).arg(fp->WT(i).V()).arg(fp->WT(i).N());
      if( m.hasDataMask(MeshModel::MM_VERTTEXCOORD) )
          buf +=QString("- uv(%1 %2) id:%3").arg(fp->V(i)->T().U()).arg(fp->V(i)->T().V()).arg(fp->V(i)->T().N());
    vcg::glLabel::render(p,fp->V(i)->P(),buf);
    }

  //p->drawText(QRect(0,0,gla->width(),gla->height()), Qt::AlignLeft | Qt::TextWordWrap, buf);
  //p->restore();
  //p->beginNativePainting();
}
Esempio n. 2
0
/* Initializes the list of parameters (called by the auto dialog framework) */
void GeometryAgingPlugin::initParameterSet(QAction *action, MeshModel &m, RichParameterSet &params)
{
	if( ID(action) != FP_ERODE)
	{
		assert (0);
		return;
	}
	bool hasQ = m.hasDataMask(MeshModel::MM_VERTQUALITY);
	std::pair<float,float> qRange(0.0, 0.0);;	// mesh quality range
	// retrieve mesh quality range
	if(hasQ) 
	{
		qRange = tri::Stat<CMeshO>::ComputePerVertexQualityMinMax(m.cm);
		if(qRange.second <= qRange.first) hasQ=false;
	}
		
		params.addParam(new RichBool("ComputeCurvature", !hasQ, "ReCompute quality from curvature", 
				"Compute per vertex quality values using mesh mean curvature <br>"
				"algorithm. In this way only the areas with higher curvature <br>"
				"will be eroded. If not checked, the quality values already <br>"
				"present over the mesh will be used."));
		params.addParam(new RichBool("SmoothQuality", false, "Smooth vertex quality", 
				"Smooth per vertex quality values. This allows to extend the <br>"
				"area affected by the erosion process."));
		params.addParam(new RichAbsPerc("QualityThreshold", qRange.first+(qRange.second-qRange.first)*0.66,
				qRange.first, qRange.second, "Min quality threshold",
				"Represents the minimum quality value two vertexes must have <br>"
				"to consider the edge they are sharing."));
		params.addParam(new RichAbsPerc("EdgeLenThreshold", m.cm.bbox.Diag()*0.02, 0,m.cm.bbox.Diag()*0.5,
				"Edge len threshold", 
				"The minimum length of an edge. Useful to avoid the creation of too many small faces."));
		params.addParam(new RichAbsPerc("ChipDepth", m.cm.bbox.Diag()*0.05, 0, m.cm.bbox.Diag(),
				"Max chip depth", "The maximum depth of a chip."));
		params.addParam(new RichInt("Octaves", 3, "Fractal Octaves", 
				"The number of octaves that are used in the generation of the <br>"
				"fractal noise using Perlin noise; reasonalble values are in the <br>"
				"1..8 range. Setting it to 1 means using a simple Perlin Noise."));
		params.addParam(new RichAbsPerc("NoiseFreqScale", m.cm.bbox.Diag()/10, 0, m.cm.bbox.Diag(), "Noise frequency scale",
				"Changes the noise frequency scale: this affects chip dimensions and <br>"
				"the distance between chips. The value denotes the average values <br>"
				"between two dents. Smaller number means small and frequent chips."));
		params.addParam(new RichFloat("NoiseClamp", 0.5, "Noise clamp threshold [0..1]",
				"All the noise values smaller than this parameter will be <br> "
				"considered as 0."));
		params.addParam(new RichFloat("DisplacementSteps", 10, "Displacement steps",
				"The whole displacement process is performed as a sequence of small <br>"
				"offsets applyed on each vertex. This parameter represents the number <br>"
				"of steps into which the displacement process will be splitted. <br>"
				"Useful to avoid the introduction of self intersections. <br>"
				"Bigger number means better accuracy."));
		params.addParam(new RichBool("Selected", m.cm.sfn>0, "Affect only selected faces", 
				"The aging procedure will be applied to the selected faces only."));
		params.addParam(new RichBool("StoreDisplacement", false, "Store erosion informations",
				"Select this option if you want to store the erosion informations <br>"
				"over the mesh. A new attribute will be added to each vertex <br>"
				"to contain the displacement offset applied to that vertex."));
}
Esempio n. 3
0
bool QualityMapperPlugin::StartEdit(MeshModel& m, GLArea *gla )
{
    
	if(!m.hasDataMask(MeshModel::MM_VERTQUALITY))
	{
			QMessageBox::warning(gla, tr("Quality Mapper"), tr("The model has no vertex quality"), QMessageBox::Ok); 
			return false;
	}
    QMap<int,RenderMode>::iterator it = gla->rendermodemap.find(m.id());  
    m.updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY);
    if (it != gla->rendermodemap.end())
    {
        it.value().setColorMode(GLW::CMPerVert);
        gla->update();
    }
    
	if(_qualityMapperDialog==0)
		_qualityMapperDialog = new QualityMapperDialog(gla->window(), m, gla);

	//drawing histogram
	//bool ret = _qualityMapperDialog->initEqualizerHistogram();
	if ( !_qualityMapperDialog->initEqualizerHistogram() )
	{
		//EndEdit(m, gla);
		return false;
	}

	//drawing transferFunction
	_qualityMapperDialog->drawTransferFunction();

	//dialog ready to be displayed. Show it now!
	_qualityMapperDialog->show();

	connect(_qualityMapperDialog, SIGNAL(closingDialog()),gla,SLOT(endEdit()) );
	return true;
}
Esempio n. 4
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;
}
Esempio n. 5
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;
}
Esempio n. 6
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);

  }


  // LP: save output
  if(mOnPrimitive == ON_FACES)
  {
	  CMeshO& cm=mm->cm;
	  if(!mm->hasDataMask(MeshModel::MM_VERTFACETOPO)) {
		  mm->updateDataMask(MeshModel::MM_VERTFACETOPO);
	  }
	  if(!mm->hasDataMask(MeshModel::MM_VERTCURV)) {
		  mm->updateDataMask(MeshModel::MM_VERTCURV);
		  // vcg::tri::UpdateCurvature<CMeshO>::VertexCurvature(cm);
	  }
	  //当前目录
	  QDir dir;
	  //dir.currentPath();
	  //设置输出文件
	  std::string ofs=dir.currentPath().toStdString();
	  ofs.append("/fq_ml.txt");
	  qDebug()<<"ofs:"<<ofs.c_str();
	  ofstream oo(ofs.c_str());
	  int face_size=cm.face.size();
	  for (int i = 0; i < face_size; i++) {
		  float gc=cm.face[i].Q();
		  oo<<i<<" "<<gc<<endl;
	  }
	  oo.close();
  }



  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;
}
Esempio n. 7
0
bool EditAreslpPlugin::StartEdit(MeshModel &mm, GLArea *gla)
{
    qDebug()<<"EditAreslpPlugin StartEdit";

    if(!mm.hasDataMask(MeshModel::MM_VERTQUALITY)) {
        mm.updateDataMask(MeshModel::MM_VERTQUALITY);
    }

    if(!mm.hasDataMask(MeshModel::MM_FACEQUALITY)) {
        mm.updateDataMask(MeshModel::MM_FACEQUALITY);
    }


    AreslpDialog dialog;
    dialog.exec();

    std::vector<int> pointset=dialog.pointset_;
    std::vector<int> faceset=dialog.faceset_;
    std::vector<int> patchset=dialog.patchset_;

    //Debug the content of above two vector
    for(int i = 0; i < pointset.size(); i++) {
        qDebug()<<pointset[i];
    }

    for(int i = 0; i < faceset.size(); i++) {
        qDebug()<<faceset[i];
    }

    for(int i = 0; i < patchset.size(); i++) {
        qDebug()<<patchset[i];
    }

    CMeshO& cm = mm.cm;

    int point_size = cm.vert.size();
    
	
	if(pointset.size()!=0){
		//先把之前设置的值清空
		for(int i = 0; i < point_size; i++) {
			cm.vert[i].Q() = 0;
		}
		for(int i = 0; i < pointset.size(); i++) {
			cm.vert[pointset[i]].Q() = 1;
		}
	}
    int face_size=cm.face.size();

	if(faceset.size()!=0){
		//先把之前设置的值清空
		for(int i = 0; i < face_size; i++) {
			cm.face[i].Q() = 0;
		}
		for(int i = 0; i < faceset.size(); i++) {
			cm.face[faceset[i]].Q() = 1;
		}
	}


	if(patchset.size()!=0){
		//patch
		std::map<int,double> qm;

		for (int i = 0; i < patchset.size(); i++) {
			std::string tstring="faceq";
			tstring.append(boost::lexical_cast<std::string>(patchset[i]));
			tstring.append(".txt");
			qDebug()<<tstring.c_str();
			std::ifstream ifile(tstring.c_str());
			int ii;
			double v;
			while(ifile >> ii >> v) {
				// qDebug()<<i<<" "<<v;
				qm.insert(make_pair<int,double>(ii,v));
			}
			ifile.close();
		}

		for (int i = 0; i < face_size; i++) {
			if (qm.find(i)!=qm.end()) {
				cm.face[i].Q()=qm[i];
			}else{
				cm.face[i].Q()=0;
			}
		}
	}
Esempio n. 8
0
bool JSONIOPlugin::save(const QString & formatName,const QString & fileName, MeshModel & m, const int mask, const RichParameterSet & par, vcg::CallBackPos * cb, QWidget * parent)
{
	(void)par;
	(void)cb;
	(void)parent;
  vcg::tri::Allocator<CMeshO>::CompactVertexVector(m.cm);
  vcg::tri::Allocator<CMeshO>::CompactFaceVector(m.cm);

  const size_t maxValuesPerLine = 10; // must be > 0

	if (formatName.toUpper() != tr("JSON")) return false;

	const bool hasPerVertexPosition = true;
	const bool hasPerVertexNormal   = ((mask & vcg::tri::io::Mask::IOM_VERTNORMAL)   != 0) && m.hasDataMask(MeshModel::MM_VERTNORMAL);
	const bool hasPerVertexColor    = ((mask & vcg::tri::io::Mask::IOM_VERTCOLOR)    != 0) && m.hasDataMask(MeshModel::MM_VERTCOLOR);
	const bool hasPerVertexTexCoord = ((mask & vcg::tri::io::Mask::IOM_VERTTEXCOORD) != 0) && m.hasDataMask(MeshModel::MM_VERTTEXCOORD);

	const CMeshO & cm = m.cm;

	const std::string filename = QFile::encodeName(fileName).constData();

	std::ofstream os(filename.c_str());
	if (!os.is_open()) return false;

	os << "{" << std::endl;

	os << "  \"version\" : \"0.1.0\"," << std::endl;
	os << std::endl;

	os << "  \"comment\" : \"Generated by MeshLab JSON Exporter\"," << std::endl;
	os << std::endl;

	os << "  \"id\"      : 1," << std::endl;
	os << "  \"name\"    : \"mesh\"," << std::endl;
	os << std::endl;

	os << "  \"vertices\" :" << std::endl;
	os << "  [" << std::endl;

	bool prevDone = false;

	if (hasPerVertexPosition)
	{
		os << "    {" << std::endl;
		os << "      \"name\"       : \"position_buffer\"," << std::endl;
		os << "      \"size\"       : 3," << std::endl;
		os << "      \"type\"       : \"float32\"," << std::endl;
		os << "      \"normalized\" : false," << std::endl;
		os << "      \"values\"     :" << std::endl;
		os << "      [" << std::endl;

		size_t it = 0;
		const size_t sz = cm.vert.size();
		while (it < sz)
		{
			const size_t n = std::min(it + maxValuesPerLine, sz);
			if (n > 0)
			{
				os << "        ";
				{
					const CMeshO::VertexType::CoordType & p = cm.vert[it].cP();
					os << p[0] << ", " << p[1] << ", " << p[2];
					it++;
				}
				for (; it<n; ++it)
				{
					const CMeshO::VertexType::CoordType & p = cm.vert[it].cP();
					os << ", " << p[0] << ", " << p[1] << ", " << p[2];
				}
				if (it <= (sz - 1))
				{
					os << ",";
				}
				os << std::endl;
			}
		}

		os << "      ]" << std::endl;
		os << "    }";

		prevDone = true;
	}

	if (hasPerVertexNormal)
	{
		if (prevDone)
		{
			os << "," << std::endl;
			os << std::endl;
		}
		os << "    {" << std::endl;
		os << "      \"name\"       : \"normal_buffer\"," << std::endl;
		os << "      \"size\"       : 3," << std::endl;
		os << "      \"type\"       : \"float32\"," << std::endl;
		os << "      \"normalized\" : false," << std::endl;
		os << "      \"values\"     :" << std::endl;
		os << "      [" << std::endl;

		size_t it = 0;
		const size_t sz = cm.vert.size();
		while (it < sz)
		{
			const size_t n = std::min(it + maxValuesPerLine, sz);
			if (n > 0)
			{
				os << "        ";
				{
					const CMeshO::VertexType::NormalType & n = cm.vert[it].cN();
					os << n[0] << ", " << n[1] << ", " << n[2];
					it++;
				}
				for (; it<n; ++it)
				{
					const CMeshO::VertexType::NormalType & n = cm.vert[it].cN();
					os << ", " << n[0] << ", " << n[1] << ", " << n[2];
				}
				if (it <= (sz - 1))
				{
					os << ",";
				}
				os << std::endl;
			}
		}

		os << "      ]" << std::endl;
		os << "    }";

		prevDone = true;
	}

	if (hasPerVertexColor)
	{
		if (prevDone)
		{
			os << "," << std::endl;
			os << std::endl;
		}
		os << "    {" << std::endl;
		os << "      \"name\"       : \"color_buffer\"," << std::endl;
		os << "      \"size\"       : 4," << std::endl;
		os << "      \"type\"       : \"uint8\"," << std::endl;
		os << "      \"normalized\" : true," << std::endl;
		os << "      \"values\"     :" << std::endl;
		os << "      [" << std::endl;

		size_t it = 0;
		const size_t sz = cm.vert.size();
		while (it < sz)
		{
			const size_t n = std::min(it + maxValuesPerLine, sz);
			if (n > 0)
			{
				os << "        ";
				{
					const CMeshO::VertexType::ColorType & c = cm.vert[it].cC();
					os << int(c[0]) << ", " << int(c[1]) << ", " << int(c[2]) << ", " << int(c[3]);
					it++;
				}
				for (; it<n; ++it)
				{
					const CMeshO::VertexType::ColorType & c = cm.vert[it].cC();
					os << ", " << int(c[0]) << ", " << int(c[1]) << ", " << int(c[2]) << ", " << int(c[3]);
				}
				if (it <= (sz - 1))
				{
					os << ",";
				}
				os << std::endl;
			}
		}

		os << "      ]" << std::endl;
		os << "    }";

		prevDone = true;
	}

	if (hasPerVertexTexCoord)
	{
		if (prevDone)
		{
			os << "," << std::endl;
			os << std::endl;
		}
		os << "    {" << std::endl;
		os << "      \"name\"       : \"texcoord_buffer\"," << std::endl;
		os << "      \"size\"       : 2," << std::endl;
		os << "      \"type\"       : \"float32\"," << std::endl;
		os << "      \"normalized\" : false," << std::endl;
		os << "      \"values\"     :" << std::endl;
		os << "      [" << std::endl;

		size_t it = 0;
		const size_t sz = cm.vert.size();
		while (it < sz)
		{
			const size_t n = std::min(it + maxValuesPerLine, sz);
			if (n > 0)
			{
				os << "        ";
				{
					const CMeshO::VertexType::TexCoordType & t = cm.vert[it].cT();
					os << t.P()[0] << ", " << t.P()[1];
					it++;
				}
				for (; it<n; ++it)
				{
					const CMeshO::VertexType::TexCoordType & t = cm.vert[it].cT();
					os << ", " << t.P()[0] << ", " << t.P()[1];
				}
				if (it <= (sz - 1))
				{
					os << ",";
				}
				os << std::endl;
			}
		}

		os << "      ]" << std::endl;
		os << "    }";

		prevDone = true;
	}

	if (prevDone)
	{
		os << std::endl;
	}

	os << "  ]," << std::endl;
	os << std::endl;

	os << "  \"connectivity\" :" << std::endl;
	os << "  [" << std::endl;

	if ((m.cm.vn > 0) && (m.cm.fn > 0))
	{
		os << "    {" << std::endl;
		os << "      \"name\"      : \"triangles\"," << std::endl;
		os << "      \"mode\"      : \"triangles_list\"," << std::endl;
		os << "      \"indexed\"   : true," << std::endl;
		os << "      \"indexType\" : \"uint32\"," << std::endl;
		os << "      \"indices\"   :" << std::endl;
		os << "      [" << std::endl;
		{
			const CMeshO::VertexType * v0 = &(m.cm.vert[0]);

			size_t k = 0;
			size_t c = 0;
			const size_t sz = cm.fn;
			while (c < sz)
			{
				const size_t n = std::min(c + maxValuesPerLine, sz);
				if (n > 0)
				{
					os << "        ";
					{
						while (cm.face[k].IsD()) k++;
						const CMeshO::FaceType & f = cm.face[k];
						os << int(f.cV(0) - v0) << ", " << int(f.cV(1) - v0) << ", " << int(f.cV(2) - v0);
						c++;
						k++;
					}
					for (; c<n; ++c)
					{
						while (cm.face[k].IsD()) k++;
						const CMeshO::FaceType & f = cm.face[k];
						os << ", " << int(f.cV(0) - v0) << ", " << int(f.cV(1) - v0) << ", " << int(f.cV(2) - v0);
						k++;
					}
					if (c <= (sz - 1))
					{
						os << ",";
					}
					os << std::endl;
				}
			}
		}
		os << "      ]" << std::endl;
		os << "    }" << std::endl;
	}

	os << "  ]," << std::endl;
	os << std::endl;

	os << "  \"mapping\" :" << std::endl;
	os << "  [" << std::endl;
	if ((m.cm.vn > 0) && (m.cm.fn > 0))
	{
		os << "    {" << std::endl;
		os << "      \"name\"       : \"standard\"," << std::endl;
		os << "      \"primitives\" : \"triangles\"," << std::endl;
		os << "      \"attributes\" :" << std::endl;
		os << "      [" << std::endl;

		prevDone = false;
		if (hasPerVertexPosition)
		{
			os << "        {" << std::endl;
			os << "          \"source\"   : \"position_buffer\"," << std::endl;
			os << "          \"semantic\" : \"position\"," << std::endl;
			os << "          \"set\"      : 0" << std::endl;
			os << "        }";
			prevDone = true;
		}
		if (hasPerVertexNormal)
		{
			if (prevDone)
			{
				os << "," << std::endl;
			}
			os << "        {" << std::endl;
			os << "          \"source\"   : \"normal_buffer\"," << std::endl;
			os << "          \"semantic\" : \"normal\"," << std::endl;
			os << "          \"set\"      : 0" << std::endl;
			os << "        }";
			prevDone = true;
		}
		if (hasPerVertexColor)
		{
			if (prevDone)
			{
				os << "," << std::endl;
			}
			os << "        {" << std::endl;
			os << "          \"source\"   : \"color_buffer\"," << std::endl;
			os << "          \"semantic\" : \"color\"," << std::endl;
			os << "          \"set\"      : 0" << std::endl;
			os << "        }";
			prevDone = true;
		}
		if (hasPerVertexTexCoord)
		{
			if (prevDone)
			{
				os << "," << std::endl;
			}
			os << "        {" << std::endl;
			os << "          \"source\"   : \"texcoord_buffer\"," << std::endl;
			os << "          \"semantic\" : \"texcoord\"," << std::endl;
			os << "          \"set\"      : 0" << std::endl;
			os << "        }";
			prevDone = true;
		}

		if (prevDone)
		{
			os << std::endl;
		}

		os << "      ]" << std::endl;
		os << "    }" << std::endl;
	}
	os << "  ]," << std::endl;
	os << std::endl;

	os << "  \"custom\" : null" << std::endl;

	os << "}" << std::endl;

	os.close();

	return true;
}
Esempio n. 9
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;
}