From 0361b308442ec01f1115ece8991c8631d34762d3 Mon Sep 17 00:00:00 2001 From: alemuntoni Date: Thu, 7 Oct 2021 14:52:48 +0200 Subject: [PATCH] refactor directional geom preserv filter, and add two more filters to add custom point attributes --- src/meshlab/layerDialog.cpp | 63 +- .../filter_func/filter_func.cpp | 2015 ++++++++++------- src/meshlabplugins/filter_func/filter_func.h | 145 +- .../filter_func/filter_refine.h | 1 + .../filter_unsharp/filter_unsharp.cpp | 1447 +++++++----- .../filter_unsharp/filter_unsharp.h | 93 +- 6 files changed, 2218 insertions(+), 1546 deletions(-) diff --git a/src/meshlab/layerDialog.cpp b/src/meshlab/layerDialog.cpp index a9d94bf29..f551a1a4a 100644 --- a/src/meshlab/layerDialog.cpp +++ b/src/meshlab/layerDialog.cpp @@ -740,47 +740,47 @@ void LayerDialog::adaptLayout(QTreeWidgetItem * item) //Add default annotations for each mesh about faces and vertices number void LayerDialog::addDefaultNotes(QTreeWidgetItem * parent, MeshModel *meshModel) { - QTreeWidgetItem *fileItem = new QTreeWidgetItem(); + QTreeWidgetItem* fileItem = new QTreeWidgetItem(); fileItem->setText(1, QString("File")); - if(!meshModel->fullName().isEmpty()) + if (!meshModel->fullName().isEmpty()) fileItem->setText(2, meshModel->shortName()); parent->addChild(fileItem); updateColumnNumber(fileItem); - QTreeWidgetItem *vertItem = new QTreeWidgetItem(); + QTreeWidgetItem* vertItem = new QTreeWidgetItem(); vertItem->setText(1, QString("Vertices")); vertItem->setText(2, QString::number(meshModel->cm.vn)); parent->addChild(vertItem); updateColumnNumber(vertItem); - if(meshModel->cm.en>0){ - QTreeWidgetItem *edgeItem = new QTreeWidgetItem(); + if (meshModel->cm.en > 0) { + QTreeWidgetItem* edgeItem = new QTreeWidgetItem(); edgeItem->setText(1, QString("Edges")); edgeItem->setText(2, QString::number(meshModel->cm.en)); parent->addChild(edgeItem); updateColumnNumber(edgeItem); } - QTreeWidgetItem *faceItem = new QTreeWidgetItem(); + QTreeWidgetItem* faceItem = new QTreeWidgetItem(); faceItem->setText(1, QString("Faces")); faceItem->setText(2, QString::number(meshModel->cm.fn)); parent->addChild(faceItem); updateColumnNumber(faceItem); std::vector vertScalarNames; - vcg::tri::Allocator::GetAllPerVertexAttribute< Scalarm >(meshModel->cm,vertScalarNames); + vcg::tri::Allocator::GetAllPerVertexAttribute(meshModel->cm, vertScalarNames); std::vector vertPointNames; - vcg::tri::Allocator::GetAllPerVertexAttribute< Point3m >(meshModel->cm,vertPointNames); + vcg::tri::Allocator::GetAllPerVertexAttribute(meshModel->cm, vertPointNames); std::vector faceScalarNames; - vcg::tri::Allocator::GetAllPerFaceAttribute< Scalarm >(meshModel->cm,faceScalarNames); + vcg::tri::Allocator::GetAllPerFaceAttribute(meshModel->cm, faceScalarNames); std::vector facePointNames; - vcg::tri::Allocator::GetAllPerFaceAttribute< Point3m >(meshModel->cm,facePointNames); + vcg::tri::Allocator::GetAllPerFaceAttribute(meshModel->cm, facePointNames); unsigned int totAttributes = vertScalarNames.size() + vertPointNames.size() + - faceScalarNames.size() + facePointNames.size(); - if (totAttributes > 0){ - QTreeWidgetItem *vertItem = new QTreeWidgetItem(); - QFont f; + faceScalarNames.size() + facePointNames.size(); + if (totAttributes > 0) { + QTreeWidgetItem* vertItem = new QTreeWidgetItem(); + QFont f; f.setBold(true); vertItem->setFont(1, f); vertItem->setText(1, QString("Custom Attrs:")); @@ -788,41 +788,41 @@ void LayerDialog::addDefaultNotes(QTreeWidgetItem * parent, MeshModel *meshModel updateColumnNumber(vertItem); } - for(const std::string& name: vertScalarNames) { - QTreeWidgetItem *vertItem = new QTreeWidgetItem(); + for (const std::string& name : vertScalarNames) { + QTreeWidgetItem* vertItem = new QTreeWidgetItem(); vertItem->setText(2, QString("Vert (scalar):")); vertItem->setText(3, QString(name.c_str())); parent->addChild(vertItem); updateColumnNumber(vertItem); } - for(const std::string& name: vertPointNames) { - QTreeWidgetItem *vertItem = new QTreeWidgetItem(); - vertItem->setText(2, QString("Vert (vec3):")); + for (const std::string& name : vertPointNames) { + QTreeWidgetItem* vertItem = new QTreeWidgetItem(); + vertItem->setText(2, QString("Vert (point):")); vertItem->setText(3, QString(name.c_str())); parent->addChild(vertItem); updateColumnNumber(vertItem); } - for(const std::string& name: faceScalarNames) { - QTreeWidgetItem *vertItem = new QTreeWidgetItem(); + for (const std::string& name : faceScalarNames) { + QTreeWidgetItem* vertItem = new QTreeWidgetItem(); vertItem->setText(2, QString("Face (scalar):")); vertItem->setText(3, QString(name.c_str())); parent->addChild(vertItem); updateColumnNumber(vertItem); } - for(const std::string& name: facePointNames) { - QTreeWidgetItem *vertItem = new QTreeWidgetItem(); - vertItem->setText(2, QString("Face (vec3):")); + for (const std::string& name : facePointNames) { + QTreeWidgetItem* vertItem = new QTreeWidgetItem(); + vertItem->setText(2, QString("Face (point):")); vertItem->setText(3, QString(name.c_str())); parent->addChild(vertItem); updateColumnNumber(vertItem); } - if (meshModel->cm.textures.size() > 0){ - QTreeWidgetItem *vertItem = new QTreeWidgetItem(); - QFont f; + if (meshModel->cm.textures.size() > 0) { + QTreeWidgetItem* vertItem = new QTreeWidgetItem(); + QFont f; f.setBold(true); vertItem->setFont(1, f); vertItem->setText(1, QString("Textures:")); @@ -830,16 +830,15 @@ void LayerDialog::addDefaultNotes(QTreeWidgetItem * parent, MeshModel *meshModel updateColumnNumber(vertItem); } - for(const std::string& name: meshModel->cm.textures) { - QTreeWidgetItem *vertItem = new QTreeWidgetItem(); + for (const std::string& name : meshModel->cm.textures) { + QTreeWidgetItem* vertItem = new QTreeWidgetItem(); vertItem->setText(2, QString(name.c_str())); - const QImage& img = meshModel->getTexture(name); - QString size = QString::number(img.width()) + "x" + QString::number(img.height()); + const QImage& img = meshModel->getTexture(name); + QString size = QString::number(img.width()) + "x" + QString::number(img.height()); vertItem->setText(3, QString(size)); parent->addChild(vertItem); updateColumnNumber(vertItem); } - } //Add, if necessary, columns to the treeWidget. diff --git a/src/meshlabplugins/filter_func/filter_func.cpp b/src/meshlabplugins/filter_func/filter_func.cpp index 4c716de29..6d9f30a6f 100644 --- a/src/meshlabplugins/filter_func/filter_func.cpp +++ b/src/meshlabplugins/filter_func/filter_func.cpp @@ -1,25 +1,25 @@ -/**************************************************************************** -* MeshLab o o * -* A versatile mesh processing toolbox o o * -* _ O _ * -* Copyright(C) 2005 \/)\/ * -* Visual Computing Lab /\/| * -* ISTI - Italian National Research Council | * -* \ * -* All rights reserved. * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * -* for more details. * -* * -****************************************************************************/ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2005-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ #include "filter_func.h" #include @@ -47,14 +47,15 @@ FilterFunctionPlugin::FilterFunctionPlugin() FF_VERT_QUALITY, FF_VERT_NORMAL, FF_FACE_QUALITY, - FF_DEF_VERT_ATTRIB, - FF_DEF_FACE_ATTRIB, + FF_DEF_VERT_SCALAR_ATTRIB, + FF_DEF_FACE_SCALAR_ATTRIB, + FF_DEF_VERT_POINT_ATTRIB, + FF_DEF_FACE_POINT_ATTRIB, FF_GRID, FF_ISOSURFACE, - FF_REFINE - }; - - for(ActionIDType tt: types()) + FF_REFINE}; + + for (ActionIDType tt : types()) actionList.push_back(new QAction(filterName(tt), this)); } @@ -70,303 +71,562 @@ QString FilterFunctionPlugin::pluginName() const // short string describing each filtering action QString FilterFunctionPlugin::filterName(ActionIDType filterId) const { - switch(filterId) { - case FF_VERT_SELECTION: return QString("Conditional Vertex Selection"); - case FF_FACE_SELECTION: return QString("Conditional Face Selection"); - case FF_GEOM_FUNC: return QString("Per Vertex Geometric Function"); - case FF_FACE_COLOR: return QString("Per Face Color Function"); - case FF_FACE_QUALITY: return QString("Per Face Quality Function"); - case FF_VERT_COLOR: return QString("Per Vertex Color Function"); - case FF_VERT_QUALITY: return QString("Per Vertex Quality Function"); - case FF_VERT_TEXTURE_FUNC: return QString("Per Vertex Texture Function"); + switch (filterId) { + case FF_VERT_SELECTION: return QString("Conditional Vertex Selection"); + case FF_FACE_SELECTION: return QString("Conditional Face Selection"); + case FF_GEOM_FUNC: return QString("Per Vertex Geometric Function"); + case FF_FACE_COLOR: return QString("Per Face Color Function"); + case FF_FACE_QUALITY: return QString("Per Face Quality Function"); + case FF_VERT_COLOR: return QString("Per Vertex Color Function"); + case FF_VERT_QUALITY: return QString("Per Vertex Quality Function"); + case FF_VERT_TEXTURE_FUNC: return QString("Per Vertex Texture Function"); case FF_WEDGE_TEXTURE_FUNC: return QString("Per Wedge Texture Function"); - case FF_VERT_NORMAL: return QString("Per Vertex Normal Function"); - case FF_DEF_VERT_ATTRIB: return QString("Define New Per Vertex Attribute"); - case FF_DEF_FACE_ATTRIB: return QString("Define New Per Face Attribute"); - case FF_GRID: return QString("Grid Generator"); - case FF_REFINE: return QString("Refine User-Defined"); - case FF_ISOSURFACE: return QString("Implicit Surface"); - + case FF_VERT_NORMAL: return QString("Per Vertex Normal Function"); + case FF_DEF_VERT_SCALAR_ATTRIB: return QString("Define New Per Vertex Custom Scalar Attribute"); + case FF_DEF_FACE_SCALAR_ATTRIB: return QString("Define New Per Face Custom Scalar Attribute"); + case FF_DEF_VERT_POINT_ATTRIB: return QString("Define New Per Vertex Custom Point Attribute"); + case FF_DEF_FACE_POINT_ATTRIB: return QString("Define New Per Face Custom Point Attribute"); + case FF_GRID: return QString("Grid Generator"); + case FF_REFINE: return QString("Refine User-Defined"); + case FF_ISOSURFACE: return QString("Implicit Surface"); + default: assert(0); } return QString("error!"); } -const QString PossibleOperators("
It's possible to use parenthesis (), and predefined operators:
" - "&& (logic and), || (logic or), <, <=, >, >=, != (not equal), == (equal), _?_:_ (c/c++ ternary operator)

"); +const QString PossibleOperators( + "
It's possible to use parenthesis (), and predefined operators:
" + "&& (logic and), || (logic or), <, <=, >, >=, " + "!= (not equal), == (equal), _?_:_ (c/c++ ternary operator)

