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; }
// The Real Core Function doing the actual mesh processing. // Move Vertex of a random quantity bool ExtraSamplePlugin::applyFilter(QAction *action, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb) { switch(ID(action)) { case FP_DECOMPOSER : { CMeshO &m = md.mm()->cm; CutMesh cm; vcg::tri::Append<CutMesh,CMeshO>::MeshCopy(cm,m); vcg::tri::Allocator<CutMesh>::CompactEveryVector(cm); vcg::tri::UpdateTopology<CutMesh>::FaceFace(cm); vcg::tri::UpdateTopology<CutMesh>::VertexFace(cm); vcg::tri::UpdateNormal<CutMesh>::PerFace(cm); //Get Parameters vcg::Point3f upperPoint = par.getPoint3f("upperPoint"); vcg::Point3f lowerPoint = par.getPoint3f("lowerPoint"); float dihedral = par.getDynamicFloat("dihedral"); float ambient = par.getDynamicFloat("ambient"); float geodesic = par.getDynamicFloat("geodesic"); float geomin = par.getDynamicFloat("geo-factor-min"); float geomax = par.getDynamicFloat("geo-factor-max"); float elength = par.getDynamicFloat("e-length"); CutMesh::FacePointer startFace = NULL; CutMesh::FacePointer endFace = NULL; //getting the closest faces to the passed point parameters TriMeshGrid grid; grid.Set(cm.face.begin(),cm.face.end()); vcg::Point3<CutMesh::ScalarType> closest; float maxDist = cm.bbox.Diag(); float minDist; startFace = vcg::tri::GetClosestFaceBase(cm, grid, upperPoint, maxDist, minDist, closest); endFace = vcg::tri::GetClosestFaceBase(cm, grid, lowerPoint, maxDist, minDist, closest); assert(startFace!=NULL && endFace!=NULL); std::vector<CutVertex::VertexPointer> seedVec; for(int i=0; i<3; i++) seedVec.push_back(startFace->V(i)); //getting the geodesic distance from the start/end face and some other data //that will be used in the weight computation typename CutMesh::template PerFaceAttributeHandle <float> gfH1 = vcg::tri::Allocator<CutMesh>::template AddPerFaceAttribute<float>(cm, std::string("GeoDis1")); vcg::tri::Geodesic<CutMesh>::Compute(cm, seedVec); float max1=0.0f; float maxq=0.0f; //getting also the maximum perFaceQuality value for(CutMesh::FaceIterator fit= cm.face.begin(); fit!=cm.face.end(); fit++){ if(fit->Q()>=maxq) maxq=fit->Q(); gfH1[fit] = (fit->V(0)->Q()+fit->V(1)->Q()+fit->V(2)->Q())/3.0f; if(gfH1[fit]>=max1) max1=gfH1[fit]; } //this functor will be used to compute edge weights on the dual graph WeightFunctor<CutMesh> wf(ambient, dihedral, geodesic, elength, startFace, endFace, gfH1, max1, geomin, geomax, maxq); //start actual computation vcg::tri::GraphBuilder<CutMesh, WeightFunctor<CutMesh> >::Compute(cm, wf, startFace, endFace); vcg::tri::Allocator<CutMesh>::DeletePerFaceAttribute(cm,gfH1); vcg::tri::Append<CMeshO,CutMesh>::MeshCopy(m,cm); return true; } } return false; }
bool FilterGeodesic::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos * /*cb*/) { MeshModel &m=*(md.mm()); CMeshO::FaceIterator fi; CMeshO::VertexIterator vi; switch (ID(filter)) { case FP_QUALITY_POINT_GEODESIC: { m.updateDataMask(MeshModel::MM_VERTFACETOPO); m.updateDataMask(MeshModel::MM_VERTMARK); m.updateDataMask(MeshModel::MM_VERTQUALITY); m.updateDataMask(MeshModel::MM_VERTCOLOR); tri::UpdateFlags<CMeshO>::FaceBorderFromVF(m.cm); tri::UpdateFlags<CMeshO>::VertexBorderFromFace(m.cm); Point3f startPoint = par.getPoint3f("startPoint"); // first search the closest point on the surface; CMeshO::VertexPointer startVertex=0; float minDist= std::numeric_limits<float>::max(); for(vi=m.cm.vert.begin();vi!=m.cm.vert.end();++vi) if(!(*vi).IsD()) if(SquaredDistance(startPoint,(*vi).P()) < minDist) { startVertex=&*vi; minDist=SquaredDistance(startPoint,(*vi).P()); } Log("Input point is %f %f %f Closest on surf is %f %f %f",startPoint[0],startPoint[1],startPoint[2],startVertex->P()[0],startVertex->P()[1],startVertex->P()[2]); // Now actually compute the geodesic distnace from the closest point float dist_thr = par.getAbsPerc("maxDistance"); tri::EuclideanDistance<CMeshO> dd; tri::Geodesic<CMeshO>::Compute(m.cm, vector<CVertexO*>(1,startVertex),dd,dist_thr); // Cleaning Quality value of the unrefernced vertices // Unreached vertexes has a quality that is maxfloat int unreachedCnt=0; float unreached = std::numeric_limits<float>::max(); for(vi=m.cm.vert.begin();vi!=m.cm.vert.end();++vi) if(!(*vi).IsD()) if((*vi).Q() == unreached) { unreachedCnt++; (*vi).Q()=0; } if(unreachedCnt >0 ) Log("Warning: %i vertices were unreacheable from the borders, probably your mesh has unreferenced vertices",unreachedCnt); tri::UpdateColor<CMeshO>::PerVertexQualityRamp(m.cm); } break; case FP_QUALITY_BORDER_GEODESIC: { m.updateDataMask(MeshModel::MM_VERTFACETOPO); m.updateDataMask(MeshModel::MM_VERTMARK); m.updateDataMask(MeshModel::MM_VERTQUALITY); m.updateDataMask(MeshModel::MM_VERTCOLOR); tri::UpdateFlags<CMeshO>::FaceBorderFromVF(m.cm); tri::UpdateFlags<CMeshO>::VertexBorderFromFace(m.cm); bool ret = tri::Geodesic<CMeshO>::DistanceFromBorder(m.cm); // Cleaning Quality value of the unrefernced vertices // Unreached vertexes has a quality that is maxfloat int unreachedCnt=0; float unreached = std::numeric_limits<float>::max(); for(vi=m.cm.vert.begin();vi!=m.cm.vert.end();++vi) if(!(*vi).IsD()) if((*vi).Q() == unreached) { unreachedCnt++; (*vi).Q()=0; } if(unreachedCnt >0 ) Log("Warning: %i vertices were unreacheable from the borders, probably your mesh has unreferenced vertices",unreachedCnt); if(!ret) Log("Mesh Has no borders. No geodesic distance computed"); else tri::UpdateColor<CMeshO>::PerVertexQualityRamp(m.cm); } break; default: assert(0); break; } return true; }
// The Real Core Function doing the actual mesh processing. bool FilterHarmonicPlugin::applyFilter(QAction * action, MeshDocument & md, RichParameterSet & par, vcg::CallBackPos * cb) { switch(ID(action)) { case FP_SCALAR_HARMONIC_FIELD : { typedef vcg::GridStaticPtr<CMeshO::VertexType, CMeshO::ScalarType> VertexGrid; typedef double CoeffScalar; // TODO, when moving the code to a class make it a template (CoeffScalar = double) typedef CMeshO::ScalarType ScalarType; typedef CMeshO::CoordType CoordType; typedef CMeshO::VertexType VertexType; typedef CMeshO::FaceType FaceType; typedef Eigen::Triplet<CoeffScalar> T; typedef Eigen::SparseMatrix<CoeffScalar> SpMat; //sparse matrix type of double CMeshO & m = md.mm()->cm; vcg::tri::Allocator<CMeshO>::CompactFaceVector(m); vcg::tri::Allocator<CMeshO>::CompactVertexVector(m); md.mm()->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTMARK); vcg::tri::UpdateBounding<CMeshO>::Box(m); vcg::tri::UpdateTopology<CMeshO>::FaceFace(m); int n = m.VN(); int fn = m.FN(); std::vector<T> coeffs; // coefficients of the system std::map<size_t,CoeffScalar> sums; // row sum of the coefficient SpMat laplaceMat; // the system to be solved laplaceMat.resize(n, n); Log("Generating coefficients.`"); cb(0, "Generating coefficients..."); vcg::tri::UpdateFlags<CMeshO>::FaceClearV(m); // Iterate over the faces for (size_t i = 0; i < m.face.size(); ++i) { CMeshO::FaceType & f = m.face[i]; if (f.IsD()) { assert(int(i) == fn); break; // TODO FIX the indexing of vertices } assert(!f.IsV()); f.SetV(); // Generate coefficients for each edge for (int idx = 0; idx < 3; ++idx) { CoeffScalar weight; WeightInfo res = ComputeWeight<FaceType, CoeffScalar>(f, idx, weight); switch (res) { case EdgeAlreadyVisited : continue; case Success : break; case BorderEdge : this->errorMessage = "Mesh not closed, cannot compute harmonic field on mesh containing holes or borders"; return false; default: assert(0); } // if (weight < 0) weight = 0; // TODO check if negative weight may be an issue // Add the weight to the coefficients vector for both the vertices of the considered edge size_t v0_idx = vcg::tri::Index(m, f.V0(idx)); size_t v1_idx = vcg::tri::Index(m, f.V1(idx)); coeffs.push_back(T(v0_idx, v1_idx, -weight)); coeffs.push_back(T(v1_idx, v0_idx, -weight)); // Add the weight to the row sum sums[v0_idx] += weight; sums[v1_idx] += weight; } f.SetV(); } // Fill the system matrix Log("Fill the system matrix"); cb(10, "Filling the system matrix..."); laplaceMat.reserve(coeffs.size()); for (std::map<size_t,CoeffScalar>::const_iterator it = sums.begin(); it != sums.end(); ++it) { coeffs.push_back(T(it->first, it->first, it->second)); } laplaceMat.setFromTriplets(coeffs.begin(), coeffs.end()); // Get the two vertices with value set VertexGrid vg; vg.Set(m.vert.begin(), m.vert.end()); vcg::vertex::PointDistanceFunctor<ScalarType> pd; vcg::tri::Tmark<CMeshO, VertexType> mv; mv.SetMesh(&m); mv.UnMarkAll(); CoordType closestP; ScalarType minDist = 0; VertexType * vp0 = vcg::GridClosest(vg, pd, mv, par.getPoint3f("point1"), m.bbox.Diag(), minDist, closestP); VertexType * vp1 = vcg::GridClosest(vg, pd, mv, par.getPoint3f("point2"), m.bbox.Diag(), minDist, closestP); if (vp0 == NULL || vp1 == NULL || vp0 == vp1) { this->errorMessage = "Error occurred for selected points."; return false; } size_t v0_idx = vcg::tri::Index(m, vp0); size_t v1_idx = vcg::tri::Index(m, vp1); // Add penalty factor alpha Log("Setting up the system matrix"); const CoeffScalar alpha = pow(10, 8); Eigen::Matrix<CoeffScalar, Eigen::Dynamic, 1> b, x; // Unknown and known terms vectors b.setZero(n); b(v0_idx) = alpha * par.getFloat("value1"); b(v1_idx) = alpha * par.getFloat("value2"); laplaceMat.coeffRef(v0_idx, v0_idx) += alpha; laplaceMat.coeffRef(v1_idx, v1_idx) += alpha; // Solve system laplacianMat x = b Log("System matrix decomposition..."); cb(20, "System matrix decomposition..."); Eigen::SimplicialLDLT<Eigen::SparseMatrix<CoeffScalar> > solver; // TODO eventually use another solver solver.compute(laplaceMat); if(solver.info() != Eigen::Success) { // decomposition failed this->errorMessage = "System matrix decomposition failed: "; if (solver.info() == Eigen::NumericalIssue) this->errorMessage += "numerical issue."; else if (solver.info() == Eigen::NoConvergence) this->errorMessage += "no convergence."; else if (solver.info() == Eigen::InvalidInput) this->errorMessage += "invalid input."; return false; } Log("Solving the system..."); cb(85, "Solving the system..."); x = solver.solve(b); if(solver.info() != Eigen::Success) { // solving failed this->errorMessage = "System solving failed."; return false; } // Colorize bands for the 0-1 interval if (par.getBool("colorize")) { float steps = 20.0f; for (size_t i = 0; int(i) < n; ++i) { bool on = (int)(x[i]*steps)%2 == 1; if (on) { m.vert[i].C() = vcg::Color4b::ColorRamp(0,2,x[i]); } else { m.vert[i].C() = vcg::Color4b::White; } } } // Set field value into vertex quality attribute for (size_t i = 0; int(i) < n; ++i) { m.vert[i].Q() = x[i]; } cb(100, "Done."); return true; } default : assert(0); } return false; }
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; }