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()); } }
/** @def This function simulate the movement of the cloud mesh, it requires that every point is associated with a Particle data structure @param MeshModel cloud - Mesh of points @param Point3f force - Direction of the force @param float l - Lenght of the movementstep @param float t - Time Step @return nothing */ void MoveCloudMeshForward(MeshModel *cloud,MeshModel *base,Point3f g,Point3f force,float l,float a,float t,int r_step){ CMeshO::PerVertexAttributeHandle<Particle<CMeshO> > ph = Allocator<CMeshO>::GetPerVertexAttribute<Particle<CMeshO> >(cloud->cm,"ParticleInfo"); CMeshO::VertexIterator vi; for(vi=cloud->cm.vert.begin();vi!=cloud->cm.vert.end();++vi) if(!vi->IsD()) MoveParticle(ph[vi],&*vi,l,t,force,g,a); //Handle falls Particle ComputeParticlesFallsPosition(base,cloud,g); //Compute Particles Repulsion for(int i=0;i<r_step;i++) ComputeRepulsion(base,cloud,50,l,g,a); }
/** 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; }
void EditPointPlugin::Decorate(MeshModel &m, GLArea * gla, QPainter *p) { this->RealTimeLog("Point Selection",m.shortName(), "<table>" "<tr><td width=50> Hop Thr:</td><td width=100 align=right><b >%8.3f </b></td><td><i> (Wheel to change it)</i> </td></tr>" "<tr><td> Radius: </td><td width=70 align=right><b> %8.3f </b></td><td><i> (Drag or Alt+Wheel to change it)</i></td></tr>" "</table>",this->maxHop,this->dist); /* When the user first click we have to find the point under the mouse pointer. At the same time we need to compute the Dijkstra algorithm over the knn-graph in order to find the distance between the selected point and the others. */ if(haveToPick) { glPushMatrix(); glMultMatrix(m.cm.Tr); vector<CMeshO::VertexPointer> NewSel; GLPickTri<CMeshO>::PickVert(cur.x(), gla->height() - cur.y(), m.cm, NewSel); if(NewSel.size() > 0) { startingVertex = NewSel.front(); tri::ComponentFinder<CMeshO>::Dijkstra(m.cm, *startingVertex, K, this->maxHop, this->NotReachableVector); ComponentVector.push_back(startingVertex); } haveToPick = false; glPopMatrix(); } /* When at least a point is selected we need to draw the selection */ if (startingVertex != NULL) { glPushMatrix(); glMultMatrix(m.cm.Tr); glPushAttrib(GL_ENABLE_BIT ); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glDepthRange (0.0, 0.9999); glDepthFunc(GL_LEQUAL); glPointSize(6.f); tri::UpdateSelection<CMeshO>::VertexClear(m.cm); /* In OldComponentVector we find all the points selected until the last click of the mouse. The other points are saved in ComponentVector. With two different structures for old and new selection we can add or subtract one from each other. */ switch (composingSelMode) { case SMSub: for(vector<CMeshO::VertexPointer>::iterator vi = OldComponentVector.begin(); vi != OldComponentVector.end(); ++vi) { (*vi)->SetS(); } for(vector<CMeshO::VertexPointer>::iterator vi = ComponentVector.begin(); vi != ComponentVector.end(); ++vi) { (*vi)->ClearS(); } break; case SMAdd: for(vector<CMeshO::VertexPointer>::iterator vi = OldComponentVector.begin(); vi != OldComponentVector.end(); ++vi) { (*vi)->SetS(); } for(vector<CMeshO::VertexPointer>::iterator vi = ComponentVector.begin(); vi != ComponentVector.end(); ++vi) { (*vi)->SetS(); } break; case SMClear: for(vector<CMeshO::VertexPointer>::iterator vi = ComponentVector.begin(); vi != ComponentVector.end(); ++vi) { (*vi)->SetS(); } break; } /* The actual selection is drawn in red (instead of the automatic drawing of selected vertex of MeshLab) */ glBegin(GL_POINTS); glColor4f(1,0,0,.5f); for (CMeshO::VertexIterator vi = m.cm.vert.begin(); vi != m.cm.vert.end(); vi++) { if (vi->IsS()) glVertex(vi->cP()); } glEnd(); /* Borders points are drawn in yellow. */ glBegin(GL_POINTS); glColor4f(1,1,0,.5f); for(vector<CMeshO::VertexPointer>::iterator vi = BorderVector.begin(); vi != BorderVector.end(); ++vi) { if ((*vi)->IsS()) glVertex((*vi)->cP()); } glEnd(); /* If the "fitting plane" plugin is selected we draw a light blue circle to visualize the actual plane found by the algorithm (and the fitted points). */ if (editType == SELECT_FITTING_PLANE_MODE) { fittingCircle.Clear(); vcg::tri::OrientedDisk<CMeshO>(fittingCircle, 192, fittingPlane.Projection(startingVertex->cP()), fittingPlane.Direction(), this->fittingRadius); glBegin(GL_TRIANGLE_FAN); glColor4f(0.69,0.93,0.93,.7f); CMeshO::VertexIterator vi; for (vi = fittingCircle.vert.begin(); vi != fittingCircle.vert.end(); vi++) { glVertex(vi->cP()); } vi = fittingCircle.vert.begin(); vi++; glVertex(vi->cP()); glEnd(); } glPopAttrib(); glPopMatrix(); } }