"); -const QString PerVertexAttributeString( "It's possible to use the following per-vertex variables in the expression:
" - "x,y,z (position), nx,ny,nz (normal), r,g,b,a (color), q (quality), " - "rad (radius), vi (vertex index), vtu,vtv,ti (texture coords and texture index), vsel (is the vertex selected? 1 yes, 0 no) " - "and all custom vertex attributes already defined by user.
"); +const QString PerVertexAttributeString( + "It's possible to use the following per-vertex variables in the expression:
" + "x,y,z (position), nx,ny,nz (normal), r,g,b,a (color), q " + "(quality), " + "rad (radius), vi (vertex index), vtu,vtv,ti (texture coords and texture " + "index), vsel (is the vertex selected? 1 yes, 0 no) " + "and all custom vertex attributes already defined by user.
"); -const QString PerFaceAttributeString("It's possible to use the following per-face variables, or variables associated to the three vertex of every face:
" - "x0,y0,z0 for the first vertex position, x1,y1,z1 for the second vertex position, x2,y2,z2 for the third vertex position, " - "nx0,ny0,nz0 nx1,ny1,nz1 nx2,ny2,nz2 for vertex normals, r0,g0,b0,a0 r1,g1,b1,a1 r2,g2,b2,a2 for vertex colors, vi0, vi1, vi2 for vertex indices, " - "q0,q1,q2 for vertex quality, wtu0,wtv0 wtu1,wtv1 wtu2,wtv2 for per-wedge texture coords, ti for face texture index, vsel0,vsel1,vsel2 for vertex selection (1 yes, 0 no) " - "fi for face index, fr,fg,fb,fa for face color, fq for face quality, fnx,fny,fnz for face normal, fsel face selection (1 yes, 0 no).
"); +const QString PerFaceAttributeString( + "It's possible to use the following per-face variables, or variables associated to the three " + "vertex of every face:
" + "x0,y0,z0 for the first vertex position, x1,y1,z1 for the second vertex " + "position, x2,y2,z2 for the third vertex position, " + "nx0,ny0,nz0 nx1,ny1,nz1 nx2,ny2,nz2 for vertex normals, r0,g0,b0,a0 r1,g1,b1,a1 " + "r2,g2,b2,a2 for vertex colors, vi0, vi1, vi2 for vertex indices, " + "q0,q1,q2 for vertex quality, wtu0,wtv0 wtu1,wtv1 wtu2,wtv2 for per-wedge " + "texture coords, ti for face texture index, vsel0,vsel1,vsel2 for vertex " + "selection (1 yes, 0 no) " + "fi for face index, fr,fg,fb,fa for face color, fq for face quality, " + "fnx,fny,fnz for face normal, fsel face selection (1 yes, 0 no).
"); // long string describing each filtering action QString FilterFunctionPlugin::filterInfo(ActionIDType filterId) const { - switch(filterId) { - case FF_VERT_SELECTION : return tr( "Boolean function using muparser lib to perform vertex selection over current mesh.
") - + PossibleOperators + PerVertexAttributeString; - - case FF_FACE_SELECTION : return tr( "Boolean function using muparser lib to perform faces selection over current mesh.
") - + PossibleOperators + PerFaceAttributeString; - - case FF_GEOM_FUNC : return tr( "Geometric function using muparser lib to generate new Coord
" - "You can change x,y,z for every vertex according to the function specified.
") + PerVertexAttributeString; - - case FF_FACE_COLOR : return tr( "Color function using muparser lib to generate new RGBA color for every face
" - "Red, Green, Blue and Alpha channels may be defined specifying a function in their respective fields.
") + PerFaceAttributeString; - - case FF_VERT_COLOR : return tr( "Color function using muparser lib to generate new RGBA color for every vertex
" - "Red, Green, Blue and Alpha channels may be defined specifying a function in their respective fields.
") + PerVertexAttributeString; - - case FF_VERT_QUALITY: return tr("Quality function using muparser to generate new Quality for every vertex
") + PerVertexAttributeString; - - case FF_VERT_TEXTURE_FUNC: return tr("Texture function using muparser to generate new texture coords for every vertex
") + PerVertexAttributeString; - - case FF_VERT_NORMAL: return tr("Normal function using muparser to generate new Normal for every vertex
") + PerVertexAttributeString; - - case FF_FACE_QUALITY : return tr("Quality function using muparser to generate new Quality for every face
" - "Insert three function each one for quality of the three vertex of a face
") +PerFaceAttributeString; - - case FF_WEDGE_TEXTURE_FUNC : return tr("Texture function using muparser to generate new per wedge tex coords for every face
" - "Insert six functions each u v for each one of the three vertex of a face
") +PerFaceAttributeString; - - case FF_DEF_VERT_ATTRIB : return tr("Add a new Per-Vertex scalar attribute to current mesh and fill it with the defined function.
" - "The name specified below can be used in other filter function") +PerVertexAttributeString; - - case FF_DEF_FACE_ATTRIB : return tr("Add a new Per-Face attribute to current mesh.
" - "You can specify custom name and a function to generate attribute's value
" - "It's possible to use per-face variables in the expression:
") +PerFaceAttributeString+ - tr("The attribute name specified below can be used in other filter function"); - - 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.
" - "It's possible to center Grid on origin."); - - 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"); - - case FF_REFINE : return tr("Refine current mesh with user defined parameters.
" - "Specify a Boolean Function needed to select which edges will be cut for refinement purpose.
" - "Each edge is identified with first and second vertex.
" - "Arguments accepted are first and second vertex attributes:
") + PossibleOperators + PerFaceAttributeString; - - default : assert(0); + switch (filterId) { + case FF_VERT_SELECTION: + return tr("Boolean function using muparser lib to perform vertex selection over current " + "mesh.
") + + PossibleOperators + PerVertexAttributeString; + + case FF_FACE_SELECTION: + return tr("Boolean function using muparser lib to perform faces selection over current " + "mesh.
") + + PossibleOperators + PerFaceAttributeString; + + case FF_GEOM_FUNC: + return tr("Geometric function using muparser lib to generate new Coord
" + "You can change x,y,z for every vertex according to the function " + "specified.
") + + PerVertexAttributeString; + + case FF_FACE_COLOR: + return tr("Color function using muparser lib to generate new RGBA color for every face
" + "Red, Green, Blue and Alpha channels may be defined specifying a function in " + "their respective fields.
") + + PerFaceAttributeString; + + case FF_VERT_COLOR: + return tr("Color function using muparser lib to generate new RGBA color for every " + "vertex
" + "Red, Green, Blue and Alpha channels may be defined specifying a function in " + "their respective fields.
") + + PerVertexAttributeString; + + case FF_VERT_QUALITY: + return tr("Quality function using muparser to generate new Quality for every vertex
") + + PerVertexAttributeString; + + case FF_VERT_TEXTURE_FUNC: + return tr("Texture function using muparser to generate new texture coords for every " + "vertex
") + + PerVertexAttributeString; + + case FF_VERT_NORMAL: + return tr("Normal function using muparser to generate new Normal for every vertex
") + + PerVertexAttributeString; + + case FF_FACE_QUALITY: + return tr("Quality function using muparser to generate new Quality for every face
" + "Insert three function each one for quality of the three vertex of a face
") + + PerFaceAttributeString; + + case FF_WEDGE_TEXTURE_FUNC: + return tr("Texture function using muparser to generate new per wedge tex coords for every " + "face
" + "Insert six functions each u v for each one of the three vertex of a face
") + + PerFaceAttributeString; + + case FF_DEF_VERT_SCALAR_ATTRIB: + return tr("Add a new Per-Vertex custom scalar attribute to current mesh and fill it with the " + "defined function.
" + "The name specified below can be used in other filter function") + + PerVertexAttributeString; + + case FF_DEF_FACE_SCALAR_ATTRIB: + return tr("Add a new Per-Face custom scalar attribute to current mesh.
" + "You can specify custom name and a function to generate attribute's values
" + "It's possible to use per-face variables in the expression:
") + + PerFaceAttributeString + + tr("The attribute name specified below can be used in other " + "filter function"); + + case FF_DEF_VERT_POINT_ATTRIB: + return tr("Add a new Per-Vertex custom point attribute to current mesh and fill it with the " + "defined function.
" + "The name specified below can be used in other filter function") + + PerVertexAttributeString; + + case FF_DEF_FACE_POINT_ATTRIB: + return tr("Add a new Per-Face custom point attribute to current mesh.
" + "You can specify custom name and a function to generate attribute's values
" + "It's possible to use per-face variables in the expression:
") + + PerFaceAttributeString + + tr("The attribute name specified below can be used in other " + "filter function"); + + 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.
" + "It's possible to center Grid on origin."); + + 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"); + + case FF_REFINE: + return tr("Refine current mesh with user defined parameters.
" + "Specify a Boolean Function needed to select which edges will be cut for " + "refinement purpose.
" + "Each edge is identified with first and second vertex.
" + "Arguments accepted are first and second vertex attributes:
") + + PossibleOperators + PerFaceAttributeString; + + default: assert(0); } return QString("filter not found!"); } -FilterFunctionPlugin::FilterClass FilterFunctionPlugin::getClass(const QAction *a) const +FilterFunctionPlugin::FilterClass FilterFunctionPlugin::getClass(const QAction* a) const { - switch(ID(a)) - { + switch (ID(a)) { case FF_FACE_SELECTION: case FF_VERT_SELECTION: return FilterPlugin::Selection; case FF_FACE_QUALITY: return FilterClass(Quality + FaceColoring); case FF_VERT_QUALITY: return FilterClass(Quality + VertexColoring); case FF_VERT_TEXTURE_FUNC: return FilterPlugin::Texture; - case FF_VERT_COLOR: return FilterPlugin::VertexColoring; - case FF_VERT_NORMAL: return FilterPlugin::Normal; + case FF_VERT_COLOR: return FilterPlugin::VertexColoring; + case FF_VERT_NORMAL: return FilterPlugin::Normal; case FF_FACE_COLOR: return FilterPlugin::FaceColoring; case FF_WEDGE_TEXTURE_FUNC: return FilterPlugin::Texture; case FF_ISOSURFACE: return FilterPlugin::MeshCreation; case FF_GRID: return FilterPlugin::MeshCreation; case FF_REFINE: return FilterPlugin::Remeshing; case FF_GEOM_FUNC: return FilterPlugin::Smoothing; - case FF_DEF_VERT_ATTRIB: return FilterPlugin::Layer; - case FF_DEF_FACE_ATTRIB: return FilterPlugin::Layer; - + case FF_DEF_VERT_SCALAR_ATTRIB: + case FF_DEF_FACE_SCALAR_ATTRIB: + case FF_DEF_VERT_POINT_ATTRIB: + case FF_DEF_FACE_POINT_ATTRIB: + return FilterPlugin::Layer; + default: return FilterPlugin::Generic; } } -int FilterFunctionPlugin::postCondition(const QAction *action) const +int FilterFunctionPlugin::postCondition(const QAction* action) const { - switch(ID(action)) - { + switch (ID(action)) { case FF_VERT_SELECTION: - case FF_FACE_SELECTION: - return MeshModel::MM_VERTFLAGSELECT | MeshModel::MM_FACEFLAGSELECT; - case FF_FACE_COLOR: - return MeshModel::MM_FACECOLOR; + case FF_FACE_SELECTION: return MeshModel::MM_VERTFLAGSELECT | MeshModel::MM_FACEFLAGSELECT; + case FF_FACE_COLOR: return MeshModel::MM_FACECOLOR; case FF_GEOM_FUNC: return MeshModel::MM_VERTCOORD + MeshModel::MM_VERTNORMAL + MeshModel::MM_FACENORMAL; - case FF_VERT_COLOR: - return MeshModel::MM_VERTCOLOR; - case FF_VERT_NORMAL: - return MeshModel::MM_VERTNORMAL; - case FF_VERT_TEXTURE_FUNC: - return MeshModel::MM_VERTTEXCOORD; - case FF_WEDGE_TEXTURE_FUNC: - return MeshModel::MM_WEDGTEXCOORD; - case FF_VERT_QUALITY: - return MeshModel::MM_VERTQUALITY + MeshModel::MM_VERTCOLOR; - case FF_FACE_QUALITY: - return MeshModel::MM_FACECOLOR + MeshModel::MM_FACEQUALITY; - - case FF_DEF_VERT_ATTRIB: - case FF_DEF_FACE_ATTRIB: - return MeshModel::MM_NONE; // none, because they do not change any existing data - - case FF_REFINE: - return MeshModel::MM_ALL; - + case FF_VERT_COLOR: return MeshModel::MM_VERTCOLOR; + case FF_VERT_NORMAL: return MeshModel::MM_VERTNORMAL; + case FF_VERT_TEXTURE_FUNC: return MeshModel::MM_VERTTEXCOORD; + case FF_WEDGE_TEXTURE_FUNC: return MeshModel::MM_WEDGTEXCOORD; + case FF_VERT_QUALITY: return MeshModel::MM_VERTQUALITY + MeshModel::MM_VERTCOLOR; + case FF_FACE_QUALITY: return MeshModel::MM_FACECOLOR + MeshModel::MM_FACEQUALITY; + + case FF_DEF_VERT_SCALAR_ATTRIB: + case FF_DEF_FACE_SCALAR_ATTRIB: + case FF_DEF_VERT_POINT_ATTRIB: + case FF_DEF_FACE_POINT_ATTRIB: + return MeshModel::MM_NONE; // none, because they do not change any existing data + + case FF_REFINE: return MeshModel::MM_ALL; + case FF_GRID: case FF_ISOSURFACE: - return MeshModel::MM_NONE; // none, because they create a new layer, without affecting old one + return MeshModel::MM_NONE; // none, because they create a new layer, without affecting old + // one } - + return MeshModel::MM_NONE; } -int FilterFunctionPlugin::getRequirements(const QAction *action) +int FilterFunctionPlugin::getRequirements(const QAction* action) { - switch(ID(action)) - { - case FF_VERT_SELECTION : - case FF_GEOM_FUNC : - case FF_VERT_COLOR : - case FF_VERT_NORMAL : - case FF_VERT_QUALITY : - case FF_VERT_TEXTURE_FUNC : - case FF_DEF_VERT_ATTRIB : - case FF_GRID : - case FF_ISOSURFACE : - case FF_DEF_FACE_ATTRIB : - case FF_FACE_SELECTION : return 0; + switch (ID(action)) { + case FF_VERT_SELECTION: + case FF_GEOM_FUNC: + case FF_VERT_COLOR: + case FF_VERT_NORMAL: + case FF_VERT_QUALITY: + case FF_VERT_TEXTURE_FUNC: + case FF_DEF_VERT_SCALAR_ATTRIB: + case FF_DEF_FACE_SCALAR_ATTRIB: + case FF_DEF_VERT_POINT_ATTRIB: + case FF_DEF_FACE_POINT_ATTRIB: + case FF_GRID: + case FF_ISOSURFACE: + case FF_FACE_SELECTION: return 0; case FF_WEDGE_TEXTURE_FUNC: return MeshModel::MM_WEDGTEXCOORD; - case FF_FACE_QUALITY : return MeshModel::MM_FACECOLOR | MeshModel::MM_FACEQUALITY; - case FF_FACE_COLOR : return MeshModel::MM_FACECOLOR; - case FF_REFINE : return MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTMARK; + case FF_FACE_QUALITY: return MeshModel::MM_FACECOLOR | MeshModel::MM_FACEQUALITY; + case FF_FACE_COLOR: return MeshModel::MM_FACECOLOR; + case FF_REFINE: return MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTMARK; default: assert(0); } return 0; } -// This function define the needed parameters for each filter. Return true if the filter has some parameters -// it is called every time, so you can set the default value of parameters according to the mesh -// For each parameter you need to define, +// This function define the needed parameters for each filter. Return true if the filter has some +// parameters it is called every time, so you can set the default value of parameters according to +// the mesh For each parameter you need to define, // - the name of the parameter, // - the string shown in the dialog // - the default value -// - a possibly long string describing the meaning of that parameter (shown as a popup help in the dialog) -RichParameterList FilterFunctionPlugin::initParameterList(const QAction *action,const MeshModel &) +// - a possibly long string describing the meaning of that parameter (shown as a popup help in the +// dialog) +RichParameterList FilterFunctionPlugin::initParameterList(const QAction* action, const MeshModel&) { RichParameterList parlst; - switch(ID(action)) { - - case FF_VERT_SELECTION : - parlst.addParam(RichString("condSelect","(q < 0)", "boolean function", - "type a boolean function that will be evaluated in order to select a subset of vertices
" - "example: (y > 0) and (ny > 0)")); + switch (ID(action)) { + case FF_VERT_SELECTION: + parlst.addParam(RichString( + "condSelect", + "(q < 0)", + "boolean function", + "type a boolean function that will be evaluated in order to select a subset of " + "vertices
" + "example: (y > 0) and (ny > 0)")); break; - - case FF_FACE_SELECTION : - parlst.addParam(RichString("condSelect","(fi == 0)", "boolean function", - "type a boolean function that will be evaluated in order to select a subset of faces
")); + + case FF_FACE_SELECTION: + parlst.addParam(RichString( + "condSelect", + "(fi == 0)", + "boolean function", + "type a boolean function that will be evaluated in order to select a subset of " + "faces
")); break; - + case FF_GEOM_FUNC: - parlst.addParam(RichString("x", "x", "func x = ", "insert function to generate new coord for x")); - parlst.addParam(RichString("y", "y", "func y = ", "insert function to generate new coord for y")); - parlst.addParam(RichString("z", "sin(x+y)", "func z = ", "insert function to generate new coord for z")); - parlst.addParam(RichBool("onselected", false, "only on selection", "if checked, only affects selected vertices")); + parlst.addParam( + RichString("x", "x", "func x = ", "insert function to generate new coord for x")); + parlst.addParam( + RichString("y", "y", "func y = ", "insert function to generate new coord for y")); + parlst.addParam(RichString( + "z", "sin(x+y)", "func z = ", "insert function to generate new coord for z")); + parlst.addParam(RichBool( + "onselected", + false, + "only on selection", + "if checked, only affects selected vertices")); break; - + case FF_VERT_NORMAL: - parlst.addParam(RichString("x", "-nx", "func nx = ", "insert function to generate new x for the normal")); - parlst.addParam(RichString("y", "-ny", "func ny = ", "insert function to generate new y for the normal")); - parlst.addParam(RichString("z", "-nz", "func nz = ", "insert function to generate new z for the normal")); - parlst.addParam(RichBool("onselected", false, "only on selection", "if checked, only affects selected vertices")); + parlst.addParam(RichString( + "x", "-nx", "func nx = ", "insert function to generate new x for the normal")); + parlst.addParam(RichString( + "y", "-ny", "func ny = ", "insert function to generate new y for the normal")); + parlst.addParam(RichString( + "z", "-nz", "func nz = ", "insert function to generate new z for the normal")); + parlst.addParam(RichBool( + "onselected", + false, + "only on selection", + "if checked, only affects selected vertices")); break; - + case FF_VERT_COLOR: - parlst.addParam(RichString("x", "255", "func r = ", "function to generate Red component. Expected Range 0-255")); - parlst.addParam(RichString("y", "255", "func g = ", "function to generate Green component. Expected Range 0-255")); - parlst.addParam(RichString("z", "0", "func b = ", "function to generate Blue component. Expected Range 0-255")); - parlst.addParam(RichString("a", "255", "func alpha = ", "function to generate Alpha component. Expected Range 0-255")); - parlst.addParam(RichBool("onselected", false, "only on selection", "if checked, only affects selected vertices")); + parlst.addParam(RichString( + "x", "255", "func r = ", "function to generate Red component. Expected Range 0-255")); + parlst.addParam(RichString( + "y", "255", "func g = ", "function to generate Green component. Expected Range 0-255")); + parlst.addParam(RichString( + "z", "0", "func b = ", "function to generate Blue component. Expected Range 0-255")); + parlst.addParam(RichString( + "a", + "255", + "func alpha = ", + "function to generate Alpha component. Expected Range 0-255")); + parlst.addParam(RichBool( + "onselected", + false, + "only on selection", + "if checked, only affects selected vertices")); break; - + case FF_VERT_TEXTURE_FUNC: - parlst.addParam(RichString("u", "x", "func u = ", "function to generate u texture coord. Expected Range 0-1")); - parlst.addParam(RichString("v", "y", "func v = ", "function to generate v texture coord. Expected Range 0-1")); - parlst.addParam(RichBool("onselected", false, "only on selection", "if checked, only affects selected vertices")); + parlst.addParam(RichString( + "u", "x", "func u = ", "function to generate u texture coord. Expected Range 0-1")); + parlst.addParam(RichString( + "v", "y", "func v = ", "function to generate v texture coord. Expected Range 0-1")); + parlst.addParam(RichBool( + "onselected", + false, + "only on selection", + "if checked, only affects selected vertices")); break; - + case FF_VERT_QUALITY: - parlst.addParam(RichString("q", "vi", "func q = ", "function to generate new Quality for every vertex")); - parlst.addParam(RichBool("normalize", false, "normalize", "if checked normalize all quality values in range [0..1]")); - parlst.addParam(RichBool("map", false, "map into color", "if checked map quality generated values into per-vertex color")); - parlst.addParam(RichBool("onselected", false, "only on selection", "if checked, only affects selected vertices")); + parlst.addParam(RichString( + "q", "vi", "func q = ", "function to generate new Quality for every vertex")); + parlst.addParam(RichBool( + "normalize", + false, + "normalize", + "if checked normalize all quality values in range [0..1]")); + parlst.addParam(RichBool( + "map", + false, + "map into color", + "if checked map quality generated values into per-vertex color")); + parlst.addParam(RichBool( + "onselected", + false, + "only on selection", + "if checked, only affects selected vertices")); break; - + case FF_FACE_COLOR: - parlst.addParam(RichString("r", "255", "func r = ", "function to generate Red component. Expected Range 0-255")); - parlst.addParam(RichString("g", "0", "func g = ", "function to generate Green component. Expected Range 0-255")); - parlst.addParam(RichString("b", "255", "func b = ", "function to generate Blue component. Expected Range 0-255")); - parlst.addParam(RichString("a", "255", "func alpha = ", "function to generate Alpha component. Expected Range 0-255")); - parlst.addParam(RichBool("onselected", false, "only on selection", "if checked, only affects selected faces")); + parlst.addParam(RichString( + "r", "255", "func r = ", "function to generate Red component. Expected Range 0-255")); + parlst.addParam(RichString( + "g", "0", "func g = ", "function to generate Green component. Expected Range 0-255")); + parlst.addParam(RichString( + "b", "255", "func b = ", "function to generate Blue component. Expected Range 0-255")); + parlst.addParam(RichString( + "a", + "255", + "func alpha = ", + "function to generate Alpha component. Expected Range 0-255")); + parlst.addParam(RichBool( + "onselected", false, "only on selection", "if checked, only affects selected faces")); break; - + case FF_FACE_QUALITY: - parlst.addParam(RichString("q", "x0+y0+z0", "func q0 = ", "function to generate new Quality foreach face")); - parlst.addParam(RichBool("normalize", false, "normalize", "if checked normalize all quality values in range [0..1]")); - parlst.addParam(RichBool("map", false, "map into color", "if checked map quality generated values into per-vertex color")); - parlst.addParam(RichBool("onselected", false, "only on selection", "if checked, only affects selected faces")); + parlst.addParam(RichString( + "q", "x0+y0+z0", "func q0 = ", "function to generate new Quality foreach face")); + parlst.addParam(RichBool( + "normalize", + false, + "normalize", + "if checked normalize all quality values in range [0..1]")); + parlst.addParam(RichBool( + "map", + false, + "map into color", + "if checked map quality generated values into per-vertex color")); + parlst.addParam(RichBool( + "onselected", false, "only on selection", "if checked, only affects selected faces")); break; - + case FF_WEDGE_TEXTURE_FUNC: - parlst.addParam(RichString("u0","x0", "func u0 = ", "function to generate u texture coord. of wedge 0. Expected Range 0-1")); - parlst.addParam(RichString("v0","y0", "func v0 = ", "function to generate v texture coord. of wedge 0. Expected Range 0-1")); - parlst.addParam(RichString("u1","x1", "func u1 = ", "function to generate u texture coord. of wedge 1. Expected Range 0-1")); - parlst.addParam(RichString("v1","y1", "func v1 = ", "function to generate v texture coord. of wedge 1. Expected Range 0-1")); - parlst.addParam(RichString("u2","x2", "func u2 = ", "function to generate u texture coord. of wedge 2. Expected Range 0-1")); - parlst.addParam(RichString("v2","y2", "func v2 = ", "function to generate v texture coord. of wedge 2. Expected Range 0-1")); - parlst.addParam(RichBool("onselected", false, "only on selection", "if checked, only affects selected faces")); + parlst.addParam(RichString( + "u0", + "x0", + "func u0 = ", + "function to generate u texture coord. of wedge 0. Expected Range 0-1")); + parlst.addParam(RichString( + "v0", + "y0", + "func v0 = ", + "function to generate v texture coord. of wedge 0. Expected Range 0-1")); + parlst.addParam(RichString( + "u1", + "x1", + "func u1 = ", + "function to generate u texture coord. of wedge 1. Expected Range 0-1")); + parlst.addParam(RichString( + "v1", + "y1", + "func v1 = ", + "function to generate v texture coord. of wedge 1. Expected Range 0-1")); + parlst.addParam(RichString( + "u2", + "x2", + "func u2 = ", + "function to generate u texture coord. of wedge 2. Expected Range 0-1")); + parlst.addParam(RichString( + "v2", + "y2", + "func v2 = ", + "function to generate v texture coord. of wedge 2. Expected Range 0-1")); + parlst.addParam(RichBool( + "onselected", false, "only on selection", "if checked, only affects selected faces")); break; - - case FF_DEF_VERT_ATTRIB: - parlst.addParam(RichString("name","Radiosity","Name", "the name of new attribute. you can access attribute in other filters through this name")); - parlst.addParam(RichString("expr","x","Function =", "function to calculate custom attribute value for each vertex")); + + case FF_DEF_VERT_SCALAR_ATTRIB: + parlst.addParam(RichString( + "name", + "Custom Attr Name", + "Name", + "the name of new attribute. you can access attribute in other filters through this " + "name")); + parlst.addParam(RichString( + "expr", + "x", + "Scalar function =", + "function to calculate custom scalar attribute value for each vertex")); break; - - case FF_DEF_FACE_ATTRIB: - parlst.addParam(RichString("name","Radiosity","Name", "the name of new attribute. you can access attribute in other filters through this name")); - parlst.addParam(RichString("expr","fi","Function =", "function to calculate custom attribute value for each face")); + + case FF_DEF_FACE_SCALAR_ATTRIB: + parlst.addParam(RichString( + "name", + "Custom Attr Name", + "Name", + "the name of new attribute. you can access attribute in other filters through this " + "name")); + parlst.addParam(RichString( + "expr", + "fi", + "Scalar function =", + "function to calculate custom scalar attribute value for each face")); break; - - case FF_GRID : - parlst.addParam(RichInt("numVertX", 10, "num vertices on x", "number of vertices on x. it must be positive")); - parlst.addParam(RichInt("numVertY", 10, "num vertices on y", "number of vertices on y. it must be positive")); + + case FF_DEF_VERT_POINT_ATTRIB: + parlst.addParam(RichString( + "name", + "Custom Attr Name", + "Name", + "the name of new attribute. you can access attribute in other filters through this " + "name")); + parlst.addParam(RichString( + "x_expr", + "x", + "x coord function =", + "function to calculate custom x coord of the point attribute value for each vertex")); + parlst.addParam(RichString( + "y_expr", + "y", + "y coord function =", + "function to calculate custom y coord of the point attribute value for each vertex")); + parlst.addParam(RichString( + "z_expr", + "z", + "z coord function =", + "function to calculate custom z coord of the point attribute value for each vertex")); + break; + + case FF_DEF_FACE_POINT_ATTRIB: + parlst.addParam(RichString( + "name", + "Custom Attr Name", + "Name", + "the name of new attribute. you can access attribute in other filters through this " + "name")); + parlst.addParam(RichString( + "x_expr", + "x0", + "x coord function =", + "function to calculate custom x coord of the point attribute value for each face")); + parlst.addParam(RichString( + "y_expr", + "y0", + "y coord function =", + "function to calculate custom y coord of the point attribute value for each face")); + parlst.addParam(RichString( + "z_expr", + "z0", + "z coord function =", + "function to calculate custom z coord of the point attribute value for each face")); + break; + + case FF_GRID: + parlst.addParam(RichInt( + "numVertX", 10, "num vertices on x", "number of vertices on x. it must be positive")); + parlst.addParam(RichInt( + "numVertY", 10, "num vertices on y", "number of vertices on y. it must be positive")); parlst.addParam(RichFloat("absScaleX", 0.3f, "x scale", "absolute scale on x (float)")); parlst.addParam(RichFloat("absScaleY", 0.3f, "y scale", "absolute scale on y (float)")); - parlst.addParam(RichBool("center",false,"centered on origin", "center grid generated by filter on origin.
" - "Grid is first generated and than moved into origin (using muparser lib to perform fast calc on every vertex)")); + parlst.addParam(RichBool( + "center", + false, + "centered on origin", + "center grid generated by filter on origin.
" + "Grid is first generated and than moved into origin (using muparser lib to perform " + "fast calc on every vertex)")); break; - case FF_ISOSURFACE : - parlst.addParam(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.")); + case FF_ISOSURFACE: + parlst.addParam(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.")); parlst.addParam(RichFloat("minX", -1.0f, "Min X", "Range where the field is sampled")); parlst.addParam(RichFloat("minY", -1.0f, "Min Y", "Range where the field is sampled")); parlst.addParam(RichFloat("minZ", -1.0f, "Min Z", "Range where the field is sampled")); parlst.addParam(RichFloat("maxX", 1.0f, "Max X", "Range where the field is sampled")); parlst.addParam(RichFloat("maxY", 1.0f, "Max Y", "Range where the field is sampled")); parlst.addParam(RichFloat("maxZ", 1.0f, "Max Z", "Range where the field is sampled")); - parlst.addParam(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.")); - + parlst.addParam(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.")); + break; - - case FF_REFINE : - parlst.addParam(RichString("condSelect","(q0 >= 0 && q1 >= 0)","boolean function","type a boolean function that will be evaluated on every edge")); - parlst.addParam(RichString("x","(x0+x1)/2","x =","function to generate x coord of new vertex in [x0,x1].
For example (x0+x1)/2")); - parlst.addParam(RichString("y","(y0+y1)/2","y =","function to generate x coord of new vertex in [y0,y1].
For example (y0+y1)/2")); - parlst.addParam(RichString("z","(z0+z1)/2","z =","function to generate x coord of new vertex in [z0,z1].
For example (z0+z1)/2")); + + case FF_REFINE: + parlst.addParam(RichString( + "condSelect", + "(q0 >= 0 && q1 >= 0)", + "boolean function", + "type a boolean function that will be evaluated on every edge")); + parlst.addParam(RichString( + "x", + "(x0+x1)/2", + "x =", + "function to generate x coord of new vertex in [x0,x1].
For example (x0+x1)/2")); + parlst.addParam(RichString( + "y", + "(y0+y1)/2", + "y =", + "function to generate x coord of new vertex in [y0,y1].
For example (y0+y1)/2")); + parlst.addParam(RichString( + "z", + "(z0+z1)/2", + "z =", + "function to generate x coord of new vertex in [z0,z1].
For example (z0+z1)/2")); break; - + default: break; // do not add any parameter for the other filters } return parlst; @@ -374,169 +634,193 @@ RichParameterList FilterFunctionPlugin::initParameterList(const QAction *action, // The Real Core Function doing the actual mesh processing. std::map FilterFunctionPlugin::applyFilter( - const QAction *filter, - const RichParameterList & par, - MeshDocument &md, - unsigned int& /*postConditionMask*/, - vcg::CallBackPos *cb) + const QAction* filter, + const RichParameterList& par, + MeshDocument& md, + unsigned int& /*postConditionMask*/, + vcg::CallBackPos* cb) { errorMsg = ""; - if(this->getClass(filter) == FilterPlugin::MeshCreation) - md.addNewMesh("",this->filterName(ID(filter))); - MeshModel &m=*(md.mm()); + if (this->getClass(filter) == FilterPlugin::MeshCreation) + md.addNewMesh("", this->filterName(ID(filter))); + MeshModel& m = *(md.mm()); Q_UNUSED(cb); - switch(ID(filter)) { - case FF_VERT_SELECTION : - { - std::string expr = par.getString("condSelect").toStdString(); - auto wexpr = conversion::fromStringToWString(expr); - + switch (ID(filter)) { + case FF_VERT_SELECTION: { + std::string expr = par.getString("condSelect").toStdString(); + auto wexpr = conversion::fromStringToWString(expr); + // muparser initialization and explicitly define parser variables Parser p; - setPerVertexVariables(p,m.cm); - + setPerVertexVariables(p, m.cm); + // set expression inserted by user as string (required by muparser) p.SetExpr(wexpr); - - int numvert = 0; - time_t start = clock(); - + + int numvert = 0; + time_t start = clock(); + // every parser variables is related to vertex coord and attributes. CMeshO::VertexIterator vi; - for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)if(!(*vi).IsD()) - { - setAttributes(vi,m.cm); - - bool selected = false; - - // use parser to evaluate boolean function specified above - // in case of fail, error dialog contains details of parser's error - try { - selected = p.Eval(); - } catch(Parser::exception_type &e) { - throw MLException(conversion::fromWStringToString(e.GetMsg()).c_str()); + for (vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) + if (!(*vi).IsD()) { + setAttributes(vi, m.cm); + + bool selected = false; + + // use parser to evaluate boolean function specified above + // in case of fail, error dialog contains details of parser's error + try { + selected = p.Eval(); + } + catch (Parser::exception_type& e) { + throw MLException(conversion::fromWStringToString(e.GetMsg()).c_str()); + } + + // set vertex as selected or clear selection + if (selected) { + (*vi).SetS(); + numvert++; + } + else + (*vi).ClearS(); } - - // set vertex as selected or clear selection - if(selected) { - (*vi).SetS(); - numvert++; - } else (*vi).ClearS(); - } - + // if succeeded log stream contains number of vertices and time elapsed - log( "selected %d vertices in %.2f sec.", numvert, (clock() - start) / (float) CLOCKS_PER_SEC); - } - break; - - case FF_FACE_SELECTION : - { + log("selected %d vertices in %.2f sec.", + numvert, + (clock() - start) / (float) CLOCKS_PER_SEC); + } break; + + case FF_FACE_SELECTION: { QString select = par.getString("condSelect"); - + // muparser initialization and explicitly define parser variables Parser p; - setPerFaceVariables(p,m.cm); - + setPerFaceVariables(p, m.cm); + // set expression inserted by user as string (required by muparser) p.SetExpr(conversion::fromStringToWString(select.toStdString())); - - int numface = 0; - time_t start = clock(); + + int numface = 0; + time_t start = clock(); // every parser variables is related to face attributes. CMeshO::FaceIterator fi; - for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)if(!(*fi).IsD()) - { - setAttributes(fi,m.cm); - - bool selected = false; - - // use parser to evaluate boolean function specified above - // in case of fail, error dialog contains details of parser's error - try { - selected = p.Eval(); - } catch(Parser::exception_type &e) { - throw MLException(conversion::fromWStringToString(e.GetMsg()).c_str()); + for (fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi) + if (!(*fi).IsD()) { + setAttributes(fi, m.cm); + + bool selected = false; + + // use parser to evaluate boolean function specified above + // in case of fail, error dialog contains details of parser's error + try { + selected = p.Eval(); + } + catch (Parser::exception_type& e) { + throw MLException(conversion::fromWStringToString(e.GetMsg()).c_str()); + } + + // set face as selected or clear selection + if (selected) { + (*fi).SetS(); + numface++; + } + else + (*fi).ClearS(); } - - // set face as selected or clear selection - if(selected) { - (*fi).SetS(); - numface++; - } else (*fi).ClearS(); - } // if succeeded log stream contains number of vertices and time elapsed - log( "selected %d faces in %.2f sec.", numface, (clock() - start) / (float) CLOCKS_PER_SEC); + log("selected %d faces in %.2f sec.", numface, (clock() - start) / (float) CLOCKS_PER_SEC); - } - break; - - case FF_GEOM_FUNC : + } break; + + case FF_GEOM_FUNC: case FF_VERT_COLOR: - case FF_VERT_NORMAL: - { - std::string func_x,func_y,func_z,func_a; + case FF_VERT_NORMAL: { + std::string func_x, func_y, func_z, func_a; // FF_VERT_COLOR : x = r, y = g, z = b // FF_VERT_NORMAL : x = r, y = g, z = b func_x = par.getString("x").toStdString(); func_y = par.getString("y").toStdString(); func_z = par.getString("z").toStdString(); - if(ID(filter) == FF_VERT_COLOR) func_a = par.getString("a").toStdString(); - + if (ID(filter) == FF_VERT_COLOR) + func_a = par.getString("a").toStdString(); + bool onSelected = par.getBool("onselected"); - + if (onSelected && m.cm.svn == 0 && m.cm.sfn == 0) // if no selection at all, fail { log("Cannot apply only on selection: there is no selection"); throw MLException("Cannot apply only on selection: there is no selection"); } - if (onSelected && (m.cm.svn == 0 && m.cm.sfn > 0)) // if no vert selected, but some faces selected, use their vertices + if (onSelected && + (m.cm.svn == 0 && + m.cm.sfn > 0)) // if no vert selected, but some faces selected, use their vertices { tri::UpdateSelection::VertexClear(m.cm); tri::UpdateSelection::VertexFromFaceLoose(m.cm); } - + // muparser initialization and explicitly define parser variables // function for x,y and z must use different parser and variables - Parser p1,p2,p3,p4; - - setPerVertexVariables(p1,m.cm); - setPerVertexVariables(p2,m.cm); - setPerVertexVariables(p3,m.cm); - setPerVertexVariables(p4,m.cm); - + Parser p1, p2, p3, p4; + + setPerVertexVariables(p1, m.cm); + setPerVertexVariables(p2, m.cm); + setPerVertexVariables(p3, m.cm); + setPerVertexVariables(p4, m.cm); + p1.SetExpr(conversion::fromStringToWString(func_x)); p2.SetExpr(conversion::fromStringToWString(func_y)); p3.SetExpr(conversion::fromStringToWString(func_z)); p4.SetExpr(conversion::fromStringToWString(func_a)); - - double newx=0,newy=0,newz=0,newa=255; + + double newx = 0, newy = 0, newz = 0, newa = 255; QString errorMsg = ""; - + time_t start = clock(); - + // every parser variables is related to vertex coord and attributes. CMeshO::VertexIterator vi; - for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) - if(!(*vi).IsD()) - if ((!onSelected) || ((*vi).IsS())) - { - setAttributes(vi,m.cm); - + for (vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) + if (!(*vi).IsD()) + if ((!onSelected) || ((*vi).IsS())) { + setAttributes(vi, m.cm); + // every function is evaluated by different parser. // errorMessage dialog contains errors for func x, func y and func z - try { newx = p1.Eval(); } catch(Parser::exception_type &e) { showParserError("1st func : ",e); } - try { newy = p2.Eval(); } catch(Parser::exception_type &e) { showParserError("2nd func : ",e); } - try { newz = p3.Eval(); } catch(Parser::exception_type &e) { showParserError("3rd func : ",e); } - if(ID(filter) == FF_VERT_COLOR) - { - try { newa = p4.Eval(); } catch(Parser::exception_type &e) { showParserError("4th func : ",e); } + try { + newx = p1.Eval(); } - if(errorMsg != "") + catch (Parser::exception_type& e) { + showParserError("1st func : ", e); + } + try { + newy = p2.Eval(); + } + catch (Parser::exception_type& e) { + showParserError("2nd func : ", e); + } + try { + newz = p3.Eval(); + } + catch (Parser::exception_type& e) { + showParserError("3rd func : ", e); + } + if (ID(filter) == FF_VERT_COLOR) { + try { + newa = p4.Eval(); + } + catch (Parser::exception_type& e) { + showParserError("4th func : ", e); + } + } + if (errorMsg != "") throw MLException(errorMsg); - - if (ID(filter) == FF_GEOM_FUNC) // set new vertex coord for this iteration + + if (ID(filter) == FF_GEOM_FUNC) // set new vertex coord for this iteration (*vi).P() = Point3m(newx, newy, newz); if (ID(filter) == FF_VERT_NORMAL) // set new color for this iteration (*vi).N() = Point3m(newx, newy, newz); @@ -545,101 +829,104 @@ std::map FilterFunctionPlugin::applyFilter( (*vi).C() = Color4b(newx, newy, newz, newa); m.updateDataMask(MeshModel::MM_VERTCOLOR); } - } - - if(ID(filter) == FF_GEOM_FUNC) { + + if (ID(filter) == FF_GEOM_FUNC) { // update bounding box, normalize normals tri::UpdateNormal::PerVertexNormalizedPerFace(m.cm); tri::UpdateNormal::NormalizePerFace(m.cm); tri::UpdateBounding::Box(m.cm); } - + // if succeeded log stream contains number of vertices processed and time elapsed - log( "%d vertices processed in %.2f sec.", m.cm.vn, (clock() - start) / (float) CLOCKS_PER_SEC); - } - break; - - case FF_VERT_QUALITY: - { - std::string func_q = par.getString("q").toStdString(); - bool onSelected = par.getBool("onselected"); - + log("%d vertices processed in %.2f sec.", + m.cm.vn, + (clock() - start) / (float) CLOCKS_PER_SEC); + } break; + + case FF_VERT_QUALITY: { + std::string func_q = par.getString("q").toStdString(); + bool onSelected = par.getBool("onselected"); + if (onSelected && m.cm.svn == 0 && m.cm.sfn == 0) // if no selection at all, fail { log("Cannot apply only on selection: there is no selection"); throw MLException("Cannot apply only on selection: there is no selection"); } - if (onSelected && (m.cm.svn == 0 && m.cm.sfn > 0)) // if no vert selected, but some faces selected, use their vertices + if (onSelected && + (m.cm.svn == 0 && + m.cm.sfn > 0)) // if no vert selected, but some faces selected, use their vertices { tri::UpdateSelection::VertexClear(m.cm); tri::UpdateSelection::VertexFromFaceLoose(m.cm); } - + m.updateDataMask(MeshModel::MM_VERTQUALITY); - + // muparser initialization and define custom variables Parser p; - setPerVertexVariables(p,m.cm); - + setPerVertexVariables(p, m.cm); + // set expression to calc with parser p.SetExpr(conversion::fromStringToWString(func_q)); - + // every parser variables is related to vertex coord and attributes. - time_t start = clock(); + time_t start = clock(); CMeshO::VertexIterator vi; - for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) - if(!(*vi).IsD()) - if ((!onSelected) || ((*vi).IsS())) - { - setAttributes(vi,m.cm); - + for (vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) + if (!(*vi).IsD()) + if ((!onSelected) || ((*vi).IsS())) { + setAttributes(vi, m.cm); + // use parser to evaluate function specified above // in case of fail, errorMessage dialog contains details of parser's error try { (*vi).Q() = p.Eval(); - } catch(Parser::exception_type &e) { + } + catch (Parser::exception_type& e) { throw MLException(conversion::fromWStringToString(e.GetMsg()).c_str()); } } - + // normalize quality with values in [0..1] - if(par.getBool("normalize")) tri::UpdateQuality::VertexNormalize(m.cm); - + if (par.getBool("normalize")) + tri::UpdateQuality::VertexNormalize(m.cm); + // map quality into per-vertex color - if(par.getBool("map")) - { + if (par.getBool("map")) { tri::UpdateColor::PerVertexQualityRamp(m.cm); m.updateDataMask(MeshModel::MM_VERTCOLOR); } // if succeeded log stream contains number of vertices and time elapsed - log( "%d vertices processed in %.2f sec.", m.cm.vn, (clock() - start) / (float) CLOCKS_PER_SEC); - } - break; - case FF_VERT_TEXTURE_FUNC: - { - std::string func_u = par.getString("u").toStdString(); - std::string func_v = par.getString("v").toStdString(); - bool onSelected = par.getBool("onselected"); - + log("%d vertices processed in %.2f sec.", + m.cm.vn, + (clock() - start) / (float) CLOCKS_PER_SEC); + } break; + case FF_VERT_TEXTURE_FUNC: { + std::string func_u = par.getString("u").toStdString(); + std::string func_v = par.getString("v").toStdString(); + bool onSelected = par.getBool("onselected"); + if (onSelected && m.cm.svn == 0 && m.cm.sfn == 0) // if no selection at all, fail { log("Cannot apply only on selection: there is no selection"); throw MLException("Cannot apply only on selection: there is no selection"); } - if (onSelected && (m.cm.svn == 0 && m.cm.sfn > 0)) // if no vert selected, but some faces selected, use their vertices + if (onSelected && + (m.cm.svn == 0 && + m.cm.sfn > 0)) // if no vert selected, but some faces selected, use their vertices { tri::UpdateSelection::VertexClear(m.cm); tri::UpdateSelection::VertexFromFaceLoose(m.cm); } - + m.updateDataMask(MeshModel::MM_VERTTEXCOORD); - + // muparser initialization and define custom variables - Parser pu,pv; - setPerVertexVariables(pu,m.cm); - setPerVertexVariables(pv,m.cm); - + Parser pu, pv; + setPerVertexVariables(pu, m.cm); + setPerVertexVariables(pv, m.cm); + // set expression to calc with parser #ifdef _UNICODE pu.SetExpr(conversion::fromStringToWString(func_u)); @@ -648,439 +935,548 @@ std::map FilterFunctionPlugin::applyFilter( pu.SetExpr(func_u); pv.SetExpr(func_v); #endif - + // every parser variables is related to vertex coord and attributes. - time_t start = clock(); + time_t start = clock(); CMeshO::VertexIterator vi; - for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) - if(!(*vi).IsD()) - if ((!onSelected) || ((*vi).IsS())) - { - setAttributes(vi,m.cm); - + for (vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) + if (!(*vi).IsD()) + if ((!onSelected) || ((*vi).IsS())) { + setAttributes(vi, m.cm); + // use parser to evaluate function specified above // in case of fail, errorMessage dialog contains details of parser's error try { (*vi).T().U() = pu.Eval(); (*vi).T().V() = pv.Eval(); - } catch(Parser::exception_type &e) { + } + catch (Parser::exception_type& e) { throw MLException(conversion::fromWStringToString(e.GetMsg()).c_str()); } } - - log( "%d vertices processed in %.2f sec.", m.cm.vn, (clock() - start) / (float) CLOCKS_PER_SEC); - } - break; - case FF_WEDGE_TEXTURE_FUNC: - { - std::string func_u0 = par.getString("u0").toStdString(); - std::string func_v0 = par.getString("v0").toStdString(); - std::string func_u1 = par.getString("u1").toStdString(); - std::string func_v1 = par.getString("v1").toStdString(); - std::string func_u2 = par.getString("u2").toStdString(); - std::string func_v2 = par.getString("v2").toStdString(); - bool onSelected = par.getBool("onselected"); - + + log("%d vertices processed in %.2f sec.", + m.cm.vn, + (clock() - start) / (float) CLOCKS_PER_SEC); + } break; + case FF_WEDGE_TEXTURE_FUNC: { + std::string func_u0 = par.getString("u0").toStdString(); + std::string func_v0 = par.getString("v0").toStdString(); + std::string func_u1 = par.getString("u1").toStdString(); + std::string func_v1 = par.getString("v1").toStdString(); + std::string func_u2 = par.getString("u2").toStdString(); + std::string func_v2 = par.getString("v2").toStdString(); + bool onSelected = par.getBool("onselected"); + if (onSelected && m.cm.sfn == 0) // if no selection, fail { log("Cannot apply only on selection: there is no selection"); throw MLException("Cannot apply only on selection: there is no selection"); } - + m.updateDataMask(MeshModel::MM_VERTTEXCOORD); - + // muparser initialization and define custom variables - Parser pu0,pv0,pu1,pv1,pu2,pv2; - setPerFaceVariables(pu0,m.cm); setPerFaceVariables(pv0,m.cm); - setPerFaceVariables(pu1,m.cm); setPerFaceVariables(pv1,m.cm); - setPerFaceVariables(pu2,m.cm); setPerFaceVariables(pv2,m.cm); - + Parser pu0, pv0, pu1, pv1, pu2, pv2; + setPerFaceVariables(pu0, m.cm); + setPerFaceVariables(pv0, m.cm); + setPerFaceVariables(pu1, m.cm); + setPerFaceVariables(pv1, m.cm); + setPerFaceVariables(pu2, m.cm); + setPerFaceVariables(pv2, m.cm); + // set expression to calc with parser - pu0.SetExpr(conversion::fromStringToWString(func_u0)); pv0.SetExpr(conversion::fromStringToWString(func_v0)); - pu1.SetExpr(conversion::fromStringToWString(func_u1)); pv1.SetExpr(conversion::fromStringToWString(func_v1)); - pu2.SetExpr(conversion::fromStringToWString(func_u2)); pv2.SetExpr(conversion::fromStringToWString(func_v2)); - + pu0.SetExpr(conversion::fromStringToWString(func_u0)); + pv0.SetExpr(conversion::fromStringToWString(func_v0)); + pu1.SetExpr(conversion::fromStringToWString(func_u1)); + pv1.SetExpr(conversion::fromStringToWString(func_v1)); + pu2.SetExpr(conversion::fromStringToWString(func_u2)); + pv2.SetExpr(conversion::fromStringToWString(func_v2)); + // every parser variables is related to vertex coord and attributes. time_t start = clock(); - for(CMeshO::FaceIterator fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi) - if(!(*fi).IsD()) - if ((!onSelected) || ((*fi).IsS())) - { - setAttributes(fi,m.cm); - + for (CMeshO::FaceIterator fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi) + if (!(*fi).IsD()) + if ((!onSelected) || ((*fi).IsS())) { + setAttributes(fi, m.cm); + // use parser to evaluate function specified above // in case of fail, errorMessage dialog contains details of parser's error try { - (*fi).WT(0).U() = pu0.Eval(); (*fi).WT(0).V() = pv0.Eval(); - (*fi).WT(1).U() = pu1.Eval(); (*fi).WT(1).V() = pv1.Eval(); - (*fi).WT(2).U() = pu2.Eval(); (*fi).WT(2).V() = pv2.Eval(); - } catch(Parser::exception_type &e) { + (*fi).WT(0).U() = pu0.Eval(); + (*fi).WT(0).V() = pv0.Eval(); + (*fi).WT(1).U() = pu1.Eval(); + (*fi).WT(1).V() = pv1.Eval(); + (*fi).WT(2).U() = pu2.Eval(); + (*fi).WT(2).V() = pv2.Eval(); + } + catch (Parser::exception_type& e) { throw MLException(conversion::fromWStringToString(e.GetMsg()).c_str()); } } - - log( "%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC); - } - break; - case FF_FACE_COLOR: - { - std::string func_r = par.getString("r").toStdString(); - std::string func_g = par.getString("g").toStdString(); - std::string func_b = par.getString("b").toStdString(); - std::string func_a = par.getString("a").toStdString(); - bool onSelected = par.getBool("onselected"); - + + log("%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC); + } break; + case FF_FACE_COLOR: { + std::string func_r = par.getString("r").toStdString(); + std::string func_g = par.getString("g").toStdString(); + std::string func_b = par.getString("b").toStdString(); + std::string func_a = par.getString("a").toStdString(); + bool onSelected = par.getBool("onselected"); + if (onSelected && m.cm.sfn == 0) // if no selection, fail { log("Cannot apply only on selection: there is no selection"); throw MLException("Cannot apply only on selection: there is no selection"); } - + m.updateDataMask(MeshModel::MM_FACECOLOR); - + // muparser initialization and explicitly define parser variables // every function must uses own parser and variables - Parser p1,p2,p3,p4; - - setPerFaceVariables(p1,m.cm); - setPerFaceVariables(p2,m.cm); - setPerFaceVariables(p3,m.cm); - setPerFaceVariables(p4,m.cm); - + Parser p1, p2, p3, p4; + + setPerFaceVariables(p1, m.cm); + setPerFaceVariables(p2, m.cm); + setPerFaceVariables(p3, m.cm); + setPerFaceVariables(p4, m.cm); + p1.SetExpr(conversion::fromStringToWString(func_r)); p2.SetExpr(conversion::fromStringToWString(func_g)); p3.SetExpr(conversion::fromStringToWString(func_b)); p4.SetExpr(conversion::fromStringToWString(func_a)); - + // RGB is related to every face CMeshO::FaceIterator fi; - double newr=0,newg=0,newb=0,newa=255; + double newr = 0, newg = 0, newb = 0, newa = 255; errorMsg = ""; - + time_t start = clock(); - + // every parser variables is related to face attributes. - for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi) - if(!(*fi).IsD()) - if ((!onSelected) || ((*fi).IsS())) - { - setAttributes(fi,m.cm); - + for (fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi) + if (!(*fi).IsD()) + if ((!onSelected) || ((*fi).IsS())) { + setAttributes(fi, m.cm); + // evaluate functions to generate new color // in case of fail, error dialog contains details of parser's error - try { newr = p1.Eval(); } catch(Parser::exception_type &e) { showParserError("func r: ",e); } - try { newg = p2.Eval(); } catch(Parser::exception_type &e) { showParserError("func g: ",e); } - try { newb = p3.Eval(); } catch(Parser::exception_type &e) { showParserError("func b: ",e); } - try { newa = p4.Eval(); } catch(Parser::exception_type &e) { showParserError("func a: ",e); } - - if(errorMsg != "") + try { + newr = p1.Eval(); + } + catch (Parser::exception_type& e) { + showParserError("func r: ", e); + } + try { + newg = p2.Eval(); + } + catch (Parser::exception_type& e) { + showParserError("func g: ", e); + } + try { + newb = p3.Eval(); + } + catch (Parser::exception_type& e) { + showParserError("func b: ", e); + } + try { + newa = p4.Eval(); + } + catch (Parser::exception_type& e) { + showParserError("func a: ", e); + } + + if (errorMsg != "") throw MLException(errorMsg); - + // set new color for this iteration - (*fi).C() = Color4b(newr,newg,newb,newa); + (*fi).C() = Color4b(newr, newg, newb, newa); } // if succeeded log stream contains number of vertices processed and time elapsed - log( "%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC); + log("%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC); + + } break; + + case FF_FACE_QUALITY: { + std::string func_q = par.getString("q").toStdString(); + bool onSelected = par.getBool("onselected"); - } - break; - - case FF_FACE_QUALITY: - { - std::string func_q = par.getString("q").toStdString(); - bool onSelected = par.getBool("onselected"); - if (onSelected && m.cm.sfn == 0) // if no selection, fail { log("Cannot apply only on selection: there is no selection"); throw MLException("Cannot apply only on selection: there is no selection"); } - + m.updateDataMask(MeshModel::MM_FACEQUALITY); - + // muparser initialization and define custom variables Parser pf; - setPerFaceVariables(pf,m.cm); - + setPerFaceVariables(pf, m.cm); + // set expression to calc with parser pf.SetExpr(conversion::fromStringToWString(func_q)); - + time_t start = clock(); - errorMsg = ""; - + errorMsg = ""; + // every parser variables is related to face attributes. CMeshO::FaceIterator fi; - for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi) - if(!(*fi).IsD()) - if ((!onSelected) || ((*fi).IsS())) - { - setAttributes(fi,m.cm); - + for (fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi) + if (!(*fi).IsD()) + if ((!onSelected) || ((*fi).IsS())) { + setAttributes(fi, m.cm); + // evaluate functions to generate new quality // in case of fail, error dialog contains details of parser's error - try { (*fi).Q() = pf.Eval(); } - catch(Parser::exception_type &e) { - showParserError("func q: ",e); + try { + (*fi).Q() = pf.Eval(); } - if(errorMsg != "") + catch (Parser::exception_type& e) { + showParserError("func q: ", e); + } + if (errorMsg != "") throw MLException(errorMsg); } - + // normalize quality with values in [0..1] - if(par.getBool("normalize")) tri::UpdateQuality::FaceNormalize(m.cm); - + if (par.getBool("normalize")) + tri::UpdateQuality::FaceNormalize(m.cm); + // map quality into per-vertex color - if(par.getBool("map")) - { + if (par.getBool("map")) { tri::UpdateColor::PerFaceQualityRamp(m.cm); m.updateDataMask(MeshModel::MM_FACECOLOR); } - - // if succeeded log stream contains number of faces processed and time elapsed - log( "%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC); - } - break; - - case FF_DEF_VERT_ATTRIB : - { + // if succeeded log stream contains number of faces processed and time elapsed + log("%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC); + + } break; + + case FF_DEF_VERT_SCALAR_ATTRIB: { std::string name = par.getString("name").toStdString(); std::string expr = par.getString("expr").toStdString(); - + // add per-vertex attribute with type float and name specified by user CMeshO::PerVertexAttributeHandle h; - if(tri::HasPerVertexAttribute(m.cm,name)) - { + if (tri::HasPerVertexAttribute(m.cm, name)) { h = tri::Allocator::FindPerVertexAttribute(m.cm, name); - if(!tri::Allocator::IsValidHandle(m.cm,h)) - { + if (!tri::Allocator::IsValidHandle(m.cm, h)) { throw MLException("attribute already exists with a different type"); } } else - h = tri::Allocator::AddPerVertexAttribute (m.cm,name); - - std::vector AllVertexAttribName; - tri::Allocator::GetAllPerVertexAttribute(m.cm,AllVertexAttribName); - qDebug("Now mesh has %lu vertex scalar attribute",AllVertexAttribName.size()); + h = tri::Allocator::AddPerVertexAttribute(m.cm, name); + Parser p; - setPerVertexVariables(p,m.cm); + setPerVertexVariables(p, m.cm); p.SetExpr(conversion::fromStringToWString(expr)); - + time_t start = clock(); - + // perform calculation of attribute's value with function specified by user CMeshO::VertexIterator vi; - for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)if(!(*vi).IsD()) - { - setAttributes(vi,m.cm); - - // add new user-defined attribute - try { - h[vi] = p.Eval(); - } catch(Parser::exception_type &e) { - throw MLException(conversion::fromWStringToString(e.GetMsg()).c_str()); + for (vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) + if (!(*vi).IsD()) { + setAttributes(vi, m.cm); + + // add new user-defined attribute + try { + h[vi] = p.Eval(); + } + catch (Parser::exception_type& e) { + throw MLException(conversion::fromWStringToString(e.GetMsg()).c_str()); + } } - } - + // add string, double and handler to vector. // vectors keep tracks of new attributes and let muparser use explicit variables // it's possible to use custom attributes in other filters v_attrNames.push_back(name); v_attrValue.push_back(0); v_handlers.push_back(h); - - // if succeeded log stream contains number of vertices processed and time elapsed - log( "%d vertices processed in %.2f sec.", m.cm.vn, (clock() - start) / (float) CLOCKS_PER_SEC); - } - break; - - case FF_DEF_FACE_ATTRIB : - { + // if succeeded log stream contains number of vertices processed and time elapsed + log("%d vertices processed in %.2f sec.", + m.cm.vn, + (clock() - start) / (float) CLOCKS_PER_SEC); + + } break; + + case FF_DEF_FACE_SCALAR_ATTRIB: { std::string name = par.getString("name").toStdString(); std::string expr = par.getString("expr").toStdString(); - + // add per-face attribute with type float and name specified by user // add per-vertex attribute with type float and name specified by user CMeshO::PerFaceAttributeHandle h; - if(tri::HasPerFaceAttribute(m.cm,name)) - { + if (tri::HasPerFaceAttribute(m.cm, name)) { h = tri::Allocator::FindPerFaceAttribute(m.cm, name); - if(!tri::Allocator::IsValidHandle(m.cm,h)) - { + if (!tri::Allocator::IsValidHandle(m.cm, h)) { throw MLException("attribute already exists with a different type"); } } else - h = tri::Allocator::AddPerFaceAttribute (m.cm,name); + h = tri::Allocator::AddPerFaceAttribute(m.cm, name); Parser p; - setPerFaceVariables(p,m.cm); + setPerFaceVariables(p, m.cm); p.SetExpr(conversion::fromStringToWString(expr)); - + time_t start = clock(); - + // every parser variables is related to face attributes. CMeshO::FaceIterator fi; - for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)if(!(*fi).IsD()) - { - setAttributes(fi,m.cm); - - // add new user-defined attribute - try { - h[fi] = p.Eval(); - } catch(Parser::exception_type &e) { - throw MLException(conversion::fromWStringToString(e.GetMsg()).c_str()); + for (fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi) + if (!(*fi).IsD()) { + setAttributes(fi, m.cm); + + // add new user-defined attribute + try { + h[fi] = p.Eval(); + } + catch (Parser::exception_type& e) { + throw MLException(conversion::fromWStringToString(e.GetMsg()).c_str()); + } + } + + // if succeeded log stream contains number of vertices processed and time elapsed + log("%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC); + + } break; + + case FF_DEF_VERT_POINT_ATTRIB: { + std::string name = par.getString("name").toStdString(); + std::string x_expr = par.getString("x_expr").toStdString(); + std::string y_expr = par.getString("y_expr").toStdString(); + std::string z_expr = par.getString("z_expr").toStdString(); + + // add per-vertex attribute with type float and name specified by user + CMeshO::PerVertexAttributeHandle h; + if (tri::HasPerVertexAttribute(m.cm, name)) { + h = tri::Allocator::FindPerVertexAttribute(m.cm, name); + if (!tri::Allocator::IsValidHandle(m.cm, h)) { + throw MLException("attribute already exists with a different type"); } } - - // // add string, double and handler to vector. - // // vectors keep tracks of new attributes and let muparser use explicit variables - // // it's possible to use custom attributes in other filters - // f_attrNames.push_back(name); - // f_attrValue.push_back(0); - // fhandlers.push_back(h); - - // if succeeded log stream contains number of vertices processed and time elapsed - log( "%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC); + else + h = tri::Allocator::AddPerVertexAttribute(m.cm, name); - } - break; - - case FF_GRID : - { + Parser p_x, p_y, p_z; + setPerVertexVariables(p_x, m.cm); + setPerVertexVariables(p_y, m.cm); + setPerVertexVariables(p_z, m.cm); + p_x.SetExpr(conversion::fromStringToWString(x_expr)); + p_y.SetExpr(conversion::fromStringToWString(y_expr)); + p_z.SetExpr(conversion::fromStringToWString(z_expr)); + + time_t start = clock(); + + // perform calculation of attribute's value with function specified by user + CMeshO::VertexIterator vi; + for (vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) + if (!(*vi).IsD()) { + setAttributes(vi, m.cm); + + try { + h[vi][0] = p_x.Eval(); + h[vi][1] = p_y.Eval(); + h[vi][2] = p_z.Eval(); + } + catch (Parser::exception_type& e) { + throw MLException(conversion::fromWStringToString(e.GetMsg()).c_str()); + } + } + + // add string, double and handler to vector. + // vectors keep tracks of new attributes and let muparser use explicit variables + // it's possible to use custom attributes in other filters + + //v_attrNames.push_back(name); + //v_attrValue.push_back(0); + //v_handlers.push_back(h); + + // if succeeded log stream contains number of vertices processed and time elapsed + log("%d vertices processed in %.2f sec.", + m.cm.vn, + (clock() - start) / (float) CLOCKS_PER_SEC); + + } break; + + case FF_DEF_FACE_POINT_ATTRIB: { + std::string name = par.getString("name").toStdString(); + std::string x_expr = par.getString("x_expr").toStdString(); + std::string y_expr = par.getString("y_expr").toStdString(); + std::string z_expr = par.getString("z_expr").toStdString(); + + // add per-face attribute with type float and name specified by user + // add per-vertex attribute with type float and name specified by user + CMeshO::PerFaceAttributeHandle h; + if (tri::HasPerFaceAttribute(m.cm, name)) { + h = tri::Allocator::FindPerFaceAttribute(m.cm, name); + if (!tri::Allocator::IsValidHandle(m.cm, h)) { + throw MLException("attribute already exists with a different type"); + } + } + else + h = tri::Allocator::AddPerFaceAttribute(m.cm, name); + Parser p_x, p_y, p_z; + setPerFaceVariables(p_x, m.cm); + setPerFaceVariables(p_y, m.cm); + setPerFaceVariables(p_z, m.cm); + p_x.SetExpr(conversion::fromStringToWString(x_expr)); + p_y.SetExpr(conversion::fromStringToWString(y_expr)); + p_z.SetExpr(conversion::fromStringToWString(z_expr)); + + time_t start = clock(); + + // every parser variables is related to face attributes. + CMeshO::FaceIterator fi; + for (fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi) + if (!(*fi).IsD()) { + setAttributes(fi, m.cm); + + // add new user-defined attribute + try { + h[fi][0] = p_x.Eval(); + h[fi][1] = p_y.Eval(); + h[fi][2] = p_z.Eval(); + } + catch (Parser::exception_type& e) { + throw MLException(conversion::fromWStringToString(e.GetMsg()).c_str()); + } + } + + // if succeeded log stream contains number of vertices processed and time elapsed + log("%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC); + + } break; + + case FF_GRID: { // obtain parameters to generate 2D Grid - int w = par.getInt("numVertX"); - int h = par.getInt("numVertY"); + int w = par.getInt("numVertX"); + int h = par.getInt("numVertY"); Scalarm wl = par.getFloat("absScaleX"); Scalarm hl = par.getFloat("absScaleY"); - - if(w <= 0 || h <= 0) { + + if (w <= 0 || h <= 0) { throw MLException("number of vertices must be positive"); } - + // use Grid function to generate Grid tri::Grid(m.cm, w, h, wl, hl); - + // if "centered on origin" is checked than move generated Grid in (0,0,0) - if(par.getBool("center")) - { + if (par.getBool("center")) { // move x and y - Scalarm halfw = Scalarm(w-1)/2; - Scalarm halfh = Scalarm(h-1)/2; - Scalarm wld = wl/Scalarm(w); - Scalarm hld = hl/Scalarm(h); - - for(auto vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) - { + Scalarm halfw = Scalarm(w - 1) / 2; + Scalarm halfh = Scalarm(h - 1) / 2; + Scalarm wld = wl / Scalarm(w); + Scalarm hld = hl / Scalarm(h); + + for (auto vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) { (*vi).P()[0] = (*vi).P()[0] - (wld * halfw); (*vi).P()[1] = (*vi).P()[1] - (hld * halfh); } } // update bounding box, normals // Matrix44m rot; rot.SetRotateDeg(180,Point3m(0,1,0)); - Matrix44m rot; rot.SetScale(-1,1,-1); - tri::UpdatePosition::Matrix(m.cm,rot,false); + Matrix44m rot; + rot.SetScale(-1, 1, -1); + tri::UpdatePosition::Matrix(m.cm, rot, false); m.updateBoxAndNormals(); - } - break; - case FF_ISOSURFACE : - { - SimpleVolume > volume; - - typedef vcg::tri::TrivialWalker > > MyWalker; - typedef vcg::tri::MarchingCubes MyMarchingCubes; - MyWalker walker; - + } break; + case FF_ISOSURFACE: { + SimpleVolume> volume; + + typedef vcg::tri::TrivialWalker>> MyWalker; + typedef vcg::tri::MarchingCubes MyMarchingCubes; + MyWalker walker; + Box3f RangeBBox; - RangeBBox.min[0]=par.getFloat("minX"); - RangeBBox.min[1]=par.getFloat("minY"); - RangeBBox.min[2]=par.getFloat("minZ"); - RangeBBox.max[0]=par.getFloat("maxX"); - RangeBBox.max[1]=par.getFloat("maxY"); - RangeBBox.max[2]=par.getFloat("maxZ"); - double step=par.getFloat("voxelSize"); - Point3i siz= Point3i::Construct((RangeBBox.max-RangeBBox.min)*(1.0/step)); - + RangeBBox.min[0] = par.getFloat("minX"); + RangeBBox.min[1] = par.getFloat("minY"); + RangeBBox.min[2] = par.getFloat("minZ"); + RangeBBox.max[0] = par.getFloat("maxX"); + RangeBBox.max[1] = par.getFloat("maxY"); + RangeBBox.max[2] = par.getFloat("maxZ"); + double step = par.getFloat("voxelSize"); + Point3i siz = Point3i::Construct((RangeBBox.max - RangeBBox.min) * (1.0 / step)); + Parser p; - double x,y,z; + double x, y, z; p.DefineVar(conversion::fromStringToWString("x"), &x); p.DefineVar(conversion::fromStringToWString("y"), &y); p.DefineVar(conversion::fromStringToWString("z"), &z); std::string expr = par.getString("expr").toStdString(); p.SetExpr(conversion::fromStringToWString(expr)); - log("Filling a Volume of %i %i %i",siz[0],siz[1],siz[2]); - volume.Init(siz,RangeBBox); - for(double i=0;i(m.cm, volume, mc, 0); // Matrix44m tr; tr.SetIdentity(); tr.SetTranslate(rbb.min[0],rbb.min[1],rbb.min[2]); // Matrix44m sc; sc.SetIdentity(); sc.SetScale(step,step,step); // tr=tr*sc; - + // tri::UpdatePosition::Matrix(m.cm,tr); tri::UpdateNormal::PerVertexNormalizedPerFace(m.cm); - tri::UpdateBounding::Box(m.cm); // updates bounding box - - } - break; - - case FF_REFINE : - { + tri::UpdateBounding::Box(m.cm); // updates bounding box + + } break; + + case FF_REFINE: { std::string condSelect = par.getString("condSelect").toStdString(); - + std::string expr1 = par.getString("x").toStdString(); std::string expr2 = par.getString("y").toStdString(); std::string expr3 = par.getString("z").toStdString(); - - bool errorMidPoint = false; - bool errorEdgePred = false; - std::string msg = ""; - + + bool errorMidPoint = false; + bool errorEdgePred = false; + std::string msg = ""; + // check parsing errors while creating two func obj // display error message - MidPointCustom mid = MidPointCustom(m.cm,expr1,expr2,expr3,errorMidPoint,msg); - CustomEdge edge = CustomEdge(condSelect,errorEdgePred,msg); - if(errorMidPoint || errorEdgePred) - { + MidPointCustom mid = + MidPointCustom(m.cm, expr1, expr2, expr3, errorMidPoint, msg); + CustomEdge edge = CustomEdge(condSelect, errorEdgePred, msg); + if (errorMidPoint || errorEdgePred) { throw MLException(msg.c_str()); } - + // Refine current mesh. // Only edge specified with CustomEdge pred are selected // and the new vertex is chosen with MidPointCustom created above - vcg::tri::RefineE, CustomEdge > - (m.cm, mid, edge, false, cb); + vcg::tri::RefineE, CustomEdge>( + m.cm, mid, edge, false, cb); m.updateBoxAndNormals(); - m.clearDataMask( MeshModel::MM_VERTMARK); - //vcg::tri::UpdateNormal::PerVertexNormalizedPerFace(m.cm); - } - break; - - default : - wrongActionCalled(filter); + m.clearDataMask(MeshModel::MM_VERTMARK); + // vcg::tri::UpdateNormal::PerVertexNormalizedPerFace(m.cm); + } break; + + default: wrongActionCalled(filter); } return std::map(); } // display parsing error in dialog -void FilterFunctionPlugin::showParserError(const QString &s, Parser::exception_type &e) +void FilterFunctionPlugin::showParserError(const QString& s, Parser::exception_type& e) { errorMsg += s; errorMsg += conversion::fromWStringToString(e.GetMsg()).c_str(); @@ -1088,160 +1484,165 @@ void FilterFunctionPlugin::showParserError(const QString &s, Parser::exception_t } // set per-vertex attributes associated to parser variables -void FilterFunctionPlugin::setAttributes(CMeshO::VertexIterator &vi, CMeshO &m) +void FilterFunctionPlugin::setAttributes(CMeshO::VertexIterator& vi, CMeshO& m) { x = (*vi).P()[0]; // coord x y = (*vi).P()[1]; // coord y z = (*vi).P()[2]; // coord z - + nx = (*vi).N()[0]; // normal coord x ny = (*vi).N()[1]; // normal coord y nz = (*vi).N()[2]; // normal coord z - - r = (*vi).C()[0]; // color R - g = (*vi).C()[1]; // color G - b = (*vi).C()[2]; // color B - a = (*vi).C()[3]; // color ALPHA - - q = (*vi).Q(); // quality - - vsel = ((*vi).IsS()) ? 1.0 : 0.0; //selection - - if(tri::HasPerVertexRadius(m)) rad = (*vi).R(); - else rad=0; - + + r = (*vi).C()[0]; // color R + g = (*vi).C()[1]; // color G + b = (*vi).C()[2]; // color B + a = (*vi).C()[3]; // color ALPHA + + q = (*vi).Q(); // quality + + vsel = ((*vi).IsS()) ? 1.0 : 0.0; // selection + + if (tri::HasPerVertexRadius(m)) + rad = (*vi).R(); + else + rad = 0; + v = vi - m.vert.begin(); // zero based index of current vertex - - if(tri::HasPerVertexTexCoord(m)) - { - vtu=(*vi).T().U(); - vtv=(*vi).T().V(); - ti = (*vi).T().N(); + + if (tri::HasPerVertexTexCoord(m)) { + vtu = (*vi).T().U(); + vtv = (*vi).T().V(); + ti = (*vi).T().N(); } - else { vtu=vtv=ti=0; } - + else { + vtu = vtv = ti = 0; + } + // if user-defined attributes exist (vector is not empty) // set variables to explicit value obtained through attribute's handler - for(int i = 0; i < (int) v_attrValue.size(); i++) + for (int i = 0; i < (int) v_attrValue.size(); i++) v_attrValue[i] = v_handlers[i][vi]; - - for(int i = 0; i < (int) v3_handlers.size(); i++) - { - v3_attrValue[i*3+0] = v3_handlers[i][vi].X(); - v3_attrValue[i*3+1] = v3_handlers[i][vi].Y(); - v3_attrValue[i*3+2] = v3_handlers[i][vi].Z(); + + for (int i = 0; i < (int) v3_handlers.size(); i++) { + v3_attrValue[i * 3 + 0] = v3_handlers[i][vi].X(); + v3_attrValue[i * 3 + 1] = v3_handlers[i][vi].Y(); + v3_attrValue[i * 3 + 2] = v3_handlers[i][vi].Z(); } } // set per-face attributes associated to parser variables -void FilterFunctionPlugin::setAttributes(CMeshO::FaceIterator &fi, CMeshO &m) +void FilterFunctionPlugin::setAttributes(CMeshO::FaceIterator& fi, CMeshO& m) { // set attributes for First vertex // coords, normal coords, quality x0 = (*fi).V(0)->P()[0]; y0 = (*fi).V(0)->P()[1]; z0 = (*fi).V(0)->P()[2]; - + nx0 = (*fi).V(0)->N()[0]; ny0 = (*fi).V(0)->N()[1]; nz0 = (*fi).V(0)->N()[2]; - + r0 = (*fi).V(0)->C()[0]; g0 = (*fi).V(0)->C()[1]; b0 = (*fi).V(0)->C()[2]; a0 = (*fi).V(0)->C()[3]; - + q0 = (*fi).V(0)->Q(); - + // set attributes for Second vertex // coords, normal coords, quality x1 = (*fi).V(1)->P()[0]; y1 = (*fi).V(1)->P()[1]; z1 = (*fi).V(1)->P()[2]; - + nx1 = (*fi).V(1)->N()[0]; ny1 = (*fi).V(1)->N()[1]; nz1 = (*fi).V(1)->N()[2]; - + r1 = (*fi).V(1)->C()[0]; g1 = (*fi).V(1)->C()[1]; b1 = (*fi).V(1)->C()[2]; a1 = (*fi).V(1)->C()[3]; - + q1 = (*fi).V(1)->Q(); - + // set attributes for Third vertex // coords, normal coords, quality x2 = (*fi).V(2)->P()[0]; y2 = (*fi).V(2)->P()[1]; z2 = (*fi).V(2)->P()[2]; - + nx2 = (*fi).V(2)->N()[0]; ny2 = (*fi).V(2)->N()[1]; nz2 = (*fi).V(2)->N()[2]; - + r2 = (*fi).V(2)->C()[0]; g2 = (*fi).V(2)->C()[1]; b2 = (*fi).V(2)->C()[2]; a2 = (*fi).V(2)->C()[3]; - + q2 = (*fi).V(2)->Q(); - - if(HasPerFaceQuality(m)) - fq=(*fi).Q(); - else fq=0; - + + if (HasPerFaceQuality(m)) + fq = (*fi).Q(); + else + fq = 0; + // set face color attributes - if(HasPerFaceColor(m)){ + if (HasPerFaceColor(m)) { fr = (*fi).C()[0]; fg = (*fi).C()[1]; fb = (*fi).C()[2]; fa = (*fi).C()[3]; - } else { - fr=fg=fb=fa=255; } - - //face normal + else { + fr = fg = fb = fa = 255; + } + + // face normal fnx = (*fi).N()[0]; fny = (*fi).N()[1]; fnz = (*fi).N()[2]; - + // zero based index of face f = fi - m.face.begin(); - + // zero based index of its vertices v0i = ((*fi).V(0) - &m.vert[0]); v1i = ((*fi).V(1) - &m.vert[0]); v2i = ((*fi).V(2) - &m.vert[0]); - - if(tri::HasPerWedgeTexCoord(m)) - { - wtu0=(*fi).WT(0).U(); - wtv0=(*fi).WT(0).V(); - wtu1=(*fi).WT(1).U(); - wtv1=(*fi).WT(1).V(); - wtu2=(*fi).WT(2).U(); - wtv2=(*fi).WT(2).V(); - ti = (*fi).WT(0).N(); + + if (tri::HasPerWedgeTexCoord(m)) { + wtu0 = (*fi).WT(0).U(); + wtv0 = (*fi).WT(0).V(); + wtu1 = (*fi).WT(1).U(); + wtv1 = (*fi).WT(1).V(); + wtu2 = (*fi).WT(2).U(); + wtv2 = (*fi).WT(2).V(); + ti = (*fi).WT(0).N(); } - else { wtu0=wtv0=wtu1=wtv1=wtu2=wtv2=ti=0; } - - //selection + else { + wtu0 = wtv0 = wtu1 = wtv1 = wtu2 = wtv2 = ti = 0; + } + + // selection vsel0 = ((*fi).V(0)->IsS()) ? 1.0 : 0.0; vsel1 = ((*fi).V(1)->IsS()) ? 1.0 : 0.0; vsel2 = ((*fi).V(2)->IsS()) ? 1.0 : 0.0; - fsel = ((*fi).IsS()) ? 1.0 : 0.0; - + fsel = ((*fi).IsS()) ? 1.0 : 0.0; + // if user-defined attributes exist (vector is not empty) // set variables to explicit value obtained through attribute's handler - for(int i = 0; i < (int) f_attrValue.size(); i++) + for (int i = 0; i < (int) f_attrValue.size(); i++) f_attrValue[i] = f_handlers[i][fi]; } // Function explicitly define parser variables to perform per-vertex filter action // x, y, z for vertex coord, nx, ny, nz for normal coord, r, g ,b for color // and q for quality -void FilterFunctionPlugin::setPerVertexVariables(Parser &p, CMeshO &m) +void FilterFunctionPlugin::setPerVertexVariables(Parser& p, CMeshO& m) { p.DefineVar(conversion::fromStringToWString("x"), &x); p.DefineVar(conversion::fromStringToWString("y"), &y); @@ -1254,13 +1655,13 @@ void FilterFunctionPlugin::setPerVertexVariables(Parser &p, CMeshO &m) p.DefineVar(conversion::fromStringToWString("b"), &b); p.DefineVar(conversion::fromStringToWString("a"), &a); p.DefineVar(conversion::fromStringToWString("q"), &q); - p.DefineVar(conversion::fromStringToWString("vi"),&v); - p.DefineVar(conversion::fromStringToWString("rad"),&rad); - p.DefineVar(conversion::fromStringToWString("vtu"),&vtu); - p.DefineVar(conversion::fromStringToWString("vtv"),&vtv); + p.DefineVar(conversion::fromStringToWString("vi"), &v); + p.DefineVar(conversion::fromStringToWString("rad"), &rad); + p.DefineVar(conversion::fromStringToWString("vtu"), &vtu); + p.DefineVar(conversion::fromStringToWString("vtv"), &vtv); p.DefineVar(conversion::fromStringToWString("ti"), &ti); p.DefineVar(conversion::fromStringToWString("vsel"), &vsel); - + // define var for user-defined attributes (if any exists) // if vector is empty, code won't be executed v_handlers.clear(); @@ -1270,42 +1671,41 @@ void FilterFunctionPlugin::setPerVertexVariables(Parser &p, CMeshO &m) v3_attrNames.clear(); v3_attrValue.clear(); std::vector AllVertexAttribName; - tri::Allocator::GetAllPerVertexAttribute< Scalarm >(m,AllVertexAttribName); - for(int i = 0; i < (int) AllVertexAttribName.size(); i++) - { - CMeshO::PerVertexAttributeHandle hh = tri::Allocator::GetPerVertexAttribute(m, AllVertexAttribName[i]); + tri::Allocator::GetAllPerVertexAttribute(m, AllVertexAttribName); + for (int i = 0; i < (int) AllVertexAttribName.size(); i++) { + CMeshO::PerVertexAttributeHandle hh = + tri::Allocator::GetPerVertexAttribute(m, AllVertexAttribName[i]); v_handlers.push_back(hh); v_attrNames.push_back(AllVertexAttribName[i]); v_attrValue.push_back(0); p.DefineVar(conversion::fromStringToWString(v_attrNames.back()), &v_attrValue.back()); - qDebug("Adding custom per vertex float variable %s",v_attrNames.back().c_str()); + qDebug("Adding custom per vertex float variable %s", v_attrNames.back().c_str()); } AllVertexAttribName.clear(); - tri::Allocator::GetAllPerVertexAttribute< Point3m >(m,AllVertexAttribName); - for(int i = 0; i < (int) AllVertexAttribName.size(); i++) - { - CMeshO::PerVertexAttributeHandle hh3 = tri::Allocator::GetPerVertexAttribute(m, AllVertexAttribName[i]); - + tri::Allocator::GetAllPerVertexAttribute(m, AllVertexAttribName); + for (int i = 0; i < (int) AllVertexAttribName.size(); i++) { + CMeshO::PerVertexAttributeHandle hh3 = + tri::Allocator::GetPerVertexAttribute(m, AllVertexAttribName[i]); + v3_handlers.push_back(hh3); - + v3_attrValue.push_back(0); - v3_attrNames.push_back(AllVertexAttribName[i]+"_x"); + v3_attrNames.push_back(AllVertexAttribName[i] + "_x"); p.DefineVar(conversion::fromStringToWString(v3_attrNames.back()), &v3_attrValue.back()); - + v3_attrValue.push_back(0); - v3_attrNames.push_back(AllVertexAttribName[i]+"_y"); + v3_attrNames.push_back(AllVertexAttribName[i] + "_y"); p.DefineVar(conversion::fromStringToWString(v3_attrNames.back()), &v3_attrValue.back()); - + v3_attrValue.push_back(0); - v3_attrNames.push_back(AllVertexAttribName[i]+"_z"); + v3_attrNames.push_back(AllVertexAttribName[i] + "_z"); p.DefineVar(conversion::fromStringToWString(v3_attrNames.back()), &v3_attrValue.back()); - qDebug("Adding custom per vertex Point3f variable %s",v3_attrNames.back().c_str()); + qDebug("Adding custom per vertex Point3f variable %s", v3_attrNames.back().c_str()); } } - // Function explicitly define parser variables to perform Per-Face filter action -void FilterFunctionPlugin::setPerFaceVariables(Parser &p, CMeshO &m) +void FilterFunctionPlugin::setPerFaceVariables(Parser& p, CMeshO& m) { // coord of the three vertices within a face p.DefineVar(conversion::fromStringToWString("x0"), &x0); @@ -1317,119 +1717,114 @@ void FilterFunctionPlugin::setPerFaceVariables(Parser &p, CMeshO &m) p.DefineVar(conversion::fromStringToWString("x2"), &x2); p.DefineVar(conversion::fromStringToWString("y2"), &y2); p.DefineVar(conversion::fromStringToWString("z2"), &z2); - + // attributes of the vertices // normals: p.DefineVar(conversion::fromStringToWString("nx0"), &nx0); p.DefineVar(conversion::fromStringToWString("ny0"), &ny0); p.DefineVar(conversion::fromStringToWString("nz0"), &nz0); - + p.DefineVar(conversion::fromStringToWString("nx1"), &nx1); p.DefineVar(conversion::fromStringToWString("ny1"), &ny1); p.DefineVar(conversion::fromStringToWString("nz1"), &nz1); - + p.DefineVar(conversion::fromStringToWString("nx2"), &nx2); p.DefineVar(conversion::fromStringToWString("ny2"), &ny2); p.DefineVar(conversion::fromStringToWString("nz2"), &nz2); - + // colors: p.DefineVar(conversion::fromStringToWString("r0"), &r0); p.DefineVar(conversion::fromStringToWString("g0"), &g0); p.DefineVar(conversion::fromStringToWString("b0"), &b0); p.DefineVar(conversion::fromStringToWString("a0"), &a0); - + p.DefineVar(conversion::fromStringToWString("r1"), &r1); p.DefineVar(conversion::fromStringToWString("g1"), &g1); p.DefineVar(conversion::fromStringToWString("b1"), &b1); p.DefineVar(conversion::fromStringToWString("a1"), &a1); - + p.DefineVar(conversion::fromStringToWString("r2"), &r2); p.DefineVar(conversion::fromStringToWString("g2"), &g2); p.DefineVar(conversion::fromStringToWString("b2"), &b2); p.DefineVar(conversion::fromStringToWString("a2"), &a2); - + // quality p.DefineVar(conversion::fromStringToWString("q0"), &q0); p.DefineVar(conversion::fromStringToWString("q1"), &q1); p.DefineVar(conversion::fromStringToWString("q2"), &q2); - + // face color p.DefineVar(conversion::fromStringToWString("fr"), &fr); p.DefineVar(conversion::fromStringToWString("fg"), &fg); p.DefineVar(conversion::fromStringToWString("fb"), &fb); p.DefineVar(conversion::fromStringToWString("fa"), &fa); - + // face normal p.DefineVar(conversion::fromStringToWString("fnx"), &fnx); p.DefineVar(conversion::fromStringToWString("fny"), &fny); p.DefineVar(conversion::fromStringToWString("fnz"), &fnz); - + // face quality p.DefineVar(conversion::fromStringToWString("fq"), &fq); - + // index - p.DefineVar(conversion::fromStringToWString("fi"),&f); - p.DefineVar(conversion::fromStringToWString("vi0"),&v0i); - p.DefineVar(conversion::fromStringToWString("vi1"),&v1i); - p.DefineVar(conversion::fromStringToWString("vi2"),&v2i); - + p.DefineVar(conversion::fromStringToWString("fi"), &f); + p.DefineVar(conversion::fromStringToWString("vi0"), &v0i); + p.DefineVar(conversion::fromStringToWString("vi1"), &v1i); + p.DefineVar(conversion::fromStringToWString("vi2"), &v2i); + // texture - p.DefineVar(conversion::fromStringToWString("wtu0"),&wtu0); - p.DefineVar(conversion::fromStringToWString("wtv0"),&wtv0); - p.DefineVar(conversion::fromStringToWString("wtu1"),&wtu1); - p.DefineVar(conversion::fromStringToWString("wtv1"),&wtv1); - p.DefineVar(conversion::fromStringToWString("wtu2"),&wtu2); - p.DefineVar(conversion::fromStringToWString("wtv2"),&wtv2); + p.DefineVar(conversion::fromStringToWString("wtu0"), &wtu0); + p.DefineVar(conversion::fromStringToWString("wtv0"), &wtv0); + p.DefineVar(conversion::fromStringToWString("wtu1"), &wtu1); + p.DefineVar(conversion::fromStringToWString("wtv1"), &wtv1); + p.DefineVar(conversion::fromStringToWString("wtu2"), &wtu2); + p.DefineVar(conversion::fromStringToWString("wtv2"), &wtv2); p.DefineVar(conversion::fromStringToWString("ti"), &ti); - - //selection + + // selection p.DefineVar(conversion::fromStringToWString("vsel0"), &vsel0); p.DefineVar(conversion::fromStringToWString("vsel1"), &vsel1); p.DefineVar(conversion::fromStringToWString("vsel2"), &vsel2); p.DefineVar(conversion::fromStringToWString("fsel"), &fsel); - + // define var for user-defined attributes (if any exists) // if vector is empty, code won't be executed std::vector AllFaceAttribName; - tri::Allocator::GetAllPerFaceAttribute< Scalarm >(m,AllFaceAttribName); + tri::Allocator::GetAllPerFaceAttribute(m, AllFaceAttribName); f_handlers.clear(); f_attrNames.clear(); f_attrValue.clear(); - for(int i = 0; i < (int) AllFaceAttribName.size(); i++) - { - CMeshO::PerFaceAttributeHandle hh = tri::Allocator::GetPerFaceAttribute(m, AllFaceAttribName[i]); + for (int i = 0; i < (int) AllFaceAttribName.size(); i++) { + CMeshO::PerFaceAttributeHandle hh = + tri::Allocator::GetPerFaceAttribute(m, AllFaceAttribName[i]); f_handlers.push_back(hh); f_attrNames.push_back(AllFaceAttribName[i]); f_attrValue.push_back(0); p.DefineVar(conversion::fromStringToWString(f_attrNames.back()), &f_attrValue.back()); } - } -FilterPlugin::FilterArity FilterFunctionPlugin::filterArity(const QAction* filter ) const +FilterPlugin::FilterArity FilterFunctionPlugin::filterArity(const QAction* filter) const { - switch(ID(filter)) - { - case FF_VERT_SELECTION: - case FF_FACE_SELECTION: - case FF_GEOM_FUNC: - case FF_FACE_COLOR: - case FF_FACE_QUALITY: - case FF_VERT_COLOR: - case FF_VERT_QUALITY: - case FF_VERT_TEXTURE_FUNC: - case FF_WEDGE_TEXTURE_FUNC: - case FF_VERT_NORMAL: - case FF_DEF_VERT_ATTRIB: - case FF_DEF_FACE_ATTRIB: - case FF_REFINE: - return FilterPlugin::SINGLE_MESH; - case FF_GRID: - case FF_ISOSURFACE: - return FilterPlugin::NONE; + switch (ID(filter)) { + case FF_VERT_SELECTION: + case FF_FACE_SELECTION: + case FF_GEOM_FUNC: + case FF_FACE_COLOR: + case FF_FACE_QUALITY: + case FF_VERT_COLOR: + case FF_VERT_QUALITY: + case FF_VERT_TEXTURE_FUNC: + case FF_WEDGE_TEXTURE_FUNC: + case FF_VERT_NORMAL: + case FF_DEF_VERT_SCALAR_ATTRIB: + case FF_DEF_FACE_SCALAR_ATTRIB: + case FF_REFINE: return FilterPlugin::SINGLE_MESH; + case FF_GRID: + case FF_ISOSURFACE: return FilterPlugin::NONE; } return FilterPlugin::NONE; } - MESHLAB_PLUGIN_NAME_EXPORTER(FilterFunctionPlugin) diff --git a/src/meshlabplugins/filter_func/filter_func.h b/src/meshlabplugins/filter_func/filter_func.h index 9e5186dd2..76fc2590f 100644 --- a/src/meshlabplugins/filter_func/filter_func.h +++ b/src/meshlabplugins/filter_func/filter_func.h @@ -1,25 +1,25 @@ -/**************************************************************************** -* MeshLab o o * -* A versatile mesh processing toolbox o o * -* _ O _ * -* Copyright(C) 2005 \/)\/ * -* Visual Computing Lab /\/| * -* ISTI - Italian National Research Council | * -* \ * -* All rights reserved. * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * -* for more details. * -* * -****************************************************************************/ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2005-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ #ifndef FILTER_FUNC_PLUGIN_H #define FILTER_FUNC_PLUGIN_H @@ -28,7 +28,6 @@ #include -#include "muParser.h" #include "filter_refine.h" class FilterFunctionPlugin : public QObject, public FilterPlugin @@ -38,65 +37,69 @@ class FilterFunctionPlugin : public QObject, public FilterPlugin Q_INTERFACES(FilterPlugin) protected: - double x,y,z,nx,ny,nz,r,g,b,a,q,rad,vtu,vtv,vsel; - double x0,y0,z0,x1,y1,z1,x2,y2,z2,nx0,ny0,nz0,nx1,ny1,nz1,nx2,ny2,nz2,r0,g0,b0,a0,r1,g1,b1,a1,r2,g2,b2,a2,q0,q1,q2,wtu0,wtv0,wtu1,wtv1,wtu2,wtv2,vsel0,vsel1,vsel2; - double fr,fg,fb,fa,fnx,fny,fnz,fq,fsel; - double v,f,v0i,v1i,v2i,ti; + double x, y, z, nx, ny, nz, r, g, b, a, q, rad, vtu, vtv, vsel; + double x0, y0, z0, x1, y1, z1, x2, y2, z2, nx0, ny0, nz0, nx1, ny1, nz1, nx2, ny2, nz2, r0, g0, + b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, q0, q1, q2, wtu0, wtv0, wtu1, wtv1, wtu2, wtv2, + vsel0, vsel1, vsel2; + double fr, fg, fb, fa, fnx, fny, fnz, fq, fsel; + double v, f, v0i, v1i, v2i, ti; std::vector v_attrNames; // names of the per vertex attributes std::vector v_attrValue; // values of the per vertex attributes - std::vector v3_attrNames; // names of the per vertex attributes There are 3x (one foreach coord _x, _y, _z) - std::vector v3_attrValue; // values of the per vertex attributes. There are 3x (one foreach coord _x, _y, _z) - std::vector f_attrNames; - std::vector f_attrValue; - std::vector > v_handlers; - std::vector > v3_handlers; - std::vector > f_handlers; - QString errorMsg; + std::vector v3_attrNames; // names of the per vertex attributes There are + // 3x (one foreach coord _x, _y, _z) + std::vector v3_attrValue; // values of the per vertex attributes. There are 3x + // (one foreach coord _x, _y, _z) + std::vector f_attrNames; + std::vector f_attrValue; + std::vector> v_handlers; + std::vector> v3_handlers; + std::vector> f_handlers; + QString errorMsg; public: enum { - FF_VERT_SELECTION, - FF_FACE_SELECTION, - FF_GEOM_FUNC, - FF_VERT_TEXTURE_FUNC, - FF_WEDGE_TEXTURE_FUNC, - FF_FACE_COLOR, - FF_VERT_COLOR, - FF_VERT_NORMAL, - FF_VERT_QUALITY, - FF_FACE_QUALITY, - FF_DEF_VERT_ATTRIB, - FF_DEF_FACE_ATTRIB, - FF_GRID, - FF_ISOSURFACE, - FF_REFINE - } ; + FF_VERT_SELECTION, + FF_FACE_SELECTION, + FF_GEOM_FUNC, + FF_VERT_TEXTURE_FUNC, + FF_WEDGE_TEXTURE_FUNC, + FF_FACE_COLOR, + FF_VERT_COLOR, + FF_VERT_NORMAL, + FF_VERT_QUALITY, + FF_FACE_QUALITY, + FF_DEF_VERT_SCALAR_ATTRIB, + FF_DEF_FACE_SCALAR_ATTRIB, + FF_DEF_VERT_POINT_ATTRIB, + FF_DEF_FACE_POINT_ATTRIB, + FF_GRID, + FF_ISOSURFACE, + FF_REFINE + }; FilterFunctionPlugin(); ~FilterFunctionPlugin(); - - QString pluginName() const; - QString filterName(ActionIDType filter) const; - QString filterInfo(ActionIDType filter) const; - FilterClass getClass(const QAction*) const; - int postCondition(const QAction *action) const; - RichParameterList initParameterList(const QAction*, const MeshModel &/*m*/); - virtual int getRequirements(const QAction*); + + QString pluginName() const; + QString filterName(ActionIDType filter) const; + QString filterInfo(ActionIDType filter) const; + FilterClass getClass(const QAction*) const; + int postCondition(const QAction* action) const; + RichParameterList initParameterList(const QAction*, const MeshModel& /*m*/); + virtual int getRequirements(const QAction*); std::map applyFilter( - const QAction* action, - const RichParameterList & parameters, - MeshDocument &md, - unsigned int& postConditionMask, - vcg::CallBackPos * cb); + const QAction* action, + const RichParameterList& parameters, + MeshDocument& md, + unsigned int& postConditionMask, + vcg::CallBackPos* cb); FilterArity filterArity(const QAction* filter) const; - - void showParserError(const QString &s, mu::Parser::exception_type &e); - void setAttributes(CMeshO::VertexIterator &vi,CMeshO &m); - void setAttributes(CMeshO::FaceIterator &fi,CMeshO &m); - void setPerVertexVariables(mu::Parser &p, CMeshO &m); - void setPerFaceVariables(mu::Parser &p, CMeshO &m); - + void showParserError(const QString& s, mu::Parser::exception_type& e); + void setAttributes(CMeshO::VertexIterator& vi, CMeshO& m); + void setAttributes(CMeshO::FaceIterator& fi, CMeshO& m); + void setPerVertexVariables(mu::Parser& p, CMeshO& m); + void setPerFaceVariables(mu::Parser& p, CMeshO& m); }; #endif diff --git a/src/meshlabplugins/filter_func/filter_refine.h b/src/meshlabplugins/filter_func/filter_refine.h index 0072f793e..ca08a127e 100644 --- a/src/meshlabplugins/filter_func/filter_refine.h +++ b/src/meshlabplugins/filter_func/filter_refine.h @@ -23,6 +23,7 @@ #include #include "string_conversion.h" +#include "muParser.h" using namespace vcg; using namespace mu; diff --git a/src/meshlabplugins/filter_unsharp/filter_unsharp.cpp b/src/meshlabplugins/filter_unsharp/filter_unsharp.cpp index 0fc38151f..c6adb234d 100644 --- a/src/meshlabplugins/filter_unsharp/filter_unsharp.cpp +++ b/src/meshlabplugins/filter_unsharp/filter_unsharp.cpp @@ -1,36 +1,36 @@ -/**************************************************************************** -* MeshLab o o * -* An extendible mesh processor o o * -* _ O _ * -* Copyright(C) 2005, 2006 \/)\/ * -* Visual Computing Lab /\/| * -* ISTI - Italian National Research Council | * -* \ * -* All rights reserved. * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * -* for more details. * -* * -****************************************************************************/ +/***************************************************************************** + * MeshLab o o * + * An extendible mesh processor o o * + * _ O _ * + * Copyright(C) 2005-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ #include "filter_unsharp.h" #include -#include #include #include +#include using namespace vcg; using namespace std; -enum WeightModeParam {WMP_AVG = 0, WMP_AREA, WMP_ANGLE, WMP_AS_DEF}; +enum WeightModeParam { WMP_AVG = 0, WMP_AREA, WMP_ANGLE, WMP_AS_DEF }; FilterUnsharp::FilterUnsharp() { @@ -42,7 +42,8 @@ FilterUnsharp::FilterUnsharp() FP_TWO_STEP_SMOOTH, FP_TAUBIN_SMOOTH, FP_DEPTH_SMOOTH, - FP_DIRECTIONAL_PRESERVATION, + //FP_DIRECTIONAL_PRESERVATION_STORE, + FP_DIRECTIONAL_PRESERVATION_BLEND, FP_VERTEX_QUALITY_SMOOTHING, FP_FACE_NORMAL_SMOOTHING, FP_UNSHARP_NORMAL, @@ -55,528 +56,820 @@ FilterUnsharp::FilterUnsharp() FP_FACE_NORMAL_NORMALIZE, FP_VERTEX_NORMAL_NORMALIZE, FP_LINEAR_MORPH, - FP_SCALAR_HARMONIC_FIELD - }; + FP_SCALAR_HARMONIC_FIELD}; - for(ActionIDType tt : types()) + for (ActionIDType tt : types()) actionList.push_back(new QAction(filterName(tt), this)); - } -FilterUnsharp::~FilterUnsharp() { +FilterUnsharp::~FilterUnsharp() +{ } QString FilterUnsharp::pluginName() const { - return "FilterUnsharp"; + return "FilterUnsharp"; } QString FilterUnsharp::filterName(ActionIDType filter) const { - switch(filter) - { - case FP_LAPLACIAN_SMOOTH : return QString("Laplacian Smooth"); - case FP_HC_LAPLACIAN_SMOOTH : return QString("HC Laplacian Smooth"); - case FP_SD_LAPLACIAN_SMOOTH : return QString("ScaleDependent Laplacian Smooth"); - case FP_TWO_STEP_SMOOTH : return QString("TwoStep Smooth"); - case FP_TAUBIN_SMOOTH : return QString("Taubin Smooth"); - case FP_DEPTH_SMOOTH : return QString("Depth Smooth"); - case FP_DIRECTIONAL_PRESERVATION : return QString("Directional Geom. Preserv."); - case FP_CREASE_CUT : return QString("Cut mesh along crease edges"); - case FP_FACE_NORMAL_NORMALIZE: return QString("Normalize Face Normals"); - case FP_VERTEX_NORMAL_NORMALIZE: return QString("Normalize Vertex Normals"); - case FP_FACE_NORMAL_SMOOTHING: return QString("Smooth Face Normals"); - case FP_VERTEX_QUALITY_SMOOTHING: return QString("Smooth Vertex Quality"); - case FP_UNSHARP_NORMAL: return QString("UnSharp Mask Normals"); - case FP_UNSHARP_GEOMETRY: return QString("UnSharp Mask Geometry"); - case FP_UNSHARP_QUALITY: return QString("UnSharp Mask Quality"); - case FP_UNSHARP_VERTEX_COLOR: return QString("UnSharp Mask Color"); - case FP_RECOMPUTE_VERTEX_NORMAL: return QString("Re-Compute Vertex Normals"); - case FP_RECOMPUTE_FACE_NORMAL: return QString("Re-Compute Face Normals"); - case FP_RECOMPUTE_QUADFACE_NORMAL: return QString("Re-Compute Per-Polygon Face Normals"); - case FP_LINEAR_MORPH : return QString("Vertex Linear Morphing"); - case FP_SCALAR_HARMONIC_FIELD: return QString("Generate Scalar Harmonic Field"); + switch (filter) { + case FP_LAPLACIAN_SMOOTH: return QString("Laplacian Smooth"); + case FP_HC_LAPLACIAN_SMOOTH: return QString("HC Laplacian Smooth"); + case FP_SD_LAPLACIAN_SMOOTH: return QString("ScaleDependent Laplacian Smooth"); + case FP_TWO_STEP_SMOOTH: return QString("TwoStep Smooth"); + case FP_TAUBIN_SMOOTH: return QString("Taubin Smooth"); + case FP_DEPTH_SMOOTH: return QString("Depth Smooth"); + //case FP_DIRECTIONAL_PRESERVATION_STORE: return QString("Directional Geom. Preserv."); + case FP_DIRECTIONAL_PRESERVATION_BLEND: return QString("Directional Geometry Preservation"); + case FP_CREASE_CUT: return QString("Cut mesh along crease edges"); + case FP_FACE_NORMAL_NORMALIZE: return QString("Normalize Face Normals"); + case FP_VERTEX_NORMAL_NORMALIZE: return QString("Normalize Vertex Normals"); + case FP_FACE_NORMAL_SMOOTHING: return QString("Smooth Face Normals"); + case FP_VERTEX_QUALITY_SMOOTHING: return QString("Smooth Vertex Quality"); + case FP_UNSHARP_NORMAL: return QString("UnSharp Mask Normals"); + case FP_UNSHARP_GEOMETRY: return QString("UnSharp Mask Geometry"); + case FP_UNSHARP_QUALITY: return QString("UnSharp Mask Quality"); + case FP_UNSHARP_VERTEX_COLOR: return QString("UnSharp Mask Color"); + case FP_RECOMPUTE_VERTEX_NORMAL: return QString("Re-Compute Vertex Normals"); + case FP_RECOMPUTE_FACE_NORMAL: return QString("Re-Compute Face Normals"); + case FP_RECOMPUTE_QUADFACE_NORMAL: return QString("Re-Compute Per-Polygon Face Normals"); + case FP_LINEAR_MORPH: return QString("Vertex Linear Morphing"); + case FP_SCALAR_HARMONIC_FIELD: return QString("Generate Scalar Harmonic Field"); - default: assert(0); - } - return QString("Error on FilterUnsharp::filterName()"); + default: assert(0); + } + return QString("Error on FilterUnsharp::filterName()"); } QString FilterUnsharp::filterInfo(ActionIDType filterId) const { - switch(filterId) - { - case FP_LAPLACIAN_SMOOTH : return tr("Laplacian smooth. Average each vertex position with weighted positions of neighbour vertices.
" - "Laplacian Mesh Processing by Olga Sorkine. EUROGRAPHICS 2005
" - "doi:10.2312/egst.20051044"); - case FP_HC_LAPLACIAN_SMOOTH : return tr("HC Laplacian Smoothing. Extended version of Laplacian Smoothing based on the article:
" - "Improved Laplacian Smoothing of Noisy Surface Meshes " - "by Vollmer, Mencl and Müller. EUROGRAPHICS Volume 18 (1999), Number 3, 131-138.
" - "doi:10.1111/1467-8659.00334"); - case FP_SD_LAPLACIAN_SMOOTH : return tr("Scale Dependent Laplacian Smoothing, extended version of Laplacian Smoothing based on the Fujiwara extended umbrella operator.
" - "Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow " - "by Desbrun, Meyer, Schroeder and Barr. SIGGRAPH 1999
" - "doi:10.1145/311535.311576"); - case FP_TWO_STEP_SMOOTH : return tr("Two Steps Smoothing, a feature preserving/enhancing fairing filter based on two stages:
  1. Normal Smoothing, where " - "similar normals are averaged together.
  2. Vertex reposition, where vertices are moved to fit on the new normals.
" - "A Comparison of Mesh Smoothing Methods by A. Belyaev and Y. Ohtake. " - "Proc. Israel-Korea Bi-National Conf. Geometric Modeling and Computer Graphics, pp. 83-87, 2003.
" - "publication"); - case FP_TAUBIN_SMOOTH : return tr("The λ-μ Taubin smoothing, combines two steps of low-pass filtering for each iteration. Based on the article:
" - "A signal processing approach to fair surface design by Gabriel Taubin, SIGGRAPH 1995
" - "doi:10.1145/218380.218473"); - case FP_DEPTH_SMOOTH : return tr("A laplacian smooth that is constrained to move vertices only in one given direction (usually the viewer direction)."); - case FP_DIRECTIONAL_PRESERVATION : return tr("Store and Blend the current geometry with the result of another previous smoothing processing step. This is useful to " - "limit the influence of any smoothing algorithm along the viewing direction. This is useful to cope with the biased " - "distribution of measuring error in many scanning devices, because TOF scanners usually have very good x,y" - "accuracy but suffer of greater depth errors."); - case FP_CREASE_CUT: return tr("Cut the mesh along crease edges, duplicating the vertices as necessary. Crease (or sharp) edges are defined according " - "to the variation of normal of the adjacent faces."); - case FP_FACE_NORMAL_NORMALIZE: return tr("Normalize Face Normal Lengths to unit vectors."); - case FP_VERTEX_NORMAL_NORMALIZE: return tr("Normalize Vertex Normal Lengths to unit vectors."); - case FP_VERTEX_QUALITY_SMOOTHING: return tr("Laplacian smooth of the quality per vertex values."); - case FP_FACE_NORMAL_SMOOTHING: return tr("Laplacian smooth of the face normals, without touching the position of the vertices."); - case FP_UNSHARP_NORMAL: return tr("Unsharp mask filtering of the normals per face, putting in more evidence normal variations.
" - "A simple normal enhancement technique for interactive non-photorealistic renderings " - "by Cignoni, Scopigno and Tarini, Comput Graph, 29 (1) (2005)
" - "doi:10.1016/j.cag.2004.11.012"); - case FP_UNSHARP_GEOMETRY: return tr("Apply Unsharp filter to geometric shape, putting in more evidence ridges and valleys variations.
" - "Unsharp Masking"); - case FP_UNSHARP_QUALITY: return tr("Apply Unsharp filter to values of quality per vertex.
" - "See Unsharp Masking"); - case FP_UNSHARP_VERTEX_COLOR: return tr("Apply Unsharp filter to the vertex color, putting in more evidence color variations.
" - "See Unsharp Masking"); - case FP_RECOMPUTE_VERTEX_NORMAL: return tr("Recompute vertex normals according to four different schemes:
" - "1) Simple (no weights) average of normals of the incident faces
" - "2) Area weighted average of normals of the incident faces
" - "3) Angle weighted sum of normals of the incident faces according to the article [1]. " - "Probably this is the best all-purpose choice. It could slightly bias the result for degenerate, fat triangles.
" - "4) Weighted sum of normals of the incident faces, as defined by article [2]. " - "The weight for each wedge is the cross product of the two edges over the product of the square of the two edge lengths." - "According to the original article it is perfect only for spherical surface, but it should perform well also in practice.
" - "[1]: Computing Vertex Normals from Polygonal Facet by G Thurmer and CA Wuthrich, JGT volume3, num 1. 1998
" - "doi:10.1080/10867651.1998.10487487
" - "[2]: Weights for Computing Vertex Normals from Facet Normals by Nelson Max, JGT vol4, num 2. 1999
" - "doi:10.1080/10867651.1999.10487501"); - case FP_RECOMPUTE_FACE_NORMAL: return tr("Recompute face normals as the normal of the plane of the face.
" - "See How to find surface normal of a triangle"); - case FP_RECOMPUTE_QUADFACE_NORMAL: return tr("Recompute face normals as the average of the normals of the triangles that builds a polygon. " - "Useful for showing uniformly shaded quad or polygonal meshes represented using " - "faux edges."); - case FP_LINEAR_MORPH : return tr("Morph deformation of current mesh towards a target mesh with the same number of vertices and same vertex ordering. " - "Each vertex of the source mesh is linearly interpolated towards the corresponding vertex on the target mesh " - "using the formula:

