diff --git a/src/fgt/filter_dirt/dirt_utils.h b/src/fgt/filter_dirt/dirt_utils.h index f374f06a1..a9ad4a416 100644 --- a/src/fgt/filter_dirt/dirt_utils.h +++ b/src/fgt/filter_dirt/dirt_utils.h @@ -24,6 +24,9 @@ #define DIRT_UTILS_H //Include Files +#include +#include +#include #include #include #include @@ -57,11 +60,13 @@ using namespace vcg; using namespace tri; + typedef GridStaticPtr MetroMeshFaceGrid; typedef GridStaticPtr MetroMeshVertexGrid; typedef FaceTmark MarkerFace; #define PI 3.14159265 +#define EPSILON 0.0001 /** @def Generate random barycentric coordinates @@ -113,20 +118,38 @@ CMeshO::CoordType fromBarCoords(Point3f bc,CMeshO::FacePointer f){ @return a point in the face f near the edge e */ -CMeshO::CoordType GetSafePosition(CMeshO::FacePointer f,int e){ - +CMeshO::CoordType GetSafePosition(CMeshO::CoordType p,CMeshO::FacePointer f,int e){ + CMeshO::CoordType safe_p; Point3f p0=f->P(0); Point3f p1=f->P(1); Point3f p2=f->P(2); + Point3f bc; +/* - Point3f bc; + InterpolationParameters(*f,p,bc); + safe_p=fromBarCoords(bc,f); + */ + /* switch(e){ + + case 0:{ + break; + } + case 1:{ + break; + } + case 2:{ + break; + } + + } + +*/ bc[0]=0.33f; bc[1]=0.33f; bc[2]=1-bc[0]-bc[1]; CMeshO::CoordType pc=fromBarCoords(bc,f); - CMeshO::CoordType safe_p; switch(e){ @@ -163,7 +186,25 @@ CMeshO::CoordType GetSafePosition(CMeshO::FacePointer f,int e){ */ bool IsOnFace(Point3f p, CMeshO::FacePointer f){ - float EPSILON=0.00001; + + //Version 1 +/* + float a_tot=DoubleArea(*f); + + + vcg::Triangle3 t0(f->P(0),f->P(1),p); + vcg::Triangle3 t1(f->P(1),f->P(2),p); + vcg::Triangle3 t2(f->P(2),f->P(0),p); + + float a0=DoubleArea(t0); + float a1=DoubleArea(t1); + float a2=DoubleArea(t2); + float diff=a_tot-a0+a1+a2; + if(math::Abs(diff)V(0)->P(); Point3f b=f->V(2)->P(); @@ -190,30 +231,33 @@ bool IsOnFace(Point3f p, CMeshO::FacePointer f){ if(math::Abs(u)= 0) && (v >= 0) && (u + v <=1+EPSILON); + + + /*Version 3 + + Point3f bc; + InterpolationParameters(*f,p,bc); + + if(bc[0]<0 || bc[1] <0 || bc [2] <0 || bc[0]+bc[1]+bc[2]>1) return false; + return true; + */ }; -float GetElapsedTime(float t,Point3f pi,Point3f pm,Point3f pf){ +float GetRemainingTime(float t,Point3f pi,Point3f pm,Point3f pf){ + float time; - float d1=Distance(pi,pf); - float d2=Distance(pi,pm); - - return t-t*(d2/d1); + float d1=Distance(pi,pm); + float d2=Distance(pi,pf); + float d=d2-d1; + if(d>0) time=t-t*d/d2; + else return 0; }; -bool IsOnEdge(CMeshO::CoordType p,CMeshO::FacePointer f){ - if(f==0) return false; - float bc[3]; - //f->C()=Color4b::Green; - InterpolationParameters(*f,f->N(),p,bc[0],bc[1],bc[2]); - if(bc[0]==0.0f || bc[1]==0.0f || bc[2]==0.0f) return true; - return false; -}; - - +//To delete? CMeshO::CoordType ComputeVelocity(CMeshO::CoordType vi,CMeshO::CoordType ac,float t){ CMeshO::CoordType n_vel; @@ -224,6 +268,7 @@ CMeshO::CoordType ComputeVelocity(CMeshO::CoordType vi,CMeshO::CoordType ac,floa return n_vel; }; +//To delete? float UpdateVelocity(CMeshO::CoordType pi,CMeshO::CoordType pf,CMeshO::CoordType v,float m,CMeshO::FacePointer &face,CMeshO::CoordType force){ CMeshO::CoordType new_vel; @@ -247,24 +292,13 @@ float UpdateVelocity(CMeshO::CoordType pi,CMeshO::CoordType pf,CMeshO::CoordType return new_v; }; -CMeshO::CoordType ComputeAcceleration(float m,CMeshO::FacePointer face,CMeshO::CoordType dir){ - CMeshO::CoordType acc; - Point3f n= face->N(); - float a=n[0]*dir[0]+n[1]*dir[1]+n[2]*dir[2]; - - acc[0]=dir[0]-a*n[0]; - acc[1]=dir[1]-a*n[1]; - acc[2]=dir[2]-a*n[2]; - - return acc; -}; /** @def */ -CMeshO::CoordType GetVelocityComponents(float v,CMeshO::FacePointer face){ +Point3f GetVelocityComponents(float v,CMeshO::FacePointer face){ Point3f vel; Point3f n=face->cN(); @@ -312,8 +346,6 @@ CMeshO::CoordType StepForward(CMeshO::CoordType p,float v,float m,CMeshO::FacePo Point3f n= face->N(); float a=n[0]*dir[0]+n[1]*dir[1]+n[2]*dir[2]; - - Point3f f; //Point3f vel=GetVelocityComponents(v,face); Point3f vel; @@ -326,47 +358,88 @@ CMeshO::CoordType StepForward(CMeshO::CoordType p,float v,float m,CMeshO::FacePo f[1]=dir[1]-a*n[1]; f[2]=dir[2]-a*n[2]; - new_pos[0]=(p[0]+vel[0]*t+0.5*(f[0]/m)*pow(t,2))*l; - new_pos[1]=(p[1]+vel[1]*t+0.5*(f[1]/m)*pow(t,2))*l; - new_pos[2]=(p[2]+vel[2]*t+0.5*(f[2]/m)*pow(t,2))*l; + + + new_pos[0]=p[0]+(vel[0]*t+0.5*(f[0]/m)*pow(t,2))*l; + new_pos[1]=p[1]+(vel[1]*t+0.5*(f[1]/m)*pow(t,2))*l; + new_pos[2]=p[2]+(vel[2]*t+0.5*(f[2]/m)*pow(t,2))*l; return new_pos; }; void DrawDust(MeshModel *base_mesh,MeshModel *cloud_mesh){ - if(base_mesh->cm.textures.size()>0){ - base_mesh->updateDataMask(MeshModel::MM_VERTTEXCOORD); + if(base_mesh->cm.HasPerWedgeTexCoord() && 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()); - CMeshO::PerVertexAttributeHandle > ph= tri::Allocator::AddPerVertexAttribute > (cloud_mesh->cm,std::string("ParticleInfo")); + 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 > ph= tri::Allocator::GetPerVertexAttribute > (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 p0=f->V(0)->T(); - TexCoord2f p1=f->V(1)->T(); - TexCoord2f p2=f->V(2)->T(); - QImage img; - img.load(base_mesh->cm.textures[0].c_str()); - - QPainter painter(&img); - painter.drawPoint(p0.U(),p0.V()); + 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); + + + //QPolygonF polygon; + //polygon.append(QPointF(p0[0],p0[1])); + //polygon.append(QPointF(p1[0],p1[1])); + //polygon.append(QPointF(p2[0],p2[1])); + + Point3f bc; + Point2f dbc; + InterpolationParameters(*f,vi->P(),bc); + dbc=p0*bc[0]+p1*bc[1]+p2*bc[2]; + //painter.drawConvexPolygon(polygon); + 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()); + } - /* float base_color=255; - float s_color; - std::pair minmax = tri::Stat::ComputePerFaceQualityMinMax(m->cm); - CMeshO::FaceIterator fi; - for(fi = m->cm.face.begin(); fi != m->cm.face.end(); ++fi) - { - s_color=base_color*(1-(((*fi).Q()-minmax.first)/(minmax.second-minmax.first))); - (*fi).C()=Color4b(s_color, s_color, s_color, 0); - } - */ +}; + + +void ColorizeMesh(MeshModel* m){ + CMeshO::FaceIterator fi; + float base_color=255; + float s_color; + for(fi = m->cm.face.begin(); fi != m->cm.face.end(); ++fi){ + s_color=(*fi).Q(); + if(s_color>255) s_color=255; + (*fi).C()=Color4b(base_color-s_color,base_color-s_color, base_color-s_color, 0); + } + + + /*float base_color=255; + float s_color; + std::pair minmax = tri::Stat::ComputePerFaceQualityMinMax(m->cm); + CMeshO::FaceIterator fi; + for(fi = m->cm.face.begin(); fi != m->cm.face.end(); ++fi){ + s_color=base_color*(1-(((*fi).Q()-minmax.first)/(minmax.second-minmax.first))); + (*fi).C()=Color4b(s_color, s_color, s_color, 0); + } +*/ }; @@ -500,6 +573,8 @@ int ComputeIntersection(CMeshO::CoordType p1,CMeshO::CoordType p2,CMeshO::FacePo }; + + /** @def Compute the Normal Dust Amount Function per face of a Mesh m @@ -517,7 +592,6 @@ void ComputeNormalDustAmount(MeshModel* m,CMeshO::CoordType u,float k,float s){ float d; for(fi=m->cm.face.begin();fi!=m->cm.face.end();++fi){ d=k/s+(1+k/s)*pow(fi->N().dot(u),s); - fi->Q()=d; } @@ -562,7 +636,6 @@ void ComputeSurfaceExposure(MeshModel* m,int r,int n_ray){ eh[fi]=0; face=f_grid.DoRay,MarkerFace>(RSectFunct,markerFunctor,ray,30,di); if(di!=0){ - fi->C()=Color4b::Blue; xi=xi+(dh/(dh-di)); } @@ -593,7 +666,7 @@ bool GenerateParticles(MeshModel* m,std::vector &cpv,std::vec float a0=0; float a=0; float a1=0; - + int n_dust=0; for(fi=m->cm.face.begin();fi!=m->cm.face.end();++fi){ a1=a0+r*eh[fi]; @@ -608,9 +681,9 @@ bool GenerateParticles(MeshModel* m,std::vector &cpv,std::vec if(eh[fi]==1) a=1; else a=0; - int n_dust=(int)d*fi->Q()*a; + n_dust=(int)d*fi->Q()*a; - for(int i=0;iP(0)*p[0]+fi->P(1)*p[1]+fi->P(2)*p[2]; @@ -634,8 +707,8 @@ return true; */ void associateParticles(MeshModel* b_m,MeshModel* c_m,float m,float v){ - MetroMeshFaceGrid unifGridFace; + MetroMeshFaceGrid unifGridFace; Point3f closestPt; CMeshO::PerVertexAttributeHandle > ph= tri::Allocator::AddPerVertexAttribute > (c_m->cm,std::string("ParticleInfo")); unifGridFace.Set(b_m->cm.face.begin(),b_m->cm.face.end()); @@ -643,19 +716,19 @@ void associateParticles(MeshModel* b_m,MeshModel* c_m,float m,float v){ markerFunctor.SetMesh(&(b_m->cm)); float dist=1; float dist_upper_bound=dist; - CMeshO::VertexIterator vi; - vcg::face::PointDistanceBaseFunctor PDistFunct; - for(vi=c_m->cm.vert.begin();vi!=c_m->cm.vert.end();++vi){ Particle part; part.face=unifGridFace.GetClosest(PDistFunct,markerFunctor,vi->P(),dist_upper_bound,dist,closestPt); + part.face->Q()=part.face->Q()+1; part.mass=m; part.vel=v; - part.face->C()=Color4b::Blue; ph[vi]=part; } + + + }; @@ -667,25 +740,26 @@ void associateParticles(MeshModel* b_m,MeshModel* c_m,float m,float v){ @return nothing */ void prepareMesh(MeshModel* m){ - //clean flags - tri::UpdateFlags::FaceClear(m->cm); + m->updateDataMask(MeshModel::MM_FACEFACETOPO); m->updateDataMask(MeshModel::MM_FACEMARK); m->updateDataMask(MeshModel::MM_FACECOLOR); m->updateDataMask(MeshModel::MM_VERTQUALITY); m->updateDataMask(MeshModel::MM_FACEQUALITY); - //m->updateDataMask(MeshModel::MM_WEDGTEXCOORD); + m->updateDataMask(MeshModel::MM_FACENORMAL); + tri::UnMarkAll(m->cm); + //clean Mesh tri::Allocator::CompactFaceVector(m->cm); - tri::Clean::RemoveUnreferencedVertex(m->cm); tri::Clean::RemoveDuplicateVertex(m->cm); tri::Allocator::CompactVertexVector(m->cm); + tri::UpdateFlags::FaceClear(m->cm); //update Mesh @@ -714,17 +788,20 @@ void MoveParticle(Particle &info,CMeshO::VertexPointer p,float l,int t,P new_pos=StepForward(current_pos,velocity,mass,current_face,dir,l,time); while(!IsOnFace(new_pos,current_face)){ int edge=ComputeIntersection(current_pos,new_pos,current_face,new_face,int_pos); - time=GetElapsedTime(time,current_pos,int_pos,new_pos); + current_face->C()=Color4b::Blue; + current_face->Q()=current_face->Q()+1;//(time -r_time); velocity=velocity/2; + time=GetRemainingTime(time,current_pos,int_pos,new_pos); if(time>0.001){ current_face=new_face; current_pos=int_pos; new_pos=StepForward(current_pos,velocity,mass,current_face,dir,l,time); }else{ - new_pos=GetSafePosition(new_face,current_face->FFi(edge)); + new_pos=GetSafePosition(int_pos,new_face,current_face->FFi(edge)); current_face=new_face; } } + current_face->Q()=current_face->Q()+1; p->P()=new_pos; info.vel=velocity; info.face=current_face; @@ -739,7 +816,7 @@ void MoveParticle(Particle &info,CMeshO::VertexPointer p,float l,int t,P @param MeshModel* c_m - cloud of points @param int k - max number of particle to repulse - +oveC @return nothing */ void ComputeRepulsion(MeshModel *c_m,int k){ @@ -756,7 +833,7 @@ void ComputeRepulsion(MeshModel *c_m,int k){ 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(),0.05f,vp,distances,v_points); + vcg::tri::GetKClosestVertex(c_m->cm,v_grid,k,vi->P(),0.0001f,vp,distances,v_points); for(int i=0;i ray=Ray3(vi->P(),dir); @@ -776,7 +853,7 @@ void ComputeRepulsion(MeshModel *c_m,int k){ @return nothing */ -void MoveCloudMeshForward(MeshModel *cloud,Point3f force,float l,float t){ +void MoveCloudMeshForward(MeshModel *cloud,Point3f force,float l,float t,int r_step){ CMeshO::PerVertexAttributeHandle > ph = Allocator::GetPerVertexAttribute >(cloud->cm,"ParticleInfo"); CMeshO::VertexIterator vi; @@ -784,8 +861,8 @@ void MoveCloudMeshForward(MeshModel *cloud,Point3f force,float l,float t){ for(vi=cloud->cm.vert.begin();vi!=cloud->cm.vert.end();++vi) MoveParticle(ph[vi],&*vi,l,t,force); -// for(int i=0;i<4;i++) -// ComputeRepulsion(cloud,10); + for(int i=0;icm.bbox.DimX(); + if(m!=0){ float perc=0.01; float max_value=m->cm.bbox.Dim()[m->cm.bbox.MaxDim()]; par.addParam(new RichPoint3f("force_dir",Point3f(0,-1,0),"force","Direction of the force acting on the points cloud")); par.addParam(new RichAbsPerc("s_length",max_value*perc,0,max_value,"Movement Length","")); - //par.addParam(new RichPoint3f("velocity",Point3f(0,0,0),"v","Initial velocity of the particle")); par.addParam(new RichFloat("velocity",0,"v","Initial velocity of the particle")); par.addParam(new RichFloat("mass",1,"m","Mass of the particle")); + par.addParam(new RichBool("colorize_mesh",false,"Map to Color","")); + } break; } default:{ @@ -146,6 +152,8 @@ bool FilterDirt::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet Point3f dir=par.getPoint3f("dust_dir"); float s=par.getFloat("slippiness"); float k=par.getFloat("adhesion"); + bool draw=par.getBool("draw_texture"); + bool colorize=par.getBool("colorize_mesh"); int n_p=par.getInt("nparticles"); MeshModel* currMM=md.mm(); @@ -155,12 +163,18 @@ bool FilterDirt::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet return false; } + if(draw && !currMM->cm.HasPerWedgeTexCoord()){ + errorMessage = "Current Mesh does not have per Wedge Tex Coordinates"; + return false; + + } vector dust_points; vector > dust_particles; prepareMesh(currMM); + ComputeNormalDustAmount(currMM,dir,k,s); ComputeSurfaceExposure(currMM,1,1); GenerateParticles(currMM,dust_points,dust_particles,n_p,0.6); @@ -182,6 +196,10 @@ bool FilterDirt::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet ++dpi; } + if(draw) DrawDust(currMM,dmm); + if(colorize) ColorizeMesh(currMM); + + break; } case FP_CLOUD_MOVEMENT:{ @@ -202,14 +220,12 @@ bool FilterDirt::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet return false; } - float default_time=1; - //Get Parameters Point3f dir=par.getPoint3f("force_dir");; float l =par.getAbsPerc("s_length"); float v=par.getFloat("velocity"); float m=par.getFloat("mass"); - + bool colorize=par.getBool("colorize_mesh"); if(!HasPerVertexAttribute(cloud_mesh->cm,"ParticleInfo")){ prepareMesh(base_mesh); //Associate every point to a mesh and a Particle to every point @@ -217,8 +233,9 @@ bool FilterDirt::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet } //Move Cloud Mesh - MoveCloudMeshForward(cloud_mesh,dir,l,1); + MoveCloudMeshForward(cloud_mesh,dir,l,1,2); + if(colorize) ColorizeMesh(base_mesh); break; } default:{ @@ -232,6 +249,19 @@ bool FilterDirt::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet + +int FilterDirt::postCondition( QAction *a) const +{ + switch (ID(a)){ + case FP_DIRT : return MeshModel::MM_UNKNOWN; + case FP_CLOUD_MOVEMENT : return MeshModel::MM_UNKNOWN; + default: assert(0); + } + + return MeshModel::MM_NONE; +} + + MeshFilterInterface::FilterClass FilterDirt::getClass(QAction *filter) { switch(ID(filter)){ diff --git a/src/fgt/filter_dirt/filter_dirt.h b/src/fgt/filter_dirt/filter_dirt.h index 23149107e..a4d18ba37 100644 --- a/src/fgt/filter_dirt/filter_dirt.h +++ b/src/fgt/filter_dirt/filter_dirt.h @@ -68,6 +68,7 @@ class FilterDirt : public QObject, public MeshFilterInterface virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/); virtual bool applyFilter(QAction* filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb); virtual bool applyFilter(QAction * /*filter */, MeshModel &, RichParameterSet & /*parent*/, vcg::CallBackPos *) { assert(0); return false;} ; + virtual int postCondition(QAction*) const; virtual FilterClass getClass(QAction *); diff --git a/src/fgt/filter_dirt/particle.h b/src/fgt/filter_dirt/particle.h index 8fecd22ce..3631bb7da 100644 --- a/src/fgt/filter_dirt/particle.h +++ b/src/fgt/filter_dirt/particle.h @@ -37,6 +37,7 @@ class Particle{ typedef typename MeshType::VertexType VertexType; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; + public: Particle(){ mass=1.0f;