Beispiel #1
0
int main(int argc, char *argv[])
{

  Histogram<float> h;
  tri::PlyMC<SMesh,Bbox_Txt_MeshProvider<SMesh> > pmc;
  tri::PlyMC<SMesh,Bbox_Txt_MeshProvider<SMesh> >::Parameter &p = pmc.p;
    pmc.MP.loadedRealBBox=false;

  // This line is required to be sure that the decimal separatore is ALWAYS the . and not the ,
  // see the comment at the beginning of the file
#ifdef WIN32
  setlocale(LC_ALL, "En_US");
#else
  std::setlocale(LC_ALL, "En_US");
#endif

  printf(   "\n                  PlyMC "_PLYMC_VER" ("__DATE__")\n"
	    "   Copyright 2002-2008 Visual Computing Group I.S.T.I. C.N.R.\n"
	    "             Paolo Cignoni ([email protected])\n\n");
  //// Parameters
  int i=1;
  if(argc<2) usage();
  while(argv[i][0]=='-')
  {
    switch(argv[i][1])
    {
	case 'o' :  p.basename=argv[i]+2;printf("Setting Basename  to %s\n",MYbasename.c_str());break;
	case 'C' :  pmc.MP.setCacheSize(atoi(argv[i]+2));printf("Setting MaxSize of MeshCache to %i\n",atoi(argv[i]+2)); break;
	case 'c' :  p.NCell   =atoi(argv[i]+2);printf("Setting NCell  to %i\n",p.NCell); break;
	case 'v' :  p.SaveVolumeFlag=true; VolumeBaseName=argv[i]+2; printf("Saving Volume enabled: volume Basename  to %s\n",VolumeBaseName.c_str());break;
	case 'V' :  p.VoxSize =atof(argv[i]+2);printf("Setting VoxSize  to %f; overridden NCell\n",p.VoxSize);p.NCell=0;break;
	case 'w' :  p.WideNum =atoi(argv[i]+2);printf("Setting WideNum  to %i\n",p.WideNum);break;
	case 'W' :  p.WideSize=atof(argv[i]+2);printf("Setting WideSize to %f;overridden WideNum\n",p.WideSize);break;
	case 'L' :  p.SmoothNum =atoi(argv[i]+2);printf("Setting Laplacian SmoothNum to %i\n",p.SmoothNum);break;
	case 'R' :  p.RefillNum =atoi(argv[i]+2);printf("Setting Refilling Num to %i\n",p.RefillNum);break;
	case 'q' :  p.QualitySmoothVox=atof(argv[i]+2);printf("Setting QualitySmoothThr  to %f; \n",p.QualitySmoothVox);break;
    case 'Q' :  p.QualitySmoothAbs=atof(argv[i]+2);printf("Setting QualitySmoothAbsolute to %f; it will override the default %f voxel value\n",p.QualitySmoothAbs,p.QualitySmoothVox);break;
	case 'l' :  p.IntraSmoothFlag=true; printf("Setting Laplacian Smooth after expansion \n");break;
	case 'G' :  p.GeodesicQualityFlag=false; printf("Disabling Geodesic Quality\n");break;
	case 'F' :  p.PLYFileQualityFlag=true; p.GeodesicQualityFlag=false; printf("Enabling PlyFile (and disabling Geodesic) Quality\n");break;
	case 'f' :  p.FillThr=atoi(argv[i]+2);printf("Setting Fill Threshold to %i\n",p.FillThr);break;
	case 'a' :  p.ExpAngleDeg=atoi(argv[i]+2);printf("Setting Expanding Angle Threshold to %f Degree\n",p.ExpAngleDeg);break;
	case 'O' :  p.OffsetThr=atof(argv[i]+2);printf("Setting Offset Threshold to %f \n",p.OffsetThr);p.OffsetFlag=true;break;
	case 's' :
	  p.IDiv[0]=atoi(argv[++i]); p.IDiv[1]=atoi(argv[++i]); p.IDiv[2]=atoi(argv[++i]);
	  p.IPosS[0]=atoi(argv[++i]);p.IPosS[1]=atoi(argv[++i]);p.IPosS[2]=atoi(argv[++i]);
	  p.IPosE[0]=p.IPosS[0]; p.IPosE[1]=p.IPosS[1]; p.IPosE[2]=p.IPosS[2];
	  if((p.IPosS[0]>=p.IDiv[0]) || (p.IPosS[1]>=p.IDiv[1]) || (p.IPosS[2]>=p.IDiv[2]))
	  {
	    printf("the subvolume you have requested is invalid (out of bounds)");
	    exit(-1);
	  }
	  printf("Computing ONLY subvolume [%i,%i,%i] on a %ix%ix%i\n",p.IPosS[0],p.IPosS[1],p.IPosS[2],p.IDiv[0],p.IDiv[1],p.IDiv[2]);
	  break;
	case 'S' :
	  p.IDiv[0]=atoi(argv[++i]);p.IDiv[1]=atoi(argv[++i]);p.IDiv[2]=atoi(argv[++i]);
	  p.IPosS=Point3i(0,0,0);
	  p.IPosE[0]=p.IDiv[0]-1; p.IPosE[1]=p.IDiv[1]-1; p.IPosE[2]=p.IDiv[2]-1;
	  printf("Autocomputing ALL subvolumes on a %ix%ix%i\n",p.IDiv[0],p.IDiv[1],p.IDiv[2]);
	  break;
	case 'K' :
	  p.IDiv[0]=atoi(argv[++i]); p.IDiv[1]=atoi(argv[++i]);p.IDiv[2]=atoi(argv[++i]);
	  p.IPosB[0]=atoi(argv[++i]);p.IPosB[1]=atoi(argv[++i]);p.IPosB[2]=atoi(argv[++i]);
	  p.IPosS=Point3i(0,0,0);
	  p.IPosE[0]=p.IDiv[0]-1; p.IPosE[1]=p.IDiv[1]-1; p.IPosE[2]=p.IDiv[2]-1;
	  if((p.IPosB[0]>=p.IDiv[0]) || (p.IPosB[1]>=p.IDiv[1]) || (p.IPosB[2]>=p.IDiv[2]))
	  {
	    printf("the start subvolume you have requested is invalid (out of bounds)");
	    exit(-1);
	  }
	  printf("Autocomputing ALL subvolumes FROM [%i,%i,%i] on a %ix%ix%i\n",p.IPosB[0],p.IPosB[1],p.IPosB[2],p.IDiv[0],p.IDiv[1],p.IDiv[2]);
	  break;
	case 'X' :
	  p.IDiv[0]=atoi(argv[++i]); p.IDiv[1]=atoi(argv[++i]);p.IDiv[2]=atoi(argv[++i]);
	  p.IPosS[0]=atoi(argv[++i]);p.IPosS[1]=atoi(argv[++i]);p.IPosS[2]=atoi(argv[++i]);
	  p.IPosE[0]=atoi(argv[++i]);p.IPosE[1]=atoi(argv[++i]);p.IPosE[2]=atoi(argv[++i]);
	  // test if the interval is ok
	  int Istart,Iend;
	  Istart = p.IPosS[2] + (p.IPosS[1]*p.IDiv[2]) + (p.IPosS[0]*p.IDiv[2]*p.IDiv[1]);
	  Iend   = p.IPosE[2] + (p.IPosE[1]*p.IDiv[2]) + (p.IPosE[0]*p.IDiv[2]*p.IDiv[1]);
	  if((Iend-Istart)<=0)
	  {
	    printf("the range you have requested is invalid (reversed or empty)");
	    exit(-1);
	  }
	  if((p.IPosS[0]>=p.IDiv[0]) || (p.IPosS[1]>=p.IDiv[1]) || (p.IPosS[2]>=p.IDiv[2]) ||
	     (p.IPosE[0]>=p.IDiv[0]) || (p.IPosE[1]>=p.IDiv[1]) || (p.IPosE[2]>=p.IDiv[2]))
	  {
	    printf("the subvolume you have requested is invalid (out of bounds)");
	    exit(-1);
	  }
	  printf("Autocomputing subvolumes FROM [%i,%i,%i] TO [%i,%i,%i] on a %ix%ix%i\n",p.IPosS[0],p.IPosS[1],p.IPosS[2],p.IPosE[0],p.IPosE[1],p.IPosE[2],p.IDiv[0],p.IDiv[1],p.IDiv[2]);
	  break;
	  //        case 'B' :	p.SafeBorder =atoi(argv[i]+2);printf("Setting SafeBorder among blocks to %i*%i (default 1)\n",p.SafeBorder,Volume<Voxelf>::BLOCKSIDE());break;
	case 'p' :	p.VertSplatFlag =true; printf("Enabling VertexSplatting instead of face rasterization\n");break;
	case 'd' : p.VerboseLevel=atoi(argv[i]+2);printf("Enabling VerboseLevel= %i )\n",p.VerboseLevel);break;
  case 'D' : p.VerboseLevel=1; p.SliceNum=atoi(argv[i]+2);printf("Enabling Debug Volume saving of %i slices (VerboseLevel=1)\n",p.SliceNum);break;
    case 'M' :	p.SimplificationFlag =true; p.SimplificationFlag =false;printf("NOT !!! Enabling PostReconstruction simplification BROKEN\n"); break;
		default : {printf("Error unable to parse option '%s'\n",argv[i]); exit(0);}
    }
    ++i;
  }



  Matrix44f Identity;
  Identity.SetIdentity();
  string alnfile;
  while(i<argc)
  {
    if(strcmp(strrchr(argv[i],'.'),".txt")==0)
      pmc.MP.openTXT(argv[i]);
    else
      pmc.MP.AddSingleMesh(argv[i]);
    ++i;
  }

  if(pmc.MP.size()==0) usage();
  printf("End Parsing\n\n");
  pmc.Process(ProgressBarCallback);

  return 0;
}
Beispiel #2
0
void EditManipulatorsPlugin::UpdateMatrix(MeshModel &model, GLArea * gla, bool applymouseoffset, bool useinputnumber)
{  
  Matrix44f newmatrix;

  Matrix44f old_rotation;  
  Matrix44f old_translation;  
  Matrix44f old_meshcenter;
  Matrix44f old_meshuncenter;

  Point3f new_scale;
  Point3f axis;
  float mouseXoff;
  float mouseYoff;

  Point3f mesh_boxcenter, mesh_origin, mesh_xaxis, mesh_yaxis, mesh_zaxis;
  mesh_boxcenter = model.cm.bbox.Center();
  mesh_origin = original_Transform.GetColumn3(3);
  mesh_xaxis = original_Transform.GetColumn3(0);
  mesh_yaxis = original_Transform.GetColumn3(1);
  mesh_zaxis = original_Transform.GetColumn3(2);

  delta_Transform.SetIdentity();
  newmatrix.SetIdentity();

  if(current_manip == EditManipulatorsPlugin::ManNone)
  {
    model.cm.Tr = original_Transform;
  }
  else
  {

    if(current_manip_mode != EditManipulatorsPlugin::ModNone)  // transform on one axis only
    {

      switch(current_manip_mode)          // which axis is active
      {
        case EditManipulatorsPlugin::ModX:
          axis = Point3f(1.0, 0.0, 0.0);
          break;
        case EditManipulatorsPlugin::ModY:
          axis = Point3f(0.0, 1.0, 0.0);
          break;
        case EditManipulatorsPlugin::ModZ:
          axis = Point3f(0.0, 0.0, 1.0);
          break;
        case EditManipulatorsPlugin::ModXX:
          axis = mesh_xaxis;
          break;
        case EditManipulatorsPlugin::ModYY:
          axis = mesh_yaxis;
          break;
        case EditManipulatorsPlugin::ModZZ:
          axis = mesh_zaxis;
          break;
        default: axis = Point3f(1.0, 1.0, 1.0); // it should never arrive here, anyway
      }

      if(current_manip == EditManipulatorsPlugin::ManMove)
      {
        // mouse offset -> single axis translation
        float xsign = ((screen_xaxis*axis)>0.0)?1.0:-1.0;
        float ysign = ((screen_yaxis*axis)>0.0)?1.0:-1.0;
        mouseXoff = xsign * screen_xaxis.Norm() * (currScreenOffset_X/float(gla->width()));
        mouseYoff = ysign * screen_yaxis.Norm() * (currScreenOffset_Y/float(gla->height()));
        displayOffset = currOffset + mouseXoff + mouseYoff;

        // snapping
        if(isSnapping)
        {
          displayOffset /= snapto; 
          displayOffset = floor(displayOffset+0.5);
          displayOffset *= snapto; 
        }

        if(useinputnumber)
          displayOffset = inputnumber;

        delta_Transform.SetTranslate(axis * displayOffset);  
        newmatrix = delta_Transform * original_Transform;
      }
      else if(current_manip == EditManipulatorsPlugin::ManRotate)
      {
        // mouse offset -> single axis rotation
        mouseXoff = (currScreenOffset_X/float(gla->width()));
        mouseYoff = (currScreenOffset_Y/float(gla->height()));
        displayOffset = currOffset + (360.0 * (mouseXoff + mouseYoff));
        if((displayOffset > 360.0) || (displayOffset < -360.0))
          displayOffset = 360.0;

        // snapping
        if(isSnapping)
        {
          displayOffset = floor(displayOffset+0.5);
        }

        if(useinputnumber)
          displayOffset = inputnumber;

        delta_Transform.SetRotateDeg(displayOffset, axis);

        old_rotation = original_Transform;
        old_rotation.SetColumn(3, Point3f(0.0, 0.0, 0.0));
        old_translation.SetTranslate(original_Transform.GetColumn3(3));
        old_meshcenter.SetTranslate(old_rotation * (-mesh_boxcenter));
        old_meshuncenter.SetTranslate(old_rotation * mesh_boxcenter);

        if(aroundOrigin)
          newmatrix = old_translation * delta_Transform * old_rotation;
        else
          newmatrix = old_translation * old_meshuncenter * delta_Transform * old_meshcenter * old_rotation;
      }
      else if(current_manip == EditManipulatorsPlugin::ManScale)
      {       
        // mouse offset -> single axis scaling
        mouseXoff = (currScreenOffset_X/float(gla->width()));
        mouseYoff = (currScreenOffset_Y/float(gla->height()));
        displayOffset = currOffset + (2.0 * (mouseXoff + mouseYoff));

        // snapping
        if(isSnapping)
        {
          displayOffset /= snapto; 
          displayOffset = floor(displayOffset+0.5);
          displayOffset *= snapto; 
        }

        if(useinputnumber)
          displayOffset = inputnumber;

        new_scale[0] = (axis[0]==0)?1.0:(axis[0] * displayOffset);
        new_scale[1] = (axis[1]==0)?1.0:(axis[1] * displayOffset);
        new_scale[2] = (axis[2]==0)?1.0:(axis[2] * displayOffset);

        delta_Transform.SetScale(new_scale);

        old_rotation = original_Transform;
        old_rotation.SetColumn(3, Point3f(0.0, 0.0, 0.0));
        old_translation.SetTranslate(original_Transform.GetColumn3(3));
        old_meshcenter.SetTranslate(-mesh_boxcenter);
        old_meshuncenter.SetTranslate(mesh_boxcenter);

        if(aroundOrigin)
          newmatrix = old_translation * delta_Transform * old_rotation;
        else
          newmatrix = old_translation * old_meshuncenter * delta_Transform * old_meshcenter * old_rotation;
      }
      else
        newmatrix = original_Transform;  // it should never arrive here, anyway
      
    }
    else   // transform on full space ? on view space ?
    {


      if(current_manip == EditManipulatorsPlugin::ManMove)
      {
        // mouse offset -> viewport translation
        mouseXoff = (currScreenOffset_X/float(gla->width()));
        mouseYoff = (currScreenOffset_Y/float(gla->height()));

        displayOffset_X = currOffset_X + (screen_xaxis[0] * mouseXoff) + (screen_yaxis[0] * mouseYoff);
        displayOffset_Y = currOffset_Y + (screen_xaxis[1] * mouseXoff) + (screen_yaxis[1] * mouseYoff);        
        displayOffset_Z = currOffset_Z + (screen_xaxis[2] * mouseXoff) + (screen_yaxis[2] * mouseYoff);

        // snapping
        if(isSnapping)
        {
          displayOffset_X /= snapto; 
          displayOffset_X = floor(displayOffset_X+0.5);
          displayOffset_X *= snapto; 
          displayOffset_Y /= snapto; 
          displayOffset_Y = floor(displayOffset_Y+0.5);
          displayOffset_Y *= snapto; 
          displayOffset_Z /= snapto; 
          displayOffset_Z = floor(displayOffset_Z+0.5);
          displayOffset_Z *= snapto; 
        }

        delta_Transform.SetTranslate(Point3f(displayOffset_X,displayOffset_Y,displayOffset_Z));  
        newmatrix = delta_Transform * original_Transform;
      }

      if(current_manip == EditManipulatorsPlugin::ManRotate)
      {
        // mouse offset -> viewport rotation
        mouseXoff = (currScreenOffset_X/float(gla->width()));
        mouseYoff = (currScreenOffset_Y/float(gla->height()));
        displayOffset = currOffset + (360.0 * (mouseXoff + mouseYoff));
        if((displayOffset > 360.0) || (displayOffset < -360.0))
          displayOffset = 360.0;

        // snapping
        if(isSnapping)
        {
          displayOffset = floor(displayOffset+0.5);
        }

        if(useinputnumber)
          displayOffset = inputnumber;

        delta_Transform.SetRotateDeg(displayOffset, screen_zaxis);

        old_rotation = original_Transform;
        old_rotation.SetColumn(3, Point3f(0.0, 0.0, 0.0));
        old_translation.SetTranslate(original_Transform.GetColumn3(3));
        old_meshcenter.SetTranslate(-mesh_boxcenter);
        old_meshuncenter.SetTranslate(mesh_boxcenter);

        if(aroundOrigin)
          newmatrix = old_translation * delta_Transform * old_rotation;
        else
          newmatrix = old_translation * old_meshuncenter * delta_Transform * old_meshcenter * old_rotation;
      }

      if(current_manip == EditManipulatorsPlugin::ManScale)
      {
        // mouse offset -> uniform scaling
        mouseXoff = (currScreenOffset_X/float(gla->width()));
        mouseYoff = (-currScreenOffset_Y/float(gla->height()));
        displayOffset = currOffset + (2.0 * (mouseXoff + mouseYoff));

        // snapping
        if(isSnapping)
        {
          displayOffset /= snapto; 
          displayOffset = floor(displayOffset+0.5);
          displayOffset *= snapto; 
        }

        if(useinputnumber)
          displayOffset = inputnumber;

        new_scale[0] = displayOffset;
        new_scale[1] = displayOffset;
        new_scale[2] = displayOffset;

        delta_Transform.SetScale(new_scale);

        old_rotation = original_Transform;
        old_rotation.SetColumn(3, Point3f(0.0, 0.0, 0.0));
        old_translation.SetTranslate(original_Transform.GetColumn3(3));
        old_meshcenter.SetTranslate(-mesh_boxcenter);
        old_meshuncenter.SetTranslate(mesh_boxcenter);

        if(aroundOrigin)
          newmatrix = old_translation * delta_Transform * old_rotation;
        else
          newmatrix = old_translation * old_meshuncenter * delta_Transform * old_meshcenter * old_rotation;
      }

    }
    model.cm.Tr = newmatrix;
  }

  if(applymouseoffset)
  {
    // user finished dragging... accumulation of mouse offset into current offset
    currOffset = displayOffset;
    currOffset_X = displayOffset_X;
    currOffset_Y = displayOffset_Y;
    currOffset_Z = displayOffset_Z;
  }
}
Beispiel #3
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;
}