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; }
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 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; }