resulti = (1-λ)*sourcei + λ*targeti

" - "Three-dimensional metamorphosis: a survey
by F. Lazarus and A. Verroust, Visual Computer, 1998
" - "doi:10.1007/s003710050149"); - case FP_SCALAR_HARMONIC_FIELD: return QString("Generates a scalar harmonic field over the mesh. Input scalar values must be assigned to two vertices " - "as Dirichlet boundary conditions. Applying the filter, a discrete Laplace operator generates the harmonic " - "field values for all the mesh vertices, which are stored in the " - "quality per vertex attribute of the mesh.
" - "For more details see:" - "Dynamic Harmonic Fields for Surface Processing by Kai Xua, Hao Zhang, Daniel Cohen-Or, Yueshan Xionga. " - "Computers & Graphics, 2009
" - "doi:10.1016/j.cag.2009.03.022"); - default: assert(0); - } - return QString("Error on FilterUnsharp::filterInfo()!"); + switch (filterId) { + case FP_LAPLACIAN_SMOOTH: + return tr( + "Laplacian smooth. Average each vertex position with weighted positions of neighbour " + "vertices.
" + "Laplacian Mesh Processing by Olga Sorkine. EUROGRAPHICS 2005
" + "doi:10.2312/egst.20051044"); + case FP_HC_LAPLACIAN_SMOOTH: + return tr( + "HC Laplacian Smoothing. Extended version of Laplacian Smoothing based on the article: " + "
" + "Improved Laplacian Smoothing of Noisy Surface Meshes " + "by Vollmer, Mencl and Müller. EUROGRAPHICS Volume 18 (1999), Number 3, " + "131-138.
" + "doi:10.1111/1467-8659.00334"); + case FP_SD_LAPLACIAN_SMOOTH: + return tr( + "Scale Dependent Laplacian Smoothing, extended version of Laplacian Smoothing based on " + "the Fujiwara extended umbrella operator.
" + "Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow " + "by Desbrun, Meyer, Schroeder and Barr. SIGGRAPH 1999
" + "doi:10.1145/311535.311576"); + case FP_TWO_STEP_SMOOTH: + return tr( + "Two Steps Smoothing, a feature preserving/enhancing fairing filter based on two " + "stages:
  1. Normal Smoothing, where " + "similar normals are averaged together.
  2. Vertex reposition, where vertices are moved " + "to fit on the new normals.
