~ubuntu-branches/ubuntu/vivid/meshlab/vivid

« back to all changes in this revision

Viewing changes to meshlab/src/fgt/filter_dirt/filter_dirt.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Teemu Ikonen
  • Date: 2011-03-28 17:54:11 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110328175411-ntj9e50d1yl0luzb
Tags: 1.3.0a+dfsg1-1
* New upstream version (closes: #618522)
* Repackage the upstream sources to get rid of some files with questionable
  licensing information and useless libraries, see the copyright file for
  details.
* Builds with GCC-4.5 (closes: #565034)
* Fix watch-file to work with new upstream names and dfsg source
  (closes: #582477)
* Require debhelper version 8 or above.
* control:
  - Update standards-version to 3.9.1, cleanup.
  - Remove build-dep to libgl-dev to fix a lintian warning about a
    build-dep to a virtual package.
  - Remove build-dep to asciidoc, add build-dep to libeigen2-dev.
* rules:
  - Remove manpage-related code.
  - Build the necessary code from meshlab/src/external. Also clean it.
  - Override dh_shlibdeps to include /usr/lib/meshlab in search path.
  - Don't install shader licenses.
* install: Install binaries from meshlab/src/distrib.
* copyright: Update to the latest DEP5 format, document changes due to
  source repackaging and add the copyright info for the files added in
  this upstream release.
* Hardcode shadersDir and pluginDir in upstream source to locations
  in the Debian binary package.
* Use source format '3.0 (quilt)'.
* Split changes affecting upstream code to branches in the git repository
  at git.d.o. Add DEP3 patch metadata headers to debian/metapatches and
  generate patches from git branches with gdp (http://gitorious.org/gdp).
  Current patches:
  - 01_muparser: Use Debian muparser.
  - 02_qhull: Use Debian qhull.
  - 03_lib3ds: Use Debian lib3ds.
  - 04_libbz2: Use Debian libbz2.
  - 05_glew: Use Debian GLEW.
  - 06_eigen: Use Debian Eigen.
  - 07_disable-updates: Disable checking for updates on startup.
  - 08_externals: Only build necessary external sources.
  - 09_rpath: Use /usr/lib/meshlab as RPATH in binaries.
  - 10_shadersdir: Hardcode shadersDir to the correct path in Debian
  - 11_pluginsdir: Hardcode pluginsDir to the correct path in Debian
* Add a README.source file documenting the patch generation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
#include <Qt>
25
25
#include <QtGui>
26
26
#include "filter_dirt.h"
 
27
#include "particle.h"
 
28
#include "dirt_utils.h"
27
29
 
 
30
#include <vcg/space/color4.h>
 
31
#include <vcg/math/random_generator.h>
 
32
#include <vcg/complex/trimesh/closest.h>
 
33
#include <vcg/space/index/spatial_hashing.h>
 
34
#include <vcg/complex/trimesh/stat.h>
 
35
#include <vcg/complex/trimesh/update/topology.h>
 
36
#include <vcg/space/box2.h>
28
37
#include <vcg/math/base.h>
29
38
#include <vcg/complex/trimesh/clean.h>
30
39
#include <vcg/complex/trimesh/stat.h>
37
46
#include <vcg/complex/trimesh/update/normal.h>
38
47
#include <vcg/complex/trimesh/point_sampling.h>
39
48
#include <vcg/space/triangle3.h>
40
 
 
 
49
#include <vcg/complex/trimesh/allocate.h>
 
50
#include <vector>
41
51
 
42
52
using namespace std;
43
53
using namespace vcg;
44
 
 
45
 
class BaseSampler
46
 
{
47
 
public:
48
 
        BaseSampler(CMeshO* _m){m=_m;};
49
 
        CMeshO *m;
50
 
        //bool uvSpaceFlag;
51
 
        /*void AddVert(const CMeshO::VertexType &p) 
52
 
        {
53
 
                tri::Allocator<CMeshO>::AddVertices(*m,1);
54
 
                m->vert.back().ImportLocal(p);
55
 
        }*/
56
 
        
57
 
        void AddFace(const CMeshO::FaceType &f, CMeshO::CoordType p) 
58
 
        {
59
 
                tri::Allocator<CMeshO>::AddVertices(*m,1);
60
 
                m->vert.back().P() = f.P(0)*p[0] + f.P(1)*p[1] +f.P(2)*p[2];
61
 
                m->vert.back().N() = f.V(0)->N()*p[0] + f.V(1)->N()*p[1] +f.V(2)->N()*p[2];
62
 
        }
63
 
        
64
 
        /*void AddTextureSample(const CMeshO::FaceType &f, const CMeshO::CoordType &p, const Point2i &tp)
65
 
        {
66
 
                tri::Allocator<CMeshO>::AddVertices(*m,1);
67
 
                
68
 
                if(uvSpaceFlag) m->vert.back().P() = Point3f(float(tp[0]),float(tp[1]),0); 
69
 
                else m->vert.back().P() = f.P(0)*p[0] + f.P(1)*p[1] +f.P(2)*p[2];
70
 
                m->vert.back().N() = f.V(0)->N()*p[0] + f.V(1)->N()*p[1] +f.V(2)->N()*p[2];
71
 
        }*/
72
 
}; // end class BaseSampler
73
 
 
74
 
FilterDirt::FilterDirt(): defaultGammaTon(500)
75
 
{
76
 
        
77
 
    typeList << 
78
 
    FP_DIRT;
 
54
using namespace tri;
 
55
 
 
56
FilterDirt::FilterDirt()
 
57
{
 
58
 
 
59
    typeList << FP_DIRT
 
60
             <<FP_CLOUD_MOVEMENT;
79
61
    
80
 
        FilterIDType tt;
81
 
        foreach(tt , types())
 
62
    FilterIDType tt;
 
63
    foreach(tt , types())
82
64
        actionList << new QAction(filterName(tt), this);
83
65
}
84
66
 
85
 
const QString FilterDirt::filterName(FilterIDType filterId) 
86
 
{
87
 
        if(filterId!= FP_DIRT)
88
 
        {
89
 
                return QString("error!");
90
 
        }
91
 
        return QString("Dirt Maker");
92
 
}
93
 
const QString FilterDirt::filterInfo(FilterIDType filterId) 
94
 
{
95
 
        
96
 
        if(filterId!= FP_DIRT)
97
 
        {
98
 
                return QString("error!");
99
 
        }
100
 
        return QString("Simulate dirt accumolation over the mesh");
101
 
}
102
 
 
103
 
const int FilterDirt::getRequirements(QAction */*action*/)
104
 
{
105
 
        
106
 
        return MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACECOLOR | MeshModel::MM_FACEMARK;   
107
 
}
108
 
 
109
 
bool FilterDirt::applyFilter(QAction * /*filter*/, MeshDocument &md, FilterParameterSet & /*par*/, vcg::CallBackPos */*cb*/)
110
 
{
111
 
        //NOTE: i know this method require a code refactoring. Appling this filter in meshlab you can see 50 gamma-tons start from a position 
112
 
        //(green face) moving down (red face). In meshlab you can see vertex position using show vertex label.
113
 
        
114
 
        typedef GridStaticPtr<CMeshO::FaceType, CMeshO::ScalarType > MetroMeshGrid;
115
 
        typedef trimesh::FaceTmark<CMeshO> MarkerFace;
116
 
        
117
 
        MarkerFace markerFunctor;
118
 
        
119
 
        vcg::tri::UpdateColor<CMeshO>::FaceConstant(md.mm()->cm,vcg::Color4b::White); //!DEBUG! painting white for debug
120
 
        
121
 
        MeshModel *curMM= md.mm();                              
122
 
        MeshModel *mm= md.addNewMesh("Dust gamma-ton"); // After Adding a mesh to a MeshDocument the new mesh is the current one 
123
 
        
124
 
        BaseSampler mps(&(mm->cm));
125
 
        vcg::tri::SurfaceSampling<CMeshO,BaseSampler>::Montecarlo(curMM->cm, mps, defaultGammaTon);
126
 
        vcg::tri::UpdateBounding<CMeshO>::Box(mm->cm);
127
 
        
128
 
        //calculate mean of face's edge segment perimeter
129
 
        CMeshO::FaceIterator fi;
130
 
        double perimeterSum=0;
131
 
        for(fi=curMM->cm.face.begin();fi!=curMM->cm.face.end();++fi)
132
 
        if(!(*fi).IsD())
133
 
        {
134
 
                perimeterSum += vcg::Perimeter((*fi));
135
 
        }
136
 
        
137
 
        //calculate single gamma-ton step size (i want stepSize equal to 1/4 mean edges segment size)
138
 
        float stepSize = (perimeterSum/12)/curMM->cm.fn;
139
 
        
140
 
        CMeshO::VertexIterator vi;      
141
 
        CMeshO::FaceType        *nearestF=NULL;
142
 
        CMeshO::FaceType        *precedentF=NULL;
143
 
        float maxDist=(*curMM).cm.bbox.Diag()/3, minDist;
144
 
        MetroMeshGrid   unifGrid;
145
 
        vcg::Point3f closestPt; 
146
 
        
147
 
        //setting up grid for space indexing
148
 
        unifGrid.Set((*curMM).cm.face.begin(),(*curMM).cm.face.end());
149
 
        markerFunctor.SetMesh(&curMM->cm);      
150
 
        
151
 
        //Require by PointDistance Functor
152
 
        vcg::tri::UpdateNormals<CMeshO>::PerFaceNormalized(curMM->cm);
153
 
        vcg::tri::UpdateFlags<CMeshO>::FaceProjection(curMM->cm);
154
 
        
155
 
        int iterationNum = (int) curMM->cm.fn/300;
156
 
        
157
 
        for (vi=mm->cm.vert.begin();vi!=mm->cm.vert.end();++vi) 
158
 
        {
159
 
                precedentF=NULL; //Visual Debug Stuff
160
 
                for (int i=0; i<iterationNum; ++i)
161
 
                {
162
 
                        //get nearest face for every gamma-ton          
163
 
                        vcg::face::PointDistanceBaseFunctor PDistFunct;
164
 
                        nearestF =  unifGrid.GetClosest(PDistFunct,markerFunctor,(*vi).P(),maxDist,minDist,closestPt);  
165
 
                        if (!nearestF) return false;
166
 
                        if (minDist == maxDist) return false;                   
167
 
                                        
168
 
                        //DEBUG STUFF
169
 
                        if (i==0) (*nearestF).C() = Color4b::Green;
170
 
                        if (precedentF!=nearestF && precedentF!=NULL){ (*nearestF).C() = Color4b::Red;}
171
 
                        precedentF = nearestF;
172
 
                        //END DEBUG STUFF
173
 
                        
174
 
                        //get gamma-ton direction over face
175
 
                        vcg::Point3f dustDirection = ((*nearestF).N().Normalize() ^  vcg::Point3f(0,-1,0)) ^ (*nearestF).N().Normalize();
176
 
                                                
177
 
                        float angle = vcg::Angle(dustDirection, vcg::Point3f(0,-1,0));                  
178
 
                        float speed;
179
 
                        //if angle>80°
180
 
                        if (angle>1.309) //(5*M_PI)/12
181
 
                                speed=0;
182
 
                        else
183
 
                                speed = stepSize * vcg::math::Cos(angle);                       
184
 
                        
185
 
                        dustDirection = dustDirection.Normalize();
186
 
                        dustDirection *= speed; 
187
 
                        dustDirection += closestPt;
188
 
                        (*vi).P() = dustDirection;              
189
 
                }
190
 
        }
191
 
        
192
 
        return true;
193
 
}
194
 
 
195
 
/*!!! I don't understand why if i did't return MeshFilterInterface::FaceColoring all my function call
196
 
 to FaceConstant (et simila) don't take effect over the mesh. I've read from Interface.c comment getClass is
197
 
 only to decide where my plugin label is in Plugin submenu of meshlab menubar.*/
198
 
const MeshFilterInterface::FilterClass FilterDirt::getClass(QAction *)
199
 
{
200
 
        return MeshFilterInterface::FaceColoring;
201
 
}
 
67
QString FilterDirt::filterName(FilterIDType filterId) const
 
68
{
 
69
    switch (filterId) {
 
70
    case FP_DIRT:{
 
71
        return QString("Dust Accumulation");
 
72
        break;
 
73
        }
 
74
    case FP_CLOUD_MOVEMENT:
 
75
        {
 
76
        return QString("Points Cloud Movement");
 
77
        break;
 
78
        }
 
79
    default:{
 
80
        assert(0); return QString("error");
 
81
        break;
 
82
        }
 
83
    }
 
84
}
 
85
 
 
86
QString FilterDirt::filterInfo(FilterIDType filterId) const
 
87
{
 
88
    switch (filterId) {
 
89
    case FP_DIRT:{
 
90
            return QString("Simulate dust accumulation over the mesh");
 
91
            break;
 
92
        }
 
93
    case FP_CLOUD_MOVEMENT:{
 
94
            return QString("Simulate the movement of a points cloud over a mesh");
 
95
            break;
 
96
        }
 
97
    default:
 
98
        assert(0); return QString("error");
 
99
        break;
 
100
    }
 
101
}
 
102
 
 
103
void FilterDirt::initParameterSet(QAction* filter,MeshDocument &md, RichParameterSet &par){
 
104
 
 
105
 
 
106
    switch(ID(filter)){
 
107
 
 
108
    case FP_DIRT:{
 
109
            MeshModel* m=md.getMesh(0);
 
110
            if(m!=0){
 
111
            par.addParam(new RichPoint3f("dust_dir",Point3f(0,1,0),"Direction","Direction of the dust source"));
 
112
            par.addParam(new RichInt("nparticles",3,"particles","Max Number of Dust Particles to Generate Per Face"));
 
113
            par.addParam(new RichFloat("slippiness",1,"s","The surface slippines"));
 
114
            par.addParam(new RichFloat("adhesion",0.2,"k","Factor to model the general adhesion"));
 
115
            par.addParam(new RichBool("draw_texture",false,"Draw Dust",""));
 
116
            par.addParam(new RichBool("colorize_mesh",false,"Map to Color",""));
 
117
            }
 
118
            break;
 
119
 
 
120
        }
 
121
    case FP_CLOUD_MOVEMENT:{
 
122
            float perc=0.01f;
 
123
            float max_value=md.mm()->cm.bbox.Diag();
 
124
            par.addParam(new RichPoint3f("force_dir",Point3f(0,-1,0),"force","Direction of the force acting on the points cloud"));
 
125
            par.addParam(new RichAbsPerc("s_length",max_value*perc,0,max_value,"Movement Length",""));
 
126
            par.addParam(new RichFloat("velocity",0,"v","Initial velocity of the particle"));
 
127
            par.addParam(new RichFloat("mass",1,"m","Mass of the particle"));
 
128
            par.addParam(new RichBool("colorize_mesh",false,"Map to Color",""));
 
129
 
 
130
            break;
 
131
        }
 
132
    default:{
 
133
        break;
 
134
        }
 
135
    }
 
136
}
 
137
 
 
138
int FilterDirt::getRequirements(QAction */*action*/)
 
139
{       
 
140
    return MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTCOLOR |MeshModel::MM_FACECOLOR;
 
141
}
 
142
 
 
143
bool FilterDirt::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet &par, vcg::CallBackPos *cb){
 
144
 
 
145
 
 
146
    switch(ID(filter)){
 
147
 
 
148
    case FP_DIRT:{
 
149
        /*Get Parameters*/
 
150
        Point3f dir=par.getPoint3f("dust_dir");
 
151
        float s=par.getFloat("slippiness");
 
152
        float k=par.getFloat("adhesion");
 
153
        bool draw=par.getBool("draw_texture");
 
154
        bool colorize=par.getBool("colorize_mesh");
 
155
        int n_p=par.getInt("nparticles");
 
156
 
 
157
        MeshModel* currMM=md.mm();
 
158
 
 
159
        if (currMM->cm.fn==0) {
 
160
                errorMessage = "This filter requires a mesh with some faces, it does not work on PointSet";
 
161
                return false;
 
162
        }
 
163
 
 
164
        if(draw && !currMM->cm.HasPerWedgeTexCoord()){
 
165
            errorMessage = "Current Mesh does not have per Wedge Tex Coordinates";
 
166
            return false;
 
167
 
 
168
        }
 
169
        vector<Point3f> dust_points;
 
170
        vector<Particle<CMeshO> > dust_particles;
 
171
 
 
172
        prepareMesh(currMM);
 
173
 
 
174
 
 
175
 
 
176
        ComputeNormalDustAmount(currMM,dir,k,s);
 
177
        ComputeSurfaceExposure(currMM,1,1);
 
178
        GenerateParticles(currMM,dust_points,dust_particles,n_p,0.6);
 
179
 
 
180
 
 
181
        MeshModel* dmm=md.addNewMesh("","dust_mesh");
 
182
        dmm->cm.Clear();
 
183
 
 
184
        tri::Allocator<CMeshO>::AddVertices(dmm->cm,dust_points.size());
 
185
        CMeshO::PerVertexAttributeHandle<Particle<CMeshO> > ph= tri::Allocator<CMeshO>::AddPerVertexAttribute<Particle<CMeshO> > (dmm->cm,std::string("ParticleInfo"));
 
186
        CMeshO::VertexIterator vi;
 
187
        vector<Point3f>::iterator dvi=dust_points.begin();
 
188
        std::vector< Particle<CMeshO> >::iterator dpi=dust_particles.begin();
 
189
 
 
190
        for(vi=dmm->cm.vert.begin();vi!=dmm->cm.vert.end();++vi){
 
191
            (*vi).P()=(*dvi);
 
192
            ph[vi]=(*dpi);
 
193
            ++dvi;
 
194
            ++dpi;
 
195
        }
 
196
 
 
197
        if(draw) DrawDust(currMM,dmm);
 
198
        if(colorize) ColorizeMesh(currMM);
 
199
 
 
200
 
 
201
        break;
 
202
        }
 
203
    case FP_CLOUD_MOVEMENT:{
 
204
            if(md.size()!=2){
 
205
                errorMessage="This filter requires two mesh";
 
206
                return false;
 
207
            }
 
208
 
 
209
        MeshModel* base_mesh=md.getMesh(0);
 
210
        if(base_mesh->cm.fn==0){
 
211
            errorMessage="The filter requires that the first mesh has some faces";
 
212
            return false;
 
213
        }
 
214
 
 
215
        MeshModel* cloud_mesh=md.getMesh(1);
 
216
        if(cloud_mesh->cm.fn!=0){
 
217
            errorMessage="The filter requires that the second mesh is a Point Set";
 
218
            return false;
 
219
        }
 
220
 
 
221
        //Get Parameters
 
222
        Point3f dir=par.getPoint3f("force_dir");;
 
223
        float l =par.getAbsPerc("s_length");
 
224
        float v=par.getFloat("velocity");
 
225
        float m=par.getFloat("mass");
 
226
        bool colorize=par.getBool("colorize_mesh");
 
227
        if(!HasPerVertexAttribute(cloud_mesh->cm,"ParticleInfo")){
 
228
            prepareMesh(base_mesh);
 
229
            //Associate every point to a mesh and a Particle to every point
 
230
            associateParticles(base_mesh,cloud_mesh,m,v);
 
231
        }
 
232
 
 
233
        //Move Cloud Mesh
 
234
        MoveCloudMeshForward(cloud_mesh,dir,l,1,2);
 
235
 
 
236
        if(colorize) ColorizeMesh(base_mesh);
 
237
        break;
 
238
        }
 
239
    default:{
 
240
        break;
 
241
        }
 
242
     }
 
243
 
 
244
 
 
245
  return true;
 
246
}//End applyFilter
 
247
 
 
248
 
 
249
 
 
250
 
 
251
int FilterDirt::postCondition( QAction *a) const
 
252
{
 
253
        switch (ID(a)){
 
254
        case FP_DIRT : return MeshModel::MM_UNKNOWN;
 
255
        case FP_CLOUD_MOVEMENT : return MeshModel::MM_UNKNOWN;
 
256
        default: assert(0);
 
257
        }
 
258
 
 
259
        return MeshModel::MM_NONE;
 
260
}
 
261
 
 
262
 
 
263
MeshFilterInterface::FilterClass FilterDirt::getClass(QAction *filter)
 
264
{
 
265
    switch(ID(filter)){
 
266
    case FP_DIRT:return MeshFilterInterface::Sampling;
 
267
    case FP_CLOUD_MOVEMENT:return MeshFilterInterface::Remeshing;
 
268
    default:assert(0);
 
269
    }
 
270
}
 
271
 
 
272
 
202
273
 
203
274
 
204
275
Q_EXPORT_PLUGIN(FilterDirt)