void ComputeParticlesFallsPosition(MeshModel* base_mesh,MeshModel* cloud_mesh,CMeshO::CoordType dir){ CMeshO::VertexIterator vi; MetroMeshFaceGrid f_grid; f_grid.Set(base_mesh->cm.face.begin(),base_mesh->cm.face.end()); MarkerFace markerFunctor; markerFunctor.SetMesh(&(base_mesh->cm)); RayTriangleIntersectionFunctor<false> RSectFunct; CMeshO::PerVertexAttributeHandle<Particle<CMeshO> > ph= tri::Allocator<CMeshO>::GetPerVertexAttribute<Particle<CMeshO> >(cloud_mesh->cm,"ParticleInfo"); std::vector<CMeshO::VertexPointer> ToDelVec; for(vi=cloud_mesh->cm.vert.begin();vi!=cloud_mesh->cm.vert.end();++vi){ Particle<CMeshO> info=ph[vi]; if((*vi).IsS()){ Point3f p_c=vi->P()+info.face->N().normalized()*0.1; Ray3<float> ray=Ray3<float>(p_c,dir); float di; CMeshO::FacePointer new_f=f_grid.DoRay<RayTriangleIntersectionFunctor<false>,MarkerFace>(RSectFunct,markerFunctor,ray,base_mesh->cm.bbox.Diag(),di); if(new_f!=0){ ph[vi].face=new_f; float u; float v; float t; IntersectionRayTriangle<float>(ray,new_f->P(0),new_f->P(1),new_f->P(2),t,u,v); Point3f bc(1-u-v,u,v); vi->P()=fromBarCoords(bc,new_f); vi->ClearS(); new_f->C()=Color4b::Red; }else{ ToDelVec.push_back(&*vi); } } } for(unsigned int i=0;i<ToDelVec.size();i++){ if(!ToDelVec[i]->IsD()) Allocator<CMeshO>::DeleteVertex(cloud_mesh->cm,*ToDelVec[i]); } }
void DrawDust(MeshModel *base_mesh,MeshModel *cloud_mesh){ if(tri::HasPerWedgeTexCoord(base_mesh->cm) && base_mesh->cm.textures.size()>0){ QImage img; //QFileInfo text_file=QFileInfo(base_mesh->cm.textures[0].c_str()); img.load(base_mesh->cm.textures[0].c_str()); QPainter painter(&img); float w=img.width(); float h=img.height(); painter.setPen(Qt::black); painter.setBrush(Qt::SolidPattern); base_mesh->updateDataMask(MeshModel::MM_WEDGTEXCOORD); CMeshO::PerVertexAttributeHandle<Particle<CMeshO> > ph= tri::Allocator<CMeshO>::GetPerVertexAttribute<Particle<CMeshO> > (cloud_mesh->cm,std::string("ParticleInfo")); CMeshO::VertexIterator vi; for(vi=cloud_mesh->cm.vert.begin();vi!=cloud_mesh->cm.vert.end();++vi){ CMeshO::FacePointer f=ph[vi].face; TexCoord2f t0=f->WT(0); TexCoord2f t1=f->WT(1); TexCoord2f t2=f->WT(2); Point2f p0=Point2f(t0.U()*w,h-t0.V()*h); Point2f p1=Point2f(t1.U()*w,h-t1.V()*h); Point2f p2=Point2f(t2.U()*w,h-t2.V()*h); Point3f bc; Point2f dbc; InterpolationParameters(*f,vi->P(),bc); dbc=p0*bc[0]+p1*bc[1]+p2*bc[2]; painter.drawPoint(dbc[0],dbc[1]); } QString path=QDir::currentPath()+"/dirt_texture.png"; img.save(path,"PNG"); base_mesh->cm.textures.clear(); base_mesh->cm.textures.push_back(path.toStdString()); } }
/** This function compute the repulsion beetwen particles @param MeshModel* b_m - base mesh @param MeshModel* c_m - cloud of points @param int k - max number of particle to repulse @param float l - lenght of the step @return nothing - adhesion factor */ void ComputeRepulsion(MeshModel* b_m,MeshModel *c_m,int k,float l,Point3f g,float a){ CMeshO::PerVertexAttributeHandle<Particle<CMeshO> > ph = Allocator<CMeshO>::GetPerVertexAttribute<Particle<CMeshO> >(c_m->cm,"ParticleInfo"); MetroMeshVertexGrid v_grid; std::vector< Point3<float> > v_points; std::vector<CMeshO::VertexPointer> vp; std::vector<float> distances; v_grid.Set(c_m->cm.vert.begin(),c_m->cm.vert.end(),b_m->cm.bbox); CMeshO::VertexIterator vi; for(vi=c_m->cm.vert.begin();vi!=c_m->cm.vert.end();++vi){ vcg::tri::GetKClosestVertex(c_m->cm,v_grid,k,vi->P(),EPSILON,vp,distances,v_points); for(unsigned int i=0;i<vp.size();i++){CMeshO::VertexPointer v = vp[i]; if(v->P()!=vi->P() && !v->IsD() && !vi->IsD()){ Ray3<float> ray(vi->P(),fromBarCoords(RandomBaricentric(),ph[vp[i]].face)); ray.Normalize(); Point3f dir=ray.Direction(); dir.Normalize(); MoveParticle(ph[vp[i]],vp[i],0.01,1,dir,g,a); } } } }
void associateParticles(MeshModel* b_m,MeshModel* c_m,float &m,float &v,CMeshO::CoordType g){ MetroMeshFaceGrid unifGridFace; Point3f closestPt; CMeshO::PerVertexAttributeHandle<Particle<CMeshO> > ph= tri::Allocator<CMeshO>::AddPerVertexAttribute<Particle<CMeshO> > (c_m->cm,std::string("ParticleInfo")); unifGridFace.Set(b_m->cm.face.begin(),b_m->cm.face.end()); MarkerFace markerFunctor; markerFunctor.SetMesh(&(b_m->cm)); float dist=1; float dist_upper_bound=dist; CMeshO::VertexIterator vi; vcg::face::PointDistanceBaseFunctor<CMeshO::ScalarType> PDistFunct; for(vi=c_m->cm.vert.begin();vi!=c_m->cm.vert.end();++vi){ Particle<CMeshO>* part = new Particle<CMeshO>(); CMeshO::FacePointer f=unifGridFace.GetClosest(PDistFunct,markerFunctor,vi->P(),dist_upper_bound,dist,closestPt); part->face=f; part->face->Q()=part->face->Q()+1; part->mass=m; part->velocity=v; part->v=getVelocityComponent(v,f,g); ph[vi]=*part; } }
int SnapVertexBorder(CMeshO &m, float threshold, vcg::CallBackPos * cb) { tri::Allocator<CMeshO>::CompactVertexVector(m); tri::Allocator<CMeshO>::CompactFaceVector(m); tri::UpdateTopology<CMeshO>::FaceFace(m); tri::UpdateFlags<CMeshO>::FaceBorderFromFF(m); tri::UpdateFlags<CMeshO>::VertexBorderFromFace(m); tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFaceNormalized(m); typedef GridStaticPtr<CMeshO::FaceType, CMeshO::ScalarType > MetroMeshFaceGrid; MetroMeshFaceGrid unifGridFace; typedef tri::FaceTmark<CMeshO> MarkerFace; MarkerFace markerFunctor; vcg::face::PointDistanceBaseFunctor<CMeshO::ScalarType> PDistFunct; tri::UpdateFlags<CMeshO>::FaceClearV(m); unifGridFace.Set(m.face.begin(),m.face.end()); markerFunctor.SetMesh(&m); int faceFound; int K = 20; Point3f startPt; float maxDist = m.bbox.Diag()/20; vector<Point3f> splitVertVec; vector<CMeshO::FacePointer> splitFaceVec; vector<int> splitEdgeVec; for(CMeshO::VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD() && (*vi).IsB()) { int percPos = (tri::Index(m,*vi) *100) / m.vn; cb(percPos,"Snapping vertices"); vector<CMeshO::FacePointer> faceVec; vector<float> distVec; vector<Point3f> pointVec; Point3f u; startPt = (*vi).P(); faceFound = unifGridFace.GetKClosest(PDistFunct,markerFunctor, K, startPt,maxDist, faceVec, distVec, pointVec); CMeshO::FacePointer bestFace = 0; float localThr, bestDist = std::numeric_limits<float>::max(); Point3f bestPoint; int bestEdge; // qDebug("Found %i face for vertex %i",faceFound,vi-m.vert.begin()); for(int i=0;i<faceFound;++i) { const float epsilonSmall = 1e-5; const float epsilonBig = 1e-2; CMeshO::FacePointer fp=faceVec[i]; InterpolationParameters(*fp,fp->cN(),pointVec[i],u); // qDebug(" face %i face for vertex %5.3f %5.3f %5.3f dist %5.3f (%c %c %c)",fp-&*m.face.begin(),u[0],u[1],u[2],distVec[i],IsBorder(*fp,0)?'b':' ',IsBorder(*fp,1)?'b':' ',IsBorder(*fp,2)?'b':' '); for(int j=0;j<3;++j) { if(IsBorder(*fp,j) && !fp->IsV()) { if( u[(j+0)%3] > epsilonBig && u[(j+1)%3] > epsilonBig && u[(j+2)%3] < epsilonSmall ) { if(distVec[i] < bestDist) { bestDist=distVec[i]; //bestPoint=pointVec[i]; bestPoint=(*vi).cP(); bestFace=fp; bestEdge=j; } } } } } // end for each faceFound if(bestFace) localThr = threshold*Distance(bestFace->P0(bestEdge),bestFace->P1(bestEdge)); if(bestDist < localThr && !bestFace->IsV()) { bestFace->SetV(); (*vi).C()= Color4b::Blue; //bestFace->C()=Color4b::LightBlue; (*vi).SetS(); splitVertVec.push_back(bestPoint); splitEdgeVec.push_back(bestEdge); splitFaceVec.push_back(bestFace); } } tri::Allocator<CMeshO>::PointerUpdater<CMeshO::FacePointer> pu; CMeshO::VertexIterator firstVert = tri::Allocator<CMeshO>::AddVertices(m,splitVertVec.size()); CMeshO::FaceIterator firstface = tri::Allocator<CMeshO>::AddFaces(m,splitVertVec.size(),pu); // // ^ ^ // / \ / | \ . // / \ / | \ . // / \ / | \ . // / fp \ / | \ . // / \ / fp | ff \ . // V0 ------------------V2 V0 -------fv---------V2 // i for(size_t i=0;i<splitVertVec.size();++i) { firstVert->P() = splitVertVec[i]; int eInd = splitEdgeVec[i]; CMeshO::FacePointer fp = splitFaceVec[i]; pu.Update(fp); firstface->V(0) = &*firstVert; firstface->V(1) = fp->V2(eInd); firstface->V(2) = fp->V0(eInd); // firstface->C()=Color4b::LightBlue; fp->V0(eInd) = &*firstVert; ++firstface; ++firstVert; } tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFaceNormalized(m); return splitVertVec.size(); }
segMesh::segMesh(MeshModel *model) : image() { CMeshO::VertexIterator vi; CMeshO::FaceIterator fi; int i = 0; double x1, y1, z1, dx, dy, dz; for(vi=model->cm.vert.begin();vi!=model->cm.vert.end();++vi) { Point3f p = vi->P(); x1 = (double)p[0]; y1 = (double)p[1]; z1 = (double)p[2]; if (!i){ minx = maxx = x1; miny = maxy = y1; minz = maxz = z1; } else { if (x1 < minx) minx = x1; if (x1 > maxx) maxx = x1; if (y1 < miny) miny = y1; if (y1 > maxy) maxy = y1; if (z1 < minz) minz = z1; if (z1 > maxz) maxz = z1; } i++; } dx = maxx - minx; dy = maxy - miny; dz = maxz - minz; norm = max(dx,max(dy,dz)); qDebug("Points: %d", i); pix = new struct point[number = w = i]; h = 1; i = 0; x = new int[number]; y = new int[number]; for(vi=model->cm.vert.begin();vi!=model->cm.vert.end();++vi) { Point3f p = vi->P(); pix[i].x = (double)p[0]; pix[i].y = (double)p[1]; pix[i].z = (double)p[2]; pix[i].n = 0; pix[i].valid = 1; pix[i].boundary = NO_BOUND; x[i] = (int)(256 * (pix[i].x - minx) / dx); y[i] = (int)(256 * (pix[i].y - miny) / dy); i++; } i = 0; const CMeshO::VertexType * v0 = &(model->cm.vert[0]); for(fi=model->cm.face.begin();fi!=model->cm.face.end();++fi) { uint a = int(fi->cV(0) - v0); uint b = int(fi->cV(1) - v0); uint c = int(fi->cV(2) - v0); add_neighbour(a,0,b); add_neighbour(a,0,c); add_neighbour(b,0,a); add_neighbour(b,0,c); add_neighbour(c,0,a); add_neighbour(c,0,b); i++; } mesh = model; qDebug("Triangles: %d", i); }
// The Real Core Function doing the actual mesh processing. bool FilterCreate::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos * /*cb*/) { MeshModel* m=md.addNewMesh("",this->filterName(ID(filter))); switch(ID(filter)) { case CR_TETRAHEDRON : vcg::tri::Tetrahedron<CMeshO>(m->cm); break; case CR_ICOSAHEDRON: vcg::tri::Icosahedron<CMeshO>(m->cm); break; case CR_DODECAHEDRON: vcg::tri::Dodecahedron<CMeshO>(m->cm); m->updateDataMask(MeshModel::MM_POLYGONAL); break; case CR_OCTAHEDRON: vcg::tri::Octahedron<CMeshO>(m->cm); break; case CR_TORUS: { float hRadius=par.getFloat("hRadius"); float vRadius=par.getFloat("vRadius"); int hSubdiv=par.getInt("hSubdiv"); int vSubdiv=par.getInt("vSubdiv"); vcg::tri::Torus(m->cm,hRadius,vRadius,hSubdiv,vSubdiv); break; } case CR_RANDOM_SPHERE: { CMeshO tt; int pointNum = par.getInt("pointNum"); int oversamplingFactor =100; if(pointNum <= 100) oversamplingFactor = 1000; if(pointNum >= 10000) oversamplingFactor = 50; if(pointNum >= 100000) oversamplingFactor = 20; vcg::math::MarsenneTwisterRNG rng; vcg::tri::Allocator<CMeshO>::AddVertices(tt,pointNum*50); for(CMeshO::VertexIterator vi=tt.vert.begin();vi!=tt.vert.end();++vi) vcg::math::GeneratePointOnUnitSphereUniform(rng,vi->P()); vcg::tri::UpdateBounding<CMeshO>::Box(tt); const float SphereArea = 4*M_PI; float poissonRadius = 2.0*sqrt((SphereArea / float(pointNum*2))/M_PI); std::vector<vcg::Point3f> poissonSamples; vcg::tri::TrivialSampler<CMeshO> pdSampler(poissonSamples); vcg::tri::SurfaceSampling<CMeshO, vcg::tri::TrivialSampler<CMeshO> >::PoissonDiskParam pp; vcg::tri::SurfaceSampling<CMeshO,vcg::tri::TrivialSampler<CMeshO> >::PoissonDiskPruning(pdSampler, tt, poissonRadius, pp); m->cm.Clear(); vcg::tri::Allocator<CMeshO>::AddVertices(m->cm,poissonSamples.size()); for(size_t i=0;i<poissonSamples.size();++i) { m->cm.vert[i].P()=poissonSamples[i]; m->cm.vert[i].N()=m->cm.vert[i].P(); } } break; case CR_SPHERE: { int rec = par.getInt("subdiv"); float radius = par.getFloat("radius"); m->cm.face.EnableFFAdjacency(); m->updateDataMask(MeshModel::MM_FACEFACETOPO); assert(vcg::tri::HasPerVertexTexCoord(m->cm) == false); vcg::tri::Sphere<CMeshO>(m->cm,rec); for(CMeshO::VertexIterator vi = m->cm.vert.begin();vi!= m->cm.vert.end();++vi) vi->P()=vi->P()*radius; break; } case CR_BOX: { float sz=par.getFloat("size"); vcg::Box3f b(vcg::Point3f(1,1,1)*(sz/2),vcg::Point3f(1,1,1)*(-sz/2)); vcg::tri::Box<CMeshO>(m->cm,b); m->updateDataMask(MeshModel::MM_POLYGONAL); break; } case CR_CONE: float r0=par.getFloat("r0"); float r1=par.getFloat("r1"); float h=par.getFloat("h"); int subdiv=par.getInt("subdiv"); vcg::tri::Cone<CMeshO>(m->cm,r0,r1,h,subdiv); break; } vcg::tri::UpdateBounding<CMeshO>::Box(m->cm); vcg::tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFaceNormalized(m->cm); return true; }