// given a RichParameterSet get back the alignment parameter  (dual of the buildParemeterSet)
void AlignParameter::buildAlignParameters(RichParameterSet &fps , AlignPair::Param &app)
{
	app.SampleNum=fps.getInt("SampleNum");
  app.MinDistAbs=fps.getFloat("MinDistAbs");
	app.TrgDistAbs=fps.getFloat("TrgDistAbs");
	app.MaxIterNum=fps.getInt("MaxIterNum");
	app.SampleMode= fps.getBool("SampleMode")?AlignPair::Param::SMNormalEqualized  : AlignPair::Param::SMRandom;
  app.ReduceFactorPerc=fps.getFloat("ReduceFactorPerc");
  app.PassHiFilter=fps.getFloat("PassHiFilter");
	app.MatchMode=fps.getBool("MatchMode")? AlignPair::Param::MMRigid : AlignPair::Param::MMClassic;
}
Example #2
0
bool DynamicMeshSubFilter::configurationHasChanged(MeshDocument& md, RichParameterSet& par){
    bool changed = m_seconds != par.getInt("seconds");
    changed |= m_fps != par.getInt("fps");
    changed |= m_iterations != par.getInt("iterations");
    changed |= m_contacts != par.getInt("contacts");
    changed |= m_bounciness != par.getFloat("bounciness");
    changed |= m_gravity != par.getFloat("gravity");
    changed |= m_friction != par.getFloat("friction");

    if(unsigned(md.size()) == m_files.size())
        for(unsigned i = 0; i < m_files.size(); i++)
            changed |= m_files.at(i) != md.getMesh(i)->fileName;
    else
        changed = true;

    m_files.clear();
    for(int i = 0; i < md.size(); i++)
        m_files.push_back(md.getMesh(i)->fileName);

    m_seconds = par.getInt("seconds");
    m_fps = par.getInt("fps");
    m_iterations = par.getInt("iterations");
    m_contacts = par.getInt("contacts");
    m_bounciness = par.getFloat("bounciness");
    m_gravity = par.getFloat("gravity");
    m_friction = par.getFloat("friction");
    return changed;
}
Example #3
0
bool MeshGridPlugin::applyFilter(QAction *algo, MeshDocument &md,
                                 RichParameterSet & par, vcg::CallBackPos *cb)
{

    int cols = par.getInt("numVertX");
    int rows = par.getInt("numVertY");

    float totalw = 1.0;
    float totalh = 1.0;
    int w = cols+1;
    int h = rows+1;
    float wl = 1.0/cols;
    float hl = 1.0/rows;

    qDebug("w %d h %d",w,h);
    if(w <= 0 || h <= 0) {
        return false;
    }

    md.addNewMesh("",QString("%1_%2").arg(rows).arg(cols));
    MeshModel &m=*(md.mm());



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


    {
        // 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)
//      {
//         // qDebug("pos x: %f y: %f",(*vi).P()[0],(*vi).P()[1]);
//        //(*vi).P()[0] = (*vi).P()[0] - (wld * halfw);
//        //(*vi).P()[1] = (*vi).P()[1] - (hld * halfh);
//        //  (*vi).P()[0] = (*vi).P()[0] - totalw/2;
//        //  (*vi).P()[1] = (*vi).P()[1] - totalh/2;
//         // qDebug("after pos x: %f y: %f",(*vi).P()[0],(*vi).P()[1]);
//      }
    }
    // update bounding box, normals
//   Matrix44f rot; rot.SetRotateDeg(180,Point3f(0,1,0));
//   tri::UpdatePosition<CMeshO>::Matrix(m.cm,rot,false);
    tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFace(m.cm);
    tri::UpdateNormal<CMeshO>::NormalizePerFace(m.cm);
    tri::UpdateBounding<CMeshO>::Box(m.cm);

    CMeshO::VertexIterator vi;


    return true;
}
 bool FilterCreateIso::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos * cb)
 {
   md.addNewMesh("",this->filterName(ID(filter)));
   MeshModel &m=*(md.mm());
   if(filter->text() == filterName(FP_CREATEISO) )
   {

     SimpleVolume<SimpleVoxel<Scalarm> > 	volume;

     typedef vcg::tri::TrivialWalker<CMeshO, SimpleVolume<SimpleVoxel<Scalarm> >	> MyWalker;
     typedef vcg::tri::MarchingCubes<CMeshO, MyWalker>	MyMarchingCubes;
     MyWalker walker;

     const int gridSize=par.getInt("Resolution");
     // Simple initialization of the volume with some cool perlin noise
     volume.Init(Point3i(gridSize,gridSize,gridSize), Box3m(Point3m(0,0,0),Point3m(1,1,1)));
     for(int i=0;i<gridSize;i++)
       for(int j=0;j<gridSize;j++)
         for(int k=0;k<gridSize;k++)
           volume.Val(i,j,k)=(j-gridSize/2)*(j-gridSize/2)+(k-gridSize/2)*(k-gridSize/2) + i*gridSize/5*(float)math::Perlin::Noise(i*.2,j*.2,k*.2);

     printf("[MARCHING CUBES] Building mesh...");
     MyMarchingCubes mc(m.cm, walker);
     walker.BuildMesh<MyMarchingCubes>(m.cm, volume, mc, (gridSize*gridSize)/10,cb);
     m.UpdateBoxAndNormals();
   }
   return true;
 }