" + "A Comparison of Mesh Smoothing Methods by A. Belyaev and Y. Ohtake. " + "Proc. Israel-Korea Bi-National Conf. Geometric Modeling and Computer Graphics, pp. " + "83-87, 2003.
" + "publication"); + case FP_TAUBIN_SMOOTH: + return tr( + "The λ-μ Taubin smoothing, combines two steps of low-pass filtering for each " + "iteration. Based on the article:
" + "A signal processing approach to fair surface design by Gabriel Taubin, " + "SIGGRAPH 1995
" + "doi:10.1145/218380.218473"); + case FP_DEPTH_SMOOTH: + return tr( + "A laplacian smooth that is constrained to move vertices only in one given direction " + "(usually the viewer direction)."); + //case FP_DIRECTIONAL_PRESERVATION_STORE: + // return tr( + // "Blend the geometry previously stored in a per vertex custom point attribute with the " + // "current geometry. This is useful to limit the influence of any smoothing algorithm " + // "along the viewing direction. This is useful to cope with the biased distribution of " + // "measuring error in many scanning devices, because TOF scanners usually have very good " + // "x,y accuracy but suffer of greater depth errors."); + case FP_DIRECTIONAL_PRESERVATION_BLEND: + return tr( + "Blend through a given direction the geometry previously stored in a per vertex " + "custom point attribute with the current geometry. This is useful to limit the " + "influence of any smoothing algorithm along the viewing direction. This is useful to " + "cope with the biased distribution of measuring error in many scanning devices, " + "because TOF scanners usually have very good x,y accuracy but suffer of greater " + "depth errors."); + case FP_CREASE_CUT: + return tr( + "Cut the mesh along crease edges, duplicating the vertices as necessary. Crease (or " + "sharp) edges are defined according " + "to the variation of normal of the adjacent faces."); + case FP_FACE_NORMAL_NORMALIZE: return tr("Normalize Face Normal Lengths to unit vectors."); + case FP_VERTEX_NORMAL_NORMALIZE: return tr("Normalize Vertex Normal Lengths to unit vectors."); + case FP_VERTEX_QUALITY_SMOOTHING: + return tr( + "Laplacian smooth of the quality per vertex values."); + case FP_FACE_NORMAL_SMOOTHING: + return tr( + "Laplacian smooth of the face normals, without touching the position of the vertices."); + case FP_UNSHARP_NORMAL: + return tr( + "Unsharp mask filtering of the normals per face, putting in more evidence normal " + "variations.
" + "A simple normal enhancement technique for interactive non-photorealistic " + "renderings " + "by Cignoni, Scopigno and Tarini, Comput Graph, 29 (1) (2005)
" + "doi:10.1016/j.cag.2004.11.012"); + case FP_UNSHARP_GEOMETRY: + return tr( + "Apply Unsharp filter to geometric shape, putting in more evidence ridges and valleys " + "variations.
" + "Unsharp Masking"); + case FP_UNSHARP_QUALITY: + return tr( + "Apply Unsharp filter to values of quality per vertex.
" + "See Unsharp Masking"); + case FP_UNSHARP_VERTEX_COLOR: + return tr( + "Apply Unsharp filter to the vertex color, putting in more evidence color " + "variations.
" + "See Unsharp Masking"); + case FP_RECOMPUTE_VERTEX_NORMAL: + return tr( + "Recompute vertex normals according to four different schemes:
" + "1) Simple (no weights) average of normals of the incident faces
" + "2) Area weighted average of normals of the incident faces
" + "3) Angle weighted sum of normals of the incident faces according to the article " + "[1]. " + "Probably this is the best all-purpose choice. It could slightly bias the result for " + "degenerate, fat triangles.
" + "4) Weighted sum of normals of the incident faces, as defined by article [2]. " + "The weight for each wedge is the cross product of the two edges over the product of " + "the square of the two edge lengths." + "According to the original article it is perfect only for spherical surface, but it " + "should perform well also in practice.
" + "[1]: Computing Vertex Normals from Polygonal Facet by G Thurmer and CA " + "Wuthrich, JGT volume3, num 1. 1998
" + "doi:10.1080/" + "10867651.1998.10487487
" + "[2]: Weights for Computing Vertex Normals from Facet Normals by Nelson " + "Max, JGT vol4, num 2. 1999
" + "doi:10.1080/" + "10867651.1999.10487501"); + case FP_RECOMPUTE_FACE_NORMAL: + return tr( + "Recompute face normals as the normal of the plane of the face.
" + "See How to find surface " + "normal of a triangle"); + case FP_RECOMPUTE_QUADFACE_NORMAL: + return tr( + "Recompute face normals as the average of the normals of the triangles that builds a " + "polygon. " + "Useful for showing uniformly shaded quad or polygonal meshes represented using " + "faux edges."); + case FP_LINEAR_MORPH: + return tr( + "Morph deformation of current mesh towards a target mesh with the same number of " + "vertices and same vertex ordering. " + "Each vertex of the source mesh is linearly interpolated towards the corresponding " + "vertex on the target mesh " + "using the formula:

resulti = " + "(1-λ)*sourcei + " + "λ*targeti

" + "Three-dimensional metamorphosis: a survey
by F. Lazarus and A. " + "Verroust, Visual Computer, 1998
" + "doi:10.1007/s003710050149"); + case FP_SCALAR_HARMONIC_FIELD: + return QString( + "Generates a scalar harmonic field over the mesh. Input scalar values must be assigned " + "to two vertices " + "as Dirichlet boundary conditions. Applying the filter, a discrete Laplace operator " + "generates the harmonic " + "field values for all the mesh vertices, which are stored in the " + "quality per vertex " + "attribute of the mesh.
" + "For more details see:" + "Dynamic Harmonic Fields for Surface Processing by Kai Xua, Hao Zhang, " + "Daniel Cohen-Or, Yueshan Xionga. " + "Computers & Graphics, 2009
" + "doi:10.1016/j.cag.2009.03.022"); + default: assert(0); + } + return QString("Error on FilterUnsharp::filterInfo()!"); } - FilterUnsharp::FilterClass FilterUnsharp::getClass(const QAction *a) const +FilterUnsharp::FilterClass FilterUnsharp::getClass(const QAction* a) const { - switch(ID(a)) - { - case FP_CREASE_CUT : - return FilterPlugin::FilterClass( FilterPlugin::Normal | FilterPlugin::Remeshing); - case FP_SD_LAPLACIAN_SMOOTH: - case FP_HC_LAPLACIAN_SMOOTH: - case FP_LAPLACIAN_SMOOTH: - case FP_TWO_STEP_SMOOTH: - case FP_TAUBIN_SMOOTH: - case FP_DEPTH_SMOOTH: - case FP_DIRECTIONAL_PRESERVATION: - case FP_FACE_NORMAL_SMOOTHING: - case FP_VERTEX_QUALITY_SMOOTHING: - case FP_UNSHARP_NORMAL: - case FP_UNSHARP_GEOMETRY: - case FP_UNSHARP_QUALITY: - case FP_LINEAR_MORPH : - return FilterPlugin::Smoothing; + switch (ID(a)) { + case FP_CREASE_CUT: + return FilterPlugin::FilterClass(FilterPlugin::Normal | FilterPlugin::Remeshing); + case FP_SD_LAPLACIAN_SMOOTH: + case FP_HC_LAPLACIAN_SMOOTH: + case FP_LAPLACIAN_SMOOTH: + case FP_TWO_STEP_SMOOTH: + case FP_TAUBIN_SMOOTH: + case FP_DEPTH_SMOOTH: + //case FP_DIRECTIONAL_PRESERVATION_STORE: + case FP_DIRECTIONAL_PRESERVATION_BLEND: + case FP_FACE_NORMAL_SMOOTHING: + case FP_VERTEX_QUALITY_SMOOTHING: + case FP_UNSHARP_NORMAL: + case FP_UNSHARP_GEOMETRY: + case FP_UNSHARP_QUALITY: + case FP_LINEAR_MORPH: return FilterPlugin::Smoothing; - case FP_UNSHARP_VERTEX_COLOR: - return FilterPlugin::FilterClass( FilterPlugin::Smoothing | FilterPlugin::VertexColoring); + case FP_UNSHARP_VERTEX_COLOR: + return FilterPlugin::FilterClass(FilterPlugin::Smoothing | FilterPlugin::VertexColoring); - case FP_RECOMPUTE_FACE_NORMAL : - case FP_RECOMPUTE_QUADFACE_NORMAL : - case FP_RECOMPUTE_VERTEX_NORMAL : - case FP_FACE_NORMAL_NORMALIZE: - case FP_VERTEX_NORMAL_NORMALIZE: - return FilterPlugin::Normal; - case FP_SCALAR_HARMONIC_FIELD: return FilterPlugin::Remeshing; + case FP_RECOMPUTE_FACE_NORMAL: + case FP_RECOMPUTE_QUADFACE_NORMAL: + case FP_RECOMPUTE_VERTEX_NORMAL: + case FP_FACE_NORMAL_NORMALIZE: + case FP_VERTEX_NORMAL_NORMALIZE: return FilterPlugin::Normal; + case FP_SCALAR_HARMONIC_FIELD: return FilterPlugin::Remeshing; - default : return FilterPlugin::Generic; - } + default: return FilterPlugin::Generic; + } } -int FilterUnsharp::getPreConditions(const QAction *a) const +int FilterUnsharp::getPreConditions(const QAction* a) const { - switch(ID(a)) - { - case FP_VERTEX_QUALITY_SMOOTHING: - case FP_UNSHARP_QUALITY: - return MeshModel::MM_FACENUMBER | MeshModel::MM_VERTQUALITY; - case FP_SD_LAPLACIAN_SMOOTH: - case FP_HC_LAPLACIAN_SMOOTH: - case FP_LAPLACIAN_SMOOTH: - case FP_TWO_STEP_SMOOTH: - case FP_TAUBIN_SMOOTH: - case FP_DEPTH_SMOOTH: - case FP_LINEAR_MORPH : - case FP_UNSHARP_NORMAL: - case FP_UNSHARP_GEOMETRY: - case FP_DIRECTIONAL_PRESERVATION: - case FP_FACE_NORMAL_SMOOTHING: - case FP_RECOMPUTE_FACE_NORMAL : - case FP_RECOMPUTE_QUADFACE_NORMAL : - case FP_RECOMPUTE_VERTEX_NORMAL : - case FP_FACE_NORMAL_NORMALIZE: - case FP_CREASE_CUT: - case FP_SCALAR_HARMONIC_FIELD: - return MeshModel::MM_FACENUMBER; - case FP_UNSHARP_VERTEX_COLOR: - return MeshModel::MM_FACENUMBER | MeshModel::MM_VERTCOLOR; - - case FP_VERTEX_NORMAL_NORMALIZE: return MeshModel::MM_NONE; - - default : assert(0); return MeshModel::MM_NONE; - } -} + switch (ID(a)) { + case FP_VERTEX_QUALITY_SMOOTHING: + case FP_UNSHARP_QUALITY: return MeshModel::MM_FACENUMBER | MeshModel::MM_VERTQUALITY; + case FP_SD_LAPLACIAN_SMOOTH: + case FP_HC_LAPLACIAN_SMOOTH: + case FP_LAPLACIAN_SMOOTH: + case FP_TWO_STEP_SMOOTH: + case FP_TAUBIN_SMOOTH: + case FP_DEPTH_SMOOTH: + case FP_LINEAR_MORPH: + case FP_UNSHARP_NORMAL: + case FP_UNSHARP_GEOMETRY: + //case FP_DIRECTIONAL_PRESERVATION_STORE: + case FP_DIRECTIONAL_PRESERVATION_BLEND: + case FP_FACE_NORMAL_SMOOTHING: + case FP_RECOMPUTE_FACE_NORMAL: + case FP_RECOMPUTE_QUADFACE_NORMAL: + case FP_RECOMPUTE_VERTEX_NORMAL: + case FP_FACE_NORMAL_NORMALIZE: + case FP_CREASE_CUT: + case FP_SCALAR_HARMONIC_FIELD: return MeshModel::MM_FACENUMBER; + case FP_UNSHARP_VERTEX_COLOR: return MeshModel::MM_FACENUMBER | MeshModel::MM_VERTCOLOR; + case FP_VERTEX_NORMAL_NORMALIZE: return MeshModel::MM_NONE; -int FilterUnsharp::postCondition(const QAction *a) const -{ - switch(ID(a)) - { - case FP_SD_LAPLACIAN_SMOOTH: - case FP_HC_LAPLACIAN_SMOOTH: - case FP_LAPLACIAN_SMOOTH: - case FP_TWO_STEP_SMOOTH: - case FP_TAUBIN_SMOOTH: - case FP_DEPTH_SMOOTH: - case FP_LINEAR_MORPH : - case FP_UNSHARP_NORMAL: - case FP_UNSHARP_GEOMETRY: return MeshModel::MM_VERTCOORD | MeshModel::MM_VERTNORMAL | MeshModel::MM_FACENORMAL; - case FP_DIRECTIONAL_PRESERVATION: - case FP_VERTEX_QUALITY_SMOOTHING: - case FP_UNSHARP_QUALITY: - case FP_CREASE_CUT: return MeshModel::MM_ALL; - case FP_FACE_NORMAL_SMOOTHING: - case FP_RECOMPUTE_FACE_NORMAL: - case FP_RECOMPUTE_QUADFACE_NORMAL: - case FP_FACE_NORMAL_NORMALIZE: return MeshModel::MM_FACENORMAL; - case FP_RECOMPUTE_VERTEX_NORMAL: - case FP_VERTEX_NORMAL_NORMALIZE: return MeshModel::MM_VERTNORMAL; - case FP_UNSHARP_VERTEX_COLOR: return MeshModel::MM_VERTCOLOR; - case FP_SCALAR_HARMONIC_FIELD: return MeshModel::MM_VERTQUALITY; - default : assert(0); return MeshModel::MM_ALL; + default: assert(0); return MeshModel::MM_NONE; } } - int FilterUnsharp::getRequirements(const QAction *action) +int FilterUnsharp::postCondition(const QAction* a) const { - switch(ID(action)) - { - case FP_TWO_STEP_SMOOTH: return MeshModel::MM_VERTFACETOPO; - - case FP_CREASE_CUT : - case FP_UNSHARP_NORMAL: - case FP_RECOMPUTE_QUADFACE_NORMAL : - case FP_FACE_NORMAL_SMOOTHING : return MeshModel::MM_FACEFACETOPO; - - case FP_RECOMPUTE_FACE_NORMAL : - case FP_RECOMPUTE_VERTEX_NORMAL : - case FP_FACE_NORMAL_NORMALIZE: - case FP_VERTEX_NORMAL_NORMALIZE: - case FP_DIRECTIONAL_PRESERVATION: - case FP_LINEAR_MORPH : - case FP_HC_LAPLACIAN_SMOOTH: - case FP_SD_LAPLACIAN_SMOOTH: - case FP_TAUBIN_SMOOTH: - case FP_DEPTH_SMOOTH: - case FP_LAPLACIAN_SMOOTH: - case FP_UNSHARP_GEOMETRY: - case FP_UNSHARP_QUALITY: - case FP_VERTEX_QUALITY_SMOOTHING: - case FP_SCALAR_HARMONIC_FIELD: - case FP_UNSHARP_VERTEX_COLOR: return MeshModel::MM_NONE; - default: assert(0); - } - return MeshModel::MM_NONE; + switch (ID(a)) { + case FP_SD_LAPLACIAN_SMOOTH: + case FP_HC_LAPLACIAN_SMOOTH: + case FP_LAPLACIAN_SMOOTH: + case FP_TWO_STEP_SMOOTH: + case FP_TAUBIN_SMOOTH: + case FP_DEPTH_SMOOTH: + case FP_LINEAR_MORPH: + case FP_UNSHARP_NORMAL: + case FP_UNSHARP_GEOMETRY: + return MeshModel::MM_VERTCOORD | MeshModel::MM_VERTNORMAL | MeshModel::MM_FACENORMAL; + //case FP_DIRECTIONAL_PRESERVATION_STORE: + case FP_DIRECTIONAL_PRESERVATION_BLEND: + case FP_VERTEX_QUALITY_SMOOTHING: + case FP_UNSHARP_QUALITY: + case FP_CREASE_CUT: return MeshModel::MM_ALL; + case FP_FACE_NORMAL_SMOOTHING: + case FP_RECOMPUTE_FACE_NORMAL: + case FP_RECOMPUTE_QUADFACE_NORMAL: + case FP_FACE_NORMAL_NORMALIZE: return MeshModel::MM_FACENORMAL; + case FP_RECOMPUTE_VERTEX_NORMAL: + case FP_VERTEX_NORMAL_NORMALIZE: return MeshModel::MM_VERTNORMAL; + case FP_UNSHARP_VERTEX_COLOR: return MeshModel::MM_VERTCOLOR; + case FP_SCALAR_HARMONIC_FIELD: return MeshModel::MM_VERTQUALITY; + default: assert(0); return MeshModel::MM_ALL; + } } -RichParameterList FilterUnsharp::initParameterList(const QAction *action, const MeshDocument &md) +int FilterUnsharp::getRequirements(const QAction* action) { - RichParameterList parlst; - switch(ID(action)) - { - case FP_RECOMPUTE_VERTEX_NORMAL : - parlst.addParam(RichEnum("weightMode", 0, QStringList() << "Simple Average" << "By Area" << "By Angle" << "As defined by N. Max", tr("Weighting Mode:"), "")); - break; - case FP_CREASE_CUT : - parlst.addParam(RichFloat("angleDeg", 90.f, tr("Crease Angle (degree)"), tr("If the angle between the normals of two adjacent faces is larger that this threshold the edge is considered a creased and the mesh is cut along it."))); - break; - case FP_UNSHARP_NORMAL: - parlst.addParam(RichBool("recalc", false, tr("Recompute Normals"), tr("Recompute normals from scratch before the unsharp masking"))); - parlst.addParam(RichFloat("weight", 0.3f, tr("Unsharp Weight"), tr("the unsharp weight wu in the unsharp mask equation:
woorig + wu (orig - lowpass)
"))); - parlst.addParam(RichFloat("weightOrig", 1.f, tr("Original Weight"), tr("How much the original signal is used, e.g. the weight wo in the above unsharp mask equation.
Usually you should not need to change the default 1.0 value."))); - parlst.addParam(RichInt("iterations", 5, "Smooth Iterations", tr("number of laplacian face smooth iterations in every run"))); - break; - case FP_UNSHARP_GEOMETRY: - parlst.addParam(RichFloat("weight", 0.3f, tr("Unsharp Weight"), tr("the unsharp weight wu in the unsharp mask equation:
woorig + wu (orig - lowpass)
"))); - parlst.addParam(RichFloat("weightOrig", 1.f, tr("Original Weight"), tr("How much the original signal is used, e.g. the weight wo in the above unsharp mask equation
Usually you should not need to change the default 1.0 value."))); - parlst.addParam(RichInt("iterations", 5, "Smooth Iterations", tr("number of iterations of laplacian smooth in every run"))); - break; - case FP_UNSHARP_VERTEX_COLOR: - parlst.addParam(RichFloat("weight", 0.3f, tr("Unsharp Weight"), tr("the unsharp weight wu in the unsharp mask equation:
woorig + wu (orig - lowpass)
"))); - parlst.addParam(RichFloat("weightOrig", 1.f, tr("Original Color Weight"), tr("How much the original signal is used, e.g. the weight wo in the above unsharp mask equation
Usually you should not need to change the default 1.0 value."))); - parlst.addParam(RichInt("iterations", 5, "Smooth Iterations", tr("number of iterations of laplacian smooth in every run"))); - break; - case FP_UNSHARP_QUALITY: - parlst.addParam(RichFloat("weight", 0.3f, tr("Unsharp Weight"), tr("the unsharp weight wu in the unsharp mask equation:
woorig + wu (orig - lowpass)
"))); - parlst.addParam(RichFloat("weightOrig", 1.f, tr("Original Weight"), tr("How much the original signal is used, e.g. the weight wo in the above unsharp mask equation
Usually you should not need to change the default 1.0 value."))); - parlst.addParam(RichInt("iterations", 5, "Smooth Iterations", tr("number of iterations of laplacian smooth in every run"))); - break; - case FP_TWO_STEP_SMOOTH: - parlst.addParam(RichInt ("stepSmoothNum", (int) 3,"Smoothing steps", "The number of times that the whole algorithm (normal smoothing + vertex fitting) is iterated.")); - parlst.addParam(RichFloat("normalThr", (float) 60,"Feature Angle Threshold (deg)", "Specify a threshold angle (0..90) for features that you want to be preserved.
Features forming angles LARGER than the specified threshold will be preserved.
0 -> no smoothing
90 -> all faces will be smoothed")); - parlst.addParam(RichInt ("stepNormalNum", (int) 20,"Normal Smoothing steps", "Number of iterations of normal smoothing step. The larger the better and (the slower)")); - parlst.addParam(RichInt ("stepFitNum", (int) 20,"Vertex Fitting steps", "Number of iterations of the vertex fitting procedure.")); - parlst.addParam(RichBool ("Selected",md.mm()->cm.sfn>0,"Affect only selected faces","If checked the filter is performed only on the selected faces")); - break; - case FP_LAPLACIAN_SMOOTH: - parlst.addParam(RichInt ("stepSmoothNum", (int) 3,"Smoothing steps", "The number of times that the whole algorithm (normal smoothing + vertex fitting) is iterated.")); - parlst.addParam(RichBool ("Boundary",true,"1D Boundary Smoothing", "Smooth boundary edges only by themselves (e.g. the polyline forming the boundary of the mesh is independently smoothed). This can reduce the shrinking on the border but can have strange effects on very small boundaries.")); - parlst.addParam(RichBool ("cotangentWeight",true,"Cotangent weighting", "Use cotangent weighting scheme for the averaging of the position. Otherwise the simpler umbrella scheme (1 if the edge is present) is used.")); - parlst.addParam(RichBool("Selected", md.mm()->cm.sfn>0, "Affect only selection", "If checked the filter is performed only on the selected area")); - break; - case FP_DEPTH_SMOOTH: - parlst.addParam(RichInt ("stepSmoothNum", (int) 3,"Smoothing steps", "The number of times that the whole algorithm (normal smoothing + vertex fitting) is iterated.")); - parlst.addParam(RichDirection ("viewPoint", Point3f(0,0,0),"Viewpoint", "The position of the view point that is used to get the constraint direction.")); - parlst.addParam(RichAbsPerc ("delta", 1.0, 0, 1.0, "Strength", "How much smoothing is applied: 0 (no smooth) e 1 (full smooth)")); - parlst.addParam(RichBool ("Selected",md.mm()->cm.sfn>0,"Affect only selection","If checked the filter is performed only on the selected area")); - break; - case FP_DIRECTIONAL_PRESERVATION: - parlst.addParam(RichEnum("step", 0, - QStringList() << "Store Vertex Position" << "Blend Vertex Position", - tr("Step:"), - tr("The purpose of this filter is to constrain any smoothing algorithm to moving vertices only along a give line of sight.
First you should store current vertex position, than after applying one of the many smoothing algorithms you should re start this filter and blend the original positions with the smoothed results.
" - "Given a view point vp , the smoothed vertex position vs and the original position v, The new vertex position is computed as the projection of vs on the line connecting v and vp."))); - parlst.addParam(RichDirection ("viewPoint", Point3f(0,0,0),"Viewpoint", "The position of the view point that is used to get the constraint direction.")); - parlst.addParam(RichBool ("Selected",md.mm()->cm.sfn>0,"Affect only selected faces","If checked the filter is performed only on the selected faces")); - break; - case FP_TAUBIN_SMOOTH: - parlst.addParam(RichFloat("lambda", (float) 0.5,"Lambda", "The lambda parameter of the Taubin Smoothing algorithm")); - parlst.addParam(RichFloat("mu", (float) -0.53,"mu", "The mu parameter of the Taubin Smoothing algorithm")); - parlst.addParam(RichInt ("stepSmoothNum", (int) 10,"Smoothing steps", "The number of times that the taubin smoothing is iterated. Usually it requires a larger number of iteration than the classical laplacian")); - parlst.addParam(RichBool ("Selected",md.mm()->cm.sfn>0,"Affect only selected faces","If checked the filter is performed only on the selected faces")); - break; - case FP_SD_LAPLACIAN_SMOOTH: - { - parlst.addParam(RichInt ("stepSmoothNum", (int) 3,"Smoothing steps", "The number of times that the whole algorithm (normal smoothing + vertex fitting) is iterated.")); - float maxVal = md.mm()->cm.bbox.Diag()/10; - parlst.addParam(RichAbsPerc("delta",maxVal*0.01,0,maxVal,"delta", "")); - parlst.addParam(RichBool ("Selected",md.mm()->cm.sfn>0,"Affect only selected faces","If checked the filter is performed only on the selected faces")); - } - break; - case FP_LINEAR_MORPH : - { - parlst.addParam(RichMesh ("TargetMesh", md.mm()->id(), &md,"Target Mesh", "The mesh that is the morph target.")); - parlst.addParam(RichDynamicFloat("PercentMorph", 0.0, -150, 250, - "% Morph", tr("The percent you want to morph towards (or away from) the target.
" - "0 means current mesh
" - "100 means targe mesh
" - "<0 and >100 linearly extrapolate between the two mesh
"))); - } - break; - case FP_SCALAR_HARMONIC_FIELD: - parlst.addParam(RichPosition("point1", md.mm()->cm.bbox.min, "Point 1", "A vertex on the mesh that represent one harmonic field boundary condition.")); - parlst.addParam(RichPosition("point2", md.mm()->cm.bbox.max, "Point 2", "A vertex on the mesh that represent one harmonic field boundary condition.")); - parlst.addParam(RichDynamicFloat("value1", 0.0f, 0.0f, 1.0f, "value for the 1st point", "Harmonic field value for the vertex.")); - parlst.addParam(RichDynamicFloat("value2", 1.0f, 0.0f, 1.0f, "value for the 2nd point", "Harmonic field value for the vertex.")); - parlst.addParam(RichBool("colorize", true, "Colorize", "Colorize the mesh to provide an indication of the obtained harmonic field.")); + switch (ID(action)) { + case FP_TWO_STEP_SMOOTH: return MeshModel::MM_VERTFACETOPO; + + case FP_CREASE_CUT: + case FP_UNSHARP_NORMAL: + case FP_RECOMPUTE_QUADFACE_NORMAL: + case FP_FACE_NORMAL_SMOOTHING: return MeshModel::MM_FACEFACETOPO; + + case FP_RECOMPUTE_FACE_NORMAL: + case FP_RECOMPUTE_VERTEX_NORMAL: + case FP_FACE_NORMAL_NORMALIZE: + case FP_VERTEX_NORMAL_NORMALIZE: + //case FP_DIRECTIONAL_PRESERVATION_STORE: + case FP_DIRECTIONAL_PRESERVATION_BLEND: + case FP_LINEAR_MORPH: + case FP_HC_LAPLACIAN_SMOOTH: + case FP_SD_LAPLACIAN_SMOOTH: + case FP_TAUBIN_SMOOTH: + case FP_DEPTH_SMOOTH: + case FP_LAPLACIAN_SMOOTH: + case FP_UNSHARP_GEOMETRY: + case FP_UNSHARP_QUALITY: + case FP_VERTEX_QUALITY_SMOOTHING: + case FP_SCALAR_HARMONIC_FIELD: + case FP_UNSHARP_VERTEX_COLOR: return MeshModel::MM_NONE; + default: assert(0); + } + return MeshModel::MM_NONE; +} + +RichParameterList FilterUnsharp::initParameterList(const QAction* action, const MeshDocument& md) +{ + RichParameterList parlst; + switch (ID(action)) { + case FP_RECOMPUTE_VERTEX_NORMAL: + parlst.addParam(RichEnum( + "weightMode", + 0, + QStringList() << "Simple Average" + << "By Area" + << "By Angle" + << "As defined by N. Max", + tr("Weighting Mode:"), + "")); break; - } - return parlst; + case FP_CREASE_CUT: + parlst.addParam(RichFloat( + "angleDeg", + 90.f, + tr("Crease Angle (degree)"), + tr("If the angle between the normals of two adjacent faces is larger that this " + "threshold the edge is considered a creased and the mesh is cut along it."))); + break; + case FP_UNSHARP_NORMAL: + parlst.addParam(RichBool( + "recalc", + false, + tr("Recompute Normals"), + tr("Recompute normals from scratch before the unsharp masking"))); + parlst.addParam(RichFloat( + "weight", + 0.3f, + tr("Unsharp Weight"), + tr("the unsharp weight wu in the unsharp mask equation: " + "
woorig + wu (orig - " + "lowpass)
"))); + parlst.addParam(RichFloat( + "weightOrig", + 1.f, + tr("Original Weight"), + tr("How much the original signal is used, e.g. the weight " + "wo in the above unsharp mask equation.
Usually " + "you should not need to change the default 1.0 value."))); + parlst.addParam(RichInt( + "iterations", + 5, + "Smooth Iterations", + tr("number of laplacian face smooth iterations in every run"))); + break; + case FP_UNSHARP_GEOMETRY: + parlst.addParam(RichFloat( + "weight", + 0.3f, + tr("Unsharp Weight"), + tr("the unsharp weight wu in the unsharp mask equation: " + "
woorig + wu (orig - " + "lowpass)
"))); + parlst.addParam(RichFloat( + "weightOrig", + 1.f, + tr("Original Weight"), + tr("How much the original signal is used, e.g. the weight " + "wo in the above unsharp mask equation
Usually you " + "should not need to change the default 1.0 value."))); + parlst.addParam(RichInt( + "iterations", + 5, + "Smooth Iterations", + tr("number of iterations of laplacian smooth in every run"))); + break; + case FP_UNSHARP_VERTEX_COLOR: + parlst.addParam(RichFloat( + "weight", + 0.3f, + tr("Unsharp Weight"), + tr("the unsharp weight wu in the unsharp mask equation: " + "
woorig + wu (orig - " + "lowpass)
"))); + parlst.addParam(RichFloat( + "weightOrig", + 1.f, + tr("Original Color Weight"), + tr("How much the original signal is used, e.g. the weight " + "wo in the above unsharp mask equation
Usually you " + "should not need to change the default 1.0 value."))); + parlst.addParam(RichInt( + "iterations", + 5, + "Smooth Iterations", + tr("number of iterations of laplacian smooth in every run"))); + break; + case FP_UNSHARP_QUALITY: + parlst.addParam(RichFloat( + "weight", + 0.3f, + tr("Unsharp Weight"), + tr("the unsharp weight wu in the unsharp mask equation: " + "
woorig + wu (orig - " + "lowpass)
"))); + parlst.addParam(RichFloat( + "weightOrig", + 1.f, + tr("Original Weight"), + tr("How much the original signal is used, e.g. the weight " + "wo in the above unsharp mask equation
Usually you " + "should not need to change the default 1.0 value."))); + parlst.addParam(RichInt( + "iterations", + 5, + "Smooth Iterations", + tr("number of iterations of laplacian smooth in every run"))); + break; + case FP_TWO_STEP_SMOOTH: + parlst.addParam(RichInt( + "stepSmoothNum", + (int) 3, + "Smoothing steps", + "The number of times that the whole algorithm (normal smoothing + vertex fitting) is " + "iterated.")); + parlst.addParam(RichFloat( + "normalThr", + (float) 60, + "Feature Angle Threshold (deg)", + "Specify a threshold angle (0..90) for features that you want to be " + "preserved.
Features forming angles LARGER than the specified threshold will be " + "preserved.
0 -> no smoothing
90 -> all faces will be smoothed")); + parlst.addParam(RichInt( + "stepNormalNum", + (int) 20, + "Normal Smoothing steps", + "Number of iterations of normal smoothing step. The larger the better and (the " + "slower)")); + parlst.addParam(RichInt( + "stepFitNum", + (int) 20, + "Vertex Fitting steps", + "Number of iterations of the vertex fitting procedure.")); + parlst.addParam(RichBool( + "Selected", + md.mm()->cm.sfn > 0, + "Affect only selected faces", + "If checked the filter is performed only on the selected faces")); + break; + case FP_LAPLACIAN_SMOOTH: + parlst.addParam(RichInt( + "stepSmoothNum", + (int) 3, + "Smoothing steps", + "The number of times that the whole algorithm (normal smoothing + vertex fitting) is " + "iterated.")); + parlst.addParam(RichBool( + "Boundary", + true, + "1D Boundary Smoothing", + "Smooth boundary edges only by themselves (e.g. the polyline forming the boundary of " + "the mesh is independently smoothed). This can reduce the shrinking on the border but " + "can have strange effects on very small boundaries.")); + parlst.addParam(RichBool( + "cotangentWeight", + true, + "Cotangent weighting", + "Use cotangent weighting scheme for the averaging of the position. Otherwise the " + "simpler umbrella scheme (1 if the edge is present) is used.")); + parlst.addParam(RichBool( + "Selected", + md.mm()->cm.sfn > 0, + "Affect only selection", + "If checked the filter is performed only on the selected area")); + break; + case FP_DEPTH_SMOOTH: + parlst.addParam(RichInt( + "stepSmoothNum", + (int) 3, + "Smoothing steps", + "The number of times that the whole algorithm (normal smoothing + vertex fitting) is " + "iterated.")); + parlst.addParam(RichDirection( + "viewPoint", + Point3f(0, 0, 0), + "Viewpoint", + "The position of the view point that is used to get the constraint direction.")); + parlst.addParam(RichAbsPerc( + "delta", + 1.0, + 0, + 1.0, + "Strength", + "How much smoothing is applied: 0 (no smooth) e 1 (full smooth)")); + parlst.addParam(RichBool( + "Selected", + md.mm()->cm.sfn > 0, + "Affect only selection", + "If checked the filter is performed only on the selected area")); + break; + //case FP_DIRECTIONAL_PRESERVATION_STORE: + //parlst.addParam(RichEnum( + // "step", + // 0, + // QStringList() << "Store Vertex Position" + // << "Blend Vertex Position", + // tr("Step:"), + // tr("The purpose of this filter is to constrain any smoothing algorithm to " + // "moving vertices only along a give line of sight.
First you should store " + // "current vertex position, than after applying one of the many smoothing algorithms " + // "you should re start this filter and blend the original positions with the smoothed " + // "results.
" + // "Given a view point vp , the smoothed vertex position vs and the " + // "original position v, The new vertex position is computed as the projection " + // "of vs on the line connecting v and vp."))); + //break; + case FP_DIRECTIONAL_PRESERVATION_BLEND: { + QString s; + if (md.mm()->cm.vert_attr.size() != 0) // get the first per vertex custom attribute name + s = QString::fromStdString((*md.mm()->cm.vert_attr.begin())._name); + parlst.addParam(RichString( + "attr_name", + s, + "Custom attribute name", + "The name of the per vertex custom point attribute that contains the previous " + "geometry.")); + parlst.addParam(RichDirection( + "viewPoint", + Point3f(0, 0, 0), + "Viewpoint", + "The position of the view point that is used to get the constraint direction.")); + } + break; + case FP_TAUBIN_SMOOTH: + parlst.addParam(RichFloat( + "lambda", + (float) 0.5, + "Lambda", + "The lambda parameter of the Taubin Smoothing algorithm")); + parlst.addParam(RichFloat( + "mu", (float) -0.53, "mu", "The mu parameter of the Taubin Smoothing algorithm")); + parlst.addParam(RichInt( + "stepSmoothNum", + (int) 10, + "Smoothing steps", + "The number of times that the taubin smoothing is iterated. Usually it requires a " + "larger number of iteration than the classical laplacian")); + parlst.addParam(RichBool( + "Selected", + md.mm()->cm.sfn > 0, + "Affect only selected faces", + "If checked the filter is performed only on the selected faces")); + break; + case FP_SD_LAPLACIAN_SMOOTH: { + parlst.addParam(RichInt( + "stepSmoothNum", + (int) 3, + "Smoothing steps", + "The number of times that the whole algorithm (normal smoothing + vertex fitting) is " + "iterated.")); + float maxVal = md.mm()->cm.bbox.Diag() / 10; + parlst.addParam(RichAbsPerc("delta", maxVal * 0.01, 0, maxVal, "delta", "")); + parlst.addParam(RichBool( + "Selected", + md.mm()->cm.sfn > 0, + "Affect only selected faces", + "If checked the filter is performed only on the selected faces")); + } break; + case FP_LINEAR_MORPH: { + parlst.addParam(RichMesh( + "TargetMesh", md.mm()->id(), &md, "Target Mesh", "The mesh that is the morph target.")); + parlst.addParam(RichDynamicFloat( + "PercentMorph", + 0.0, + -150, + 250, + "% Morph", + tr("The percent you want to morph towards (or away from) the target.
" + "0 means current mesh
" + "100 means targe mesh
" + "<0 and >100 linearly extrapolate between the two mesh
"))); + } break; + case FP_SCALAR_HARMONIC_FIELD: + parlst.addParam(RichPosition( + "point1", + md.mm()->cm.bbox.min, + "Point 1", + "A vertex on the mesh that represent one harmonic field boundary condition.")); + parlst.addParam(RichPosition( + "point2", + md.mm()->cm.bbox.max, + "Point 2", + "A vertex on the mesh that represent one harmonic field boundary condition.")); + parlst.addParam(RichDynamicFloat( + "value1", + 0.0f, + 0.0f, + 1.0f, + "value for the 1st point", + "Harmonic field value for the vertex.")); + parlst.addParam(RichDynamicFloat( + "value2", + 1.0f, + 0.0f, + 1.0f, + "value for the 2nd point", + "Harmonic field value for the vertex.")); + parlst.addParam(RichBool( + "colorize", + true, + "Colorize", + "Colorize the mesh to provide an indication of the obtained harmonic field.")); + break; + } + return parlst; } std::map FilterUnsharp::applyFilter( - const QAction *filter, - const RichParameterList & par, - MeshDocument &md, - unsigned int& /*postConditionMask*/, - vcg::CallBackPos * cb) + const QAction* filter, + const RichParameterList& par, + MeshDocument& md, + unsigned int& /*postConditionMask*/, + vcg::CallBackPos* cb) { - MeshModel &m=*(md.mm()); - switch(ID(filter)) - { - case FP_CREASE_CUT :{ - if ( tri::Clean::CountNonManifoldEdgeFF(m.cm,false) > 0 || tri::Clean::CountNonManifoldVertexFF(m.cm,false) > 0) - { - throw MLException("Mesh has some not 2 manifold faces, this filter require manifoldness"); + MeshModel& m = *(md.mm()); + switch (ID(filter)) { + case FP_CREASE_CUT: { + if (tri::Clean::CountNonManifoldEdgeFF(m.cm, false) > 0 || + tri::Clean::CountNonManifoldVertexFF(m.cm, false) > 0) { + throw MLException( + "Mesh has some not 2 manifold faces, this filter require manifoldness"); } Scalarm angleDeg = par.getFloat("angleDeg"); tri::CreaseCut(m.cm, math::ToRad(angleDeg)); m.clearDataMask(MeshModel::MM_FACEFACETOPO); - } - break; + } break; - case FP_FACE_NORMAL_SMOOTHING : + case FP_FACE_NORMAL_SMOOTHING: tri::UpdateFlags::FaceBorderFromNone(m.cm); tri::Smooth::FaceNormalLaplacianFF(m.cm); break; - case FP_VERTEX_QUALITY_SMOOTHING : + case FP_VERTEX_QUALITY_SMOOTHING: tri::UpdateFlags::FaceBorderFromNone(m.cm); tri::Smooth::VertexQualityLaplacian(m.cm); break; - case FP_LAPLACIAN_SMOOTH : - { + case FP_LAPLACIAN_SMOOTH: { tri::UpdateFlags::FaceBorderFromNone(m.cm); - int stepSmoothNum = par.getInt("stepSmoothNum"); - bool Selected=par.getBool("Selected"); - if(Selected && m.cm.svn==0) - m.cm.svn=tri::UpdateSelection::VertexFromFaceStrict(m.cm); - - bool boundarySmooth = par.getBool("Boundary"); - bool cotangentWeight = par.getBool("cotangentWeight"); - if(!boundarySmooth) tri::UpdateFlags::FaceClearB(m.cm); - - tri::Smooth::VertexCoordLaplacian(m.cm,stepSmoothNum,Selected,cotangentWeight,cb); - log( "Smoothed %d vertices", Selected ? m.cm.svn : m.cm.vn); - m.updateBoxAndNormals(); - } - break; - case FP_DEPTH_SMOOTH : - { - int stepSmoothNum = par.getInt("stepSmoothNum"); - bool Selected = par.getBool("Selected"); + int stepSmoothNum = par.getInt("stepSmoothNum"); + bool Selected = par.getBool("Selected"); if (Selected && m.cm.svn == 0) m.cm.svn = tri::UpdateSelection::VertexFromFaceStrict(m.cm); - Scalarm delta = par.getAbsPerc("delta"); + + bool boundarySmooth = par.getBool("Boundary"); + bool cotangentWeight = par.getBool("cotangentWeight"); + if (!boundarySmooth) + tri::UpdateFlags::FaceClearB(m.cm); + + tri::Smooth::VertexCoordLaplacian( + m.cm, stepSmoothNum, Selected, cotangentWeight, cb); + log("Smoothed %d vertices", Selected ? m.cm.svn : m.cm.vn); + m.updateBoxAndNormals(); + } break; + case FP_DEPTH_SMOOTH: { + int stepSmoothNum = par.getInt("stepSmoothNum"); + bool Selected = par.getBool("Selected"); + if (Selected && m.cm.svn == 0) + m.cm.svn = tri::UpdateSelection::VertexFromFaceStrict(m.cm); + Scalarm delta = par.getAbsPerc("delta"); Point3m viewpoint = par.getPoint3m("viewPoint"); - tri::Smooth::VertexCoordViewDepth(m.cm, viewpoint, delta, stepSmoothNum, Selected,true); + tri::Smooth::VertexCoordViewDepth( + m.cm, viewpoint, delta, stepSmoothNum, Selected, true); log("depth Smoothed %d vertices", Selected ? m.cm.svn : m.cm.vn); m.updateBoxAndNormals(); - } - break; - case FP_DIRECTIONAL_PRESERVATION: - { - const std::string AttribName("SavedVertPosition"); - int stepNum = par.getEnum("step"); - Point3m viewpoint = par.getPoint3m("viewPoint"); - float alpha = 1; + } break; +// case FP_DIRECTIONAL_PRESERVATION_STORE: { +// const std::string AttribName("SavedVertPosition"); +// if (tri::HasPerVertexAttribute(m.cm, AttribName)) { +// vcg::tri::Allocator::DeletePerVertexAttribute(m.cm, AttribName); +// } +// CMeshO::PerVertexAttributeHandle h = +// tri::Allocator::AddPerVertexAttribute(m.cm, AttribName); +// CMeshO::VertexIterator vi; - switch (stepNum) { - case 0: { // ***** Storing Vertex Data ***** - if(tri::HasPerVertexAttribute(m.cm,AttribName)) { - vcg::tri::Allocator::DeletePerVertexAttribute(m.cm,AttribName); - } - CMeshO::PerVertexAttributeHandle h = tri::Allocator::AddPerVertexAttribute (m.cm,AttribName); - CMeshO::VertexIterator vi; +// for (vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) +// h[vi] = vi->cP(); - for(vi =m.cm.vert.begin();vi!= m.cm.vert.end();++vi) - h[vi] = vi->cP(); - - log( "Stored Position %d vertices", m.cm.vn); - break; +// log("Stored Position %d vertices", m.cm.vn); +// break; +// } + case FP_DIRECTIONAL_PRESERVATION_BLEND: { + const std::string attribName = par.getString("attr_name").toStdString(); + Point3m viewpoint = par.getPoint3m("viewPoint"); + float alpha = 1; + if (!tri::HasPerVertexAttribute(m.cm, attribName)) { + throw MLException( + "Failed to retrieve the stored vertex position. Current mesh has not a per vertex " + "custom point attribute called \"" + QString::fromStdString(attribName) + "\"
" + "You can create it by running the filter \"Define new per vertex custom point " + "attribute.\""); + } + CMeshO::PerVertexAttributeHandle h = + tri::Allocator::GetPerVertexAttribute(m.cm, attribName); + if (!vcg::tri::Allocator::IsValidHandle(m.cm, h)) { + throw MLException( + "Failed to retrieve the stored vertex position. Current mesh has not a per vertex " + "custom point attribute called \"" + QString::fromStdString(attribName) + "\"
" + "You can create it by running the filter \"Define new per vertex custom point " + "attribute.\""); } - case 1: { // ***** Recovering and Projection Vertex Data ***** - if(!tri::HasPerVertexAttribute(m.cm,AttribName)) { - throw MLException("Failed to retrieve the stored vertex position. First Store than recover."); - } - CMeshO::PerVertexAttributeHandle h = tri::Allocator::GetPerVertexAttribute (m.cm,AttribName); - CMeshO::VertexIterator vi; - for(vi= m.cm.vert.begin();vi!= m.cm.vert.end();++vi) { - Point3m d = h[vi] - viewpoint; - d.Normalize(); - Scalarm s = d * ( (*vi).cP() - h[vi] ); - (*vi).P() = h[vi] + d * (s*alpha); - } - m.updateBoxAndNormals(); - log("Projected smoothed Position %d vertices", m.cm.vn); - break; - } + CMeshO::VertexIterator vi; + for (vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) { + Point3m d = h[vi] - viewpoint; + d.Normalize(); + Scalarm s = d * ((*vi).cP() - h[vi]); + (*vi).P() = h[vi] + d * (s * alpha); } + m.updateBoxAndNormals(); + log("Projected smoothed Position %d vertices", m.cm.vn); break; } - case FP_SD_LAPLACIAN_SMOOTH: - { + case FP_SD_LAPLACIAN_SMOOTH: { tri::UpdateFlags::FaceBorderFromNone(m.cm); - int stepSmoothNum = par.getInt("stepSmoothNum"); - size_t cnt=tri::UpdateSelection::VertexFromFaceStrict(m.cm); + int stepSmoothNum = par.getInt("stepSmoothNum"); + size_t cnt = tri::UpdateSelection::VertexFromFaceStrict(m.cm); // Small hack tri::UpdateFlags::FaceClearB(m.cm); Scalarm delta = par.getAbsPerc("delta"); - tri::Smooth::VertexCoordScaleDependentLaplacian_Fujiwara(m.cm,stepSmoothNum,delta); - log( "Smoothed %d vertices", cnt>0 ? cnt : m.cm.vn); + tri::Smooth::VertexCoordScaleDependentLaplacian_Fujiwara( + m.cm, stepSmoothNum, delta); + log("Smoothed %d vertices", cnt > 0 ? cnt : m.cm.vn); m.updateBoxAndNormals(); - } - break; - case FP_HC_LAPLACIAN_SMOOTH: - { + } break; + case FP_HC_LAPLACIAN_SMOOTH: { tri::UpdateFlags::FaceBorderFromNone(m.cm); - size_t cnt=tri::UpdateSelection::VertexFromFaceStrict(m.cm); - tri::Smooth::VertexCoordLaplacianHC(m.cm,1,cnt>0); + size_t cnt = tri::UpdateSelection::VertexFromFaceStrict(m.cm); + tri::Smooth::VertexCoordLaplacianHC(m.cm, 1, cnt > 0); m.updateBoxAndNormals(); - } - break; - case FP_TWO_STEP_SMOOTH: - { + } break; + case FP_TWO_STEP_SMOOTH: { tri::Clean::RemoveUnreferencedVertex(m.cm); tri::UpdateSelection::VertexFromFaceStrict(m.cm); int stepSmoothNum = par.getInt("stepSmoothNum"); // sigma==0 all is smoothed // sigma==1 nothing is smoothed - Scalarm sigma = cos(math::ToRad(par.getFloat("normalThr"))); - if(sigma<0) sigma=0; + Scalarm sigma = cos(math::ToRad(par.getFloat("normalThr"))); + if (sigma < 0) + sigma = 0; - int stepNormalNum = par.getInt("stepNormalNum"); - int stepFitNum = par.getInt("stepFitNum"); - bool selectedFlag = par.getBool("Selected"); - for(int i=0;i::PerFaceNormalized(m.cm); - tri::Smooth::VertexCoordPasoDoble(m.cm, stepNormalNum, sigma, stepFitNum,selectedFlag); + tri::Smooth::VertexCoordPasoDoble( + m.cm, stepNormalNum, sigma, stepFitNum, selectedFlag); } m.updateBoxAndNormals(); - } - break; - case FP_TAUBIN_SMOOTH : - { + } break; + case FP_TAUBIN_SMOOTH: { tri::UpdateFlags::FaceBorderFromNone(m.cm); - int stepSmoothNum = par.getInt("stepSmoothNum"); - Scalarm lambda=par.getFloat("lambda"); - Scalarm mu=par.getFloat("mu"); + int stepSmoothNum = par.getInt("stepSmoothNum"); + Scalarm lambda = par.getFloat("lambda"); + Scalarm mu = par.getFloat("mu"); - size_t cnt=tri::UpdateSelection::VertexFromFaceStrict(m.cm); - tri::Smooth::VertexCoordTaubin(m.cm,stepSmoothNum,lambda,mu,cnt>0,cb); - log( "Smoothed %d vertices", cnt>0 ? cnt : m.cm.vn); + size_t cnt = tri::UpdateSelection::VertexFromFaceStrict(m.cm); + tri::Smooth::VertexCoordTaubin(m.cm, stepSmoothNum, lambda, mu, cnt > 0, cb); + log("Smoothed %d vertices", cnt > 0 ? cnt : m.cm.vn); m.updateBoxAndNormals(); - } - break; - case FP_RECOMPUTE_FACE_NORMAL : - tri::UpdateNormal::PerFace(m.cm); - break; - case FP_RECOMPUTE_QUADFACE_NORMAL : + } break; + case FP_RECOMPUTE_FACE_NORMAL: tri::UpdateNormal::PerFace(m.cm); break; + case FP_RECOMPUTE_QUADFACE_NORMAL: // tri::UpdateNormal::PerBitQuadFaceNormalized(m.cm); tri::UpdateNormal::PerBitPolygonFaceNormalized(m.cm); break; - case FP_RECOMPUTE_VERTEX_NORMAL : - { + case FP_RECOMPUTE_VERTEX_NORMAL: { /** ToDo: This filter should NEVER modify per face normals... **/ int weightMode = par.getEnum("weightMode"); - switch(weightMode) - { + switch (weightMode) { case WMP_AVG: tri::UpdateNormal::NormalizePerFace(m.cm); tri::UpdateNormal::PerVertexFromCurrentFaceNormal(m.cm); @@ -595,226 +888,214 @@ std::map FilterUnsharp::applyFilter( tri::UpdateNormal::PerVertexNelsonMaxWeighted(m.cm); tri::UpdateNormal::NormalizePerVertex(m.cm); break; - default : - break; + default: break; } - } - break; - case FP_FACE_NORMAL_NORMALIZE : - tri::UpdateNormal::NormalizePerFace(m.cm); - break; - case FP_VERTEX_NORMAL_NORMALIZE : - tri::UpdateNormal::NormalizePerVertex(m.cm); - break; + } break; + case FP_FACE_NORMAL_NORMALIZE: tri::UpdateNormal::NormalizePerFace(m.cm); break; + case FP_VERTEX_NORMAL_NORMALIZE: tri::UpdateNormal::NormalizePerVertex(m.cm); break; - case FP_UNSHARP_NORMAL: - { + case FP_UNSHARP_NORMAL: { tri::UpdateFlags::FaceBorderFromNone(m.cm); - Scalarm alpha=par.getFloat("weight"); - Scalarm alphaorig=par.getFloat("weightOrig"); - int smoothIter = par.getInt("iterations"); + Scalarm alpha = par.getFloat("weight"); + Scalarm alphaorig = par.getFloat("weightOrig"); + int smoothIter = par.getInt("iterations"); tri::Allocator::CompactFaceVector(m.cm); vector normalOrig(m.cm.fn); - //Save original normal per face - for(int i=0;i::FaceNormalLaplacianFF(m.cm); - //Unsharp filter normal per face - for(int i=0;i::FaceBorderFromNone(m.cm); tri::UpdateFlags::FaceBorderFromNone(m.cm); - Scalarm alpha=par.getFloat("weight"); - Scalarm alphaorig=par.getFloat("weightOrig"); - int smoothIter = par.getInt("iterations"); + Scalarm alpha = par.getFloat("weight"); + Scalarm alphaorig = par.getFloat("weightOrig"); + int smoothIter = par.getInt("iterations"); tri::Allocator::CompactVertexVector(m.cm); vector geomOrig(m.cm.vn); - for(int i=0;i::VertexCoordLaplacian(m.cm,smoothIter); + tri::Smooth::VertexCoordLaplacian(m.cm, smoothIter); - for(int i=0;i::FaceBorderFromNone(m.cm); - Scalarm alpha=par.getFloat("weight"); - Scalarm alphaorig=par.getFloat("weightOrig"); - int smoothIter = par.getInt("iterations"); + Scalarm alpha = par.getFloat("weight"); + Scalarm alphaorig = par.getFloat("weightOrig"); + int smoothIter = par.getInt("iterations"); tri::Allocator::CompactVertexVector(m.cm); vector colorOrig(m.cm.vn); - for(int i=0;i::VertexColorLaplacian(m.cm,smoothIter); - for(int i=0;i::VertexColorLaplacian(m.cm, smoothIter); + for (int i = 0; i < m.cm.vn; ++i) { Color4f colorDelta = colorOrig[i] - Color4f::Construct(m.cm.vert[i].C()); - Color4f newCol = colorOrig[i]*alphaorig + colorDelta*alpha; // Unsharp formula + Color4f newCol = colorOrig[i] * alphaorig + colorDelta * alpha; // Unsharp formula Clamp(newCol); // Clamp everything in the 0..1 range m.cm.vert[i].C().Import(newCol); - } - } break; - case FP_UNSHARP_QUALITY: - { + } break; + case FP_UNSHARP_QUALITY: { tri::UpdateFlags::FaceBorderFromNone(m.cm); - Scalarm alpha=par.getFloat("weight"); - Scalarm alphaorig=par.getFloat("weightOrig"); - int smoothIter = par.getInt("iterations"); + Scalarm alpha = par.getFloat("weight"); + Scalarm alphaorig = par.getFloat("weightOrig"); + int smoothIter = par.getInt("iterations"); tri::Allocator::CompactVertexVector(m.cm); vector qualityOrig(m.cm.vn); - for(int i=0;i::VertexQualityLaplacian(m.cm, smoothIter); - for(int i=0;icm; - CMeshO &sourceMesh = m.cm; + case FP_LINEAR_MORPH: { + CMeshO& targetMesh = md.getMesh(par.getMeshId("TargetMesh"))->cm; + CMeshO& sourceMesh = m.cm; - //if the numbers of vertices don't match up - if(sourceMesh.vn != targetMesh.vn) - { - throw MLException("Number of vertices is not the same so you can't morph between these two meshes."); + // if the numbers of vertices don't match up + if (sourceMesh.vn != targetMesh.vn) { + throw MLException( + "Number of vertices is not the same so you can't morph between these two meshes."); } vcg::tri::Allocator::CompactEveryVector(sourceMesh); vcg::tri::Allocator::CompactEveryVector(targetMesh); - Scalarm percentage = par.getDynamicFloat("PercentMorph")/100.f; + Scalarm percentage = par.getDynamicFloat("PercentMorph") / 100.f; int i; - for(i=0;iupdateDataMask(MeshModel::MM_FACEFACETOPO); cb(1, "Computing harmonic field..."); - CMeshO & m = md.mm()->cm; + CMeshO& m = md.mm()->cm; vcg::tri::Allocator::CompactEveryVector(m); if (vcg::tri::Clean::CountConnectedComponents(m) > 1) { - throw MLException("A mesh composed by a single connected component is required by the filter to properly work."); + throw MLException( + "A mesh composed by a single connected component is required by the filter to " + "properly work."); } if (vcg::tri::Clean::CountNonManifoldEdgeFF(md.mm()->cm) > 0) { - throw MLException("Mesh has some not 2-manifold faces, this filter requires manifoldness"); + throw MLException( + "Mesh has some not 2-manifold faces, this filter requires manifoldness"); } - if (vcg::tri::Clean::CountNonManifoldVertexFF(md.mm()->cm) > 0) { - throw MLException("Mesh has some not 2-manifold vertices, this filter requires manifoldness"); + if (vcg::tri::Clean::CountNonManifoldVertexFF(md.mm()->cm) > 0) { + throw MLException( + "Mesh has some not 2-manifold vertices, this filter requires manifoldness"); } - md.mm()->updateDataMask(MeshModel::MM_VERTMARK | MeshModel::MM_FACEMARK | MeshModel::MM_FACEFLAG); + md.mm()->updateDataMask( + MeshModel::MM_VERTMARK | MeshModel::MM_FACEMARK | MeshModel::MM_FACEFLAG); // Get the two vertices with value set vcg::GridStaticPtr vg; vg.Set(m.vert.begin(), m.vert.end()); vcg::vertex::PointDistanceFunctor pd; - vcg::tri::Tmark mv; + vcg::tri::Tmark mv; mv.SetMesh(&m); mv.UnMarkAll(); - Point3m closestP; - Scalarm minDist = 0; - CVertexO * vp0 = vcg::GridClosest(vg, pd, mv, par.getPoint3m("point1"), m.bbox.Diag(), minDist, closestP); - CVertexO * vp1 = vcg::GridClosest(vg, pd, mv, par.getPoint3m("point2"), m.bbox.Diag(), minDist, closestP); - if (vp0 == NULL || vp1 == NULL || vp0 == vp1) - { + Point3m closestP; + Scalarm minDist = 0; + CVertexO* vp0 = vcg::GridClosest( + vg, pd, mv, par.getPoint3m("point1"), m.bbox.Diag(), minDist, closestP); + CVertexO* vp1 = vcg::GridClosest( + vg, pd, mv, par.getPoint3m("point2"), m.bbox.Diag(), minDist, closestP); + if (vp0 == NULL || vp1 == NULL || vp0 == vp1) { throw MLException("Error occurred for selected points."); } vcg::tri::Harmonic::ConstraintVec constraints; - constraints.push_back(vcg::tri::Harmonic::Constraint(vp0, FieldScalar(par.getFloat("value1")))); - constraints.push_back(vcg::tri::Harmonic::Constraint(vp1, FieldScalar(par.getFloat("value2")))); + constraints.push_back(vcg::tri::Harmonic::Constraint( + vp0, FieldScalar(par.getFloat("value1")))); + constraints.push_back(vcg::tri::Harmonic::Constraint( + vp1, FieldScalar(par.getFloat("value2")))); - CMeshO::PerVertexAttributeHandle handle = vcg::tri::Allocator::GetPerVertexAttribute(m, "harmonic"); + CMeshO::PerVertexAttributeHandle handle = + vcg::tri::Allocator::GetPerVertexAttribute(m, "harmonic"); - bool ok = vcg::tri::Harmonic::ComputeScalarField(m, constraints, handle); + bool ok = + vcg::tri::Harmonic::ComputeScalarField(m, constraints, handle); - if (!ok) - { + if (!ok) { throw MLException("An error occurred."); } md.mm()->updateDataMask(MeshModel::MM_VERTQUALITY); for (auto vi = m.vert.begin(); vi != m.vert.end(); ++vi) vi->Q() = handle[vi]; - if (par.getBool("colorize")) - { + if (par.getBool("colorize")) { md.mm()->updateDataMask(MeshModel::MM_VERTCOLOR); vcg::tri::UpdateColor::PerVertexQualityRamp(m); } cb(100, "Done."); } break; - default : - wrongActionCalled(filter); + default: wrongActionCalled(filter); } return std::map(); } -FilterPlugin::FilterArity FilterUnsharp::filterArity(const QAction * filter ) const +FilterPlugin::FilterArity FilterUnsharp::filterArity(const QAction* filter) const { - switch(ID(filter)) - { - case FP_LAPLACIAN_SMOOTH : - case FP_HC_LAPLACIAN_SMOOTH : - case FP_SD_LAPLACIAN_SMOOTH : - case FP_TWO_STEP_SMOOTH : - case FP_TAUBIN_SMOOTH : - case FP_DEPTH_SMOOTH : - case FP_DIRECTIONAL_PRESERVATION : - case FP_CREASE_CUT : - case FP_FACE_NORMAL_NORMALIZE: - case FP_VERTEX_NORMAL_NORMALIZE: - case FP_FACE_NORMAL_SMOOTHING: - case FP_VERTEX_QUALITY_SMOOTHING: - case FP_UNSHARP_NORMAL: - case FP_UNSHARP_GEOMETRY: - case FP_UNSHARP_QUALITY: - case FP_UNSHARP_VERTEX_COLOR: - case FP_RECOMPUTE_VERTEX_NORMAL: - case FP_RECOMPUTE_FACE_NORMAL: - case FP_RECOMPUTE_QUADFACE_NORMAL: - case FP_SCALAR_HARMONIC_FIELD: - return FilterPlugin::SINGLE_MESH; - case FP_LINEAR_MORPH : - return FilterPlugin::FIXED; - } - return FilterPlugin::NONE; + switch (ID(filter)) { + case FP_LAPLACIAN_SMOOTH: + case FP_HC_LAPLACIAN_SMOOTH: + case FP_SD_LAPLACIAN_SMOOTH: + case FP_TWO_STEP_SMOOTH: + case FP_TAUBIN_SMOOTH: + case FP_DEPTH_SMOOTH: + case FP_DIRECTIONAL_PRESERVATION_BLEND: + case FP_CREASE_CUT: + case FP_FACE_NORMAL_NORMALIZE: + case FP_VERTEX_NORMAL_NORMALIZE: + case FP_FACE_NORMAL_SMOOTHING: + case FP_VERTEX_QUALITY_SMOOTHING: + case FP_UNSHARP_NORMAL: + case FP_UNSHARP_GEOMETRY: + case FP_UNSHARP_QUALITY: + case FP_UNSHARP_VERTEX_COLOR: + case FP_RECOMPUTE_VERTEX_NORMAL: + case FP_RECOMPUTE_FACE_NORMAL: + case FP_RECOMPUTE_QUADFACE_NORMAL: + case FP_SCALAR_HARMONIC_FIELD: return FilterPlugin::SINGLE_MESH; + case FP_LINEAR_MORPH: return FilterPlugin::FIXED; + } + return FilterPlugin::NONE; } - MESHLAB_PLUGIN_NAME_EXPORTER(FilterUnsharp) diff --git a/src/meshlabplugins/filter_unsharp/filter_unsharp.h b/src/meshlabplugins/filter_unsharp/filter_unsharp.h index cad9cfc66..99decf0d9 100644 --- a/src/meshlabplugins/filter_unsharp/filter_unsharp.h +++ b/src/meshlabplugins/filter_unsharp/filter_unsharp.h @@ -1,32 +1,31 @@ -/**************************************************************************** -* MeshLab o o * -* A versatile mesh processing toolbox o o * -* _ O _ * -* Copyright(C) 2007 \/)\/ * -* Visual Computing Lab /\/| * -* ISTI - Italian National Research Council | * -* \ * -* All rights reserved. * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * -* for more details. * -* * -****************************************************************************/ -#ifndef FilterUnsharp_PLUGIN_H -#define FilterUnsharp_PLUGIN_H +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2007-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ +#ifndef FILTER_UNSHARP_PLUGIN_H +#define FILTER_UNSHARP_PLUGIN_H #include #include - class FilterUnsharp : public QObject, public FilterPlugin { Q_OBJECT @@ -34,14 +33,11 @@ class FilterUnsharp : public QObject, public FilterPlugin Q_INTERFACES(FilterPlugin) public: - /* naming convention : - - FP -> Filter Plugin - - name of the plugin separated by _ - */ enum { FP_CREASE_CUT, FP_LAPLACIAN_SMOOTH, - FP_DIRECTIONAL_PRESERVATION, + //FP_DIRECTIONAL_PRESERVATION_STORE, + FP_DIRECTIONAL_PRESERVATION_BLEND, FP_DEPTH_SMOOTH, FP_HC_LAPLACIAN_SMOOTH, FP_SD_LAPLACIAN_SMOOTH, @@ -61,29 +57,26 @@ public: FP_RECOMPUTE_QUADFACE_NORMAL, FP_LINEAR_MORPH, FP_SCALAR_HARMONIC_FIELD - } ; - - /* default values for standard parameters' values of the plugin actions */ + }; + FilterUnsharp(); ~FilterUnsharp(); - QString pluginName() const; - QString filterName(ActionIDType filter) const; - QString filterInfo(ActionIDType filter) const; - FilterClass getClass(const QAction*) const; - int getRequirements(const QAction*); + QString pluginName() const; + QString filterName(ActionIDType filter) const; + QString filterInfo(ActionIDType filter) const; + FilterClass getClass(const QAction*) const; + int getRequirements(const QAction*); std::map applyFilter( - const QAction* action, - const RichParameterList & parameters, - MeshDocument &md, - unsigned int& postConditionMask, - vcg::CallBackPos * cb); - RichParameterList initParameterList(const QAction* action, const MeshDocument &/*m*/); - int postCondition(const QAction* ) const; - int getPreConditions(const QAction*) const; - FilterArity filterArity(const QAction* filter) const; - + const QAction* action, + const RichParameterList& parameters, + MeshDocument& md, + unsigned int& postConditionMask, + vcg::CallBackPos* cb); + RichParameterList initParameterList(const QAction* action, const MeshDocument& /*m*/); + int postCondition(const QAction*) const; + int getPreConditions(const QAction*) const; + FilterArity filterArity(const QAction* filter) const; }; - -#endif +#endif // FILTER_UNSHARP_PLUGIN_H