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>&lt;</b>, <b>&lt;=</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