Example #5
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 #6
0
void U3DIOPlugin::saveParameters(const RichParameterSet &par)
{
        vcg::Point3f from_target_to_camera = vcg::Point3f(par.getPoint3f(QString("position_val")) - par.getPoint3f(QString("target_val")));
	vcg::tri::io::u3dparametersclasses::Movie15Parameters::CameraParameters* sw = _param._campar;
	//vcg::Point3f p = avoidExponentialNotation(sw->_obj_pos,_param._campar->_obj_bbox_diag);
	vcg::Point3f p = sw->_obj_pos;
	_param._campar = new vcg::tri::io::u3dparametersclasses::Movie15Parameters::CameraParameters(
		par.getFloat(QString("fov_val")),0.0f,from_target_to_camera,from_target_to_camera.Norm(),sw->_obj_bbox_diag,p);
	_param.positionQuality = par.getInt(QString("compression_val"));

	delete sw;
}
Example #7
0
// The Real Core Function doing the actual mesh processing.
bool FilterCreate::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos * /*cb*/)
{
    MeshModel &m=(*md.mm());
  switch(ID(filter))	 {
    case CR_TETRAHEDRON :
      vcg::tri::Tetrahedron<CMeshO>(m.cm);
      break;
    case CR_ICOSAHEDRON:
      vcg::tri::Icosahedron<CMeshO>(m.cm);
      break;
    case CR_DODECAHEDRON:
      vcg::tri::Dodecahedron<CMeshO>(m.cm);
			m.updateDataMask(MeshModel::MM_POLYGONAL);
      break;
    case CR_OCTAHEDRON:
      vcg::tri::Octahedron<CMeshO>(m.cm);
      break;
    case CR_SPHERE:
      vcg::tri::Sphere<CMeshO>(m.cm);
      break;
    case CR_BOX:
    {
      float sz=par.getFloat("size");
      vcg::Box3f b(vcg::Point3f(1,1,1)*(sz/2),vcg::Point3f(1,1,1)*(-sz/2));
      vcg::tri::Box<CMeshO>(m.cm,b);
			m.updateDataMask(MeshModel::MM_POLYGONAL);

      break;
    }
    case CR_CONE:
      float r0=par.getFloat("r0");
      float r1=par.getFloat("r1");
      float h=par.getFloat("h");
      int subdiv=par.getInt("subdiv");
      vcg::tri::Cone<CMeshO>(m.cm,r0,r1,h,subdiv);
      break;
   }
 	 vcg::tri::UpdateBounding<CMeshO>::Box(m.cm);
   vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFaceNormalized(m.cm);
	return true;
}
Example #8
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 #9
0
bool CleanFilter::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos * cb)
{
    MeshModel &m=*(md.mm());
    switch(ID(filter))
  {
    case FP_BALL_PIVOTING:
    {
      float Radius = par.getAbsPerc("BallRadius");
      float Clustering = par.getFloat("Clustering") / 100.0f;
      float CreaseThr = math::ToRad(par.getFloat("CreaseThr"));
      bool DeleteFaces = par.getBool("DeleteFaces");
      if(DeleteFaces) {
        m.cm.fn=0;
        m.cm.face.resize(0);
      }
      m.updateDataMask(MeshModel::MM_VERTFACETOPO);
      int startingFn=m.cm.fn;
      tri::BallPivoting<CMeshO> pivot(m.cm, Radius, Clustering, CreaseThr);
      // the main processing
      pivot.BuildMesh(cb);
      m.clearDataMask(MeshModel::MM_FACEFACETOPO);
      Log("Reconstructed surface. Added %i faces",m.cm.fn-startingFn);
    } break;
    case FP_REMOVE_ISOLATED_DIAMETER:
    {
      float minCC= par.getAbsPerc("MinComponentDiag");
      std::pair<int,int> delInfo= tri::Clean<CMeshO>::RemoveSmallConnectedComponentsDiameter(m.cm,minCC);
      Log("Removed %2 connected components out of %1", delInfo.second, delInfo.first);
    }break;
    case FP_REMOVE_ISOLATED_COMPLEXITY:
	  {
      float minCC= par.getInt("MinComponentSize");		
      std::pair<int,int> delInfo=tri::Clean<CMeshO>::RemoveSmallConnectedComponentsSize(m.cm,minCC);
			Log("Removed %i connected components out of %i", delInfo.second, delInfo.first); 		
	  }break;
    case FP_REMOVE_WRT_Q:
	  {
			int deletedFN=0;
			int deletedVN=0;
      float val=par.getAbsPerc("MaxQualityThr");		
      CMeshO::VertexIterator vi;
      for(vi=m.cm.vert.begin();vi!=m.cm.vert.end();++vi)
						if(!(*vi).IsD() && (*vi).Q()<val)
						{
							tri::Allocator<CMeshO>::DeleteVertex(m.cm, *vi);
							deletedVN++;
						}
        
      CMeshO::FaceIterator fi;
      for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
				 if((*fi).V(0)->IsD() ||(*fi).V(1)->IsD() ||(*fi).V(2)->IsD() ) 
						 {
								tri::Allocator<CMeshO>::DeleteFace(m.cm, *fi);
								deletedFN++;
						 }
								 
	  m.clearDataMask(MeshModel::MM_FACEFACETOPO);
			Log("Deleted %i vertices and %i faces with a quality lower than %f", deletedVN,deletedFN,val); 		

	  }break;

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

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

      int total = tri::Clean<CMeshO>::SplitNonManifoldVertex(m.cm,threshold);
      Log("Successfully split %d non manifold vertices faces", total);
  }
  break;
  case FP_SNAP_MISMATCHED_BORDER :
    {
      float threshold = par.getFloat("EdgeDistRatio");
      int total = SnapVertexBorder(m.cm, threshold,cb);
      Log("Successfully Splitted %d faces to snap", total);
    } break;
	
  case FP_COMPACT_FACE :
	  {
		  vcg::tri::Allocator<CMeshO>::CompactFaceVector(m.cm);
		  break;
	  }
  case FP_COMPACT_VERT :
	  {
		  vcg::tri::Allocator<CMeshO>::CompactVertexVector(m.cm);
		  break;
	  }
  default : assert(0); // unknown filter;
	}
	return true;
}
Example #10
0
bool ExtraMeshColorizePlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb){
 MeshModel &m=*(md.mm());
 switch(ID(filter)) {
  case CP_SATURATE_QUALITY:{
     m.updateDataMask(MeshModel::MM_VERTFACETOPO);
     tri::UpdateQuality<CMeshO>::VertexSaturate(m.cm, par.getFloat("gradientThr"));
     if(par.getBool("updateColor"))
     {
       Histogramf H;
       tri::Stat<CMeshO>::ComputePerVertexQualityHistogram(m.cm,H);
       m.updateDataMask(MeshModel::MM_VERTCOLOR);
       tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,H.Percentile(0.1f),H.Percentile(0.9f));
     }
     Log("Saturated ");
   }
break;
  case CP_MAP_VQUALITY_INTO_COLOR:
     m.updateDataMask(MeshModel::MM_VERTCOLOR);
  case CP_CLAMP_QUALITY:
      {
      float RangeMin = par.getFloat("minVal");	
      float RangeMax = par.getFloat("maxVal");		
			bool usePerc = par.getDynamicFloat("perc")>0;
			
			Histogramf H;
			tri::Stat<CMeshO>::ComputePerVertexQualityHistogram(m.cm,H);

			float PercLo = H.Percentile(par.getDynamicFloat("perc")/100.f);
			float PercHi = H.Percentile(1.0-par.getDynamicFloat("perc")/100.f);
			
			if(par.getBool("zeroSym"))
				{
					RangeMin = min(RangeMin, -math::Abs(RangeMax));
					RangeMax = max(math::Abs(RangeMin), RangeMax);
					PercLo = min(PercLo, -math::Abs(PercHi));
					PercHi = max(math::Abs(PercLo), PercHi);
				}

      if(usePerc)
      {
        if(ID(filter)==CP_CLAMP_QUALITY) tri::UpdateQuality<CMeshO>::VertexClamp(m.cm,PercLo,PercHi);
                                    else tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,PercLo,PercHi);
        Log("Quality Range: %f %f; Used (%f %f) percentile (%f %f) ",H.MinV(),H.MaxV(),PercLo,PercHi,par.getDynamicFloat("perc"),100-par.getDynamicFloat("perc"));
      } else {
        if(ID(filter)==CP_CLAMP_QUALITY) tri::UpdateQuality<CMeshO>::VertexClamp(m.cm,RangeMin,RangeMax);
                                    else tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,RangeMin,RangeMax);
        Log("Quality Range: %f %f; Used (%f %f)",H.MinV(),H.MaxV(),RangeMin,RangeMax);
      }
      break;
    }
   case CP_MAP_FQUALITY_INTO_COLOR: {
       m.updateDataMask(MeshModel::MM_FACECOLOR);
       float RangeMin = par.getFloat("minVal");
       float RangeMax = par.getFloat("maxVal");
       float perc = par.getDynamicFloat("perc");

       Histogramf H;
       tri::Stat<CMeshO>::ComputePerFaceQualityHistogram(m.cm,H);
       float PercLo = H.Percentile(perc/100.f);
       float PercHi = H.Percentile(1.0-perc/100.f);

       // Make the range and percentile symmetric w.r.t. zero, so that
       // the value zero is always colored in yellow
       if(par.getBool("zeroSym")){
         RangeMin = min(RangeMin, -math::Abs(RangeMax));
         RangeMax = max(math::Abs(RangeMin), RangeMax);
         PercLo = min(PercLo, -math::Abs(PercHi));
         PercHi = max(math::Abs(PercLo), PercHi);
       }

       tri::UpdateColor<CMeshO>::FaceQualityRamp(m.cm,PercLo,PercHi);
       Log("Quality Range: %f %f; Used (%f %f) percentile (%f %f) ",
           H.MinV(), H.MaxV(), PercLo, PercHi, perc, 100-perc);
       break;
   }

  case CP_DISCRETE_CURVATURE:
    {
      m.updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTCURV);
      m.updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY);
      tri::UpdateFlags<CMeshO>::FaceBorderFromFF(m.cm);

      if ( tri::Clean<CMeshO>::CountNonManifoldEdgeFF(m.cm) > 0) {
				errorMessage = "Mesh has some not 2-manifold faces, Curvature computation requires manifoldness"; // text
				return false; // can't continue, mesh can't be processed
			}
			
			int delvert=tri::Clean<CMeshO>::RemoveUnreferencedVertex(m.cm);
			if(delvert) Log("Pre-Curvature Cleaning: Removed %d unreferenced vertices",delvert);
			tri::Allocator<CMeshO>::CompactVertexVector(m.cm);
			tri::UpdateCurvature<CMeshO>::MeanAndGaussian(m.cm);
      int curvType = par.getEnum("CurvatureType");
			
			switch(curvType){ 
          case 0: tri::UpdateQuality<CMeshO>::VertexFromMeanCurvature(m.cm);        Log( "Computed Mean Curvature");      break;
			    case 1: tri::UpdateQuality<CMeshO>::VertexFromGaussianCurvature(m.cm);    Log( "Computed Gaussian Curvature"); break;
          case 2: tri::UpdateQuality<CMeshO>::VertexFromRMSCurvature(m.cm);         Log( "Computed RMS Curvature"); break;
          case 3: tri::UpdateQuality<CMeshO>::VertexFromAbsoluteCurvature(m.cm);    Log( "Computed ABS Curvature"); break;
					default : assert(0);
      }      
      
      Histogramf H;
      tri::Stat<CMeshO>::ComputePerVertexQualityHistogram(m.cm,H);
      tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,H.Percentile(0.1f),H.Percentile(0.9f));
      Log( "Curvature Range: %f %f (Used 90 percentile %f %f) ",H.MinV(),H.MaxV(),H.Percentile(0.1f),H.Percentile(0.9f));
    break;
    }  
   case CP_TRIANGLE_QUALITY:
   {
     m.updateDataMask(MeshModel::MM_FACECOLOR | MeshModel::MM_FACEQUALITY);
     CMeshO::FaceIterator fi;
     Distribution<float> distrib;
     float minV = 0;
     float maxV = 1.0;
     int metric = par.getEnum("Metric");
     if(metric ==4 || metric ==5 )
     {
       if(!m.hasDataMask(MeshModel::MM_VERTTEXCOORD) && !m.hasDataMask(MeshModel::MM_WEDGTEXCOORD))
       {
         this->errorMessage = "This metric need Texture Coordinate";
         return false;
       }
     }
     switch(metric){

       case 0: { //area / max edge
         minV = 0;
         maxV = sqrt(3.0f)/2.0f;
         for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
             (*fi).Q() = vcg::Quality((*fi).P(0), (*fi).P(1),(*fi).P(2));
       } break;

       case 1: { //inradius / circumradius
         for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
             (*fi).Q() = vcg::QualityRadii((*fi).P(0), (*fi).P(1), (*fi).P(2));
       } break;

       case 2: { //mean ratio
         for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
             (*fi).Q() = vcg::QualityMeanRatio((*fi).P(0), (*fi).P(1), (*fi).P(2));
       } break;

       case 3: { // AREA
         for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
           (*fi).Q() = vcg::DoubleArea((*fi))*0.5f;
         tri::Stat<CMeshO>::ComputePerFaceQualityMinMax(m.cm,minV,maxV);
       } break;

       case 4: { //TEXTURE Angle Distortion
         if(m.hasDataMask(MeshModel::MM_WEDGTEXCOORD))
         {
           for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
             (*fi).Q() = Distortion<CMeshO,true>::AngleDistortion(&*fi);
         } else {
           for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
             (*fi).Q() = Distortion<CMeshO,false>::AngleDistortion(&*fi);
         }
         tri::Stat<CMeshO>::ComputePerFaceQualityDistribution(m.cm,distrib);
         minV = distrib.Percentile(0.05);
         maxV = distrib.Percentile(0.95);
       } break;

       case 5: { //TEXTURE Area Distortion
         float areaScaleVal, edgeScaleVal;
         if(m.hasDataMask(MeshModel::MM_WEDGTEXCOORD))
         {
           Distortion<CMeshO,true>::MeshScalingFactor(m.cm, areaScaleVal,edgeScaleVal);
           for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
             (*fi).Q() = Distortion<CMeshO,true>::AreaDistortion(&*fi,areaScaleVal);
         } else {
           Distortion<CMeshO,false>::MeshScalingFactor(m.cm, areaScaleVal,edgeScaleVal);
           for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
             (*fi).Q() = Distortion<CMeshO,false>::AreaDistortion(&*fi,areaScaleVal);

         }
         tri::Stat<CMeshO>::ComputePerFaceQualityDistribution(m.cm,distrib);
         minV = distrib.Percentile(0.05);
         maxV = distrib.Percentile(0.95);
       } break;

       default: assert(0);
     }
     tri::UpdateColor<CMeshO>::FaceQualityRamp(m.cm,minV,maxV,false);
     break;
   }


  case CP_RANDOM_CONNECTED_COMPONENT:
   m.updateDataMask(MeshModel::MM_FACEFACETOPO);
   m.updateDataMask(MeshModel::MM_FACEMARK | MeshModel::MM_FACECOLOR);
   vcg::tri::UpdateColor<CMeshO>::FaceRandomConnectedComponent(m.cm);
   break;

 case CP_RANDOM_FACE:
     m.updateDataMask(MeshModel::MM_FACEFACETOPO);
     m.updateDataMask(MeshModel::MM_FACEMARK | MeshModel::MM_FACECOLOR);
    vcg::tri::UpdateColor<CMeshO>::MultiFaceRandom(m.cm);
    break;

  case CP_VERTEX_SMOOTH:
		{
		int iteration = par.getInt("iteration");
		tri::Smooth<CMeshO>::VertexColorLaplacian(m.cm,iteration,false,cb);
		}
		break;
  case CP_FACE_SMOOTH:
		{
    m.updateDataMask(MeshModel::MM_FACEFACETOPO);
		int iteration = par.getInt("iteration");
		tri::Smooth<CMeshO>::FaceColorLaplacian(m.cm,iteration,false,cb);
		}
		break;
  case CP_FACE_TO_VERTEX:
     m.updateDataMask(MeshModel::MM_VERTCOLOR);
     tri::UpdateColor<CMeshO>::VertexFromFace(m.cm);
		break;
	 case CP_VERTEX_TO_FACE:
     m.updateDataMask(MeshModel::MM_FACECOLOR);
     tri::UpdateColor<CMeshO>::FaceFromVertex(m.cm);
		 break;
  case CP_TEXTURE_TO_VERTEX:
		{
      m.updateDataMask(MeshModel::MM_VERTCOLOR);
      if(!HasPerWedgeTexCoord(m.cm)) break;
			CMeshO::FaceIterator fi; 
			QImage tex(m.cm.textures[0].c_str());
			for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) 
			{
				for (int i=0; i<3; i++)
				{
          // note the trick for getting only the fractional part of the uv with the correct wrapping (e.g. 1.5 -> 0.5 and -0.3 -> 0.7)
          vcg::Point2f newcoord((*fi).WT(i).P().X()-floor((*fi).WT(i).P().X()),(*fi).WT(i).P().Y()-floor((*fi).WT(i).P().Y()));
          QRgb val = tex.pixel(newcoord[0]*tex.width(),(1-newcoord[1])*tex.height()-1);
					(*fi).V(i)->C().SetRGB(qRed(val),qGreen(val),qBlue(val));
				}
			}
	    }
		
		break;
 }
	return true;
}
Example #11
0
// Core Function doing the actual mesh processing.
bool FilterMeasurePlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos */*cb*/)
{
	CMeshO::FaceIterator fi;

	switch(ID(filter))
  {
		case FP_MEASURE_TOPO : 
			{
				CMeshO &m=md.mm()->cm;	
				md.mm()->updateDataMask(MeshModel::MM_FACEFACETOPO);				
				md.mm()->updateDataMask(MeshModel::MM_VERTFACETOPO);				
        tri::Allocator<CMeshO>::CompactFaceVector(m);
        tri::Allocator<CMeshO>::CompactVertexVector(m);
        tri::UpdateTopology<CMeshO>::FaceFace(m);
				tri::UpdateTopology<CMeshO>::VertexFace(m);
				
        int edgeManif = tri::Clean<CMeshO>::CountNonManifoldEdgeFF(m,true);
        int faceEdgeManif = tri::UpdateSelection<CMeshO>::CountFace(m);
        tri::UpdateSelection<CMeshO>::ClearVertex(m);
        tri::UpdateSelection<CMeshO>::ClearFace(m);

        int vertManif = tri::Clean<CMeshO>::CountNonManifoldVertexFF(m,true);
        tri::UpdateSelection<CMeshO>::FaceFromVertexLoose(m);
        int faceVertManif = tri::UpdateSelection<CMeshO>::CountFace(m);
				int edgeNum=0,borderNum=0;
				tri::Clean<CMeshO>::CountEdges(m, edgeNum, borderNum);
				int holeNum;
				Log("V: %6i E: %6i F:%6i",m.vn,edgeNum,m.fn);
				Log("Boundary Edges %i",borderNum); 
				
        int connectedComponentsNum = tri::Clean<CMeshO>::CountConnectedComponents(m);
				Log("Mesh is composed by %i connected component(s)",connectedComponentsNum);
				
        if(edgeManif==0 && vertManif==0)
					Log("Mesh has is two-manifold ");
					
        if(edgeManif!=0) Log("Mesh has %i non two manifold edges and %i faces are incident on these edges\n",edgeManif,faceEdgeManif);

        if(vertManif!=0) Log("Mesh has %i non two manifold vertexes and %i faces are incident on these vertices\n",vertManif,faceVertManif);
				
				// For Manifold meshes compute some other stuff
				if(vertManif && edgeManif)
				{
					holeNum = tri::Clean<CMeshO>::CountHoles(m);
					Log("Mesh has %i holes",holeNum);
					
					int genus = tri::Clean<CMeshO>::MeshGenus(m, holeNum, connectedComponentsNum, edgeNum);
					Log("Genus is %i",genus);
				}
			}
		break;
		/************************************************************/ 
		case FP_MEASURE_TOPO_QUAD : 
			{
					CMeshO &m=md.mm()->cm;	
					md.mm()->updateDataMask(MeshModel::MM_FACEFACETOPO);				
					md.mm()->updateDataMask(MeshModel::MM_FACEQUALITY);				

					if (! tri::Clean<CMeshO>::IsFFAdjacencyConsistent(m)){
											Log("Error: mesh has a not consistent FF adjacency");
											return false;
										}
					if (! tri::Clean<CMeshO>::HasConsistentPerFaceFauxFlag(m)) {
											Log("Warning: mesh has a not consistent FauxEdge tagging");
											return false;
										}
					if (! tri::Clean<CMeshO>::IsBitTriQuadOnly(m)) {
											Log("Warning: IsBitTriQuadOnly");
											//return false;
										}
					//										if (! tri::Clean<CMeshO>::HasConsistentEdges(m)) lastErrorDetected |= NOT_EDGES_CONST;
					int nsinglets= tri::BitQuadOptimization< tri::BitQuad<CMeshO> >::MarkSinglets(m);
					if ( nsinglets  )  {
											Log("Warning: MarkSinglets");
											//return false;
										}
					
					if (! tri::BitQuad<CMeshO>::HasConsistentValencyFlag(m))
					 {
											Log("Warning: HasConsistentValencyFlag");
											//return false;
										}
				
			int nQuads = tri::Clean<CMeshO>::CountBitQuads(m);
			int nTris = tri::Clean<CMeshO>::CountBitTris(m);
			int nPolys = tri::Clean<CMeshO>::CountBitPolygons(m);
			
			Log("Mesh has %i tri %i quad and %i polig",nTris,nQuads,nPolys);

			}
			break;
		/************************************************************/ 
		case FP_MEASURE_GEOM : 
			{
				CMeshO &m=md.mm()->cm;
				tri::Inertia<CMeshO> I;
				I.Compute(m);
				
				tri::UpdateBounding<CMeshO>::Box(m); 
				float Area = tri::Stat<CMeshO>::ComputeMeshArea(m);
				float Volume = I.Mass(); 
				Log("Mesh Bounding Box Size %f %f %f", m.bbox.DimX(), m.bbox.DimY(), m.bbox.DimZ());			
				Log("Mesh Bounding Box Diag %f ", m.bbox.Diag());			
				Log("Mesh Volume  is %f", Volume);			
				Log("Center of Mass  is %f %f %f", I.CenterOfMass()[0], I.CenterOfMass()[1], I.CenterOfMass()[2]);		
				
				
				Matrix33f IT;
				I.InertiaTensor(IT);
				Log("Inertia Tensor is :");		
        Log("    | %9.6f  %9.6f  %9.6f |",IT[0][0],IT[0][1],IT[0][2]);
        Log("    | %9.6f  %9.6f  %9.6f |",IT[1][0],IT[1][1],IT[1][2]);
        Log("    | %9.6f  %9.6f  %9.6f |",IT[2][0],IT[2][1],IT[2][2]);
				
				Log("Mesh Surface is %f", Area);
				
        Matrix44f PCA;
        Point4f pcav;
        I.InertiaTensorEigen(PCA,pcav);
        Log("Principal axes are :");
        Log("    | %9.6f  %9.6f  %9.6f |",PCA[0][0],PCA[0][1],PCA[0][2]);
        Log("    | %9.6f  %9.6f  %9.6f |",PCA[1][0],PCA[1][1],PCA[1][2]);
        Log("    | %9.6f  %9.6f  %9.6f |",PCA[2][0],PCA[2][1],PCA[2][2]);

       // Point3f ax0(PCA[0][0],PCA[0][1],PCA[0][2]);
       // Point3f ax1(PCA[1][0],PCA[1][1],PCA[1][2]);
       // Point3f ax2(PCA[2][0],PCA[2][1],PCA[2][2]);

       // Log("ax0*ax1 %f (len ax0 %f) ",ax0*ax1, Norm(ax0));
       // Log("ax1*ax2 %f (len ax1 %f) ",ax1*ax2, Norm(ax1));
       // Log("ax0*ax2 %f (len ax2 %f) ",ax0*ax2, Norm(ax2));

        Log("axis momenta are :");
        Log("    | %9.6f  %9.6f  %9.6f |",pcav[0],pcav[1],pcav[2]);

			}
		break;
        /************************************************************/
        case FP_MEASURE_VERTEX_QUALITY_DISTRIBUTION :
  case FP_MEASURE_FACE_QUALITY_DISTRIBUTION :
			{
				CMeshO &m=md.mm()->cm;
				Distribution<float> DD;
        if(ID(filter)==FP_MEASURE_VERTEX_QUALITY_DISTRIBUTION)
          tri::Stat<CMeshO>::ComputePerVertexQualityDistribution(m, DD, false);
        else
          tri::Stat<CMeshO>::ComputePerFaceQualityDistribution(m, DD, false);
				
				Log("   Min %f Max %f",DD.Min(),DD.Max());		
				Log("   Avg %f Med %f",DD.Avg(),DD.Percentile(0.5f));		
				Log("   StdDev		%f",DD.StandardDeviation());		
				Log("   Variance  %f",DD.Variance());						
			}
		break;

		case FP_MEASURE_GAUSSCURV : 
			{
				CMeshO &m=md.mm()->cm;
				SimpleTempData<CMeshO::VertContainer, float> TDArea(m.vert,0.0f);
				SimpleTempData<CMeshO::VertContainer, float> TDAngleSum(m.vert,0);

				tri::UpdateQuality<CMeshO>::VertexConstant(m,0);
				float angle[3];
				CMeshO::FaceIterator fi;
				for(fi=m.face.begin(); fi!= m.face.end(); ++fi)
					{
						angle[0] = math::Abs(Angle(	(*fi).P(1)-(*fi).P(0),(*fi).P(2)-(*fi).P(0) ));
						angle[1] = math::Abs(Angle(	(*fi).P(0)-(*fi).P(1),(*fi).P(2)-(*fi).P(1) ));
						angle[2] = M_PI-(angle[0]+angle[1]);

						float area= DoubleArea(*fi)/6.0f;
							for(int i=0;i<3;++i)
							{
								TDArea[(*fi).V(i)]+=area;
								TDAngleSum[(*fi).V(i)]+=angle[i];
							}
					}
				CMeshO::VertexIterator vi;
				float totalSum=0;
				for(vi=m.vert.begin(); vi!= m.vert.end(); ++vi)
					{
						(*vi).Q() = (2.0*M_PI-TDAngleSum[vi]);//*TDArea[vi];
						//if((*vi).IsS()) 
						totalSum += (*vi).Q(); 
					}
				Log("integrated is %f (%f*pi)", totalSum,totalSum/M_PI);												
			} break;
  case FP_MEASURE_VERTEX_QUALITY_HISTOGRAM:
  case FP_MEASURE_FACE_QUALITY_HISTOGRAM:
            {
            CMeshO &m=md.mm()->cm;
            float RangeMin = par.getFloat("minVal");
            float RangeMax = par.getFloat("maxVal");
            int binNum = par.getInt("binNum");


            Histogramf H;
            H.SetRange(RangeMin,RangeMax,binNum);
            if(ID(filter)==FP_MEASURE_VERTEX_QUALITY_DISTRIBUTION)
            {
              for(CMeshO::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
                if(!(*vi).IsD())
                {
                assert(!math::IsNAN((*vi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)");
                H.Add((*vi).Q());
              }
            }else{
              for(CMeshO::FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
                if(!(*fi).IsD())
                {
                assert(!math::IsNAN((*fi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)");
                H.Add((*fi).Q());
              }
            }
            Log("(         -inf..%15.7f) : %i",RangeMin,H.BinCountInd(0));
            for(int i=1;i<=binNum;++i)
              Log("[%15.7f..%15.7f) : %i",H.BinLowerBound(i),H.BinUpperBound(i),H.BinCountInd(i));

            Log("[%15.7f..             +inf) : %i",RangeMax,H.BinCountInd(binNum+1));
        } break;

          default: assert(0);
  }
	return true;
}
Example #12
0
//read source files and write to destination file
//if it's found the attribute name with value "dummy", the following geometry statement
//are replaced with a current mesh conversion
bool IORenderman::makeScene(MeshModel* m,
									   QStringList* textureList,
									   const RichParameterSet &par,
                     QFileInfo* templateFile,
									   QString destDirString,
									   QStringList* shaderDirs,
									   QStringList* textureDirs,
									   QStringList* proceduralDirs,
									   QStringList* imagesRendered)
{
  
  //rib file structure
  RibFileStack files(templateFile->absolutePath()); //constructor
	//open file and stream
  if(!files.pushFile(templateFile->absoluteFilePath())) {
		this->errorMessage = "Template path is wrong: " + templateFile->absoluteFilePath();
		return false;
	}
	
	//output file
	FILE* fout;
	fout = fopen(qPrintable(destDirString + QDir::separator() + mainFileName()),"wb");
	if(fout==NULL)	{
    this->errorMessage = "Impossible to create file: " + destDirString + QDir::separator() + mainFileName();
    return false;
	}
	qDebug("Starting to write rib file into %s",qPrintable(destDirString + QDir::separator() + mainFileName()));
	
	FILE* fmain = fout; //if change the output file, the main is saved here
  convertedGeometry = false; //if the mesh is already converted
	int currentFrame = 0; //frame counter
	
  bool stop = false;
	bool currentDisplayTypeIsFile = false;
	bool anyOtherDisplayType = false;
	numberOfDummies = 0; //the dummy object could be than one (e.g. for ambient occlusion passes)
	QString newFormat = "Format " + 
						QString::number(par.getInt("FormatX")) + " " +
						QString::number(par.getInt("FormatY")) + " " +
						QString::number(par.getFloat("PixelAspectRatio"));
  numOfWorldBegin = 0; //the number of world begin statement found (for progress bar)
	numOfObject = 0;
  bool foundDummy = false;
  bool solidBegin = false; //true only if define a dummy object
	bool writeLine = true; //true if the line has to be write to final file
  resetGraphicsState(); //transformation matrix, bound, surface shader
  QQueue<Procedure> procedures = QQueue<Procedure>(); //every time it's found a procedural call it's stored here
	
  //reading cycle
	while(files.hasNext() && !stop) {
		if(!solidBegin)
      writeLine = true;
    int statementType = 0; //type of statement
		QString line = files.nextStatement(&statementType); //current line
    
    switch(statementType) {
      //declare other directory for the template 
			case ribParser::OPTION: {
				QStringList token = ribParser::splitStatement(&line);
				if(token[2] == "searchpath") {
					int type = 0;
					QStringList dirList = readSearchPath(&token,&type);
					switch(type) {
						case IORenderman::ARCHIVE:
							files.addSubDirs(dirList);
							break;
						case IORenderman::SHADER:
							*shaderDirs = dirList;
							break;
						case IORenderman::TEXTURE:
							*textureDirs = dirList;
							break;
						case IORenderman::PROCEDURAL:
							files.addSubDirs(dirList);
							*proceduralDirs = dirList;					
							break;
						case IORenderman::ERR:
							//ignore: maybe an error or another searchpath type (not in RISpec3.2)
							break;
					}
				}
				break;
			}
      //make a map (create the path if needed)
			case ribParser::MAKE:
			case ribParser::MAKECUBEFACEENVIRONMENT:
			{
				QStringList token = ribParser::splitStatement(&line);				
				QString path = token[2]; //for MakeTexture, MakeShadow, MakeLatLongEnvironment
				if(statementType == ribParser::MAKECUBEFACEENVIRONMENT)
					path = token[7];
				path = QFileInfo(path).path();
				//qDebug("check dir! line: %s\npath: %s",qPrintable(line),qPrintable(path));
				checkDir(&destDirString,&path);
				break;
			}
      //begin a new frame
      case ribParser::FRAMEBEGIN:
			{
				QStringList token = ribParser::splitStatement(&line);				
        bool isNum;
        int i = token[1].toInt(&isNum);
				if(isNum)
          currentFrame = i;
				break;
			}
      //set output type (create the path if needed)
      case ribParser::DISPLAY: 
			{
				//if output is not a file the format must be the same!! framebuffer is ignored and commented
				QStringList token = ribParser::splitStatement(&line);							
				//create the path if needed
				QString path = token[2];
        if(path.startsWith('+.'))
				  path = path.mid(2,path.size());
				path = QFileInfo(path).path();
				//qDebug("check dir! line: %s\npath: %s",qPrintable(line),qPrintable(path));
				checkDir(&destDirString,&path);

				//if there's more "Display" statement with one that's "file" is not considered a final image
				if(token[5] != "framebuffer")
					if (!anyOtherDisplayType && token[5] == "file") {
						currentDisplayTypeIsFile = true;
						QString img = token[2];
						if(img.startsWith('+'))
							img = img.mid(1,img.size());
						*imagesRendered << img;
					}
					else
						anyOtherDisplayType = true;
				//else
					//line = "#" + line; //if there's a framebuffer will be open pqsl automatically									 
				break;
			}
      case ribParser::SCREENWINDOW:
      {
        writeLine = false;
        break;
      }
      //a new world description (reset graphics state)
			case ribParser::WORLDBEGIN:
			{
        //make the conversion of texture mesh before the first WorldBegin statement
        if(numOfWorldBegin == 0 && !textureList->empty() && (m->cm.HasPerWedgeTexCoord() || m->cHasPerVertexTexCoord(m))) {
          QString textureName = QFileInfo(textureList->first()).completeBaseName();
          fprintf(fout,"MakeTexture \"%s.tiff\" \"%s.tx\" \"periodic\" \"periodic\" \"box\" 1 1\n", qPrintable(textureName),qPrintable(textureName));
        }
  
				numOfWorldBegin++;
				//if there's another type of display the format is not change
				if(!anyOtherDisplayType && currentDisplayTypeIsFile) {
					fprintf(fout,"%s\n", qPrintable(newFormat));
				}
				currentDisplayTypeIsFile = false;
				anyOtherDisplayType = false;
				//is right?yes,because before the next WorldBegin will there be a new Display statement
        resetGraphicsState(); //reset the graphics state
				break;
			}
      //set transform in graphics state
      case ribParser::TRANSFORM:
			{
        transfMatrixStack.pop();
        transfMatrixStack.push(getMatrix(&line));
				break;
      }
      //set surface in graphics state
      case ribParser::SURFACE: 
			{
				//the surface shader remain the same of template
				surfaceShaderStack.pop();
        surfaceShaderStack.push(line);
				break;
			}
      //set bound in graphics state
      case ribParser::BOUND: 
			{
				//take the transformation bound
				QStringList token = ribParser::splitStatement(&line);
				int index = 1;
				if(token[index] == "[")
					index++;
				for(int i=0; i<6; i++) {
					bool isNumber;
					float number = token[index+i].toFloat(&isNumber);
					if(isNumber)
						objectBound[i] = number;
				}
				break;
			}
      //looking for a dummy
      case ribParser::ATTRIBUTE: 
			{
				QStringList token = ribParser::splitStatement(&line);				
				//RISpec3.2 not specify what and how many attributes are there in renderman
				//we take care of name only
				if(token[2] == "identifier") {
					//Attribute "identifier" "string name" [ "object name" ]
					if(token[5] == "string name" || token[5] == "name") {
						int index = 7;
						if(token[index] == "[")
							index++;
						if(token[index] == "\"")
							index++;
						if(token[index].trimmed().toLower() == "dummy") {//found a dummy object?
							foundDummy = true;
						}
					}
				}
				break;
			}
      //the begin of a set of statement to define a solid
      case ribParser::SOLIDBEGIN: {
        if(foundDummy) {
          solidBegin = true;
          writeLine = false;
        }
      }
      //the end of solid definition
      case ribParser::SOLIDEND: {
        if(solidBegin) { //if and only if foundDummy is true
          QString filename = convertObject(currentFrame, destDirString, m, par, textureList);
          qDebug("dummy conversion, filename: %s",qPrintable(filename));
				  if(filename == "") { //error in parseObject
            fclose(fmain);
            return false;
          }
				  fprintf(fout,"ReadArchive \"%s\"\n",qPrintable(filename));
          
          solidBegin = false;
          foundDummy = false;
        }
        //reset bound (and surface?)
        resetBound();
        break;
      }
      //there's a geometric statement...if there was a dummy too, replace geometry
      case ribParser::GEOMETRIC: {
        if(foundDummy) {
          QString filename = convertObject(currentFrame, destDirString, m, par, textureList);
          qDebug("dummy conversion, filename: %s",qPrintable(filename));
				  if(filename == "") { //error in parseObject
            fclose(fmain);
            return false;
          }
				  fprintf(fout,"ReadArchive \"%s\"\n",qPrintable(filename));
          
          writeLine = false;
          foundDummy = false;
        }
        //reset bound (and surface?)
        resetBound();
        break;
      }
      //add a new graphics state "level"
      case ribParser::ATTRIBUTEBEGIN: 
			{
        transfMatrixStack.push(transfMatrixStack.top());
        surfaceShaderStack.push(surfaceShaderStack.top());
        break;
			}
      //remove a "level" to graphics state stack
      case ribParser::ATTRIBUTEEND:
      {
        transfMatrixStack.pop();
        surfaceShaderStack.pop();
        break;
      }
      //a procedural statement: managed at the end of cycle
      case ribParser::PROCEDURAL: 
      {
        //manage only dealayedreadarchive
        //0: Procedural 
        //1: " 
        //2: DelayedReadArchive
        //3: " 
        //4: [ 
        //5: " 
        //6: filename 
        //7: " 
        //8: ]
        //9: [
        //10-15: bound element
        //11: ]
        QStringList token = ribParser::splitStatement(&line);
        if(token[2] == "DelayedReadArchive") {
          qDebug("found a procedural: %s",qPrintable(token[6]));
          Procedure p = Procedure();
          p.name = token[6];
          p.matrix = transfMatrixStack.top();
          p.surfaceShader = surfaceShaderStack.top();
          //have i to read bound from actual graphics state or from procedural call?
          for(int i = 0; i < 6; i++)
            p.bound[i] = token[10 + i].toFloat(); //from procedural call (don't check if it's a number)
            //p.bound[i] = objectBound[i]; //from actual graphics state
          procedures.enqueue(p);
        }
        break;				
      }
      //the end of scene is reached
			case ribParser::NOMORESTATEMENT:
			{
				qDebug("Stack empty");
        stop = true;
				writeLine = false;        
			}
		} //end of switch

		if(writeLine) {
			//copy the same line in file
			fprintf(fout,"%s\n",qPrintable(line));
		}
    
    if((!files.hasNext() || stop) && !procedures.isEmpty()) {
      qDebug("There's a procedural to manage");
      //continue the cycle over procedure files..
      Procedure p = procedures.dequeue();
      //add procedure to rib file stack if exist
      bool noProc = false;
      while(!files.searchFile(p.name) && !noProc)
        if(procedures.isEmpty())
          noProc = true;
        else
          p = procedures.dequeue();
      
      if(!noProc) { //it's true only if all procedures elements don't exist
        fclose(fout);
        fout = fopen(qPrintable(destDirString + QDir::separator() + p.name),"wb");
	      if(fout==NULL)	{
          this->errorMessage = "Impossible to create file: " + destDirString + QDir::separator() + p.name;
          return false;
	      }
	      qDebug("Starting to write rib file into %s",qPrintable(destDirString + QDir::separator() + p.name));
	
        //restore the graphics state to the procedure call state
        transfMatrixStack << p.matrix;
        surfaceShaderStack << p.surfaceShader;
        for(int i = 0; i < 6; i++)
          objectBound[i] = p.bound[i];
        //continue cycle
        writeLine = true;
        stop = false;
      }
    }

	} //end of cycle
	fclose(fout);
  
	return true;
}
Example #13
0
// The Real Core Function doing the actual mesh processing.
bool FilterCreate::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos * /*cb*/)
{
    MeshModel* m=md.addNewMesh("",this->filterName(ID(filter)));
  switch(ID(filter))	 {
    case CR_TETRAHEDRON :
      vcg::tri::Tetrahedron<CMeshO>(m->cm);
      break;
    case CR_ICOSAHEDRON:
      vcg::tri::Icosahedron<CMeshO>(m->cm);
      break;
    case CR_DODECAHEDRON:
      vcg::tri::Dodecahedron<CMeshO>(m->cm);
      m->updateDataMask(MeshModel::MM_POLYGONAL);
      break;
    case CR_OCTAHEDRON:
      vcg::tri::Octahedron<CMeshO>(m->cm);
      break;
    case CR_TORUS:
    {
      float hRadius=par.getFloat("hRadius");
      float vRadius=par.getFloat("vRadius");
      int hSubdiv=par.getInt("hSubdiv");
      int vSubdiv=par.getInt("vSubdiv");
      vcg::tri::Torus(m->cm,hRadius,vRadius,hSubdiv,vSubdiv);
        break;
    }
  case CR_RANDOM_SPHERE:
    {
    CMeshO tt;

    int pointNum = par.getInt("pointNum");
    int oversamplingFactor =100;
    if(pointNum <= 100) oversamplingFactor = 1000;
    if(pointNum >= 10000) oversamplingFactor = 50;
    if(pointNum >= 100000) oversamplingFactor = 20;

    vcg::math::MarsenneTwisterRNG rng;
    vcg::tri::Allocator<CMeshO>::AddVertices(tt,pointNum*50);
    for(CMeshO::VertexIterator vi=tt.vert.begin();vi!=tt.vert.end();++vi)
      vcg::math::GeneratePointOnUnitSphereUniform(rng,vi->P());
    vcg::tri::UpdateBounding<CMeshO>::Box(tt);

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

    std::vector<vcg::Point3f> poissonSamples;
    vcg::tri::TrivialSampler<CMeshO> pdSampler(poissonSamples);
    vcg::tri::SurfaceSampling<CMeshO, vcg::tri::TrivialSampler<CMeshO> >::PoissonDiskParam pp;

    vcg::tri::SurfaceSampling<CMeshO,vcg::tri::TrivialSampler<CMeshO> >::PoissonDiskPruning(pdSampler, tt, poissonRadius, pp);
    m->cm.Clear();
    vcg::tri::Allocator<CMeshO>::AddVertices(m->cm,poissonSamples.size());
    for(size_t i=0;i<poissonSamples.size();++i)
    {
      m->cm.vert[i].P()=poissonSamples[i];
      m->cm.vert[i].N()=m->cm.vert[i].P();
    }
  } break;

  case CR_SPHERE:
    {
        int rec = par.getInt("subdiv");
        float radius = par.getFloat("radius");
        m->cm.face.EnableFFAdjacency();
        m->updateDataMask(MeshModel::MM_FACEFACETOPO);
        assert(vcg::tri::HasPerVertexTexCoord(m->cm) == false);
        vcg::tri::Sphere<CMeshO>(m->cm,rec);

		for(CMeshO::VertexIterator vi = m->cm.vert.begin();vi!= m->cm.vert.end();++vi)
		  vi->P()=vi->P()*radius;

		break;
	}
	case CR_BOX:
	{
	  float sz=par.getFloat("size");
	  vcg::Box3f b(vcg::Point3f(1,1,1)*(sz/2),vcg::Point3f(1,1,1)*(-sz/2));
	  vcg::tri::Box<CMeshO>(m->cm,b);
			m->updateDataMask(MeshModel::MM_POLYGONAL);

      break;
    }
    case CR_CONE:
      float r0=par.getFloat("r0");
      float r1=par.getFloat("r1");
      float h=par.getFloat("h");
      int subdiv=par.getInt("subdiv");
      vcg::tri::Cone<CMeshO>(m->cm,r0,r1,h,subdiv);
      break;
   }
     vcg::tri::UpdateBounding<CMeshO>::Box(m->cm);
   vcg::tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFaceNormalized(m->cm);
    return true;
}
Example #14
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 #15
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 #16
0
// The Real Core Function doing the actual mesh processing.
bool FilterCreate::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, CallBackPos * /*cb*/)
{
	MeshModel & currM = *md.mm();
	MeshModel* m;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

	} break;

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


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

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

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

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

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

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

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

	}//CASE FILTER

	tri::UpdateBounding<CMeshO>::Box(m->cm);
	tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFaceNormalized(m->cm);
    return true;
}
Example #17
0
bool SdfGpuPlugin::applyFilter(QAction */*filter*/, MeshDocument &md, RichParameterSet & pars, vcg::CallBackPos *cb)
{
  MeshModel* mm = md.mm();

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

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

  std::vector<Point3f> coneDirVec;

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


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

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

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

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


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

  coneDirVec.clear();

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

        this->glContext->makeCurrent();

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

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

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

  }



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

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

  //Clean & Exit
  releaseGL(*mm);

  mDepthComplexity = 0;

  return true;
}
// 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 #19
0
bool SdfPlugin::applyFilter(MeshDocument& md, RichParameterSet& pars, vcg::CallBackPos* cb){
  enum ONPRIMITIVE{ON_VERTICES, ON_FACES} onPrimitive;
  MeshModel* mm = md.mm();
  CMeshO& m = mm->cm;

  //--- Retrieve parameters
  float widenessRad = math::ToRad(pars.getFloat("coneWidth"));
  int raysPerCone = pars.getInt("numberRays");
  onPrimitive = (ONPRIMITIVE) pars.getEnum("onPrimitive");
  qDebug() << "which primitive?" << onPrimitive;
  float lo01pec = pars.getFloat("lowQuantile");
  float hi01pec = pars.getFloat("hiQuantile");
  assert( onPrimitive==ON_VERTICES && "Face mode not supported yet" );
  
  //--- If on vertices, do some cleaning first
  if( onPrimitive == ON_VERTICES ){
    int dup = tri::Clean<CMeshO>::RemoveDuplicateVertex(m);
    int unref =  tri::Clean<CMeshO>::RemoveUnreferencedVertex(m);
    if (dup > 0 || unref > 0) Log("Removed %i duplicate and %i unreferenced vertices\n",dup,unref);
  }

  //--- Updating mesh metadata
  tri::UpdateBounding<CMeshO>::Box(m);
  tri::UpdateNormals<CMeshO>::PerFaceNormalized(m);
  tri::UpdateNormals<CMeshO>::PerVertexAngleWeighted(m);
  tri::UpdateNormals<CMeshO>::NormalizeVertex(m);
  tri::UpdateFlags<CMeshO>::FaceProjection(m);
    
  //--- Enable & Reset the necessary attributes
  switch(onPrimitive){
    case ON_VERTICES:   
      // qDebug() << "initializing vert quality";
      mm->updateDataMask(MeshModel::MM_VERTQUALITY); 
      tri::UpdateQuality<CMeshO>::VertexConstant(m,0);
      break;
    case ON_FACES:   
      mm->updateDataMask(MeshModel::MM_FACEQUALITY); 
      tri::UpdateQuality<CMeshO>::FaceConstant(m,0);
      break; 
  }
  
  //--- Add the mesh to an indexing structure (fast ray intersection)
  Log("Initializing spatial accelleration...");
  mm->updateDataMask(MeshModel::MM_FACEMARK);
  TriMeshGrid static_grid; //TODO: rename spatial index
  static_grid.Set(m.face.begin(), m.face.end());
  Log("Initializing spatial accelleration... DONE!");
   
  // since we are measuring the interior of the shape
  // A ray should never go beyond this value 
  float maxDist=m.bbox.Diag();
  // This is a small number to avoid self-intersection during ray 
  // casting. It's a very common trick
  float epsilon = maxDist / 10000.0; 

  //--- Ray casting
  vector<Ray3f> cone;
  vector<float> coneSdf;
  Ray3f ray; 
  float t;
  for(unsigned int i=0; i<m.vert.size(); i++){
    CVertexO& v = m.vert[i];
    //--- Update progressbar
    cb( i/m.vert.size(), "Casting rays into volume...");
    
    //--- Generate the set of cones
    ray.Set( v.P(), -v.N() );
    ray.SetOrigin( ray.P(epsilon) );
    generateRayCone( ray, widenessRad, raysPerCone, cone, coneSdf, (i==266) );
        
    //--- Trace rays in cone
    float mind = +numeric_limits<float>::max();
    float maxd = -numeric_limits<float>::max();
    for(unsigned int j=0; j<cone.size(); j++){
      bool hasInt = tri::DoRay<CMeshO,TriMeshGrid>(m,static_grid,cone[j],maxDist,t);
      coneSdf[j] = (hasInt==true) ? t : numeric_limits<float>::quiet_NaN();
      mind = (hasInt && (t<mind)) ? t : mind;
      maxd = (hasInt && (t>maxd)) ? t : maxd;

      if( i==266 ){
        qDebug() << " sampled: " << coneSdf[j] 
                 << " dir: " << toString(cone[j].Direction())
                 << " hasInt: " << hasInt;
      }
    }
    
    //--- Compute per-cone statistics
    Histogram<float> H;
    H.Clear();
    H.SetRange( mind, maxd, 100);
    for(unsigned int j=0; j<cone.size(); j++)
      if(!math::IsNAN(coneSdf[j]))
        H.Add(coneSdf[j]);
    float loperc = H.Percentile(lo01pec);
    float hiperc = H.Percentile(hi01pec);

    if( i == 266){
      qDebug() << "percentiles: " << loperc << " " << hiperc;
    }
    
    
    //--- Compute average of samples, throwing away outliers
    if( i == 266) 
      qDebug() << "averaging samples";
    float totVal = 0, totCnt = 0;
    for(unsigned int j=0; j<coneSdf.size(); j++)
      if( !math::IsNAN(coneSdf[j]) ){
        // Histogram statistics valid only for dense sets (more 3 members..)
        if( coneSdf[j]<loperc || coneSdf[j]>hiperc && coneSdf.size()>3) 
          continue;
        
        // Weight giving more importance to aligned samples
        float weight = cone[j].Direction().dot( ray.Direction() );
        // Even more importance
        weight = powf( weight, 10 );
        
        if( i==266 ){
          qDebug() << "sampled: " << coneSdf[j] << "weight " << weight 
                   << " dir:" << toString(cone[j].Direction());
        }
        
        totVal += weight*coneSdf[j];
        totCnt += weight;
      } 
         
    //--- Save in mesh
    v.Q() = totCnt>0 ? (totVal/totCnt) : 0;
  }

  //----------------------------------------------------------------------------//
  // 
  //                          STEROIDS STARTS HERE 
  //
  //----------------------------------------------------------------------------//
  //--- Create the medial cloud by offsetting the samples of the medial amount
  MeshModel* medCloud = md.addNewMesh("medial cloud.obj", NULL, false);
  for(unsigned int i=0; i<m.vert.size(); i++){
    Ray3f r;
    r.Set(m.vert[i].P(), -m.vert[i].N());
    tri::Allocator<CMeshO>::AddVertices(medCloud->cm,1);
    medCloud->cm.vert.back().P() = r.P(m.vert[i].Q() / 2 );
  }
  
  //--- Data for distance queries
  vcg::tri::FaceTmark<CMeshO> mf; 
  mf.SetMesh( &m );
  vcg::face::PointDistanceBaseFunctor<float> PDistFunct;
    
  Log("querying real distances");
  
  // Query the location of closest point on the mesh, then measure the difference
  float allowedDiff = .02;
  vector<float> realdistances(m.vn, 0);
  for(unsigned int i=0; i<m.vert.size(); i++){
    Point3f currp = medCloud->cm.vert[i].P();
    float minDist = maxDist;
    Point3f closest;  
    GridClosest(static_grid, PDistFunct, mf, currp, maxDist, minDist, closest);  
    float difference = m.vert[i].Q()/2.0 - minDist;
    m.vert[i].Q() = exp( -powf(difference/allowedDiff,2) );
  }
 
  // Correct the viewmodel so that after this is done the original mesh
  // is shown in wireframe and the medial as a cloud.
  // mm->glw.cdm = vcg::GLW::DMWire; // show original mesh in wireframe
  medCloud->glw.cdm = vcg::GLW::DMPoints; // show cloud
  return true;
}
Example #20
0
bool AmbientOcclusionPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
    MeshModel &m=*(md.mm());
    if(ID(filter)==FP_FACE_AMBIENT_OCCLUSION ) perFace=true;
	else perFace = false;
	
	useGPU = par.getBool("useGPU");
	useVBO = par.getBool("useVBO");
	depthTexSize = par.getInt("depthTexSize");
	depthTexArea = depthTexSize*depthTexSize;
	numViews = par.getInt("reqViews");
	errInit = false;
	float dirBias = par.getFloat("dirBias");
	Point3f coneDir = par.getPoint3f("coneDir");
	float coneAngle = par.getFloat("coneAngle");
	
	if(perFace) 
	  m.updateDataMask(MeshModel::MM_FACEQUALITY | MeshModel::MM_FACECOLOR);
	else 
		m.updateDataMask(MeshModel::MM_VERTQUALITY | MeshModel::MM_VERTCOLOR);

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

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


	this->glContext->makeCurrent();
	this->initGL(cb,m.cm.vn);
	unsigned int widgetSize = std::min(maxTexSize, depthTexSize);
	QSize fbosize(widgetSize,widgetSize);
	QGLFramebufferObjectFormat frmt;
	frmt.setInternalTextureFormat(GL_RGBA);
	frmt.setAttachment(QGLFramebufferObject::Depth);
	QGLFramebufferObject fbo(fbosize,frmt);
	qDebug("Start Painting window size %i %i", fbo.width(), fbo.height());
	GLenum err = glGetError();
	fbo.bind();
	processGL(m,viewDirVec);
	fbo.release();
	err = glGetError();
	const GLubyte* errname = gluErrorString(err);
	qDebug("End Painting");
	this->glContext->doneCurrent();
	return !errInit;
}
Example #21
0
bool BaseMeshIOPlugin::open(const QString &formatName, const QString &fileName, MeshModel &m, int& mask, const RichParameterSet &parlst, CallBackPos *cb, QWidget * /*parent*/)
{
	bool normalsUpdated = false;

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

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

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

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

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

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

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

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

		m.Enable(importparams.mask);

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

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

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

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

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

	return true;
}
Example #22
0
// The Real Core Function doing the actual mesh processing.
// Move Vertex of a random quantity
bool PoissonPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
	MeshModel &m=*md.mm();
  MeshModel &pm =*md.addNewMesh("","Poisson mesh");
  vector<Point3D<float> > Pts(m.cm.vn);
	vector<Point3D<float> > Nor(m.cm.vn); 	
	CoredVectorMeshData mesh;

	if (m.hasDataMask(MeshModel::MM_WEDGTEXCOORD)){
		m.clearDataMask(MeshModel::MM_WEDGTEXCOORD);
	}
	if (m.hasDataMask(MeshModel::MM_VERTTEXCOORD)){
		m.clearDataMask(MeshModel::MM_VERTTEXCOORD);
	}

    //Useless control on the normals. It can just avoid crashes derived from an importer setting up to [0.0f,0.0f,0.0f] the normal vectors of a mesh without per-vertex normal attribute.
    int zeronrm = 0;
    for(CMeshO::VertexIterator vi=m.cm.vert.begin(); vi!=m.cm.vert.end(); ++vi)
    {
        if(!(*vi).IsD())
        {
            if ((*vi).N() == vcg::Point3f(0.0f,0.0f,0.0f))
                ++zeronrm;
        }
    }

    if (zeronrm == m.cm.vn)
    {
        Log(GLLogStream::SYSTEM,"All the normal vectors are set to [0.0,0.0,0.0]. Poisson reconstruction filter requires a set of valid per-vertex normal. Filter will be aborted.");
        return false;
    }

    int cnt=0;
	for(CMeshO::VertexIterator vi=m.cm.vert.begin(); vi!=m.cm.vert.end(); ++vi)
	if(!(*vi).IsD()){
			(*vi).N().Normalize();
			for(int ii=0;ii<3;++ii){
					Pts[cnt].coords[ii]=(*vi).P()[ii];
					Nor[cnt].coords[ii]=(*vi).N()[ii];
			}
			++cnt;
		}
	assert(cnt==m.cm.vn);
	// Log function dump textual info in the lower part of the MeshLab screen. 
	PoissonParam pp;
	pp.Depth=par.getInt("OctDepth");
	pp.SamplesPerNode = par.getFloat("SamplesPerNode");
	pp.SolverDivide=par.getInt("SolverDivide");
	pp.Offset = par.getFloat("Offset");
	Point3D<float> center;
	float scale;
	
	int ret= Execute2(pp, Pts, Nor, mesh,center,scale,cb);
	mesh.resetIterator();
	int vm = mesh.outOfCorePointCount()+mesh.inCorePoints.size();
	int fm = mesh.triangleCount();

	Log("Successfully created a mesh of %i vert and %i faces",vm,fm);
	
	//m.cm.Clear();
	
	tri::Allocator<CMeshO>::AddVertices(pm.cm,vm);
	tri::Allocator<CMeshO>::AddFaces(pm.cm,fm);

  Point3D<float> p;
	int i;
	for (i=0; i < int(mesh.inCorePoints.size()); i++){
		p=mesh.inCorePoints[i];
		pm.cm.vert[i].P()[0] = p.coords[0]*scale+center.coords[0];
		pm.cm.vert[i].P()[1] = p.coords[1]*scale+center.coords[1];
		pm.cm.vert[i].P()[2] = p.coords[2]*scale+center.coords[2];
		}
	for (int ii=0; ii < mesh.outOfCorePointCount(); ii++){
		mesh.nextOutOfCorePoint(p);
		pm.cm.vert[ii+i].P()[0] = p.coords[0]*scale+center.coords[0];
		pm.cm.vert[ii+i].P()[1] = p.coords[1]*scale+center.coords[1];
		pm.cm.vert[ii+i].P()[2] = p.coords[2]*scale+center.coords[2];
	}

