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,¶_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,¶_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; }
// 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; }
bool FilterOutputOpticalFlowPlugin::applyFilter( QAction *act, MeshDocument &md, RichParameterSet &par, vcg::CallBackPos * /*cb*/ ) { if( glewInit() != GLEW_OK ) return false; bool retValue = true; m_Mesh = &md.mm()->cm; QList<OOCRaster> rasters; if( md.rasterList.isEmpty() ) { QString filename = QFileDialog::getOpenFileName( NULL, "Select a MeshLab project file", QString(), "MeshLab project (*.mlp)" ); if( filename.isNull() || !loadRasterList(filename,rasters) ) return false; } else { foreach( RasterModel *rm, md.rasterList ) rasters.push_back( OOCRaster(rm) ); } std::list<vcg::Shotf> initialShots; for( QList<OOCRaster>::iterator r=rasters.begin(); r!=rasters.end(); ++r ) { initialShots.push_back( r->shot ); r->shot.ApplyRigidTransformation( vcg::Inverse(m_Mesh->Tr) ); } switch( ID(act) ) { case FP_OUTPUT_OPTICAL_FLOW: { for( CMeshO::FaceIterator f=m_Mesh->face.begin(); f!=m_Mesh->face.end(); ++f ) f->ClearV(); int weightMask = 0; if( par.getBool("useDistanceWeight") ) weightMask |= DominancyClassifier::W_DISTANCE; if( par.getBool("useImgBorderWeight") ) weightMask |= DominancyClassifier::W_IMG_BORDER; if( par.getBool("useSilhouetteWeight") ) weightMask |= DominancyClassifier::W_SILHOUETTE; if( par.getBool("useOrientationWeight") ) weightMask |= DominancyClassifier::W_ORIENTATION; DominancyClassifier *set = new DominancyClassifier( *m_Mesh, rasters, weightMask ); if( par.getBool("colorFromDominancy") ) { md.mm()->updateDataMask( MeshModel::MM_VERTCOLOR ); for( CMeshO::VertexIterator v=m_Mesh->vert.begin(); v!=m_Mesh->vert.end(); ++v ) if( (*set)[v].isOnBoundary() ) { unsigned char c = (unsigned char)( 255.0f*(*set)[v].borderWeight() ); v->C() = vcg::Color4b( 255-c, 255-c, 255-c, 255 ); } else v->C() = vcg::Color4b( 0, 0, 255, 255 ); delete set; } else { RasterFaceMap facesByDomImg; set->dominancyCoverage( facesByDomImg ); delete set; //if( int n = par.getInt("dominantAreaExpansion") ) //{ // md.mm()->updateDataMask( MeshModel::MM_FACEFACETOPO ); // md.mm()->updateDataMask( MeshModel::MM_VERTFACETOPO ); // for( RasterFaceMap::iterator rm=facesByDomImg.begin(); rm!=facesByDomImg.end(); ++rm ) // expands( rm.value(), n ); //} QMap<int,QVector<int>> validPairs; retroProjection( facesByDomImg, 0.01f*par.getFloat("minCoverage"), validPairs ); saveXMLProject( par.getString("xmlFileName"), md.mm(), facesByDomImg, validPairs ); } break; } } return retValue; }
bool FilterIsoParametrization::applyFilter(QAction *filter, MeshDocument& md, RichParameterSet & par, vcg::CallBackPos *cb) { MeshModel* m = md.mm(); //get current mesh from document CMeshO *mesh=&m->cm; switch(ID(filter)) { case ISOP_PARAM : { int targetAbstractMinFaceNum = par.getInt("targetAbstractMinFaceNum"); int targetAbstractMaxFaceNum = par.getInt("targetAbstractMaxFaceNum"); int convergenceSpeed = par.getInt("convergenceSpeed"); int stopCriteria=par.getEnum("stopCriteria"); bool doublestep=par.getBool("DoubleStep"); IsoParametrizator Parametrizator; m->updateDataMask(MeshModel::MM_FACEFACETOPO); m->updateDataMask(MeshModel::MM_VERTQUALITY); // needed to store patch index bool isTXTenabled=m->hasDataMask(MeshModel::MM_VERTTEXCOORD); if (!isTXTenabled) m->updateDataMask(MeshModel::MM_VERTTEXCOORD); bool isVMarkenabled=m->hasDataMask(MeshModel::MM_VERTMARK); if (!isVMarkenabled) m->updateDataMask(MeshModel::MM_VERTMARK); bool isFMarkenabled=m->hasDataMask(MeshModel::MM_FACEMARK); if (!isFMarkenabled) m->updateDataMask(MeshModel::MM_FACEMARK); bool isVColorenabled=m->hasDataMask(MeshModel::MM_VERTCOLOR); if (!isVColorenabled) m->updateDataMask(MeshModel::MM_VERTCOLOR); bool isFColorenabled=m->hasDataMask(MeshModel::MM_FACECOLOR); if (!isFColorenabled) m->updateDataMask(MeshModel::MM_FACECOLOR); int tolerance = targetAbstractMaxFaceNum-targetAbstractMinFaceNum; switch (stopCriteria) { case 0: Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Euristic,convergenceSpeed); break; case 1: Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Corr,convergenceSpeed); break; case 2: Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Reg,convergenceSpeed); break; case 3: Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_L2,convergenceSpeed); break; default: Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Euristic,convergenceSpeed); break; } tri::ParamEdgeCollapseParameter pecp; IsoParametrizator::ReturnCode ret=Parametrizator.Parametrize<CMeshO>(mesh,pecp,doublestep); if (ret==IsoParametrizator::Done) { Parametrizator.PrintAttributes(); float aggregate,L2; int n_faces; Parametrizator.getValues(aggregate,L2,n_faces); Log("Num Faces of Abstract Domain: %d, One way stretch efficiency: %.4f, Area+Angle Distorsion %.4f ",n_faces,L2,aggregate*100.f); } else { if (!isTXTenabled) m->clearDataMask(MeshModel::MM_VERTTEXCOORD); if (!isFMarkenabled) m->clearDataMask(MeshModel::MM_FACEMARK); if (!isVMarkenabled) m->clearDataMask(MeshModel::MM_VERTMARK); if (!isVColorenabled) m->clearDataMask(MeshModel::MM_VERTCOLOR); if (!isFColorenabled) m->clearDataMask(MeshModel::MM_FACECOLOR); switch(ret) { case IsoParametrizator::MultiComponent: this->errorMessage="non possible parameterization because of multi componet mesh"; return false; case IsoParametrizator::NonSizeCons: this->errorMessage="non possible parameterization because of non size consistent mesh"; return false; case IsoParametrizator::NonManifoldE: this->errorMessage="non possible parameterization because of non manifold edges"; return false; case IsoParametrizator::NonManifoldV: this->errorMessage="non possible parameterization because of non manifold vertices"; return false; case IsoParametrizator::NonWatertigh: this->errorMessage="non possible parameterization because of non watertight mesh"; return false; case IsoParametrizator::FailParam: this->errorMessage="non possible parameterization cause one of the following reasons:\n Topologycal noise \n Too Low resolution mesh \n Too Bad triangulation \n"; return false; default: this->errorMessage="unknown error"; return false; } } // At this point we are sure that everithing went ok so we can allocate surely the abstract AbstractMesh *abs_mesh = new AbstractMesh(); ParamMesh *para_mesh = new ParamMesh(); Parametrizator.ExportMeshes(*para_mesh,*abs_mesh); CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle; isoPHandle=tri::Allocator<CMeshO>::AddPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); bool isOK=isoPHandle().Init(abs_mesh,para_mesh); ///copy back to original mesh isoPHandle().CopyParametrization<CMeshO>(mesh); if (!isOK) { this->errorMessage="Problems gathering parameterization \n"; return false; } if (!isVMarkenabled) m->clearDataMask(MeshModel::MM_VERTMARK); if (!isFMarkenabled) m->clearDataMask(MeshModel::MM_FACEMARK); return true; } case ISOP_REMESHING : { CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle = tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); bool b=tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle); if (!b) { this->errorMessage="You must compute the Base domain before remeshing. Use the Isoparametrization command."; return false; } int SamplingRate=par.getInt("SamplingRate"); if (!SamplingRate>2) { this->errorMessage="Sampling rate must be >1"; return false; } MeshModel* mm=md.addNewMesh("","Re-meshed"); CMeshO *rem=&mm->cm; DiamSampler DiamSampl; DiamSampl.Init(&isoPHandle()); bool done=DiamSampl.SamplePos(SamplingRate); assert(done); DiamSampl.GetMesh<CMeshO>(*rem); int n_diamonds,inFace,inEdge,inStar,n_merged; DiamSampl.getResData(n_diamonds,inFace,inEdge,inStar,n_merged); Log("INTERPOLATION DOMAINS"); Log("In Face: %d \n",inFace); Log("In Diamond: %d \n",inEdge); Log("In Star: %d \n",inStar); Log("Merged %d vertices\n",n_merged); mm->updateDataMask(MeshModel::MM_FACEFACETOPO); mm->updateDataMask(MeshModel::MM_VERTFACETOPO); PrintStats(rem); tri::UpdateNormal<CMeshO>::PerFace(*rem); return true; } case ISOP_DIAMPARAM : { CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle = tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); bool b=tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle); if (!b) { this->errorMessage="You must compute the Base domain before remeshing. Use the Isoparametrization command."; return false; } float border_size=par.getDynamicFloat("BorderSize"); MeshModel* mm=md.addNewMesh("","Diam-Parameterized"); mm->updateDataMask(MeshModel::MM_WEDGTEXCOORD); mm->updateDataMask(MeshModel::MM_VERTCOLOR); CMeshO *rem=&mm->cm; DiamondParametrizator DiaPara; DiaPara.Init(&isoPHandle()); DiaPara.SetCoordinates<CMeshO>(*rem,border_size); tri::UpdateNormal<CMeshO>::PerFace(*rem); return true; } case ISOP_LOAD : { QString AbsName = par.getString("AbsName"); m->updateDataMask(MeshModel::MM_WEDGTEXCOORD); m->updateDataMask(MeshModel::MM_VERTTEXCOORD); m->updateDataMask(MeshModel::MM_FACECOLOR); m->updateDataMask(MeshModel::MM_VERTQUALITY); m->updateDataMask(MeshModel::MM_FACEMARK); if(!QFile(m->fullName()).exists()) { this->errorMessage="File not exists"; return false; } CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle = tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); bool b=tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle); if (!b) isoPHandle=tri::Allocator<CMeshO>::AddPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); QByteArray ba = AbsName.toLatin1(); char *path=ba.data(); AbstractMesh *abs_mesh = new AbstractMesh(); ParamMesh *para_mesh = new ParamMesh(); bool Done=isoPHandle().LoadBaseDomain<CMeshO>(path,mesh,para_mesh,abs_mesh,true); if (!Done) { this->errorMessage="Abstract domain doesnt fit well with the parametrized mesh"; delete para_mesh; delete abs_mesh; return false; } return true; } case ISOP_SAVE : { m->updateDataMask(MeshModel::MM_VERTQUALITY); CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle = tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); bool b=tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle); if (!b) { this->errorMessage="You must compute the Base domain before remeshing. Use the Isoparametrization command."; return false; } /*QString Qpath=m->fullName();*/ QString AbsName = par.getString("AbsName"); QByteArray ba = AbsName.toLatin1(); char *path=ba.data(); isoPHandle().SaveBaseDomain(path); return true; } case ISOP_TRANSFER: { MeshModel *mmtrg = par.getMesh("targetMesh"); MeshModel *mmsrc = par.getMesh("targetMesh"); CMeshO *trgMesh=&mmtrg->cm; CMeshO *srcMesh=&mmsrc->cm; CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle = tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization"); bool b=tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*srcMesh,isoPHandle); if (!b) { this->errorMessage="Your source mesh must have the abstract isoparametrization. Use the Isoparametrization command."; return false; } IsoTransfer IsoTr; AbstractMesh *abs_mesh = isoPHandle().AbsMesh(); ParamMesh *para_mesh = isoPHandle().ParaMesh(); mmtrg->updateDataMask(MeshModel::MM_WEDGTEXCOORD); mmtrg->updateDataMask(MeshModel::MM_VERTTEXCOORD); mmtrg->updateDataMask(MeshModel::MM_FACECOLOR); mmtrg->updateDataMask(MeshModel::MM_VERTQUALITY); mmtrg->updateDataMask(MeshModel::MM_FACEMARK); IsoTr.Transfer<CMeshO>(isoPHandle(),*trgMesh); isoPHandle().Clear(); tri::Allocator<CMeshO>::DeletePerMeshAttribute(*srcMesh,isoPHandle); isoPHandle=tri::Allocator<CMeshO>::AddPerMeshAttribute<IsoParametrization>(*trgMesh,"isoparametrization"); isoPHandle().AbsMesh()=abs_mesh; isoPHandle().SetParamMesh<CMeshO>(trgMesh,para_mesh); return true; } } return false; }