1 /****************************************************************************
2 * MeshLab o o *
3 * A versatile mesh processing toolbox o o *
4 * _ O _ *
5 * Copyright(C) 2005 \/)\/ *
6 * Visual Computing Lab /\/| *
7 * ISTI - Italian National Research Council | *
8 * \ *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20 * for more details. *
21 * *
22 ****************************************************************************/
23
24 #include "filter_func.h"
25 #include <vcg/complex/algorithms/create/platonic.h>
26
27 #include <vcg/complex/algorithms/create/marching_cubes.h>
28 #include <vcg/complex/algorithms/create/mc_trivial_walker.h>
29
30 #include "muParser.h"
31 #include "string_conversion.h"
32
33 using namespace mu;
34 using namespace vcg;
35
36 // Constructor
FilterFunctionPlugin()37 FilterFunctionPlugin::FilterFunctionPlugin()
38 {
39 typeList
40 << FF_VERT_SELECTION
41 << FF_FACE_SELECTION
42 << FF_GEOM_FUNC
43 << FF_WEDGE_TEXTURE_FUNC
44 << FF_VERT_TEXTURE_FUNC
45 << FF_FACE_COLOR
46 << FF_VERT_COLOR
47 << FF_VERT_QUALITY
48 << FF_VERT_NORMAL
49 << FF_FACE_QUALITY
50 << FF_DEF_VERT_ATTRIB
51 << FF_DEF_FACE_ATTRIB
52 << FF_GRID
53 << FF_ISOSURFACE
54 << FF_REFINE;
55
56 foreach(FilterIDType tt , types())
57 actionList << new QAction(filterName(tt), this);
58 }
59
~FilterFunctionPlugin()60 FilterFunctionPlugin::~FilterFunctionPlugin()
61 {
62 for (int i = 0; i < actionList.count() ; i++ )
63 delete actionList.at(i);
64 }
65
66 // short string describing each filtering action
filterName(FilterIDType filterId) const67 QString FilterFunctionPlugin::filterName(FilterIDType filterId) const
68 {
69 switch(filterId) {
70 case FF_VERT_SELECTION: return QString("Conditional Vertex Selection");
71 case FF_FACE_SELECTION: return QString("Conditional Face Selection");
72 case FF_GEOM_FUNC: return QString("Per Vertex Geometric Function");
73 case FF_FACE_COLOR: return QString("Per Face Color Function");
74 case FF_FACE_QUALITY: return QString("Per Face Quality Function");
75 case FF_VERT_COLOR: return QString("Per Vertex Color Function");
76 case FF_VERT_QUALITY: return QString("Per Vertex Quality Function");
77 case FF_VERT_TEXTURE_FUNC: return QString("Per Vertex Texture Function");
78 case FF_WEDGE_TEXTURE_FUNC: return QString("Per Wedge Texture Function");
79 case FF_VERT_NORMAL: return QString("Per Vertex Normal Function");
80 case FF_DEF_VERT_ATTRIB: return QString("Define New Per Vertex Attribute");
81 case FF_DEF_FACE_ATTRIB: return QString("Define New Per Face Attribute");
82 case FF_GRID: return QString("Grid Generator");
83 case FF_REFINE: return QString("Refine User-Defined");
84 case FF_ISOSURFACE: return QString("Implicit Surface");
85
86 default: assert(0);
87 }
88 return QString("error!");
89 }
90
91 const QString PossibleOperators("<br>It's possible to use parenthesis <b>()</b>, and predefined operators:<br>"
92 "<b>&&</b> (logic and), <b>||</b> (logic or), <b><</b>, <b><=</b>, <b>></b>, <b>>=</b>, <b>!=</b> (not equal), <b>==</b> (equal), <b>_?_:_</b> (c/c++ ternary operator)<br><br>");
93
94 const QString PerVertexAttributeString( "It's possible to use the following per-vertex variables in the expression:<br>"
95 "<b>x,y,z</b> (position), <b>nx,ny,nz</b> (normal), <b>r,g,b,a</b> (color), <b>q</b> (quality), "
96 "<b>rad</b> (radius), <b>vi</b> (vertex index), <b>vtu,vtv,ti</b> (texture coords and texture index), <b>vsel</b> (is the vertex selected? 1 yes, 0 no) "
97 "and all custom <i>vertex attributes</i> already defined by user.<br>");
98
99 const QString PerFaceAttributeString("It's possible to use the following per-face variables, or variables associated to the three vertex of every face:<br>"
100 "<b>x0,y0,z0</b> for the first vertex position, <b>x1,y1,z1</b> for the second vertex position, <b>x2,y2,z2</b> for the third vertex position, "
101 "<b>nx0,ny0,nz0 nx1,ny1,nz1 nx2,ny2,nz2</b> for vertex normals, <b>r0,g0,b0,a0 r1,g1,b1,a1 r2,g2,b2,a2</b> for vertex colors, "
102 "<b>q0,q1,q2</b> for vertex quality, <b>wtu0,wtv0 wtu1,wtv1 wtu2,wtv2</b> for per-wedge texture coords, <b>ti</b> for face texture index, <b>vsel0,vsel1,vsel2</b> for vertex selection (1 yes, 0 no) "
103 "<b>fr,fg,fb,fa</b> for face color, <b>fq</b> for face quality, <b>fnx,fny,fnz</b> for face normal, <b>fsel</b> face selection (1 yes, 0 no).<br>");
104
105 // long string describing each filtering action
filterInfo(FilterIDType filterId) const106 QString FilterFunctionPlugin::filterInfo(FilterIDType filterId) const
107 {
108 switch(filterId) {
109 case FF_VERT_SELECTION : return tr( "Boolean function using muparser lib to perform vertex selection over current mesh.<br>")
110 + PossibleOperators + PerVertexAttributeString;
111
112 case FF_FACE_SELECTION : return tr( "Boolean function using muparser lib to perform faces selection over current mesh.<br>")
113 + PossibleOperators + PerFaceAttributeString;
114
115 case FF_GEOM_FUNC : return tr( "Geometric function using muparser lib to generate new Coord<br>"
116 "You can change x,y,z for every vertex according to the function specified.<br>") + PerVertexAttributeString;
117
118 case FF_FACE_COLOR : return tr( "Color function using muparser lib to generate new RGBA color for every face<br>"
119 "Red, Green, Blue and Alpha channels may be defined specifying a function in their respective fields.<br>") + PerFaceAttributeString;
120
121 case FF_VERT_COLOR : return tr( "Color function using muparser lib to generate new RGBA color for every vertex<br>"
122 "Red, Green, Blue and Alpha channels may be defined specifying a function in their respective fields.<br>") + PerVertexAttributeString;
123
124 case FF_VERT_QUALITY: return tr("Quality function using muparser to generate new Quality for every vertex<br>") + PerVertexAttributeString;
125
126 case FF_VERT_TEXTURE_FUNC: return tr("Texture function using muparser to generate new texture coords for every vertex<br>") + PerVertexAttributeString;
127
128 case FF_VERT_NORMAL: return tr("Normal function using muparser to generate new Normal for every vertex<br>") + PerVertexAttributeString;
129
130 case FF_FACE_QUALITY : return tr("Quality function using muparser to generate new Quality for every face<br>"
131 "Insert three function each one for quality of the three vertex of a face<br>") +PerFaceAttributeString;
132
133 case FF_WEDGE_TEXTURE_FUNC : return tr("Texture function using muparser to generate new per wedge tex coords for every face<br>"
134 "Insert six functions each u v for each one of the three vertex of a face<br>") +PerFaceAttributeString;
135
136 case FF_DEF_VERT_ATTRIB : return tr("Add a new Per-Vertex scalar attribute to current mesh and fill it with the defined function.<br>"
137 "The name specified below can be used in other filter function") +PerVertexAttributeString;
138
139 case FF_DEF_FACE_ATTRIB : return tr("Add a new Per-Face attribute to current mesh.<br>"
140 "You can specify custom name and a function to generate attribute's value<br>"
141 "It's possible to use per-face variables in the expression:<br>") +PerFaceAttributeString+
142 tr("<font color=\"#FF0000\">The attribute name specified below can be used in other filter function</font>");
143
144 case FF_GRID : return tr("Generate a new 2D Grid mesh with number of vertices on X and Y axis specified by user with absolute length/height.<br>"
145 "It's possible to center Grid on origin.");
146
147 case FF_ISOSURFACE : return tr("Generate a new mesh that corresponds to the 0 valued isosurface defined by the scalar field generated by the given expression");
148
149 case FF_REFINE : return tr("Refine current mesh with user defined parameters.<br>"
150 "Specify a Boolean Function needed to select which edges will be cut for refinement purpose.<br>"
151 "Each edge is identified with first and second vertex.<br>"
152 "Arguments accepted are first and second vertex attributes:<br>") + PossibleOperators + PerFaceAttributeString;
153
154 default : assert(0);
155 }
156 return QString("filter not found!");
157 }
158
getClass(QAction * a)159 FilterFunctionPlugin::FilterClass FilterFunctionPlugin::getClass(QAction *a)
160 {
161 switch(ID(a))
162 {
163 case FF_FACE_SELECTION:
164 case FF_VERT_SELECTION: return MeshFilterInterface::Selection;
165 case FF_FACE_QUALITY: return FilterClass(Quality + FaceColoring);
166 case FF_VERT_QUALITY: return FilterClass(Quality + VertexColoring);
167 case FF_VERT_TEXTURE_FUNC: return MeshFilterInterface::Texture;
168 case FF_VERT_COLOR: return MeshFilterInterface::VertexColoring;
169 case FF_VERT_NORMAL: return MeshFilterInterface::Normal;
170 case FF_FACE_COLOR: return MeshFilterInterface::FaceColoring;
171 case FF_WEDGE_TEXTURE_FUNC: return MeshFilterInterface::Texture;
172 case FF_ISOSURFACE: return MeshFilterInterface::MeshCreation;
173 case FF_GRID: return MeshFilterInterface::MeshCreation;
174 case FF_REFINE: return MeshFilterInterface::Remeshing;
175 case FF_GEOM_FUNC: return MeshFilterInterface::Smoothing;
176 case FF_DEF_VERT_ATTRIB: return MeshFilterInterface::Layer;
177 case FF_DEF_FACE_ATTRIB: return MeshFilterInterface::Layer;
178
179 default: return MeshFilterInterface::Generic;
180 }
181 }
182
postCondition(QAction * action) const183 int FilterFunctionPlugin::postCondition(QAction *action) const
184 {
185 switch(ID(action))
186 {
187 case FF_VERT_SELECTION:
188 case FF_FACE_SELECTION:
189 return MeshModel::MM_VERTFLAGSELECT | MeshModel::MM_FACEFLAGSELECT;
190 case FF_FACE_COLOR:
191 return MeshModel::MM_FACECOLOR;
192 case FF_GEOM_FUNC:
193 return MeshModel::MM_VERTCOORD + MeshModel::MM_VERTNORMAL + MeshModel::MM_FACENORMAL;
194 case FF_VERT_COLOR:
195 return MeshModel::MM_VERTCOLOR;
196 case FF_VERT_NORMAL:
197 return MeshModel::MM_VERTNORMAL;
198 case FF_VERT_TEXTURE_FUNC:
199 return MeshModel::MM_VERTTEXCOORD;
200 case FF_WEDGE_TEXTURE_FUNC:
201 return MeshModel::MM_WEDGTEXCOORD;
202 case FF_VERT_QUALITY:
203 return MeshModel::MM_VERTQUALITY + MeshModel::MM_VERTCOLOR;
204 case FF_FACE_QUALITY:
205 return MeshModel::MM_FACECOLOR + MeshModel::MM_FACEQUALITY;
206
207 case FF_DEF_VERT_ATTRIB:
208 case FF_DEF_FACE_ATTRIB:
209 return MeshModel::MM_NONE; // none, because they do not change any existing data
210
211 case FF_REFINE:
212 return MeshModel::MM_ALL;
213
214 case FF_GRID:
215 case FF_ISOSURFACE:
216 return MeshModel::MM_NONE; // none, because they create a new layer, without affecting old one
217 }
218
219 return MeshModel::MM_NONE;
220 }
221
getRequirements(QAction * action)222 int FilterFunctionPlugin::getRequirements(QAction *action)
223 {
224 switch(ID(action))
225 {
226 case FF_VERT_SELECTION :
227 case FF_GEOM_FUNC :
228 case FF_VERT_COLOR :
229 case FF_VERT_NORMAL :
230 case FF_VERT_QUALITY :
231 case FF_VERT_TEXTURE_FUNC:
232 case FF_WEDGE_TEXTURE_FUNC:
233 case FF_DEF_VERT_ATTRIB :
234 case FF_GRID :
235 case FF_ISOSURFACE :
236 case FF_DEF_FACE_ATTRIB :
237 case FF_FACE_SELECTION : return 0;
238 case FF_FACE_QUALITY : return MeshModel::MM_FACECOLOR + MeshModel::MM_FACEQUALITY;
239 case FF_FACE_COLOR : return MeshModel::MM_FACECOLOR;
240 case FF_REFINE : return MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTMARK;
241 default: assert(0);
242 }
243 return 0;
244 }
245
246 // This function define the needed parameters for each filter. Return true if the filter has some parameters
247 // it is called every time, so you can set the default value of parameters according to the mesh
248 // For each parameter you need to define,
249 // - the name of the parameter,
250 // - the string shown in the dialog
251 // - the default value
252 // - a possibly long string describing the meaning of that parameter (shown as a popup help in the dialog)
initParameterSet(QAction * action,MeshModel & m,RichParameterSet & parlst)253 void FilterFunctionPlugin::initParameterSet(QAction *action,MeshModel &m, RichParameterSet & parlst)
254 {
255 Q_UNUSED(m);
256 switch(ID(action)) {
257
258 case FF_VERT_SELECTION :
259 parlst.addParam(new RichString("condSelect","(q < 0)", "boolean function",
260 "type a boolean function that will be evaluated in order to select a subset of vertices<br>"
261 "example: (y > 0) and (ny > 0)"));
262 break;
263
264 case FF_FACE_SELECTION :
265 parlst.addParam(new RichString("condSelect","(fi == 0)", "boolean function",
266 "type a boolean function that will be evaluated in order to select a subset of faces<br>"));
267 break;
268
269 case FF_GEOM_FUNC:
270 parlst.addParam(new RichString("x", "x", "func x = ", "insert function to generate new coord for x"));
271 parlst.addParam(new RichString("y", "y", "func y = ", "insert function to generate new coord for y"));
272 parlst.addParam(new RichString("z", "sin(x+y)", "func z = ", "insert function to generate new coord for z"));
273 parlst.addParam(new RichBool("onselected", false, "only on selection", "if checked, only affects selected vertices"));
274 break;
275
276 case FF_VERT_NORMAL:
277 parlst.addParam(new RichString("x", "-nx", "func nx = ", "insert function to generate new x for the normal"));
278 parlst.addParam(new RichString("y", "-ny", "func ny = ", "insert function to generate new y for the normal"));
279 parlst.addParam(new RichString("z", "-nz", "func nz = ", "insert function to generate new z for the normal"));
280 parlst.addParam(new RichBool("onselected", false, "only on selection", "if checked, only affects selected vertices"));
281 break;
282
283 case FF_VERT_COLOR:
284 parlst.addParam(new RichString("x", "255", "func r = ", "function to generate Red component. Expected Range 0-255"));
285 parlst.addParam(new RichString("y", "255", "func g = ", "function to generate Green component. Expected Range 0-255"));
286 parlst.addParam(new RichString("z", "0", "func b = ", "function to generate Blue component. Expected Range 0-255"));
287 parlst.addParam(new RichString("a", "255", "func alpha = ", "function to generate Alpha component. Expected Range 0-255"));
288 parlst.addParam(new RichBool("onselected", false, "only on selection", "if checked, only affects selected vertices"));
289 break;
290
291 case FF_VERT_TEXTURE_FUNC:
292 parlst.addParam(new RichString("u", "x", "func u = ", "function to generate u texture coord. Expected Range 0-1"));
293 parlst.addParam(new RichString("v", "y", "func v = ", "function to generate v texture coord. Expected Range 0-1"));
294 parlst.addParam(new RichBool("onselected", false, "only on selection", "if checked, only affects selected vertices"));
295 break;
296
297 case FF_VERT_QUALITY:
298 parlst.addParam(new RichString("q", "vi", "func q = ", "function to generate new Quality for every vertex"));
299 parlst.addParam(new RichBool("normalize", false, "normalize", "if checked normalize all quality values in range [0..1]"));
300 parlst.addParam(new RichBool("map", false, "map into color", "if checked map quality generated values into per-vertex color"));
301 parlst.addParam(new RichBool("onselected", false, "only on selection", "if checked, only affects selected vertices"));
302 break;
303
304 case FF_FACE_COLOR:
305 parlst.addParam(new RichString("r", "255", "func r = ", "function to generate Red component. Expected Range 0-255"));
306 parlst.addParam(new RichString("g", "0", "func g = ", "function to generate Green component. Expected Range 0-255"));
307 parlst.addParam(new RichString("b", "255", "func b = ", "function to generate Blue component. Expected Range 0-255"));
308 parlst.addParam(new RichString("a", "255", "func alpha = ", "function to generate Alpha component. Expected Range 0-255"));
309 parlst.addParam(new RichBool("onselected", false, "only on selection", "if checked, only affects selected faces"));
310 break;
311
312 case FF_FACE_QUALITY:
313 parlst.addParam(new RichString("q", "x0+y0+z0", "func q0 = ", "function to generate new Quality foreach face"));
314 parlst.addParam(new RichBool("normalize", false, "normalize", "if checked normalize all quality values in range [0..1]"));
315 parlst.addParam(new RichBool("map", false, "map into color", "if checked map quality generated values into per-vertex color"));
316 parlst.addParam(new RichBool("onselected", false, "only on selection", "if checked, only affects selected faces"));
317 break;
318
319 case FF_WEDGE_TEXTURE_FUNC:
320 parlst.addParam(new RichString("u0","x0", "func u0 = ", "function to generate u texture coord. of wedge 0. Expected Range 0-1"));
321 parlst.addParam(new RichString("v0","y0", "func v0 = ", "function to generate v texture coord. of wedge 0. Expected Range 0-1"));
322 parlst.addParam(new RichString("u1","x1", "func u1 = ", "function to generate u texture coord. of wedge 1. Expected Range 0-1"));
323 parlst.addParam(new RichString("v1","y1", "func v1 = ", "function to generate v texture coord. of wedge 1. Expected Range 0-1"));
324 parlst.addParam(new RichString("u2","x2", "func u2 = ", "function to generate u texture coord. of wedge 2. Expected Range 0-1"));
325 parlst.addParam(new RichString("v2","y2", "func v2 = ", "function to generate v texture coord. of wedge 2. Expected Range 0-1"));
326 parlst.addParam(new RichBool("onselected", false, "only on selection", "if checked, only affects selected faces"));
327 break;
328
329 case FF_DEF_VERT_ATTRIB:
330 parlst.addParam(new RichString("name","Radiosity","Name", "the name of new attribute. you can access attribute in other filters through this name"));
331 parlst.addParam(new RichString("expr","x","Function =", "function to calculate custom attribute value for each vertex"));
332 break;
333
334 case FF_DEF_FACE_ATTRIB:
335 parlst.addParam(new RichString("name","Radiosity","Name", "the name of new attribute. you can access attribute in other filters through this name"));
336 parlst.addParam(new RichString("expr","fi","Function =", "function to calculate custom attribute value for each face"));
337 break;
338
339 case FF_GRID :
340 parlst.addParam(new RichInt("numVertX", 10, "num vertices on x", "number of vertices on x. it must be positive"));
341 parlst.addParam(new RichInt("numVertY", 10, "num vertices on y", "number of vertices on y. it must be positive"));
342 parlst.addParam(new RichFloat("absScaleX", 0.3f, "x scale", "absolute scale on x (float)"));
343 parlst.addParam(new RichFloat("absScaleY", 0.3f, "y scale", "absolute scale on y (float)"));
344 parlst.addParam(new RichBool("center",false,"centered on origin", "center grid generated by filter on origin.<br>"
345 "Grid is first generated and than moved into origin (using muparser lib to perform fast calc on every vertex)"));
346 break;
347 case FF_ISOSURFACE :
348 parlst.addParam(new RichFloat("voxelSize", 0.05f, "Size of Voxel", "Size of the voxel that is used by for the grid where the field is sampled. Smaller this value, higher precision, but higher processing times."));
349 parlst.addParam(new RichFloat("minX", -1.0f, "Min X", "Range where the field is sampled"));
350 parlst.addParam(new RichFloat("minY", -1.0f, "Min Y", "Range where the field is sampled"));
351 parlst.addParam(new RichFloat("minZ", -1.0f, "Min Z", "Range where the field is sampled"));
352 parlst.addParam(new RichFloat("maxX", 1.0f, "Max X", "Range where the field is sampled"));
353 parlst.addParam(new RichFloat("maxY", 1.0f, "Max Y", "Range where the field is sampled"));
354 parlst.addParam(new RichFloat("maxZ", 1.0f, "Max Z", "Range where the field is sampled"));
355 parlst.addParam(new RichString("expr","x*x+y*y+z*z-0.5","Function =", "This expression is evaluated for each voxel of the grid. The surface passing through the zero valued points of this field is then extracted using marching cube."));
356
357 break;
358
359 case FF_REFINE :
360 parlst.addParam(new RichString("condSelect","(q0 >= 0 && q1 >= 0)","boolean function","type a boolean function that will be evaluated on every edge"));
361 parlst.addParam(new RichString("x","(x0+x1)/2","x =","function to generate x coord of new vertex in [x0,x1].<br>For example (x0+x1)/2"));
362 parlst.addParam(new RichString("y","(y0+y1)/2","y =","function to generate x coord of new vertex in [y0,y1].<br>For example (y0+y1)/2"));
363 parlst.addParam(new RichString("z","(z0+z1)/2","z =","function to generate x coord of new vertex in [z0,z1].<br>For example (z0+z1)/2"));
364 break;
365
366 default: break; // do not add any parameter for the other filters
367 }
368 }
369
370 // The Real Core Function doing the actual mesh processing.
applyFilter(QAction * filter,MeshDocument & md,RichParameterSet & par,vcg::CallBackPos * cb)371 bool FilterFunctionPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
372 {
373 if(this->getClass(filter) == MeshFilterInterface::MeshCreation)
374 md.addNewMesh("",this->filterName(ID(filter)));
375 MeshModel &m=*(md.mm());
376 Q_UNUSED(cb);
377 switch(ID(filter)) {
378 case FF_VERT_SELECTION :
379 {
380 std::string expr = par.getString("condSelect").toStdString();
381 auto wexpr = conversion::fromStringToWString(expr);
382
383 // muparser initialization and explicitly define parser variables
384 Parser p;
385 setPerVertexVariables(p,m.cm);
386
387 // set expression inserted by user as string (required by muparser)
388 p.SetExpr(wexpr);
389
390 int numvert = 0;
391 time_t start = clock();
392
393 // every parser variables is related to vertex coord and attributes.
394 CMeshO::VertexIterator vi;
395 for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)if(!(*vi).IsD())
396 {
397 setAttributes(vi,m.cm);
398
399 bool selected = false;
400
401 // use parser to evaluate boolean function specified above
402 // in case of fail, error dialog contains details of parser's error
403 try {
404 selected = p.Eval();
405 } catch(Parser::exception_type &e) {
406 errorMessage = conversion::fromWStringToString(e.GetMsg()).c_str();
407 return false;
408 }
409
410 // set vertex as selected or clear selection
411 if(selected) {
412 (*vi).SetS();
413 numvert++;
414 } else (*vi).ClearS();
415 }
416
417 // if succeeded log stream contains number of vertices and time elapsed
418 Log( "selected %d vertices in %.2f sec.", numvert, (clock() - start) / (float) CLOCKS_PER_SEC);
419
420 return true;
421 }
422 break;
423
424 case FF_FACE_SELECTION :
425 {
426 QString select = par.getString("condSelect");
427
428 // muparser initialization and explicitly define parser variables
429 Parser p;
430 setPerFaceVariables(p,m.cm);
431
432 // set expression inserted by user as string (required by muparser)
433 p.SetExpr(conversion::fromStringToWString(select.toStdString()));
434
435 int numface = 0;
436 time_t start = clock();
437
438 // every parser variables is related to face attributes.
439 CMeshO::FaceIterator fi;
440 for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)if(!(*fi).IsD())
441 {
442 setAttributes(fi,m.cm);
443
444 bool selected = false;
445
446 // use parser to evaluate boolean function specified above
447 // in case of fail, error dialog contains details of parser's error
448 try {
449 selected = p.Eval();
450 } catch(Parser::exception_type &e) {
451 errorMessage = conversion::fromWStringToString(e.GetMsg()).c_str();
452 return false;
453 }
454
455 // set face as selected or clear selection
456 if(selected) {
457 (*fi).SetS();
458 numface++;
459 } else (*fi).ClearS();
460 }
461
462 // if succeeded log stream contains number of vertices and time elapsed
463 Log( "selected %d faces in %.2f sec.", numface, (clock() - start) / (float) CLOCKS_PER_SEC);
464
465 return true;
466 }
467 break;
468
469 case FF_GEOM_FUNC :
470 case FF_VERT_COLOR:
471 case FF_VERT_NORMAL:
472 {
473 std::string func_x,func_y,func_z,func_a;
474 // FF_VERT_COLOR : x = r, y = g, z = b
475 // FF_VERT_NORMAL : x = r, y = g, z = b
476 func_x = par.getString("x").toStdString();
477 func_y = par.getString("y").toStdString();
478 func_z = par.getString("z").toStdString();
479 if(ID(filter) == FF_VERT_COLOR) func_a = par.getString("a").toStdString();
480
481 bool onSelected = par.getBool("onselected");
482
483 if (onSelected && m.cm.svn == 0 && m.cm.sfn == 0) // if no selection at all, fail
484 {
485 Log("Cannot apply only on selection: there is no selection");
486 errorMessage = "Cannot apply only on selection: there is no selection";
487 return false;
488 }
489 if (onSelected && (m.cm.svn == 0 && m.cm.sfn > 0)) // if no vert selected, but some faces selected, use their vertices
490 {
491 tri::UpdateSelection<CMeshO>::VertexClear(m.cm);
492 tri::UpdateSelection<CMeshO>::VertexFromFaceLoose(m.cm);
493 }
494
495 // muparser initialization and explicitly define parser variables
496 // function for x,y and z must use different parser and variables
497 Parser p1,p2,p3,p4;
498
499 setPerVertexVariables(p1,m.cm);
500 setPerVertexVariables(p2,m.cm);
501 setPerVertexVariables(p3,m.cm);
502 setPerVertexVariables(p4,m.cm);
503
504 p1.SetExpr(conversion::fromStringToWString(func_x));
505 p2.SetExpr(conversion::fromStringToWString(func_y));
506 p3.SetExpr(conversion::fromStringToWString(func_z));
507 p4.SetExpr(conversion::fromStringToWString(func_a));
508
509 double newx=0,newy=0,newz=0,newa=255;
510 errorMessage = "";
511
512 time_t start = clock();
513
514 // every parser variables is related to vertex coord and attributes.
515 CMeshO::VertexIterator vi;
516 for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)
517 if(!(*vi).IsD())
518 if ((!onSelected) || ((*vi).IsS()))
519 {
520 setAttributes(vi,m.cm);
521
522 // every function is evaluated by different parser.
523 // errorMessage dialog contains errors for func x, func y and func z
524 try { newx = p1.Eval(); } catch(Parser::exception_type &e) { showParserError("1st func : ",e); }
525 try { newy = p2.Eval(); } catch(Parser::exception_type &e) { showParserError("2nd func : ",e); }
526 try { newz = p3.Eval(); } catch(Parser::exception_type &e) { showParserError("3rd func : ",e); }
527 if(ID(filter) == FF_VERT_COLOR)
528 {
529 try { newa = p4.Eval(); } catch(Parser::exception_type &e) { showParserError("4th func : ",e); }
530 }
531 if(errorMessage != "") return false;
532
533 if (ID(filter) == FF_GEOM_FUNC) // set new vertex coord for this iteration
534 (*vi).P() = Point3m(newx, newy, newz);
535 if (ID(filter) == FF_VERT_NORMAL) // set new color for this iteration
536 (*vi).N() = Point3m(newx, newy, newz);
537 if (ID(filter) == FF_VERT_COLOR) // set new color for this iteration
538 {
539 (*vi).C() = Color4b(newx, newy, newz, newa);
540 m.updateDataMask(MeshModel::MM_VERTCOLOR);
541 }
542
543 }
544
545 if(ID(filter) == FF_GEOM_FUNC) {
546 // update bounding box, normalize normals
547 tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFace(m.cm);
548 tri::UpdateNormal<CMeshO>::NormalizePerFace(m.cm);
549 tri::UpdateBounding<CMeshO>::Box(m.cm);
550 }
551
552 // if succeeded log stream contains number of vertices processed and time elapsed
553 Log( "%d vertices processed in %.2f sec.", m.cm.vn, (clock() - start) / (float) CLOCKS_PER_SEC);
554
555 return true;
556 }
557 break;
558
559 case FF_VERT_QUALITY:
560 {
561 std::string func_q = par.getString("q").toStdString();
562 bool onSelected = par.getBool("onselected");
563
564 if (onSelected && m.cm.svn == 0 && m.cm.sfn == 0) // if no selection at all, fail
565 {
566 Log("Cannot apply only on selection: there is no selection");
567 errorMessage = "Cannot apply only on selection: there is no selection";
568 return false;
569 }
570 if (onSelected && (m.cm.svn == 0 && m.cm.sfn > 0)) // if no vert selected, but some faces selected, use their vertices
571 {
572 tri::UpdateSelection<CMeshO>::VertexClear(m.cm);
573 tri::UpdateSelection<CMeshO>::VertexFromFaceLoose(m.cm);
574 }
575
576 m.updateDataMask(MeshModel::MM_VERTQUALITY);
577
578 // muparser initialization and define custom variables
579 Parser p;
580 setPerVertexVariables(p,m.cm);
581
582 // set expression to calc with parser
583 p.SetExpr(conversion::fromStringToWString(func_q));
584
585 // every parser variables is related to vertex coord and attributes.
586 time_t start = clock();
587 CMeshO::VertexIterator vi;
588 for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)
589 if(!(*vi).IsD())
590 if ((!onSelected) || ((*vi).IsS()))
591 {
592 setAttributes(vi,m.cm);
593
594 // use parser to evaluate function specified above
595 // in case of fail, errorMessage dialog contains details of parser's error
596 try {
597 (*vi).Q() = p.Eval();
598 } catch(Parser::exception_type &e) {
599 errorMessage = conversion::fromWStringToString(e.GetMsg()).c_str();
600 return false;
601 }
602 }
603
604 // normalize quality with values in [0..1]
605 if(par.getBool("normalize")) tri::UpdateQuality<CMeshO>::VertexNormalize(m.cm);
606
607 // map quality into per-vertex color
608 if(par.getBool("map"))
609 {
610 tri::UpdateColor<CMeshO>::PerVertexQualityRamp(m.cm);
611 m.updateDataMask(MeshModel::MM_VERTCOLOR);
612 }
613 // if succeeded log stream contains number of vertices and time elapsed
614 Log( "%d vertices processed in %.2f sec.", m.cm.vn, (clock() - start) / (float) CLOCKS_PER_SEC);
615
616 return true;
617 }
618 break;
619 case FF_VERT_TEXTURE_FUNC:
620 {
621 std::string func_u = par.getString("u").toStdString();
622 std::string func_v = par.getString("v").toStdString();
623 bool onSelected = par.getBool("onselected");
624
625 if (onSelected && m.cm.svn == 0 && m.cm.sfn == 0) // if no selection at all, fail
626 {
627 Log("Cannot apply only on selection: there is no selection");
628 errorMessage = "Cannot apply only on selection: there is no selection";
629 return false;
630 }
631 if (onSelected && (m.cm.svn == 0 && m.cm.sfn > 0)) // if no vert selected, but some faces selected, use their vertices
632 {
633 tri::UpdateSelection<CMeshO>::VertexClear(m.cm);
634 tri::UpdateSelection<CMeshO>::VertexFromFaceLoose(m.cm);
635 }
636
637 m.updateDataMask(MeshModel::MM_VERTTEXCOORD);
638
639 // muparser initialization and define custom variables
640 Parser pu,pv;
641 setPerVertexVariables(pu,m.cm);
642 setPerVertexVariables(pv,m.cm);
643
644 // set expression to calc with parser
645 #ifdef _UNICODE
646 pu.SetExpr(conversion::fromStringToWString(func_u));
647 pv.SetExpr(conversion::fromStringToWString(func_v));
648 #else
649 pu.SetExpr(func_u);
650 pv.SetExpr(func_v);
651 #endif
652
653 // every parser variables is related to vertex coord and attributes.
654 time_t start = clock();
655 CMeshO::VertexIterator vi;
656 for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)
657 if(!(*vi).IsD())
658 if ((!onSelected) || ((*vi).IsS()))
659 {
660 setAttributes(vi,m.cm);
661
662 // use parser to evaluate function specified above
663 // in case of fail, errorMessage dialog contains details of parser's error
664 try {
665 (*vi).T().U() = pu.Eval();
666 (*vi).T().V() = pv.Eval();
667 } catch(Parser::exception_type &e) {
668 errorMessage = conversion::fromWStringToString(e.GetMsg()).c_str();
669 return false;
670 }
671 }
672
673 Log( "%d vertices processed in %.2f sec.", m.cm.vn, (clock() - start) / (float) CLOCKS_PER_SEC);
674 return true;
675 }
676 break;
677 case FF_WEDGE_TEXTURE_FUNC:
678 {
679 std::string func_u0 = par.getString("u0").toStdString();
680 std::string func_v0 = par.getString("v0").toStdString();
681 std::string func_u1 = par.getString("u1").toStdString();
682 std::string func_v1 = par.getString("v1").toStdString();
683 std::string func_u2 = par.getString("u2").toStdString();
684 std::string func_v2 = par.getString("v2").toStdString();
685 bool onSelected = par.getBool("onselected");
686
687 if (onSelected && m.cm.sfn == 0) // if no selection, fail
688 {
689 Log("Cannot apply only on selection: there is no selection");
690 errorMessage = "Cannot apply only on selection: there is no selection";
691 return false;
692 }
693
694 m.updateDataMask(MeshModel::MM_VERTTEXCOORD);
695
696 // muparser initialization and define custom variables
697 Parser pu0,pv0,pu1,pv1,pu2,pv2;
698 setPerFaceVariables(pu0,m.cm); setPerFaceVariables(pv0,m.cm);
699 setPerFaceVariables(pu1,m.cm); setPerFaceVariables(pv1,m.cm);
700 setPerFaceVariables(pu2,m.cm); setPerFaceVariables(pv2,m.cm);
701
702 // set expression to calc with parser
703 pu0.SetExpr(conversion::fromStringToWString(func_u0)); pv0.SetExpr(conversion::fromStringToWString(func_v0));
704 pu1.SetExpr(conversion::fromStringToWString(func_u1)); pv1.SetExpr(conversion::fromStringToWString(func_v1));
705 pu2.SetExpr(conversion::fromStringToWString(func_u2)); pv2.SetExpr(conversion::fromStringToWString(func_v2));
706
707 // every parser variables is related to vertex coord and attributes.
708 time_t start = clock();
709 CMeshO::VertexIterator vi;
710 for(CMeshO::FaceIterator fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)
711 if(!(*fi).IsD())
712 if ((!onSelected) || ((*fi).IsS()))
713 {
714 setAttributes(fi,m.cm);
715
716 // use parser to evaluate function specified above
717 // in case of fail, errorMessage dialog contains details of parser's error
718 try {
719 (*fi).WT(0).U() = pu0.Eval(); (*fi).WT(0).V() = pv0.Eval();
720 (*fi).WT(1).U() = pu1.Eval(); (*fi).WT(1).V() = pv1.Eval();
721 (*fi).WT(2).U() = pu2.Eval(); (*fi).WT(2).V() = pv2.Eval();
722 } catch(Parser::exception_type &e) {
723 errorMessage = conversion::fromWStringToString(e.GetMsg()).c_str();
724 return false;
725 }
726 }
727
728 Log( "%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC);
729 return true;
730 }
731 break;
732 case FF_FACE_COLOR:
733 {
734 std::string func_r = par.getString("r").toStdString();
735 std::string func_g = par.getString("g").toStdString();
736 std::string func_b = par.getString("b").toStdString();
737 std::string func_a = par.getString("a").toStdString();
738 bool onSelected = par.getBool("onselected");
739
740 if (onSelected && m.cm.sfn == 0) // if no selection, fail
741 {
742 Log("Cannot apply only on selection: there is no selection");
743 errorMessage = "Cannot apply only on selection: there is no selection";
744 return false;
745 }
746
747 m.updateDataMask(MeshModel::MM_FACECOLOR);
748
749 // muparser initialization and explicitly define parser variables
750 // every function must uses own parser and variables
751 Parser p1,p2,p3,p4;
752
753 setPerFaceVariables(p1,m.cm);
754 setPerFaceVariables(p2,m.cm);
755 setPerFaceVariables(p3,m.cm);
756 setPerFaceVariables(p4,m.cm);
757
758 p1.SetExpr(conversion::fromStringToWString(func_r));
759 p2.SetExpr(conversion::fromStringToWString(func_g));
760 p3.SetExpr(conversion::fromStringToWString(func_b));
761 p4.SetExpr(conversion::fromStringToWString(func_a));
762
763 // RGB is related to every face
764 CMeshO::FaceIterator fi;
765 double newr=0,newg=0,newb=0,newa=255;
766 errorMessage = "";
767
768 time_t start = clock();
769
770 // every parser variables is related to face attributes.
771 for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)
772 if(!(*fi).IsD())
773 if ((!onSelected) || ((*fi).IsS()))
774 {
775 setAttributes(fi,m.cm);
776
777 // evaluate functions to generate new color
778 // in case of fail, error dialog contains details of parser's error
779 try { newr = p1.Eval(); } catch(Parser::exception_type &e) { showParserError("func r: ",e); }
780 try { newg = p2.Eval(); } catch(Parser::exception_type &e) { showParserError("func g: ",e); }
781 try { newb = p3.Eval(); } catch(Parser::exception_type &e) { showParserError("func b: ",e); }
782 try { newa = p4.Eval(); } catch(Parser::exception_type &e) { showParserError("func a: ",e); }
783
784 if(errorMessage != "") return false;
785
786 // set new color for this iteration
787 (*fi).C() = Color4b(newr,newg,newb,newa);
788 }
789
790 // if succeeded log stream contains number of vertices processed and time elapsed
791 Log( "%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC);
792
793 return true;
794
795 }
796 break;
797
798 case FF_FACE_QUALITY:
799 {
800 std::string func_q = par.getString("q").toStdString();
801 bool onSelected = par.getBool("onselected");
802
803 if (onSelected && m.cm.sfn == 0) // if no selection, fail
804 {
805 Log("Cannot apply only on selection: there is no selection");
806 errorMessage = "Cannot apply only on selection: there is no selection";
807 return false;
808 }
809
810 m.updateDataMask(MeshModel::MM_FACEQUALITY);
811
812 // muparser initialization and define custom variables
813 Parser pf;
814 setPerFaceVariables(pf,m.cm);
815
816 // set expression to calc with parser
817 pf.SetExpr(conversion::fromStringToWString(func_q));
818
819 time_t start = clock();
820 errorMessage = "";
821
822 // every parser variables is related to face attributes.
823 CMeshO::FaceIterator fi;
824 for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)
825 if(!(*fi).IsD())
826 if ((!onSelected) || ((*fi).IsS()))
827 {
828 setAttributes(fi,m.cm);
829
830 // evaluate functions to generate new quality
831 // in case of fail, error dialog contains details of parser's error
832 try { (*fi).Q() = pf.Eval(); }
833 catch(Parser::exception_type &e) {
834 showParserError("func q: ",e);
835 }
836 if(errorMessage != "") return false;
837 }
838
839 // normalize quality with values in [0..1]
840 if(par.getBool("normalize")) tri::UpdateQuality<CMeshO>::FaceNormalize(m.cm);
841
842 // map quality into per-vertex color
843 if(par.getBool("map"))
844 {
845 tri::UpdateColor<CMeshO>::PerFaceQualityRamp(m.cm);
846 m.updateDataMask(MeshModel::MM_FACECOLOR);
847 }
848
849 // if succeeded log stream contains number of faces processed and time elapsed
850 Log( "%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC);
851
852 return true;
853 }
854 break;
855
856 case FF_DEF_VERT_ATTRIB :
857 {
858 std::string name = par.getString("name").toStdString();
859 std::string expr = par.getString("expr").toStdString();
860
861 // add per-vertex attribute with type float and name specified by user
862 CMeshO::PerVertexAttributeHandle<float> h;
863 if(tri::HasPerVertexAttribute(m.cm,name))
864 {
865 h = tri::Allocator<CMeshO>::FindPerVertexAttribute<float>(m.cm, name);
866 if(!tri::Allocator<CMeshO>::IsValidHandle<float>(m.cm,h))
867 {
868 errorMessage = "attribute already exists with a different type";
869 return false;
870 }
871 }
872 else
873 h = tri::Allocator<CMeshO>::AddPerVertexAttribute<float> (m.cm,name);
874
875 std::vector<std::string> AllVertexAttribName;
876 tri::Allocator<CMeshO>::GetAllPerVertexAttribute< float >(m.cm,AllVertexAttribName);
877 qDebug("Now mesh has %lu vertex float attribute",AllVertexAttribName.size());
878 Parser p;
879 setPerVertexVariables(p,m.cm);
880 p.SetExpr(conversion::fromStringToWString(expr));
881
882 time_t start = clock();
883
884 // perform calculation of attribute's value with function specified by user
885 CMeshO::VertexIterator vi;
886 for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)if(!(*vi).IsD())
887 {
888 setAttributes(vi,m.cm);
889
890 // add new user-defined attribute
891 try {
892 h[vi] = p.Eval();
893 } catch(Parser::exception_type &e) {
894 errorMessage = conversion::fromWStringToString(e.GetMsg()).c_str();
895 return false;
896 }
897 }
898
899 // add string, double and handler to vector.
900 // vectors keep tracks of new attributes and let muparser use explicit variables
901 // it's possible to use custom attributes in other filters
902 v_attrNames.push_back(name);
903 v_attrValue.push_back(0);
904 v_handlers.push_back(h);
905
906 // if succeeded log stream contains number of vertices processed and time elapsed
907 Log( "%d vertices processed in %.2f sec.", m.cm.vn, (clock() - start) / (float) CLOCKS_PER_SEC);
908
909 return true;
910 }
911 break;
912
913 case FF_DEF_FACE_ATTRIB :
914 {
915 std::string name = par.getString("name").toStdString();
916 std::string expr = par.getString("expr").toStdString();
917
918 // add per-face attribute with type float and name specified by user
919 // add per-vertex attribute with type float and name specified by user
920 CMeshO::PerFaceAttributeHandle<float> h;
921 if(tri::HasPerFaceAttribute(m.cm,name))
922 {
923 h = tri::Allocator<CMeshO>::FindPerFaceAttribute<float>(m.cm, name);
924 if(!tri::Allocator<CMeshO>::IsValidHandle<float>(m.cm,h))
925 {
926 errorMessage = "attribute already exists with a different type";
927 return false;
928 }
929 }
930 else
931 h = tri::Allocator<CMeshO>::AddPerFaceAttribute<float> (m.cm,name);
932 Parser p;
933 setPerFaceVariables(p,m.cm);
934 p.SetExpr(conversion::fromStringToWString(expr));
935
936 time_t start = clock();
937
938 // every parser variables is related to face attributes.
939 CMeshO::FaceIterator fi;
940 for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)if(!(*fi).IsD())
941 {
942 setAttributes(fi,m.cm);
943
944 // add new user-defined attribute
945 try {
946 h[fi] = p.Eval();
947 } catch(Parser::exception_type &e) {
948 errorMessage = conversion::fromWStringToString(e.GetMsg()).c_str();
949 return false;
950 }
951 }
952
953 // // add string, double and handler to vector.
954 // // vectors keep tracks of new attributes and let muparser use explicit variables
955 // // it's possible to use custom attributes in other filters
956 // f_attrNames.push_back(name);
957 // f_attrValue.push_back(0);
958 // fhandlers.push_back(h);
959
960 // if succeeded log stream contains number of vertices processed and time elapsed
961 Log( "%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC);
962
963 return true;
964 }
965 break;
966
967 case FF_GRID :
968 {
969 // obtain parameters to generate 2D Grid
970 int w = par.getInt("numVertX");
971 int h = par.getInt("numVertY");
972 float wl = par.getFloat("absScaleX");
973 float hl = par.getFloat("absScaleY");
974
975 if(w <= 0 || h <= 0) {
976 errorMessage = "number of vertices must be positive";
977 return false;
978 }
979
980 // use Grid function to generate Grid
981 tri::Grid<CMeshO>(m.cm, w, h, wl, hl);
982
983 // if "centered on origin" is checked than move generated Grid in (0,0,0)
984 if(par.getBool("center"))
985 {
986 // move x and y
987 Scalarm halfw = Scalarm(w-1)/2;
988 Scalarm halfh = Scalarm(h-1)/2;
989 Scalarm wld = wl/Scalarm(w);
990 Scalarm hld = hl/Scalarm(h);
991
992 for(auto vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)
993 {
994 (*vi).P()[0] = (*vi).P()[0] - (wld * halfw);
995 (*vi).P()[1] = (*vi).P()[1] - (hld * halfh);
996 }
997 }
998 // update bounding box, normals
999 // Matrix44m rot; rot.SetRotateDeg(180,Point3m(0,1,0));
1000 Matrix44m rot; rot.SetScale(-1,1,-1);
1001 tri::UpdatePosition<CMeshO>::Matrix(m.cm,rot,false);
1002 m.UpdateBoxAndNormals();
1003 return true;
1004 }
1005 break;
1006 case FF_ISOSURFACE :
1007 {
1008 SimpleVolume<SimpleVoxel <float > > volume;
1009
1010 typedef vcg::tri::TrivialWalker<CMeshO, SimpleVolume<SimpleVoxel<float> > > MyWalker;
1011 typedef vcg::tri::MarchingCubes<CMeshO, MyWalker> MyMarchingCubes;
1012 MyWalker walker;
1013
1014 Box3f RangeBBox;
1015 RangeBBox.min[0]=par.getFloat("minX");
1016 RangeBBox.min[1]=par.getFloat("minY");
1017 RangeBBox.min[2]=par.getFloat("minZ");
1018 RangeBBox.max[0]=par.getFloat("maxX");
1019 RangeBBox.max[1]=par.getFloat("maxY");
1020 RangeBBox.max[2]=par.getFloat("maxZ");
1021 double step=par.getFloat("voxelSize");
1022 Point3i siz= Point3i::Construct((RangeBBox.max-RangeBBox.min)*(1.0/step));
1023
1024 Parser p;
1025 double x,y,z;
1026 p.DefineVar(conversion::fromStringToWString("x"), &x);
1027 p.DefineVar(conversion::fromStringToWString("y"), &y);
1028 p.DefineVar(conversion::fromStringToWString("z"), &z);
1029 std::string expr = par.getString("expr").toStdString();
1030 p.SetExpr(conversion::fromStringToWString(expr));
1031 Log("Filling a Volume of %i %i %i",siz[0],siz[1],siz[2]);
1032 volume.Init(siz,RangeBBox);
1033 for(double i=0;i<siz[0];i++)
1034 for(double j=0;j<siz[1];j++)
1035 for(double k=0;k<siz[2];k++)
1036 {
1037 x = RangeBBox.min[0]+step*i;
1038 y = RangeBBox.min[1]+step*j;
1039 z = RangeBBox.min[2]+step*k;
1040 try {
1041 volume.Val(i,j,k)=p.Eval();
1042 } catch(Parser::exception_type &e) {
1043 errorMessage = conversion::fromWStringToString(e.GetMsg()).c_str();
1044 return false;
1045 }
1046 }
1047
1048 // MARCHING CUBES
1049 Log("[MARCHING CUBES] Building mesh...");
1050 MyMarchingCubes mc(m.cm, walker);
1051 walker.BuildMesh<MyMarchingCubes>(m.cm, volume, mc, 0);
1052 // Matrix44m tr; tr.SetIdentity(); tr.SetTranslate(rbb.min[0],rbb.min[1],rbb.min[2]);
1053 // Matrix44m sc; sc.SetIdentity(); sc.SetScale(step,step,step);
1054 // tr=tr*sc;
1055
1056 // tri::UpdatePosition<CMeshO>::Matrix(m.cm,tr);
1057 tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFace(m.cm);
1058 tri::UpdateBounding<CMeshO>::Box(m.cm); // updates bounding box
1059 return true;
1060
1061 }
1062 break;
1063
1064 case FF_REFINE :
1065 {
1066 std::string condSelect = par.getString("condSelect").toStdString();
1067
1068 std::string expr1 = par.getString("x").toStdString();
1069 std::string expr2 = par.getString("y").toStdString();
1070 std::string expr3 = par.getString("z").toStdString();
1071
1072 bool errorMidPoint = false;
1073 bool errorEdgePred = false;
1074 std::string msg = "";
1075
1076 // check parsing errors while creating two func obj
1077 // display error message
1078 MidPointCustom<CMeshO> mid = MidPointCustom<CMeshO>(m.cm,expr1,expr2,expr3,errorMidPoint,msg);
1079 CustomEdge<CMeshO> edge = CustomEdge<CMeshO>(condSelect,errorEdgePred,msg);
1080 if(errorMidPoint || errorEdgePred)
1081 {
1082 errorMessage = msg.c_str();
1083 return false;
1084 }
1085
1086 // Refine current mesh.
1087 // Only edge specified with CustomEdge pred are selected
1088 // and the new vertex is chosen with MidPointCustom created above
1089 vcg::tri::RefineE<CMeshO, MidPointCustom<CMeshO>, CustomEdge<CMeshO> >
1090 (m.cm, mid, edge, false, cb);
1091 m.UpdateBoxAndNormals();
1092 m.clearDataMask( MeshModel::MM_VERTMARK);
1093 //vcg::tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFace(m.cm);
1094
1095 return true;
1096 }
1097 break;
1098
1099 default : assert (0);
1100 }
1101 return false;
1102 }
1103
1104 // display parsing error in dialog
showParserError(const QString & s,Parser::exception_type & e)1105 void FilterFunctionPlugin::showParserError(const QString &s, Parser::exception_type &e)
1106 {
1107 errorMessage += s;
1108 errorMessage += conversion::fromWStringToString(e.GetMsg()).c_str();
1109 errorMessage += "\n";
1110 }
1111
1112 // set per-vertex attributes associated to parser variables
setAttributes(CMeshO::VertexIterator & vi,CMeshO & m)1113 void FilterFunctionPlugin::setAttributes(CMeshO::VertexIterator &vi, CMeshO &m)
1114 {
1115 x = (*vi).P()[0]; // coord x
1116 y = (*vi).P()[1]; // coord y
1117 z = (*vi).P()[2]; // coord z
1118
1119 nx = (*vi).N()[0]; // normal coord x
1120 ny = (*vi).N()[1]; // normal coord y
1121 nz = (*vi).N()[2]; // normal coord z
1122
1123 r = (*vi).C()[0]; // color R
1124 g = (*vi).C()[1]; // color G
1125 b = (*vi).C()[2]; // color B
1126 a = (*vi).C()[3]; // color ALPHA
1127
1128 q = (*vi).Q(); // quality
1129
1130 vsel = ((*vi).IsS()) ? 1.0 : 0.0; //selection
1131
1132 if(tri::HasPerVertexRadius(m)) rad = (*vi).R();
1133 else rad=0;
1134
1135 v = vi - m.vert.begin(); // zero based index of current vertex
1136
1137 if(tri::HasPerVertexTexCoord(m))
1138 {
1139 vtu=(*vi).T().U();
1140 vtv=(*vi).T().V();
1141 ti = (*vi).T().N();
1142 }
1143 else { vtu=vtv=ti=0; }
1144
1145 // if user-defined attributes exist (vector is not empty)
1146 // set variables to explicit value obtained through attribute's handler
1147 for(int i = 0; i < (int) v_attrValue.size(); i++)
1148 v_attrValue[i] = v_handlers[i][vi];
1149
1150 for(int i = 0; i < (int) v3_handlers.size(); i++)
1151 {
1152 v3_attrValue[i*3+0] = v3_handlers[i][vi].X();
1153 v3_attrValue[i*3+1] = v3_handlers[i][vi].Y();
1154 v3_attrValue[i*3+2] = v3_handlers[i][vi].Z();
1155 }
1156 }
1157
1158 // set per-face attributes associated to parser variables
setAttributes(CMeshO::FaceIterator & fi,CMeshO & m)1159 void FilterFunctionPlugin::setAttributes(CMeshO::FaceIterator &fi, CMeshO &m)
1160 {
1161 // set attributes for First vertex
1162 // coords, normal coords, quality
1163 x0 = (*fi).V(0)->P()[0];
1164 y0 = (*fi).V(0)->P()[1];
1165 z0 = (*fi).V(0)->P()[2];
1166
1167 nx0 = (*fi).V(0)->N()[0];
1168 ny0 = (*fi).V(0)->N()[1];
1169 nz0 = (*fi).V(0)->N()[2];
1170
1171 r0 = (*fi).V(0)->C()[0];
1172 g0 = (*fi).V(0)->C()[1];
1173 b0 = (*fi).V(0)->C()[2];
1174 a0 = (*fi).V(0)->C()[3];
1175
1176 q0 = (*fi).V(0)->Q();
1177
1178 // set attributes for Second vertex
1179 // coords, normal coords, quality
1180 x1 = (*fi).V(1)->P()[0];
1181 y1 = (*fi).V(1)->P()[1];
1182 z1 = (*fi).V(1)->P()[2];
1183
1184 nx1 = (*fi).V(1)->N()[0];
1185 ny1 = (*fi).V(1)->N()[1];
1186 nz1 = (*fi).V(1)->N()[2];
1187
1188 r1 = (*fi).V(1)->C()[0];
1189 g1 = (*fi).V(1)->C()[1];
1190 b1 = (*fi).V(1)->C()[2];
1191 a1 = (*fi).V(1)->C()[3];
1192
1193 q1 = (*fi).V(1)->Q();
1194
1195 // set attributes for Third vertex
1196 // coords, normal coords, quality
1197 x2 = (*fi).V(2)->P()[0];
1198 y2 = (*fi).V(2)->P()[1];
1199 z2 = (*fi).V(2)->P()[2];
1200
1201 nx2 = (*fi).V(2)->N()[0];
1202 ny2 = (*fi).V(2)->N()[1];
1203 nz2 = (*fi).V(2)->N()[2];
1204
1205 r2 = (*fi).V(2)->C()[0];
1206 g2 = (*fi).V(2)->C()[1];
1207 b2 = (*fi).V(2)->C()[2];
1208 a2 = (*fi).V(2)->C()[3];
1209
1210 q2 = (*fi).V(2)->Q();
1211
1212 if(HasPerFaceQuality(m))
1213 fq=(*fi).Q();
1214 else fq=0;
1215
1216 // set face color attributes
1217 if(HasPerFaceColor(m)){
1218 fr = (*fi).C()[0];
1219 fg = (*fi).C()[1];
1220 fb = (*fi).C()[2];
1221 fa = (*fi).C()[3];
1222 } else {
1223 fr=fg=fb=fa=255;
1224 }
1225
1226 //face normal
1227 fnx = (*fi).N()[0];
1228 fny = (*fi).N()[1];
1229 fnz = (*fi).N()[2];
1230
1231 // zero based index of face
1232 f = fi - m.face.begin();
1233
1234 // zero based index of its vertices
1235 v0i = ((*fi).V(0) - &m.vert[0]);
1236 v1i = ((*fi).V(1) - &m.vert[0]);
1237 v2i = ((*fi).V(2) - &m.vert[0]);
1238
1239 if(tri::HasPerWedgeTexCoord(m))
1240 {
1241 wtu0=(*fi).WT(0).U();
1242 wtv0=(*fi).WT(0).V();
1243 wtu1=(*fi).WT(1).U();
1244 wtv1=(*fi).WT(1).V();
1245 wtu2=(*fi).WT(2).U();
1246 wtv2=(*fi).WT(2).V();
1247 ti = (*fi).WT(0).N();
1248 }
1249 else { wtu0=wtv0=wtu1=wtv1=wtu2=wtv2=ti=0; }
1250
1251 //selection
1252 vsel0 = ((*fi).V(0)->IsS()) ? 1.0 : 0.0;
1253 vsel1 = ((*fi).V(1)->IsS()) ? 1.0 : 0.0;
1254 vsel2 = ((*fi).V(2)->IsS()) ? 1.0 : 0.0;
1255 fsel = ((*fi).IsS()) ? 1.0 : 0.0;
1256
1257 // if user-defined attributes exist (vector is not empty)
1258 // set variables to explicit value obtained through attribute's handler
1259 for(int i = 0; i < (int) f_attrValue.size(); i++)
1260 f_attrValue[i] = f_handlers[i][fi];
1261 }
1262
1263 // Function explicitly define parser variables to perform per-vertex filter action
1264 // x, y, z for vertex coord, nx, ny, nz for normal coord, r, g ,b for color
1265 // and q for quality
setPerVertexVariables(Parser & p,CMeshO & m)1266 void FilterFunctionPlugin::setPerVertexVariables(Parser &p, CMeshO &m)
1267 {
1268 p.DefineVar(conversion::fromStringToWString("x"), &x);
1269 p.DefineVar(conversion::fromStringToWString("y"), &y);
1270 p.DefineVar(conversion::fromStringToWString("z"), &z);
1271 p.DefineVar(conversion::fromStringToWString("nx"), &nx);
1272 p.DefineVar(conversion::fromStringToWString("ny"), &ny);
1273 p.DefineVar(conversion::fromStringToWString("nz"), &nz);
1274 p.DefineVar(conversion::fromStringToWString("r"), &r);
1275 p.DefineVar(conversion::fromStringToWString("g"), &g);
1276 p.DefineVar(conversion::fromStringToWString("b"), &b);
1277 p.DefineVar(conversion::fromStringToWString("a"), &a);
1278 p.DefineVar(conversion::fromStringToWString("q"), &q);
1279 p.DefineVar(conversion::fromStringToWString("vi"),&v);
1280 p.DefineVar(conversion::fromStringToWString("rad"),&rad);
1281 p.DefineVar(conversion::fromStringToWString("vtu"),&vtu);
1282 p.DefineVar(conversion::fromStringToWString("vtv"),&vtv);
1283 p.DefineVar(conversion::fromStringToWString("ti"), &ti);
1284 p.DefineVar(conversion::fromStringToWString("vsel"), &vsel);
1285
1286 // define var for user-defined attributes (if any exists)
1287 // if vector is empty, code won't be executed
1288 v_handlers.clear();
1289 v_attrNames.clear();
1290 v_attrValue.clear();
1291 v3_handlers.clear();
1292 v3_attrNames.clear();
1293 v3_attrValue.clear();
1294 std::vector<std::string> AllVertexAttribName;
1295 tri::Allocator<CMeshO>::GetAllPerVertexAttribute< float >(m,AllVertexAttribName);
1296 for(int i = 0; i < (int) AllVertexAttribName.size(); i++)
1297 {
1298 CMeshO::PerVertexAttributeHandle<float> hh = tri::Allocator<CMeshO>::GetPerVertexAttribute<float>(m, AllVertexAttribName[i]);
1299 v_handlers.push_back(hh);
1300 v_attrNames.push_back(AllVertexAttribName[i]);
1301 v_attrValue.push_back(0);
1302 p.DefineVar(conversion::fromStringToWString(v_attrNames.back()), &v_attrValue.back());
1303 qDebug("Adding custom per vertex float variable %s",v_attrNames.back().c_str());
1304 }
1305 AllVertexAttribName.clear();
1306 tri::Allocator<CMeshO>::GetAllPerVertexAttribute< Point3f >(m,AllVertexAttribName);
1307 for(int i = 0; i < (int) AllVertexAttribName.size(); i++)
1308 {
1309 CMeshO::PerVertexAttributeHandle<Point3f> hh3 = tri::Allocator<CMeshO>::GetPerVertexAttribute<Point3f>(m, AllVertexAttribName[i]);
1310
1311 v3_handlers.push_back(hh3);
1312
1313 v3_attrValue.push_back(0);
1314 v3_attrNames.push_back(AllVertexAttribName[i]+"_x");
1315 p.DefineVar(conversion::fromStringToWString(v3_attrNames.back()), &v3_attrValue.back());
1316
1317 v3_attrValue.push_back(0);
1318 v3_attrNames.push_back(AllVertexAttribName[i]+"_y");
1319 p.DefineVar(conversion::fromStringToWString(v3_attrNames.back()), &v3_attrValue.back());
1320
1321 v3_attrValue.push_back(0);
1322 v3_attrNames.push_back(AllVertexAttribName[i]+"_z");
1323 p.DefineVar(conversion::fromStringToWString(v3_attrNames.back()), &v3_attrValue.back());
1324 qDebug("Adding custom per vertex Point3f variable %s",v3_attrNames.back().c_str());
1325 }
1326 }
1327
1328
1329 // Function explicitly define parser variables to perform Per-Face filter action
setPerFaceVariables(Parser & p,CMeshO & m)1330 void FilterFunctionPlugin::setPerFaceVariables(Parser &p, CMeshO &m)
1331 {
1332 // coord of the three vertices within a face
1333 p.DefineVar(conversion::fromStringToWString("x0"), &x0);
1334 p.DefineVar(conversion::fromStringToWString("y0"), &y0);
1335 p.DefineVar(conversion::fromStringToWString("z0"), &z0);
1336 p.DefineVar(conversion::fromStringToWString("x1"), &x1);
1337 p.DefineVar(conversion::fromStringToWString("y1"), &y1);
1338 p.DefineVar(conversion::fromStringToWString("z1"), &z1);
1339 p.DefineVar(conversion::fromStringToWString("x2"), &x2);
1340 p.DefineVar(conversion::fromStringToWString("y2"), &y2);
1341 p.DefineVar(conversion::fromStringToWString("z2"), &z2);
1342
1343 // attributes of the vertices
1344 // normals:
1345 p.DefineVar(conversion::fromStringToWString("nx0"), &nx0);
1346 p.DefineVar(conversion::fromStringToWString("ny0"), &ny0);
1347 p.DefineVar(conversion::fromStringToWString("nz0"), &nz0);
1348
1349 p.DefineVar(conversion::fromStringToWString("nx1"), &nx1);
1350 p.DefineVar(conversion::fromStringToWString("ny1"), &ny1);
1351 p.DefineVar(conversion::fromStringToWString("nz1"), &nz1);
1352
1353 p.DefineVar(conversion::fromStringToWString("nx2"), &nx2);
1354 p.DefineVar(conversion::fromStringToWString("ny2"), &ny2);
1355 p.DefineVar(conversion::fromStringToWString("nz2"), &nz2);
1356
1357 // colors:
1358 p.DefineVar(conversion::fromStringToWString("r0"), &r0);
1359 p.DefineVar(conversion::fromStringToWString("g0"), &g0);
1360 p.DefineVar(conversion::fromStringToWString("b0"), &b0);
1361 p.DefineVar(conversion::fromStringToWString("a0"), &a0);
1362
1363 p.DefineVar(conversion::fromStringToWString("r1"), &r1);
1364 p.DefineVar(conversion::fromStringToWString("g1"), &g1);
1365 p.DefineVar(conversion::fromStringToWString("b1"), &b1);
1366 p.DefineVar(conversion::fromStringToWString("a1"), &a1);
1367
1368 p.DefineVar(conversion::fromStringToWString("r2"), &r2);
1369 p.DefineVar(conversion::fromStringToWString("g2"), &g2);
1370 p.DefineVar(conversion::fromStringToWString("b2"), &b2);
1371 p.DefineVar(conversion::fromStringToWString("a2"), &a2);
1372
1373 // quality
1374 p.DefineVar(conversion::fromStringToWString("q0"), &q0);
1375 p.DefineVar(conversion::fromStringToWString("q1"), &q1);
1376 p.DefineVar(conversion::fromStringToWString("q2"), &q2);
1377
1378 // face color
1379 p.DefineVar(conversion::fromStringToWString("fr"), &fr);
1380 p.DefineVar(conversion::fromStringToWString("fg"), &fg);
1381 p.DefineVar(conversion::fromStringToWString("fb"), &fb);
1382 p.DefineVar(conversion::fromStringToWString("fa"), &fa);
1383
1384 // face normal
1385 p.DefineVar(conversion::fromStringToWString("fnx"), &fnx);
1386 p.DefineVar(conversion::fromStringToWString("fny"), &fny);
1387 p.DefineVar(conversion::fromStringToWString("fnz"), &fnz);
1388
1389 // face quality
1390 p.DefineVar(conversion::fromStringToWString("fq"), &fq);
1391
1392 // index
1393 p.DefineVar(conversion::fromStringToWString("fi"),&f);
1394 p.DefineVar(conversion::fromStringToWString("vi0"),&v0i);
1395 p.DefineVar(conversion::fromStringToWString("vi1"),&v1i);
1396 p.DefineVar(conversion::fromStringToWString("vi2"),&v2i);
1397
1398 // texture
1399 p.DefineVar(conversion::fromStringToWString("wtu0"),&wtu0);
1400 p.DefineVar(conversion::fromStringToWString("wtv0"),&wtv0);
1401 p.DefineVar(conversion::fromStringToWString("wtu1"),&wtu1);
1402 p.DefineVar(conversion::fromStringToWString("wtv1"),&wtv1);
1403 p.DefineVar(conversion::fromStringToWString("wtu2"),&wtu2);
1404 p.DefineVar(conversion::fromStringToWString("wtv2"),&wtv2);
1405 p.DefineVar(conversion::fromStringToWString("ti"), &ti);
1406
1407 //selection
1408 p.DefineVar(conversion::fromStringToWString("vsel0"), &vsel0);
1409 p.DefineVar(conversion::fromStringToWString("vsel1"), &vsel1);
1410 p.DefineVar(conversion::fromStringToWString("vsel2"), &vsel2);
1411 p.DefineVar(conversion::fromStringToWString("fsel"), &fsel);
1412
1413 // define var for user-defined attributes (if any exists)
1414 // if vector is empty, code won't be executed
1415 std::vector<std::string> AllFaceAttribName;
1416 tri::Allocator<CMeshO>::GetAllPerFaceAttribute< float >(m,AllFaceAttribName);
1417 f_handlers.clear();
1418 f_attrNames.clear();
1419 f_attrValue.clear();
1420 for(int i = 0; i < (int) AllFaceAttribName.size(); i++)
1421 {
1422 CMeshO::PerFaceAttributeHandle<float> hh = tri::Allocator<CMeshO>::GetPerFaceAttribute<float>(m, AllFaceAttribName[i]);
1423 f_handlers.push_back(hh);
1424 f_attrNames.push_back(AllFaceAttribName[i]);
1425 f_attrValue.push_back(0);
1426 p.DefineVar(conversion::fromStringToWString(f_attrNames.back()), &f_attrValue.back());
1427 }
1428
1429 }
1430
filterArity(QAction * filter) const1431 MeshFilterInterface::FILTER_ARITY FilterFunctionPlugin::filterArity( QAction* filter ) const
1432 {
1433 switch(ID(filter))
1434 {
1435 case FF_VERT_SELECTION:
1436 case FF_FACE_SELECTION:
1437 case FF_GEOM_FUNC:
1438 case FF_FACE_COLOR:
1439 case FF_FACE_QUALITY:
1440 case FF_VERT_COLOR:
1441 case FF_VERT_QUALITY:
1442 case FF_VERT_TEXTURE_FUNC:
1443 case FF_WEDGE_TEXTURE_FUNC:
1444 case FF_VERT_NORMAL:
1445 case FF_DEF_VERT_ATTRIB:
1446 case FF_DEF_FACE_ATTRIB:
1447 case FF_REFINE:
1448 return MeshFilterInterface::SINGLE_MESH;
1449 case FF_GRID:
1450 case FF_ISOSURFACE:
1451 return MeshFilterInterface::NONE;
1452 }
1453 return MeshFilterInterface::NONE;
1454 }
1455
1456
1457 MESHLAB_PLUGIN_NAME_EXPORTER(FilterFunctionPlugin)
1458