TriangleIndex tIndex;
int inCoreFlag;
int nr_faces=mesh.triangleCount();	
for (i=0; i < nr_faces; i++){
		//
		// create and fill a struct that the ply code can handle
		//
		mesh.nextTriangle(tIndex,inCoreFlag);
		if(!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[0])){tIndex.idx[0]+=int(mesh.inCorePoints.size());}
		if(!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[1])){tIndex.idx[1]+=int(mesh.inCorePoints.size());}
		if(!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[2])){tIndex.idx[2]+=int(mesh.inCorePoints.size());}
		for(int j=0; j < 3; j++)
		{
			pm.cm.face[i].V(j) = &pm.cm.vert[tIndex.idx[j]];
		}
		//ply_put_element(ply, (void *) &ply_face);
		//delete[] ply_face.vertices;
	}  // for, write faces


//	for(int i=0;i<mesh.inCorePoints.size();++i){
//		mesh.triangles[i].idx[0]+=mesh.inCorePoints.size();
//		mesh.triangles[i].idx[1]+=mesh.inCorePoints.size();
//		mesh.triangles[i].idx[2]+=mesh.inCorePoints.size();
//		}
//	Build(m.cm,mesh.inCorePoints,mesh.triangles);
	Log("Successfully created a mesh of %i faces",pm.cm.vn);
	
	pm.UpdateBoxAndNormals();
	return true;
}
Example #23
0
// The Real Core Function doing the actual mesh processing.
bool FilterFunctionPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
  if(this->getClass(filter) == MeshFilterInterface::MeshCreation)
       md.addNewMesh("",this->filterName(ID(filter)));
  MeshModel &m=*(md.mm());
	Q_UNUSED(cb);
	switch(ID(filter)) {
		case FF_VERT_SELECTION :
			{
				std::string expr = par.getString("condSelect").toStdString();
			
				// muparser initialization and explicitely define parser variables
				Parser p;
        setPerVertexVariables(p,m.cm);

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

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

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

					bool selected = false;

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

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

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

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

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

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

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

					bool selected = false;

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

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

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

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

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

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

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

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

				time_t start = clock();

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

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

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

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

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

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

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

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

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

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

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

				return true;
			}
		break;

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

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

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

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

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

				time_t start = clock();

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

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

					if(errorMessage != "") return false;

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

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

				return true;

			}
		break;

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

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

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

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

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

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

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

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

				return true;
			}
		break;

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

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

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

				time_t start = clock();

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

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

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

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

				return true;
			}
		break;

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

				time_t start = clock();

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

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

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

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

				return true;
			}
		break;

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

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

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

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

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

			}
		break;

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

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

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

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

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

				return true;
			}
		break;

		default : assert (0);
	}
	return false;
}
Example #24
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 #25
0
/* The Real Core Function doing the actual mesh processing */
bool GeometryAgingPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet &params, vcg::CallBackPos *cb)
{	
    MeshModel &m=*(md.mm());
    if( ID(filter) != FP_ERODE)
	{
		assert (0);
		return false;
	}

	m.updateDataMask(MeshModel::MM_VERTQUALITY);
	
	bool curvature = params.getBool("ComputeCurvature");
	if(curvature)	computeMeanCurvature(m.cm);
		
	// other plugin parameters
	bool smoothQ = params.getBool("SmoothQuality");
	float qualityTh = params.getAbsPerc("QualityThreshold");
	float edgeLenTh = params.getAbsPerc("EdgeLenThreshold");
	float chipDepth = params.getAbsPerc("ChipDepth");
	int octaves = params.getInt("Octaves");
	float noiseScale = params.getAbsPerc("NoiseFreqScale");
	float noiseClamp = params.getFloat("NoiseClamp");
	int dispSteps = (int)params.getFloat("DisplacementSteps");
	bool selected = params.getBool("Selected");
	bool storeDispl = params.getBool("StoreDisplacement");
	
	// error checking on parameters values
	if(edgeLenTh == 0.0) edgeLenTh = m.cm.bbox.Diag()*0.02;
	if(chipDepth == 0.0) chipDepth = m.cm.bbox.Diag()*0.05;
	noiseClamp = math::Clamp<float>(noiseClamp, 0.0, 1.0);
	
			// quality threshold percentage value
			std::pair<float, float> qRange = tri::Stat<CMeshO>::ComputePerVertexQualityMinMax(m.cm);
			float qperc = (qualityTh-qRange.first) / (qRange.second-qRange.first);
			
			// compute mesh quality, if requested
			if(curvature) {
				if(cb) (*cb)(0, "Computing quality values...");
				computeMeanCurvature(m.cm);
			}
			
			// eventually, smooth quality values
			if(smoothQ) tri::Smooth<CMeshO>::VertexQualityLaplacian(m.cm);
			
			// if quality values have been recomputed quality threshold may not 
			// be valid, so we recompute its absolute value using the percentage
			// value chosen by the user
			if(curvature || smoothQ) {
				qRange = tri::Stat<CMeshO>::ComputePerVertexQualityMinMax(m.cm);
				qualityTh = qRange.first + (qRange.second-qRange.first) * qperc;
			}
			
			// edge predicate
			QualityEdgePred ep = QualityEdgePred(selected, edgeLenTh, qualityTh);
			
			// refine needed edges
			refineMesh(m.cm, ep, selected, cb);
			
			// if requested, add erosion attribute to vertexes and initialize it
			if(storeDispl) {
				CMeshO::PerVertexAttributeHandle<Point3f> vah = 
						(tri::HasPerVertexAttribute(m.cm, "Erosion") ?
						 tri::Allocator<CMeshO>::GetPerVertexAttribute<Point3f>(m.cm, "Erosion") :
						 tri::Allocator<CMeshO>::AddPerVertexAttribute<Point3f>(m.cm, std::string("Erosion")));
				for(CMeshO::VertexIterator vi=m.cm.vert.begin(); vi!=m.cm.vert.end(); vi++)
					vah[vi] = Point3f(0.0, 0.0, 0.0);
			}
			CMeshO::PerVertexAttributeHandle<Point3f> vah = vcg::tri::Allocator<CMeshO>::GetPerVertexAttribute<Point3f>(m.cm, "Erosion");
			
			// vertexes along selection border will not be displaced 
			if(selected) tri::UpdateSelection<CMeshO>::VertexFromFaceStrict(m.cm);
			
			// clear vertexes V bit (will be used to mark the vertexes as displaced) 
			tri::UpdateFlags<CMeshO>::VertexClearV(m.cm);
			
			// displace vertexes
			for(int i=0; i<dispSteps; i++) {
				GridStaticPtr<CFaceO, CMeshO::ScalarType> gM;
				gM.Set(m.cm.face.begin(), m.cm.face.end());
				
				if(cb) (*cb)( (i+1)*100/dispSteps, "Aging...");
				
				// blend toghether face normals and recompute vertex normal from these normals 
				// to get smoother offest directions
				tri::Smooth<CMeshO>::FaceNormalLaplacianFF(m.cm, 3); 
				tri::UpdateNormals<CMeshO>::PerVertexFromCurrentFaceNormal(m.cm);
				tri::UpdateNormals<CMeshO>::NormalizeVertex(m.cm);
				
				for(CMeshO::FaceIterator fi=m.cm.face.begin(); fi!=m.cm.face.end(); fi++) {
					if((*fi).IsD()) continue;
					for(int j=0; j<3; j++) {
						if(ep.qVertTest(face::Pos<CMeshO::FaceType>(&*fi,j))  &&
						   !(*fi).V(j)->IsV() &&		
						   (!selected || ((*fi).IsS() && (*fi).FFp(j)->IsS())) ) {
								double noise;						// noise value
								Point3f dispDir = (*fi).V(j)->N();	// displacement direction
								
								Point3f p = (*fi).V(j)->P() / noiseScale;
								noise = generateNoiseValue(octaves, p);
								// only values bigger than noiseClamp will be considered
								noise = (noise<noiseClamp?0.0:(noise-noiseClamp));
								
								// displacement offset
								Point3f offset = -(dispDir * chipDepth * noise) / dispSteps;
								
								(*fi).V(j)->P() += offset;
								if(faceIntersections(m.cm, face::Pos<CMeshO::FaceType>(&*fi,j), gM))
									(*fi).V(j)->P() -= offset;
								else if(storeDispl)	// store displacement
									vah[(*fi).V(j)] = vah[(*fi).V(j)] + offset;
								
								// mark as visited (displaced)
								(*fi).V(j)->SetV();
							}
					}
				}
				// clear vertexes V bit again
				tri::UpdateFlags<CMeshO>::VertexClearV(m.cm);
			}
			
			// update normals
			vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m.cm);
			
			smoothPeaks(m.cm, selected, storeDispl);
			
			// readjust selection
			if(selected) tri::UpdateSelection<CMeshO>::VertexFromFaceLoose(m.cm);
						
			return true;
}
Example #26
0
// The Real Core Function doing the actual mesh processing.
// Run mesh optimization
bool TriOptimizePlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
    MeshModel &m=*(md.mm());
    float limit = -std::numeric_limits<float>::epsilon();
	
	if (ID(filter) == FP_CURVATURE_EDGE_FLIP) {		
		int delvert = tri::Clean<CMeshO>::RemoveUnreferencedVertex(m.cm);
		if (delvert)
			Log(
			    "Pre-Curvature Cleaning: Removed %d unreferenced vertices",
			    delvert);

		tri::Allocator<CMeshO>::CompactVertexVector(m.cm);
		tri::Allocator<CMeshO>::CompactFaceVector(m.cm);
		m.updateDataMask(MeshModel::MM_FACEFACETOPO);
		vcg::tri::UpdateFlags<CMeshO>::FaceBorderFromFF(m.cm);
		
    if ( tri::Clean<CMeshO>::CountNonManifoldEdgeFF(m.cm) >0) {
			errorMessage = "Mesh has some not 2-manifold faces, edge flips requires manifoldness";
			return false; // can't continue, mesh can't be processed
		}
    vcg::tri::PlanarEdgeFlipParameter pp;

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

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

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

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

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

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

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

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

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

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

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

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

	return true;
}
Example #27
0
bool FilterIsoParametrization::applyFilter(QAction *filter, MeshDocument& md, RichParameterSet & par, vcg::CallBackPos  *cb)
{
  MeshModel* m = md.mm();  //get current mesh from document
  CMeshO *mesh=&m->cm;
  switch(ID(filter))
  {
	case ISOP_PARAM :
	{

		int targetAbstractMinFaceNum = par.getInt("targetAbstractMinFaceNum");
		int targetAbstractMaxFaceNum = par.getInt("targetAbstractMaxFaceNum");
		int convergenceSpeed = par.getInt("convergenceSpeed");
		int stopCriteria=par.getEnum("stopCriteria");
		bool doublestep=par.getBool("DoubleStep");
		IsoParametrizator Parametrizator;

    m->updateDataMask(MeshModel::MM_FACEFACETOPO);

		bool isTXTenabled=m->hasDataMask(MeshModel::MM_VERTTEXCOORD);
		if (!isTXTenabled)
			m->updateDataMask(MeshModel::MM_VERTTEXCOORD);

		bool isVMarkenabled=m->hasDataMask(MeshModel::MM_VERTMARK);
		if (!isVMarkenabled)
			m->updateDataMask(MeshModel::MM_VERTMARK);

		bool isFMarkenabled=m->hasDataMask(MeshModel::MM_FACEMARK);
		if (!isFMarkenabled)
			m->updateDataMask(MeshModel::MM_FACEMARK);

		bool isVColorenabled=m->hasDataMask(MeshModel::MM_VERTCOLOR);
		if (!isVColorenabled)
			m->updateDataMask(MeshModel::MM_VERTCOLOR);

		bool isFColorenabled=m->hasDataMask(MeshModel::MM_FACECOLOR);
		if (!isFColorenabled)
			m->updateDataMask(MeshModel::MM_FACECOLOR);
		int tolerance = targetAbstractMaxFaceNum-targetAbstractMinFaceNum;
		switch (stopCriteria)
		{
			case 0:Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Euristic,convergenceSpeed);break;
			case 1:Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Corr,convergenceSpeed);break;
			case 2:Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Reg,convergenceSpeed);break;
			case 3:Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_L2,convergenceSpeed);break;
			default:Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Euristic,convergenceSpeed);break;
		}
		IsoParametrizator::ReturnCode ret=Parametrizator.Parametrize<CMeshO>(mesh,doublestep);
		
		if (ret==IsoParametrizator::Done)
		{
			Parametrizator.PrintAttributes();
			float aggregate,L2;
			int n_faces;
			Parametrizator.getValues(aggregate,L2,n_faces);
			Log("Num Faces of Abstract Domain: %d, One way stretch efficiency: %.4f, Area+Angle Distorsion %.4f  ",n_faces,L2,aggregate*100.f);
		}
		else
		{
			if (!isTXTenabled)
				m->clearDataMask(MeshModel::MM_VERTTEXCOORD);
			if (!isFMarkenabled)
				m->clearDataMask(MeshModel::MM_FACEMARK);
			if (!isVMarkenabled)
				m->clearDataMask(MeshModel::MM_VERTMARK);
			if (!isVColorenabled)
				m->clearDataMask(MeshModel::MM_VERTCOLOR);
			if (!isFColorenabled)
				m->clearDataMask(MeshModel::MM_FACECOLOR);
			if (ret==IsoParametrizator::NonPrecondition)
				this->errorMessage="non possible parameterization because of violated preconditions";
			else
			if (ret==IsoParametrizator::FailParam)
				this->errorMessage="non possible parameterization cause because missing the intepolation for some triangle of original the mesh (maybe due to topologycal noise)";
			return false;
		}
		Parametrizator.ExportMeshes(para_mesh,abs_mesh);
		isoPHandle=vcg::tri::Allocator<CMeshO>::AddPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization");
		bool isOK=isoPHandle().Init(&abs_mesh,&para_mesh);

		///copy back to original mesh
    isoPHandle().CopyParametrization<CMeshO>(mesh);

		if (!isOK)
		{
			Log("Problems gathering parameterization \n");
			return false;
		}
    if (!isVMarkenabled)
				m->clearDataMask(MeshModel::MM_VERTMARK);
		if (!isFMarkenabled)
				m->clearDataMask(MeshModel::MM_FACEMARK);
    return true;
	}
	case ISOP_REMESHING :
	{
		bool b=vcg::tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle);
		if (!b)
		{
			this->errorMessage="You must compute the Base domain before remeshing. Use the Isoparametrization command.";
			return false;
		}
		

		int SamplingRate=par.getInt("SamplingRate");
		MeshModel* mm=md.addNewMesh("Re-meshed");
		
		CMeshO *rem=&mm->cm;
		
		DiamSampl.Init(&isoPHandle());
		DiamSampl.SamplePos(SamplingRate);
		DiamSampl.GetMesh<CMeshO>(*rem);

		int n_diamonds,inFace,inEdge,inStar,n_merged;
		DiamSampl.getResData(n_diamonds,inFace,inEdge,inStar,n_merged);

		Log("INTERPOLATION DOMAINS");
		Log("In Face: %d \n",inFace);
		Log("In Diamond: %d \n",inEdge);
		Log("In Star: %d \n",inStar);
		Log("Merged %d vertices\n",n_merged);
		mm->updateDataMask(MeshModel::MM_FACEFACETOPO);
		mm->updateDataMask(MeshModel::MM_VERTFACETOPO);
		PrintStats(rem);
		vcg::tri::UpdateNormals<CMeshO>::PerFace(*rem);
		return true;
	}
	case ISOP_DIAMPARAM :
	{
		bool b=vcg::tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle);
		if (!b)
		{
			this->errorMessage="You must compute the Base domain before remeshing. Use the Isoparametrization command.";
			return false;
		}
		
		float border_size=par.getDynamicFloat("BorderSize");
		MeshModel* mm=md.addNewMesh("Diam-Parameterized");
		mm->updateDataMask(MeshModel::MM_WEDGTEXCOORD);
		mm->updateDataMask(MeshModel::MM_VERTCOLOR);
		CMeshO *rem=&mm->cm;
		DiamondParametrizator DiaPara;
		DiaPara.Init(&isoPHandle());
		DiaPara.SetCoordinates<CMeshO>(*rem,border_size);
		vcg::tri::UpdateNormals<CMeshO>::PerFace(*rem);
		return true;
	}
	case ISOP_LOAD : 
	{
		QString AbsName = par.getString("AbsName");
		bool isTXTenabled=m->hasDataMask(MeshModel::MM_VERTTEXCOORD);
		if (!isTXTenabled)
		{
			this->errorMessage="Per Vertex Text Coordinates are not enabled";
			return false;
		}
		if(!QFile(m->fullName()).exists())
		{
			this->errorMessage="File not exists";
			return false;
		}
		bool b=vcg::tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle);
		if (!b)
			isoPHandle=vcg::tri::Allocator<CMeshO>::AddPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization");

		QByteArray ba = AbsName.toLatin1();
		char *path=ba.data();
		bool Done=isoPHandle().LoadBaseDomain<CMeshO>(path,mesh,&para_mesh,true);
		if (!Done)
		{
			this->errorMessage="Abstract domain doesnt fit well with the parametrized mesh";
			return false;
		}
		return true;
	}
	case ISOP_SAVE : 
	{
		bool b=vcg::tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle);
		if (!b)
		{
			this->errorMessage="You must compute the Base domain before remeshing. Use the Isoparametrization command.";
			return false;
		}
		/*QString Qpath=m->fullName();*/

		QString AbsName = par.getString("AbsName");
		
		QByteArray ba = AbsName.toLatin1();
		char *path=ba.data();
		isoPHandle().SaveBaseDomain(path);
		return true;
	}
  }
  return false;
}
Example #28
0
// The Real Core Function doing the actual mesh processing.
// Move Vertex of a random quantity
bool ExtraSampleGPUPlugin::applyFilter(QAction * a, MeshDocument & md , RichParameterSet & par, vcg::CallBackPos * /*cb*/)
{
	switch(ID(a))
	{
		case FP_GPU_EXAMPLE:
		{
			CMeshO & mesh = md.mm()->cm;
			if ((mesh.vn < 3) || (mesh.fn < 1)) return false;

			const unsigned char * p0      = (const unsigned char *)(&(mesh.vert[0].P()));
			const unsigned char * p1      = (const unsigned char *)(&(mesh.vert[1].P()));
			const void *          pbase   = p0;
			GLsizei               pstride = GLsizei(p1 - p0);

			const unsigned char * n0      = (const unsigned char *)(&(mesh.vert[0].N()));
			const unsigned char * n1      = (const unsigned char *)(&(mesh.vert[1].N()));
			const void *          nbase   = n0;
			GLsizei               nstride = GLsizei(n1 - n0);

			glContext->makeCurrent();
			glewInit();

			glPushAttrib(GL_ALL_ATTRIB_BITS);

			Context ctx;
			ctx.acquire();

			const GLsizeiptr psize = GLsizeiptr(GLsizei(mesh.vn) * pstride);
			BufferHandle hPositionBuffer = createBuffer(ctx, psize, pbase);

			const GLsizeiptr nsize = GLsizeiptr(GLsizei(mesh.vn) * nstride);
			BufferHandle hNormalBuffer = createBuffer(ctx, nsize, nbase);

			const GLsizeiptr isize = GLsizeiptr(mesh.fn * 3 * sizeof(GLuint));
			BufferHandle hIndexBuffer = createBuffer(ctx, isize);

			{
				BoundIndexBufferHandle indexBuffer = ctx.bindIndexBuffer(hIndexBuffer);

				const CMeshO::VertexType * vbase   = &(mesh.vert[0]);
				GLuint *                   indices = (GLuint *)indexBuffer->map(GL_WRITE_ONLY);
				for (size_t i=0; i<mesh.face.size(); ++i)
				{
					const CMeshO::FaceType & f = mesh.face[i];
					if (f.IsD()) continue;
					for (int v=0; v<3; ++v)
					{
						*indices++ = GLuint(vcg::tri::Index(mesh,f.cV(v)));
					}
				}
				indexBuffer->unmap();

				ctx.unbindIndexBuffer();
			}

			const GLsizei width  = GLsizei(par.getInt("ImageWidth" ));
			const GLsizei height = GLsizei(par.getInt("ImageHeight"));

			RenderbufferHandle hDepth       = createRenderbuffer(ctx, GL_DEPTH_COMPONENT24, width, height);
			Texture2DHandle    hColor       = createTexture2D(ctx, GL_RGBA8, width, height, GL_RGBA, GL_UNSIGNED_BYTE);
			FramebufferHandle  hFramebuffer = createFramebuffer(ctx, renderbufferTarget(hDepth), texture2DTarget(hColor));

			const std::string vertSrc = GLW_STRINGIFY
			(
				varying vec3 vNormalVS;
				void main(void)
				{
					vNormalVS   = gl_NormalMatrix * gl_Normal;
					gl_Position = ftransform();
				}
			);

			const std::string fragSrc = GLW_STRINGIFY
			(
				uniform vec3 uLightDirectionVS;
				varying vec3 vNormalVS;
				void main(void)
				{
					vec3  normal  = normalize(vNormalVS);
					float lambert = max(0.0, dot(normal, -uLightDirectionVS));
					gl_FragColor  = vec4(vec3(lambert), 1.0);
				}
Example #29
0
bool DynamicMeshSubFilter::parametersAreNotCorrect(MeshDocument&, RichParameterSet& par){
    return par.getInt("seconds") < 0 || par.getInt("fps") <= 0 || par.getInt("iterations") <= 0 || par.getInt("contacts") <= 0 || par.getFloat("bounciness") < 0 || par.getFloat("bounciness") > 1;
}
Example #30
0
// The Real Core Function doing the actual mesh processing.
// Move Vertex of a random quantity
bool FilterMutualInfoPlugin::applyFilter(QAction *action, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
	QTime filterTime;
	filterTime.start();

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

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

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

			this->glContext->makeCurrent();

			this->initGL();

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

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

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

		return true;



}