void LandmarkCapturePlugin::drawFace(CMeshO::FacePointer fp, MeshModel &m, GLArea *gla, QPainter *p) { //glDepthMask(GL_FALSE); //glDisable(GL_DEPTH_TEST); //p->endNativePainting(); //p->save(); //p->setRenderHint(QPainter::TextAntialiasing); //p->setPen(Qt::white); //QFont qFont; //qFont.setStyleStrategy(QFont::NoAntialias); //qFont.setFamily("Helvetica"); //qFont.setPixelSize(12); //p->setFont(qFont); QString buf = QString("f%1\n (%3 %4 %5)").arg(tri::Index(m.cm,fp)).arg(tri::Index(m.cm,fp->V(0))).arg(tri::Index(m.cm,fp->V(1))).arg(tri::Index(m.cm,fp->V(2))); Point3f c=Barycenter(*fp); vcg::glLabel::render(p,c,buf); for(int i=0;i<3;++i) { buf =QString("\nv%1:%2 (%3 %4 %5)").arg(i).arg(fp->V(i) - &m.cm.vert[0]).arg(fp->P(i)[0]).arg(fp->P(i)[1]).arg(fp->P(i)[2]); if( m.hasDataMask(MeshModel::MM_VERTQUALITY) ) buf +=QString(" - Q(%1)").arg(fp->V(i)->Q()); if( m.hasDataMask(MeshModel::MM_WEDGTEXCOORD) ) buf +=QString("- uv(%1 %2) id:%3").arg(fp->WT(i).U()).arg(fp->WT(i).V()).arg(fp->WT(i).N()); if( m.hasDataMask(MeshModel::MM_VERTTEXCOORD) ) buf +=QString("- uv(%1 %2) id:%3").arg(fp->V(i)->T().U()).arg(fp->V(i)->T().V()).arg(fp->V(i)->T().N()); vcg::glLabel::render(p,fp->V(i)->P(),buf); } //p->drawText(QRect(0,0,gla->width(),gla->height()), Qt::AlignLeft | Qt::TextWordWrap, buf); //p->restore(); //p->beginNativePainting(); }
/* Initializes the list of parameters (called by the auto dialog framework) */ void GeometryAgingPlugin::initParameterSet(QAction *action, MeshModel &m, RichParameterSet ¶ms) { if( ID(action) != FP_ERODE) { assert (0); return; } bool hasQ = m.hasDataMask(MeshModel::MM_VERTQUALITY); std::pair<float,float> qRange(0.0, 0.0);; // mesh quality range // retrieve mesh quality range if(hasQ) { qRange = tri::Stat<CMeshO>::ComputePerVertexQualityMinMax(m.cm); if(qRange.second <= qRange.first) hasQ=false; } params.addParam(new RichBool("ComputeCurvature", !hasQ, "ReCompute quality from curvature", "Compute per vertex quality values using mesh mean curvature <br>" "algorithm. In this way only the areas with higher curvature <br>" "will be eroded. If not checked, the quality values already <br>" "present over the mesh will be used.")); params.addParam(new RichBool("SmoothQuality", false, "Smooth vertex quality", "Smooth per vertex quality values. This allows to extend the <br>" "area affected by the erosion process.")); params.addParam(new RichAbsPerc("QualityThreshold", qRange.first+(qRange.second-qRange.first)*0.66, qRange.first, qRange.second, "Min quality threshold", "Represents the minimum quality value two vertexes must have <br>" "to consider the edge they are sharing.")); params.addParam(new RichAbsPerc("EdgeLenThreshold", m.cm.bbox.Diag()*0.02, 0,m.cm.bbox.Diag()*0.5, "Edge len threshold", "The minimum length of an edge. Useful to avoid the creation of too many small faces.")); params.addParam(new RichAbsPerc("ChipDepth", m.cm.bbox.Diag()*0.05, 0, m.cm.bbox.Diag(), "Max chip depth", "The maximum depth of a chip.")); params.addParam(new RichInt("Octaves", 3, "Fractal Octaves", "The number of octaves that are used in the generation of the <br>" "fractal noise using Perlin noise; reasonalble values are in the <br>" "1..8 range. Setting it to 1 means using a simple Perlin Noise.")); params.addParam(new RichAbsPerc("NoiseFreqScale", m.cm.bbox.Diag()/10, 0, m.cm.bbox.Diag(), "Noise frequency scale", "Changes the noise frequency scale: this affects chip dimensions and <br>" "the distance between chips. The value denotes the average values <br>" "between two dents. Smaller number means small and frequent chips.")); params.addParam(new RichFloat("NoiseClamp", 0.5, "Noise clamp threshold [0..1]", "All the noise values smaller than this parameter will be <br> " "considered as 0.")); params.addParam(new RichFloat("DisplacementSteps", 10, "Displacement steps", "The whole displacement process is performed as a sequence of small <br>" "offsets applyed on each vertex. This parameter represents the number <br>" "of steps into which the displacement process will be splitted. <br>" "Useful to avoid the introduction of self intersections. <br>" "Bigger number means better accuracy.")); params.addParam(new RichBool("Selected", m.cm.sfn>0, "Affect only selected faces", "The aging procedure will be applied to the selected faces only.")); params.addParam(new RichBool("StoreDisplacement", false, "Store erosion informations", "Select this option if you want to store the erosion informations <br>" "over the mesh. A new attribute will be added to each vertex <br>" "to contain the displacement offset applied to that vertex.")); }
bool QualityMapperPlugin::StartEdit(MeshModel& m, GLArea *gla ) { if(!m.hasDataMask(MeshModel::MM_VERTQUALITY)) { QMessageBox::warning(gla, tr("Quality Mapper"), tr("The model has no vertex quality"), QMessageBox::Ok); return false; } QMap<int,RenderMode>::iterator it = gla->rendermodemap.find(m.id()); m.updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY); if (it != gla->rendermodemap.end()) { it.value().setColorMode(GLW::CMPerVert); gla->update(); } if(_qualityMapperDialog==0) _qualityMapperDialog = new QualityMapperDialog(gla->window(), m, gla); //drawing histogram //bool ret = _qualityMapperDialog->initEqualizerHistogram(); if ( !_qualityMapperDialog->initEqualizerHistogram() ) { //EndEdit(m, gla); return false; } //drawing transferFunction _qualityMapperDialog->drawTransferFunction(); //dialog ready to be displayed. Show it now! _qualityMapperDialog->show(); connect(_qualityMapperDialog, SIGNAL(closingDialog()),gla,SLOT(endEdit()) ); return true; }
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; }
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; }
bool SdfGpuPlugin::applyFilter(QAction */*filter*/, MeshDocument &md, RichParameterSet & pars, vcg::CallBackPos *cb) { MeshModel* mm = md.mm(); //RETRIEVE PARAMETERS mOnPrimitive = (ONPRIMITIVE) pars.getEnum("onPrimitive"); // assert( mOnPrimitive==ON_VERTICES && "Face mode not supported yet" ); unsigned int numViews = pars.getInt("numberRays"); int peel = pars.getInt("peelingIteration"); mTolerance = pars.getFloat("peelingTolerance"); mPeelingTextureSize = pars.getInt("DepthTextureSize"); mUseVBO = pars.getBool("useVBO"); if(mAction != SDF_DEPTH_COMPLEXITY) mMinCos = vcg::math::Cos(math::ToRad(pars.getFloat("coneAngle")/2.0)); std::vector<Point3f> coneDirVec; if(mAction == SDF_OBSCURANCE) mTau = pars.getFloat("obscuranceExponent"); else if(mAction==SDF_SDF) { mRemoveFalse = pars.getBool("removeFalse"); mRemoveOutliers = pars.getBool("removeOutliers"); } //MESH CLEAN UP setupMesh( md, mOnPrimitive ); //GL INIT if(!initGL(*mm)) return false; // if(mOnPrimitive==ON_VERTICES) vertexDataToTexture(*mm); else faceDataToTexture(*mm); //Uniform sampling of directions over a sphere std::vector<Point3f> unifDirVec; GenNormal<float>::Uniform(numViews,unifDirVec); Log(0, "Number of rays: %i ", unifDirVec.size() ); Log(0, "Number of rays for GPU outliers removal: %i ", coneDirVec.size() ); coneDirVec.clear(); vector<int> mDepthDistrib(peel,0); //Do the actual calculation of sdf or obscurance for each ray unsigned int tracedRays = 0; for(vector<vcg::Point3f>::iterator vi = unifDirVec.begin(); vi != unifDirVec.end(); vi++) { (*vi).Normalize(); TraceRay(peel, (*vi), md.mm()); cb(100*((float)tracedRays/(float)unifDirVec.size()), "Tracing rays..."); this->glContext->makeCurrent(); ++tracedRays; mDepthComplexity = std::max(mDepthComplexity, mTempDepthComplexity); mDepthDistrib[mTempDepthComplexity]++; mTempDepthComplexity = 0; } //read back the result texture and store result in the mesh if(mAction == SDF_OBSCURANCE) { if(mOnPrimitive == ON_VERTICES) applyObscurancePerVertex(*mm,unifDirVec.size()); else applyObscurancePerFace(*mm,unifDirVec.size()); } else if(mAction == SDF_SDF) { if(mOnPrimitive == ON_VERTICES) applySdfPerVertex(*mm); else applySdfPerFace(*mm); } // LP: save output if(mOnPrimitive == ON_FACES) { CMeshO& cm=mm->cm; if(!mm->hasDataMask(MeshModel::MM_VERTFACETOPO)) { mm->updateDataMask(MeshModel::MM_VERTFACETOPO); } if(!mm->hasDataMask(MeshModel::MM_VERTCURV)) { mm->updateDataMask(MeshModel::MM_VERTCURV); // vcg::tri::UpdateCurvature<CMeshO>::VertexCurvature(cm); } //当前目录 QDir dir; //dir.currentPath(); //设置输出文件 std::string ofs=dir.currentPath().toStdString(); ofs.append("/fq_ml.txt"); qDebug()<<"ofs:"<<ofs.c_str(); ofstream oo(ofs.c_str()); int face_size=cm.face.size(); for (int i = 0; i < face_size; i++) { float gc=cm.face[i].Q(); oo<<i<<" "<<gc<<endl; } oo.close(); } Log(0, "Mesh depth complexity %i (The accuracy of the result depends on the value you provided for the max number of peeling iterations, \n if you get warnings try increasing" " the peeling iteration parameter)\n", mDepthComplexity ); //Depth complexity distribution log. Useful to know which is the probability to find a number of layers looking at the mesh or scene. Log(0, "Depth complexity NumberOfViews\n", mDepthComplexity ); for(int j = 0; j < peel; j++) { Log(0, " %i %i\n", j, mDepthDistrib[j] ); } //Clean & Exit releaseGL(*mm); mDepthComplexity = 0; return true; }
bool EditAreslpPlugin::StartEdit(MeshModel &mm, GLArea *gla) { qDebug()<<"EditAreslpPlugin StartEdit"; if(!mm.hasDataMask(MeshModel::MM_VERTQUALITY)) { mm.updateDataMask(MeshModel::MM_VERTQUALITY); } if(!mm.hasDataMask(MeshModel::MM_FACEQUALITY)) { mm.updateDataMask(MeshModel::MM_FACEQUALITY); } AreslpDialog dialog; dialog.exec(); std::vector<int> pointset=dialog.pointset_; std::vector<int> faceset=dialog.faceset_; std::vector<int> patchset=dialog.patchset_; //Debug the content of above two vector for(int i = 0; i < pointset.size(); i++) { qDebug()<<pointset[i]; } for(int i = 0; i < faceset.size(); i++) { qDebug()<<faceset[i]; } for(int i = 0; i < patchset.size(); i++) { qDebug()<<patchset[i]; } CMeshO& cm = mm.cm; int point_size = cm.vert.size(); if(pointset.size()!=0){ //先把之前设置的值清空 for(int i = 0; i < point_size; i++) { cm.vert[i].Q() = 0; } for(int i = 0; i < pointset.size(); i++) { cm.vert[pointset[i]].Q() = 1; } } int face_size=cm.face.size(); if(faceset.size()!=0){ //先把之前设置的值清空 for(int i = 0; i < face_size; i++) { cm.face[i].Q() = 0; } for(int i = 0; i < faceset.size(); i++) { cm.face[faceset[i]].Q() = 1; } } if(patchset.size()!=0){ //patch std::map<int,double> qm; for (int i = 0; i < patchset.size(); i++) { std::string tstring="faceq"; tstring.append(boost::lexical_cast<std::string>(patchset[i])); tstring.append(".txt"); qDebug()<<tstring.c_str(); std::ifstream ifile(tstring.c_str()); int ii; double v; while(ifile >> ii >> v) { // qDebug()<<i<<" "<<v; qm.insert(make_pair<int,double>(ii,v)); } ifile.close(); } for (int i = 0; i < face_size; i++) { if (qm.find(i)!=qm.end()) { cm.face[i].Q()=qm[i]; }else{ cm.face[i].Q()=0; } } }
bool JSONIOPlugin::save(const QString & formatName,const QString & fileName, MeshModel & m, const int mask, const RichParameterSet & par, vcg::CallBackPos * cb, QWidget * parent) { (void)par; (void)cb; (void)parent; vcg::tri::Allocator<CMeshO>::CompactVertexVector(m.cm); vcg::tri::Allocator<CMeshO>::CompactFaceVector(m.cm); const size_t maxValuesPerLine = 10; // must be > 0 if (formatName.toUpper() != tr("JSON")) return false; const bool hasPerVertexPosition = true; const bool hasPerVertexNormal = ((mask & vcg::tri::io::Mask::IOM_VERTNORMAL) != 0) && m.hasDataMask(MeshModel::MM_VERTNORMAL); const bool hasPerVertexColor = ((mask & vcg::tri::io::Mask::IOM_VERTCOLOR) != 0) && m.hasDataMask(MeshModel::MM_VERTCOLOR); const bool hasPerVertexTexCoord = ((mask & vcg::tri::io::Mask::IOM_VERTTEXCOORD) != 0) && m.hasDataMask(MeshModel::MM_VERTTEXCOORD); const CMeshO & cm = m.cm; const std::string filename = QFile::encodeName(fileName).constData(); std::ofstream os(filename.c_str()); if (!os.is_open()) return false; os << "{" << std::endl; os << " \"version\" : \"0.1.0\"," << std::endl; os << std::endl; os << " \"comment\" : \"Generated by MeshLab JSON Exporter\"," << std::endl; os << std::endl; os << " \"id\" : 1," << std::endl; os << " \"name\" : \"mesh\"," << std::endl; os << std::endl; os << " \"vertices\" :" << std::endl; os << " [" << std::endl; bool prevDone = false; if (hasPerVertexPosition) { os << " {" << std::endl; os << " \"name\" : \"position_buffer\"," << std::endl; os << " \"size\" : 3," << std::endl; os << " \"type\" : \"float32\"," << std::endl; os << " \"normalized\" : false," << std::endl; os << " \"values\" :" << std::endl; os << " [" << std::endl; size_t it = 0; const size_t sz = cm.vert.size(); while (it < sz) { const size_t n = std::min(it + maxValuesPerLine, sz); if (n > 0) { os << " "; { const CMeshO::VertexType::CoordType & p = cm.vert[it].cP(); os << p[0] << ", " << p[1] << ", " << p[2]; it++; } for (; it<n; ++it) { const CMeshO::VertexType::CoordType & p = cm.vert[it].cP(); os << ", " << p[0] << ", " << p[1] << ", " << p[2]; } if (it <= (sz - 1)) { os << ","; } os << std::endl; } } os << " ]" << std::endl; os << " }"; prevDone = true; } if (hasPerVertexNormal) { if (prevDone) { os << "," << std::endl; os << std::endl; } os << " {" << std::endl; os << " \"name\" : \"normal_buffer\"," << std::endl; os << " \"size\" : 3," << std::endl; os << " \"type\" : \"float32\"," << std::endl; os << " \"normalized\" : false," << std::endl; os << " \"values\" :" << std::endl; os << " [" << std::endl; size_t it = 0; const size_t sz = cm.vert.size(); while (it < sz) { const size_t n = std::min(it + maxValuesPerLine, sz); if (n > 0) { os << " "; { const CMeshO::VertexType::NormalType & n = cm.vert[it].cN(); os << n[0] << ", " << n[1] << ", " << n[2]; it++; } for (; it<n; ++it) { const CMeshO::VertexType::NormalType & n = cm.vert[it].cN(); os << ", " << n[0] << ", " << n[1] << ", " << n[2]; } if (it <= (sz - 1)) { os << ","; } os << std::endl; } } os << " ]" << std::endl; os << " }"; prevDone = true; } if (hasPerVertexColor) { if (prevDone) { os << "," << std::endl; os << std::endl; } os << " {" << std::endl; os << " \"name\" : \"color_buffer\"," << std::endl; os << " \"size\" : 4," << std::endl; os << " \"type\" : \"uint8\"," << std::endl; os << " \"normalized\" : true," << std::endl; os << " \"values\" :" << std::endl; os << " [" << std::endl; size_t it = 0; const size_t sz = cm.vert.size(); while (it < sz) { const size_t n = std::min(it + maxValuesPerLine, sz); if (n > 0) { os << " "; { const CMeshO::VertexType::ColorType & c = cm.vert[it].cC(); os << int(c[0]) << ", " << int(c[1]) << ", " << int(c[2]) << ", " << int(c[3]); it++; } for (; it<n; ++it) { const CMeshO::VertexType::ColorType & c = cm.vert[it].cC(); os << ", " << int(c[0]) << ", " << int(c[1]) << ", " << int(c[2]) << ", " << int(c[3]); } if (it <= (sz - 1)) { os << ","; } os << std::endl; } } os << " ]" << std::endl; os << " }"; prevDone = true; } if (hasPerVertexTexCoord) { if (prevDone) { os << "," << std::endl; os << std::endl; } os << " {" << std::endl; os << " \"name\" : \"texcoord_buffer\"," << std::endl; os << " \"size\" : 2," << std::endl; os << " \"type\" : \"float32\"," << std::endl; os << " \"normalized\" : false," << std::endl; os << " \"values\" :" << std::endl; os << " [" << std::endl; size_t it = 0; const size_t sz = cm.vert.size(); while (it < sz) { const size_t n = std::min(it + maxValuesPerLine, sz); if (n > 0) { os << " "; { const CMeshO::VertexType::TexCoordType & t = cm.vert[it].cT(); os << t.P()[0] << ", " << t.P()[1]; it++; } for (; it<n; ++it) { const CMeshO::VertexType::TexCoordType & t = cm.vert[it].cT(); os << ", " << t.P()[0] << ", " << t.P()[1]; } if (it <= (sz - 1)) { os << ","; } os << std::endl; } } os << " ]" << std::endl; os << " }"; prevDone = true; } if (prevDone) { os << std::endl; } os << " ]," << std::endl; os << std::endl; os << " \"connectivity\" :" << std::endl; os << " [" << std::endl; if ((m.cm.vn > 0) && (m.cm.fn > 0)) { os << " {" << std::endl; os << " \"name\" : \"triangles\"," << std::endl; os << " \"mode\" : \"triangles_list\"," << std::endl; os << " \"indexed\" : true," << std::endl; os << " \"indexType\" : \"uint32\"," << std::endl; os << " \"indices\" :" << std::endl; os << " [" << std::endl; { const CMeshO::VertexType * v0 = &(m.cm.vert[0]); size_t k = 0; size_t c = 0; const size_t sz = cm.fn; while (c < sz) { const size_t n = std::min(c + maxValuesPerLine, sz); if (n > 0) { os << " "; { while (cm.face[k].IsD()) k++; const CMeshO::FaceType & f = cm.face[k]; os << int(f.cV(0) - v0) << ", " << int(f.cV(1) - v0) << ", " << int(f.cV(2) - v0); c++; k++; } for (; c<n; ++c) { while (cm.face[k].IsD()) k++; const CMeshO::FaceType & f = cm.face[k]; os << ", " << int(f.cV(0) - v0) << ", " << int(f.cV(1) - v0) << ", " << int(f.cV(2) - v0); k++; } if (c <= (sz - 1)) { os << ","; } os << std::endl; } } } os << " ]" << std::endl; os << " }" << std::endl; } os << " ]," << std::endl; os << std::endl; os << " \"mapping\" :" << std::endl; os << " [" << std::endl; if ((m.cm.vn > 0) && (m.cm.fn > 0)) { os << " {" << std::endl; os << " \"name\" : \"standard\"," << std::endl; os << " \"primitives\" : \"triangles\"," << std::endl; os << " \"attributes\" :" << std::endl; os << " [" << std::endl; prevDone = false; if (hasPerVertexPosition) { os << " {" << std::endl; os << " \"source\" : \"position_buffer\"," << std::endl; os << " \"semantic\" : \"position\"," << std::endl; os << " \"set\" : 0" << std::endl; os << " }"; prevDone = true; } if (hasPerVertexNormal) { if (prevDone) { os << "," << std::endl; } os << " {" << std::endl; os << " \"source\" : \"normal_buffer\"," << std::endl; os << " \"semantic\" : \"normal\"," << std::endl; os << " \"set\" : 0" << std::endl; os << " }"; prevDone = true; } if (hasPerVertexColor) { if (prevDone) { os << "," << std::endl; } os << " {" << std::endl; os << " \"source\" : \"color_buffer\"," << std::endl; os << " \"semantic\" : \"color\"," << std::endl; os << " \"set\" : 0" << std::endl; os << " }"; prevDone = true; } if (hasPerVertexTexCoord) { if (prevDone) { os << "," << std::endl; } os << " {" << std::endl; os << " \"source\" : \"texcoord_buffer\"," << std::endl; os << " \"semantic\" : \"texcoord\"," << std::endl; os << " \"set\" : 0" << std::endl; os << " }"; prevDone = true; } if (prevDone) { os << std::endl; } os << " ]" << std::endl; os << " }" << std::endl; } os << " ]," << std::endl; os << std::endl; os << " \"custom\" : null" << std::endl; os << "}" << std::endl; os.close(); return true; }
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; }