mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-16 01:24:36 +00:00
new optional glContext requirement for FilterPlugins
This commit is contained in:
parent
9171c1f26c
commit
05afd8510d
@ -28,15 +28,16 @@
|
||||
#include "../ml_document/mesh_document.h"
|
||||
|
||||
/**
|
||||
\brief The FilterPluginInterface class provide the interface of the filter plugins.
|
||||
|
||||
*/
|
||||
*\brief The FilterPluginInterface class provide the interface of the filter plugins.
|
||||
*
|
||||
*/
|
||||
class FilterPluginInterface : public PluginInterface
|
||||
{
|
||||
public:
|
||||
/** The FilterClass enum represents the set of keywords that must be used to categorize a filter.
|
||||
Each filter can belong to one or more filtering class, or-ed together.
|
||||
*/
|
||||
/**
|
||||
* @brief The FilterClass enum represents the set of keywords that must be used to categorize a filter.
|
||||
* Each filter can belong to one or more filtering class, or-ed together.
|
||||
*/
|
||||
enum FilterClass
|
||||
{
|
||||
Generic = 0x00000, /*!< Should be avoided if possible. */ //
|
||||
@ -63,111 +64,131 @@ public:
|
||||
|
||||
|
||||
|
||||
FilterPluginInterface() : PluginInterface(), glContext(NULL)
|
||||
FilterPluginInterface() : PluginInterface(), glContext(nullptr)
|
||||
{
|
||||
}
|
||||
virtual ~FilterPluginInterface() {}
|
||||
|
||||
|
||||
/** The very short string (a few words) describing each filtering action
|
||||
// This string is used also to define the menu entry
|
||||
*/
|
||||
/**
|
||||
* @brief The very short string (a few words) describing each filtering action
|
||||
* This string is used also to define the menu entry
|
||||
*/
|
||||
virtual QString filterName(FilterIDType) const = 0;
|
||||
|
||||
/** The long, formatted string describing each filtering action.
|
||||
// This string is printed in the top of the parameter window
|
||||
// so it should be at least one or two paragraphs long. The more the better.
|
||||
// you can use simple html formatting tags (like "<br>" "<b>" and "<i>") to improve readability.
|
||||
// This string is used in the 'About plugin' dialog and by meshlabserver to create the filter list wiki page and the doxygen documentation of the filters.
|
||||
// Here is the place where you should put you bibliographic references in a form like this:
|
||||
<br>
|
||||
See: <br />
|
||||
<i>Luiz Velho, Denis Zorin </i><br/>
|
||||
<b>"4-8 Subdivision"</b><br/>
|
||||
CAGD, volume 18, Issue 5, Pages 397-427.<br/>
|
||||
<br>
|
||||
e.g. italic for authors, bold for title (quoted) and plain for bib ref.
|
||||
*/
|
||||
/**
|
||||
* @brief The long, formatted string describing each filtering action.
|
||||
* This string is printed in the top of the parameter window
|
||||
* so it should be at least one or two paragraphs long. The more the better.
|
||||
* you can use simple html formatting tags (like "<br>" "<b>" and "<i>") to improve readability.
|
||||
* This string is used in the 'About plugin' dialog and by meshlabserver to create the filter list wiki page and the doxygen documentation of the filters.
|
||||
* Here is the place where you should put you bibliographic references in a form like this:
|
||||
* <br>
|
||||
* See: <br />
|
||||
* <i>Luiz Velho, Denis Zorin </i><br/>
|
||||
* <b>"4-8 Subdivision"</b><br/>
|
||||
* CAGD, volume 18, Issue 5, Pages 397-427.<br/>
|
||||
* <br>
|
||||
* e.g. italic for authors, bold for title (quoted) and plain for bib ref.
|
||||
*/
|
||||
virtual QString filterInfo(FilterIDType filter) const = 0;
|
||||
|
||||
/** The FilterClass describes in which generic class of filters it fits.
|
||||
// This choice affect the submenu in which each filter will be placed
|
||||
// For example filters that perform an action only on the selection will be placed in the Selection Class
|
||||
*/
|
||||
/**
|
||||
* @brief The FilterClass describes in which generic class of filters it fits.
|
||||
* This choice affect the submenu in which each filter will be placed
|
||||
* For example filters that perform an action only on the selection will be placed in the Selection Class
|
||||
*/
|
||||
virtual FilterClass getClass(const QAction*) const { return FilterPluginInterface::Generic; }
|
||||
|
||||
/**
|
||||
The filters can have some additional requirements on the mesh capabiliteis.
|
||||
// For example if a filters requires Face-Face Adjacency you should re-implement
|
||||
// this function making it returns MeshModel::MM_FACEFACETOPO.
|
||||
// The framework will ensure that the mesh has the requirements satisfied before invoking the applyFilter function
|
||||
//
|
||||
// Furthermore, requirements are checked just before the invocation of a filter. If your filter
|
||||
// outputs a never used before mesh property (e.g. face colors), it will be allocated by a call
|
||||
// to MeshModel::updateDataMask(...)
|
||||
*/
|
||||
* @brief The filters can have some additional requirements on the mesh capabiliteis.
|
||||
* For example if a filters requires Face-Face Adjacency you should re-implement
|
||||
* this function making it returns MeshModel::MM_FACEFACETOPO.
|
||||
* The framework will ensure that the mesh has the requirements satisfied before invoking the applyFilter function
|
||||
*
|
||||
* Furthermore, requirements are checked just before the invocation of a filter. If your filter
|
||||
* outputs a never used before mesh property (e.g. face colors), it will be allocated by a call
|
||||
* to MeshModel::updateDataMask(...)
|
||||
*/
|
||||
virtual int getRequirements(const QAction*) { return MeshModel::MM_NONE; }
|
||||
|
||||
/**
|
||||
* @brief This function should require true if the glContext is used by the
|
||||
* filter. Without this, the glContext will remain set to nullptr on non-GUI
|
||||
* softwares that will use the filter (E.G. PyMeshLab).
|
||||
* Note: every filter that uses the glContext should first check if
|
||||
* glContext != nullptr.
|
||||
*/
|
||||
virtual bool requiresGLContext(const QAction*) const {return false;}
|
||||
|
||||
/** The FilterPrecondition mask is used to explicitate what kind of data a filter really needs to be applied.
|
||||
// For example algorithms that compute per face quality have as precondition the existence of faces
|
||||
// (but quality per face is not a precondition, because quality per face is created by these algorithms)
|
||||
// on the other hand an algorithm that deletes faces according to the stored quality has both FaceQuality
|
||||
// and Face as precondition.
|
||||
// These conditions do NOT include computed properties like borderFlags, manifoldness or watertightness.
|
||||
// They are also used to grayout menus un-appliable entries.
|
||||
*/
|
||||
/**
|
||||
* @brief The FilterPrecondition mask is used to explicitate what kind of data a filter really needs to be applied.
|
||||
* For example algorithms that compute per face quality have as precondition the existence of faces
|
||||
* (but quality per face is not a precondition, because quality per face is created by these algorithms)
|
||||
* on the other hand an algorithm that deletes faces according to the stored quality has both FaceQuality
|
||||
* and Face as precondition.
|
||||
* These conditions do NOT include computed properties like borderFlags, manifoldness or watertightness.
|
||||
* They are also used to grayout menus un-appliable entries.
|
||||
*/
|
||||
virtual int getPreConditions(const QAction*) const { return MeshModel::MM_NONE; }
|
||||
|
||||
/** Function used by the framework to get info about the mesh properties changed by the filter.
|
||||
// It is widely used by the meshlab's preview system.
|
||||
//TO BE REPLACED WITH = 0
|
||||
*/
|
||||
/**
|
||||
* @brief Function used by the framework to get info about the mesh properties changed by the filter.
|
||||
* It is widely used by the meshlab's preview system.
|
||||
* TO BE REPLACED WITH = 0
|
||||
*/
|
||||
virtual int postCondition(const QAction*) const { return MeshModel::MM_ALL; }
|
||||
|
||||
/** \brief applies the selected filter with the already stabilished parameters
|
||||
* This function is called by the framework after getting values for the parameters specified in the \ref InitParameterSet
|
||||
* NO GUI interaction should be done here. No dialog asking, no messagebox errors.
|
||||
* Think that his function will also be called by the commandline framework.
|
||||
* If you want report errors, use the \ref errorMsg() string. It will displayed in case of filters returning false.
|
||||
* When implementing your applyFilter, you should use the cb function to report to the framework the current state of the processing.
|
||||
* During your (long) processing you should call from time to time cb(perc,descriptiveString), where perc is an int (0..100)
|
||||
* saying what you are doing and at what point of the computation you currently are.
|
||||
* \sa errorMsg
|
||||
* \sa initParameterSet
|
||||
*/
|
||||
/**
|
||||
* @brief applies the selected filter with the already stabilished parameters
|
||||
* This function is called by the framework after getting values for the parameters specified in the \ref InitParameterSet
|
||||
* NO GUI interaction should be done here. No dialog asking, no messagebox errors.
|
||||
* Think that his function will also be called by the commandline framework.
|
||||
* If you want report errors, use the \ref errorMsg() string. It will displayed in case of filters returning false.
|
||||
* When implementing your applyFilter, you should use the cb function to report to the framework the current state of the processing.
|
||||
* During your (long) processing you should call from time to time cb(perc,descriptiveString), where perc is an int (0..100)
|
||||
* saying what you are doing and at what point of the computation you currently are.
|
||||
* @sa errorMsg
|
||||
* @sa initParameterSet
|
||||
*/
|
||||
virtual bool applyFilter(const QAction* filter, MeshDocument& md, std::map<std::string, QVariant>& outputValues, unsigned int& postConditionMask, const RichParameterList& par, vcg::CallBackPos* cb) = 0;
|
||||
|
||||
/** \brief tests if a filter is applicable to a mesh.
|
||||
This function is a handy wrapper used by the framework for the \a getPreConditions callback;
|
||||
For instance a colorize by quality filter cannot be applied to a mesh without per-vertex-quality.
|
||||
On failure (returning false) the function fills the MissingItems list with strings describing the missing items.
|
||||
*/
|
||||
/**
|
||||
* \brief tests if a filter is applicable to a mesh.
|
||||
* This function is a handy wrapper used by the framework for the \a getPreConditions callback;
|
||||
* For instance a colorize by quality filter cannot be applied to a mesh without per-vertex-quality.
|
||||
* On failure (returning false) the function fills the MissingItems list with strings describing the missing items.
|
||||
*/
|
||||
bool isFilterApplicable(const QAction* act, const MeshModel& m, QStringList &MissingItems) const;
|
||||
|
||||
|
||||
enum FILTER_ARITY { NONE = 0, SINGLE_MESH = 1, FIXED = 2, VARIABLE = 3, UNKNOWN_ARITY = 4 };
|
||||
|
||||
/** \brief this function informs the MeshLab core on how many meshes the filter will work on.
|
||||
Valid value:
|
||||
- SINGLE_MESH: the filter works just on the current mesh
|
||||
- FIXED: the number (and the names) of the meshes involved in the filter computation is determined by the parameters selected in the filter's parameters form
|
||||
- VARIABLE: the filter works on a not predetermined number of meshes. The meshes involved are typically selected by the user checking on the correspondent layer on the layer dialog
|
||||
*/
|
||||
/**
|
||||
* @brief this function informs the MeshLab core on how many meshes the filter will work on.
|
||||
* Valid value:
|
||||
* - SINGLE_MESH: the filter works just on the current mesh
|
||||
* - FIXED: the number (and the names) of the meshes involved in the filter computation is determined by the parameters selected in the filter's parameters form
|
||||
* - VARIABLE: the filter works on a not predetermined number of meshes. The meshes involved are typically selected by the user checking on the correspondent layer on the layer dialog
|
||||
*/
|
||||
virtual FILTER_ARITY filterArity(const QAction *act) const = 0;
|
||||
|
||||
// This function is called to initialized the list of parameters.
|
||||
// it is always called. If a filter does not need parameter it leave it empty and the framework
|
||||
// will not create a dialog (unless for previewing)
|
||||
/**
|
||||
* @brief This function is called to initialized the list of parameters.
|
||||
* it is always called. If a filter does not need parameter it leave it empty and the framework
|
||||
* will not create a dialog (unless for previewing)
|
||||
*/
|
||||
virtual void initParameterList(const QAction*, MeshModel &/*m*/, RichParameterList & /*par*/) {}
|
||||
virtual void initParameterList(const QAction* filter, MeshDocument &md, RichParameterList &par)
|
||||
{
|
||||
initParameterList(filter, *(md.mm()), par);
|
||||
}
|
||||
|
||||
/** \brief is invoked by the framework when the applyFilter fails to give some info to the user about the filter failure
|
||||
* Filters \b must never use QMessageBox for reporting errors.
|
||||
* Failing filters should put some meaningful information inside the errorMessage string and return false with the \ref applyFilter
|
||||
*/
|
||||
/**
|
||||
* @brief is invoked by the framework when the applyFilter fails to give some info to the user about the filter failure
|
||||
* Filters \b must never use QMessageBox for reporting errors.
|
||||
* Failing filters should put some meaningful information inside the errorMessage string and return false with the \ref applyFilter
|
||||
*/
|
||||
const QString& errorMsg() const { return this->errorMessage; }
|
||||
virtual QString filterInfo(const QAction* a) const { return this->filterInfo(ID(a)); }
|
||||
virtual QString filterName(const QAction* a) const { return this->filterName(ID(a)); }
|
||||
@ -181,8 +202,10 @@ public:
|
||||
virtual QList<QAction*> actions() const { return actionList; }
|
||||
virtual QList<FilterIDType> types() const { return typeList; }
|
||||
|
||||
/** Generate the mask of attributes would be created IF the MeshFilterInterface filt would has been called on MeshModel mm
|
||||
BE CAREFUL! this function does NOT change in anyway the state of the MeshModel!!!! **/
|
||||
/**
|
||||
* Generate the mask of attributes would be created IF the MeshFilterInterface filt would has been called on MeshModel mm
|
||||
* BE CAREFUL! this function does NOT change in anyway the state of the MeshModel!!!!
|
||||
*/
|
||||
int previewOnCreatedAttributes(const QAction* act, const MeshModel& mm) const;
|
||||
QString generatedScriptCode;
|
||||
|
||||
|
||||
@ -84,19 +84,29 @@ QString AmbientOcclusionPlugin::filterName(FilterIDType filterId) const
|
||||
|
||||
QString AmbientOcclusionPlugin::filterInfo(FilterIDType filterId) const
|
||||
{
|
||||
switch(filterId)
|
||||
{
|
||||
case FP_AMBIENT_OCCLUSION: return QString("Compute ambient occlusions values; it takes a number of well distributed view direction and for point of the surface it computes how many time it is visible from these directions. This value is saved into quality and automatically mapped into a gray shade. The average direction is saved into an attribute named 'BentNormal'");
|
||||
default : assert(0);
|
||||
}
|
||||
|
||||
return QString("");
|
||||
switch(filterId) {
|
||||
case FP_AMBIENT_OCCLUSION:
|
||||
return QString("Compute ambient occlusions values; it takes a number of well distributed view direction and for point of the surface it computes how many time it is visible from these directions. This value is saved into quality and automatically mapped into a gray shade. The average direction is saved into an attribute named 'BentNormal'");
|
||||
default : assert(0);
|
||||
}
|
||||
return QString("");
|
||||
}
|
||||
|
||||
int AmbientOcclusionPlugin::getRequirements(const QAction * /*action*/)
|
||||
{
|
||||
//no requirements needed
|
||||
return 0;
|
||||
//no requirements needed
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool AmbientOcclusionPlugin::requiresGLContext(const QAction* action) const
|
||||
{
|
||||
switch (ID(action)) {
|
||||
case FP_AMBIENT_OCCLUSION:
|
||||
return true;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
FilterPluginInterface::FILTER_ARITY AmbientOcclusionPlugin::filterArity(const QAction*) const
|
||||
@ -134,65 +144,71 @@ void AmbientOcclusionPlugin::initParameterList(const QAction *action, MeshModel
|
||||
}
|
||||
bool AmbientOcclusionPlugin::applyFilter(const QAction * /*filter*/, MeshDocument &md, std::map<std::string, QVariant>&, unsigned int& /*postConditionMask*/, const RichParameterList & par, vcg::CallBackPos *cb)
|
||||
{
|
||||
MeshModel &m=*(md.mm());
|
||||
if (glContext != nullptr) {
|
||||
MeshModel &m=*(md.mm());
|
||||
|
||||
int occlusionMode = par.getEnum("occMode");
|
||||
if (occlusionMode == 1)
|
||||
perFace = true;
|
||||
else
|
||||
perFace = false;
|
||||
|
||||
useGPU = par.getBool("useGPU");
|
||||
if (perFace) //GPU only works per-vertex
|
||||
useGPU = false;
|
||||
depthTexSize = par.getInt("depthTexSize");
|
||||
depthTexArea = depthTexSize*depthTexSize;
|
||||
numViews = par.getInt("reqViews");
|
||||
errInit = false;
|
||||
Scalarm dirBias = par.getFloat("dirBias");
|
||||
Point3m coneDir = par.getPoint3m("coneDir");
|
||||
Scalarm coneAngle = par.getFloat("coneAngle");
|
||||
|
||||
if(perFace)
|
||||
m.updateDataMask(MeshModel::MM_FACEQUALITY | MeshModel::MM_FACECOLOR);
|
||||
else
|
||||
m.updateDataMask(MeshModel::MM_VERTQUALITY | MeshModel::MM_VERTCOLOR);
|
||||
|
||||
std::vector<Point3m> unifDirVec;
|
||||
GenNormal<Scalarm>::Fibonacci(numViews,unifDirVec);
|
||||
|
||||
std::vector<Point3m> coneDirVec;
|
||||
GenNormal<Scalarm>::UniformCone(numViews, coneDirVec, math::ToRad(coneAngle), coneDir);
|
||||
|
||||
std::random_shuffle(unifDirVec.begin(),unifDirVec.end());
|
||||
std::random_shuffle(coneDirVec.begin(),coneDirVec.end());
|
||||
|
||||
int unifNum = floor(unifDirVec.size() * (1.0 - dirBias ));
|
||||
int coneNum = floor(coneDirVec.size() * (dirBias ));
|
||||
|
||||
viewDirVec.clear();
|
||||
viewDirVec.insert(viewDirVec.end(),unifDirVec.begin(),unifDirVec.begin()+unifNum);
|
||||
viewDirVec.insert(viewDirVec.end(),coneDirVec.begin(),coneDirVec.begin()+coneNum);
|
||||
numViews = viewDirVec.size();
|
||||
|
||||
this->glContext->makeCurrent();
|
||||
this->initGL(cb,m.cm.vn);
|
||||
unsigned int widgetSize = std::min(maxTexSize, depthTexSize);
|
||||
QSize fbosize(widgetSize,widgetSize);
|
||||
QGLFramebufferObjectFormat frmt;
|
||||
frmt.setInternalTextureFormat(GL_RGBA);
|
||||
frmt.setAttachment(QGLFramebufferObject::Depth);
|
||||
QGLFramebufferObject fbo(fbosize,frmt);
|
||||
qDebug("Start Painting window size %i %i", fbo.width(), fbo.height());
|
||||
GLenum err = glGetError();
|
||||
fbo.bind();
|
||||
processGL(m,viewDirVec);
|
||||
fbo.release();
|
||||
err = glGetError();
|
||||
const GLubyte* errname = gluErrorString(err); (void)errname;
|
||||
qDebug("End Painting");
|
||||
this->glContext->doneCurrent();
|
||||
return !errInit;
|
||||
int occlusionMode = par.getEnum("occMode");
|
||||
if (occlusionMode == 1)
|
||||
perFace = true;
|
||||
else
|
||||
perFace = false;
|
||||
|
||||
useGPU = par.getBool("useGPU");
|
||||
if (perFace) //GPU only works per-vertex
|
||||
useGPU = false;
|
||||
depthTexSize = par.getInt("depthTexSize");
|
||||
depthTexArea = depthTexSize*depthTexSize;
|
||||
numViews = par.getInt("reqViews");
|
||||
errInit = false;
|
||||
Scalarm dirBias = par.getFloat("dirBias");
|
||||
Point3m coneDir = par.getPoint3m("coneDir");
|
||||
Scalarm coneAngle = par.getFloat("coneAngle");
|
||||
|
||||
if(perFace)
|
||||
m.updateDataMask(MeshModel::MM_FACEQUALITY | MeshModel::MM_FACECOLOR);
|
||||
else
|
||||
m.updateDataMask(MeshModel::MM_VERTQUALITY | MeshModel::MM_VERTCOLOR);
|
||||
|
||||
std::vector<Point3m> unifDirVec;
|
||||
GenNormal<Scalarm>::Fibonacci(numViews,unifDirVec);
|
||||
|
||||
std::vector<Point3m> coneDirVec;
|
||||
GenNormal<Scalarm>::UniformCone(numViews, coneDirVec, math::ToRad(coneAngle), coneDir);
|
||||
|
||||
std::random_shuffle(unifDirVec.begin(),unifDirVec.end());
|
||||
std::random_shuffle(coneDirVec.begin(),coneDirVec.end());
|
||||
|
||||
int unifNum = floor(unifDirVec.size() * (1.0 - dirBias ));
|
||||
int coneNum = floor(coneDirVec.size() * (dirBias ));
|
||||
|
||||
viewDirVec.clear();
|
||||
viewDirVec.insert(viewDirVec.end(),unifDirVec.begin(),unifDirVec.begin()+unifNum);
|
||||
viewDirVec.insert(viewDirVec.end(),coneDirVec.begin(),coneDirVec.begin()+coneNum);
|
||||
numViews = viewDirVec.size();
|
||||
|
||||
this->glContext->makeCurrent();
|
||||
this->initGL(cb,m.cm.vn);
|
||||
unsigned int widgetSize = std::min(maxTexSize, depthTexSize);
|
||||
QSize fbosize(widgetSize,widgetSize);
|
||||
QGLFramebufferObjectFormat frmt;
|
||||
frmt.setInternalTextureFormat(GL_RGBA);
|
||||
frmt.setAttachment(QGLFramebufferObject::Depth);
|
||||
QGLFramebufferObject fbo(fbosize,frmt);
|
||||
qDebug("Start Painting window size %i %i", fbo.width(), fbo.height());
|
||||
GLenum err = glGetError();
|
||||
fbo.bind();
|
||||
processGL(m,viewDirVec);
|
||||
fbo.release();
|
||||
err = glGetError();
|
||||
const GLubyte* errname = gluErrorString(err); (void)errname;
|
||||
qDebug("End Painting");
|
||||
this->glContext->doneCurrent();
|
||||
return !errInit;
|
||||
}
|
||||
else {
|
||||
errorMessage = "Fatal error: glContext not initialized";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool AmbientOcclusionPlugin::processGL(MeshModel &m, vector<Point3f> &posVect)
|
||||
|
||||
@ -73,6 +73,7 @@ public:
|
||||
QString filterInfo(FilterIDType filterId) const;
|
||||
FILTER_ARITY filterArity(const QAction*) const;
|
||||
int getRequirements (const QAction* action);
|
||||
bool requiresGLContext(const QAction* action) const;
|
||||
FilterClass getClass(const QAction* filter) const;
|
||||
|
||||
void initParameterList(const QAction*, MeshModel &/*m*/, RichParameterList & /*parent*/);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -29,31 +29,30 @@
|
||||
|
||||
class FilterColorProjectionPlugin : public QObject, public FilterPluginInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
MESHLAB_PLUGIN_IID_EXPORTER(FILTER_PLUGIN_INTERFACE_IID)
|
||||
Q_INTERFACES(FilterPluginInterface)
|
||||
|
||||
public:
|
||||
enum { FP_SINGLEIMAGEPROJ, FP_MULTIIMAGETRIVIALPROJ, FP_MULTIIMAGETRIVIALPROJTEXTURE };
|
||||
|
||||
FilterColorProjectionPlugin();
|
||||
|
||||
QString pluginName() const;
|
||||
virtual QString filterName(FilterIDType filter) const;
|
||||
virtual QString filterInfo(FilterIDType filter) const;
|
||||
int postCondition( const QAction* ) const;
|
||||
|
||||
virtual FilterClass getClass(const QAction*) const;
|
||||
virtual void initParameterList(const QAction*, MeshDocument &/*m*/, RichParameterList & /*parent*/);
|
||||
virtual int getRequirements(const QAction*);
|
||||
virtual bool applyFilter(const QAction* filter, MeshDocument &md, std::map<std::string, QVariant>& outputValues, unsigned int& postConditionMask, const RichParameterList & /*parent*/, vcg::CallBackPos * cb);
|
||||
|
||||
FILTER_ARITY filterArity(const QAction *) const {return SINGLE_MESH;}
|
||||
|
||||
Q_OBJECT
|
||||
MESHLAB_PLUGIN_IID_EXPORTER(FILTER_PLUGIN_INTERFACE_IID)
|
||||
Q_INTERFACES(FilterPluginInterface)
|
||||
|
||||
public:
|
||||
enum { FP_SINGLEIMAGEPROJ, FP_MULTIIMAGETRIVIALPROJ, FP_MULTIIMAGETRIVIALPROJTEXTURE };
|
||||
|
||||
FilterColorProjectionPlugin();
|
||||
|
||||
QString pluginName() const;
|
||||
QString filterName(FilterIDType filter) const;
|
||||
QString filterInfo(FilterIDType filter) const;
|
||||
int postCondition( const QAction* ) const;
|
||||
|
||||
FilterClass getClass(const QAction*) const;
|
||||
void initParameterList(const QAction*, MeshDocument &/*m*/, RichParameterList & /*parent*/);
|
||||
int getRequirements(const QAction*);
|
||||
bool requiresGLContext(const QAction* action) const;
|
||||
bool applyFilter(const QAction* filter, MeshDocument &md, std::map<std::string, QVariant>& outputValues, unsigned int& postConditionMask, const RichParameterList & /*parent*/, vcg::CallBackPos * cb);
|
||||
|
||||
FILTER_ARITY filterArity(const QAction *) const {return SINGLE_MESH;}
|
||||
|
||||
private:
|
||||
|
||||
int calculateNearFarAccurate(MeshDocument &md, std::vector<float> *near, std::vector<float> *far);
|
||||
|
||||
int calculateNearFarAccurate(MeshDocument &md, std::vector<float> *near, std::vector<float> *far);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -96,6 +96,20 @@ int FilterImgPatchParamPlugin::getRequirements(const QAction *act )
|
||||
}
|
||||
}
|
||||
|
||||
bool FilterImgPatchParamPlugin::requiresGLContext(const QAction* action) const
|
||||
{
|
||||
switch(ID(action)){
|
||||
case FP_PATCH_PARAM_ONLY:
|
||||
case FP_PATCH_PARAM_AND_TEXTURING:
|
||||
case FP_RASTER_VERT_COVERAGE:
|
||||
case FP_RASTER_FACE_COVERAGE:
|
||||
return true;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
FilterPluginInterface::FilterClass FilterImgPatchParamPlugin::getClass(const QAction *act ) const
|
||||
{
|
||||
@ -199,97 +213,66 @@ bool FilterImgPatchParamPlugin::applyFilter(
|
||||
const RichParameterList &par,
|
||||
vcg::CallBackPos * /*cb*/ )
|
||||
{
|
||||
|
||||
|
||||
glContext->makeCurrent();
|
||||
if( !GLExtensionsManager::initializeGLextensions_notThrowing() )
|
||||
{
|
||||
this->errorMessage="Failed GLEW initialization";
|
||||
return false;
|
||||
}
|
||||
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
||||
|
||||
delete m_Context;
|
||||
m_Context = new glw::Context();
|
||||
m_Context->acquire();
|
||||
|
||||
if( !VisibilityCheck::GetInstance(*m_Context) )
|
||||
{
|
||||
this->errorMessage="VisibilityCheck failed";
|
||||
return false;
|
||||
}
|
||||
VisibilityCheck::ReleaseInstance();
|
||||
|
||||
|
||||
bool retValue = true;
|
||||
|
||||
CMeshO &mesh = md.mm()->cm;
|
||||
|
||||
std::list<Shotm> initialShots;
|
||||
QList<RasterModel*> activeRasters;
|
||||
foreach( RasterModel *rm, md.rasterList )
|
||||
{
|
||||
initialShots.push_back( rm->shot );
|
||||
rm->shot.ApplyRigidTransformation( vcg::Inverse(mesh.Tr) );
|
||||
if( rm->visible )
|
||||
activeRasters.push_back( rm );
|
||||
}
|
||||
|
||||
if( activeRasters.empty() ) {
|
||||
this->errorMessage="No active Raster";
|
||||
if (glContext != nullptr){
|
||||
glContext->makeCurrent();
|
||||
if( !GLExtensionsManager::initializeGLextensions_notThrowing() )
|
||||
{
|
||||
glContext->doneCurrent();
|
||||
errorMessage = "You need to have at least one valid raster layer in your project, to apply this filter"; // text
|
||||
this->errorMessage="Failed GLEW initialization";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch( ID(act) )
|
||||
{
|
||||
case FP_PATCH_PARAM_ONLY:
|
||||
{
|
||||
if (vcg::tri::Clean<CMeshO>::CountNonManifoldEdgeFF(md.mm()->cm)>0)
|
||||
{
|
||||
glContext->doneCurrent();
|
||||
errorMessage = "Mesh has some not 2-manifold faces, this filter requires manifoldness"; // text
|
||||
return false; // can't continue, mesh can't be processed
|
||||
}
|
||||
vcg::tri::Allocator<CMeshO>::CompactFaceVector(md.mm()->cm);
|
||||
vcg::tri::Allocator<CMeshO>::CompactVertexVector(md.mm()->cm);
|
||||
vcg::tri::UpdateTopology<CMeshO>::FaceFace(md.mm()->cm);
|
||||
vcg::tri::UpdateTopology<CMeshO>::VertexFace(md.mm()->cm);
|
||||
glContext->meshAttributesUpdated(md.mm()->id(),true,MLRenderingData::RendAtts());
|
||||
RasterPatchMap patches;
|
||||
PatchVec nullPatches;
|
||||
patchBasedTextureParameterization( patches,
|
||||
nullPatches,
|
||||
md.mm()->id(),
|
||||
mesh,
|
||||
activeRasters,
|
||||
par );
|
||||
|
||||
break;
|
||||
}
|
||||
case FP_PATCH_PARAM_AND_TEXTURING:
|
||||
{
|
||||
if (vcg::tri::Clean<CMeshO>::CountNonManifoldEdgeFF(md.mm()->cm)>0)
|
||||
{
|
||||
glContext->doneCurrent();
|
||||
errorMessage = "Mesh has some not 2-manifold faces, this filter requires manifoldness"; // text
|
||||
return false; // can't continue, mesh can't be processed
|
||||
}
|
||||
vcg::tri::Allocator<CMeshO>::CompactEveryVector(md.mm()->cm);
|
||||
vcg::tri::UpdateTopology<CMeshO>::FaceFace(md.mm()->cm);
|
||||
vcg::tri::UpdateTopology<CMeshO>::VertexFace(md.mm()->cm);
|
||||
glContext->meshAttributesUpdated(md.mm()->id(),true,MLRenderingData::RendAtts());
|
||||
QString texName = par.getString( "textureName" ).simplified();
|
||||
int pathEnd = std::max( texName.lastIndexOf('/'), texName.lastIndexOf('\\') );
|
||||
if( pathEnd != -1 )
|
||||
texName = texName.right( texName.size()-pathEnd-1 );
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
||||
|
||||
if( (retValue = texName.size()!=0) )
|
||||
delete m_Context;
|
||||
m_Context = new glw::Context();
|
||||
m_Context->acquire();
|
||||
|
||||
if( !VisibilityCheck::GetInstance(*m_Context) )
|
||||
{
|
||||
this->errorMessage="VisibilityCheck failed";
|
||||
return false;
|
||||
}
|
||||
VisibilityCheck::ReleaseInstance();
|
||||
|
||||
|
||||
bool retValue = true;
|
||||
|
||||
CMeshO &mesh = md.mm()->cm;
|
||||
|
||||
std::list<Shotm> initialShots;
|
||||
QList<RasterModel*> activeRasters;
|
||||
foreach( RasterModel *rm, md.rasterList )
|
||||
{
|
||||
initialShots.push_back( rm->shot );
|
||||
rm->shot.ApplyRigidTransformation( vcg::Inverse(mesh.Tr) );
|
||||
if( rm->visible )
|
||||
activeRasters.push_back( rm );
|
||||
}
|
||||
|
||||
if( activeRasters.empty() ) {
|
||||
this->errorMessage="No active Raster";
|
||||
{
|
||||
glContext->doneCurrent();
|
||||
errorMessage = "You need to have at least one valid raster layer in your project, to apply this filter"; // text
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch( ID(act) )
|
||||
{
|
||||
case FP_PATCH_PARAM_ONLY:
|
||||
{
|
||||
if (vcg::tri::Clean<CMeshO>::CountNonManifoldEdgeFF(md.mm()->cm)>0)
|
||||
{
|
||||
glContext->doneCurrent();
|
||||
errorMessage = "Mesh has some not 2-manifold faces, this filter requires manifoldness"; // text
|
||||
return false; // can't continue, mesh can't be processed
|
||||
}
|
||||
vcg::tri::Allocator<CMeshO>::CompactFaceVector(md.mm()->cm);
|
||||
vcg::tri::Allocator<CMeshO>::CompactVertexVector(md.mm()->cm);
|
||||
vcg::tri::UpdateTopology<CMeshO>::FaceFace(md.mm()->cm);
|
||||
vcg::tri::UpdateTopology<CMeshO>::VertexFace(md.mm()->cm);
|
||||
glContext->meshAttributesUpdated(md.mm()->id(),true,MLRenderingData::RendAtts());
|
||||
RasterPatchMap patches;
|
||||
PatchVec nullPatches;
|
||||
patchBasedTextureParameterization( patches,
|
||||
@ -299,99 +282,134 @@ bool FilterImgPatchParamPlugin::applyFilter(
|
||||
activeRasters,
|
||||
par );
|
||||
|
||||
TexturePainter painter( *m_Context, par.getInt("textureSize") );
|
||||
if( (retValue = painter.isInitialized()) )
|
||||
break;
|
||||
}
|
||||
case FP_PATCH_PARAM_AND_TEXTURING:
|
||||
{
|
||||
if (vcg::tri::Clean<CMeshO>::CountNonManifoldEdgeFF(md.mm()->cm)>0)
|
||||
{
|
||||
QElapsedTimer t; t.start();
|
||||
painter.paint( patches );
|
||||
if( par.getBool("colorCorrection") )
|
||||
painter.rectifyColor( patches, par.getInt("colorCorrectionFilterSize") );
|
||||
log( "TEXTURE PAINTING: %.3f sec.", 0.001f*t.elapsed() );
|
||||
glContext->doneCurrent();
|
||||
errorMessage = "Mesh has some not 2-manifold faces, this filter requires manifoldness"; // text
|
||||
return false; // can't continue, mesh can't be processed
|
||||
}
|
||||
vcg::tri::Allocator<CMeshO>::CompactEveryVector(md.mm()->cm);
|
||||
vcg::tri::UpdateTopology<CMeshO>::FaceFace(md.mm()->cm);
|
||||
vcg::tri::UpdateTopology<CMeshO>::VertexFace(md.mm()->cm);
|
||||
glContext->meshAttributesUpdated(md.mm()->id(),true,MLRenderingData::RendAtts());
|
||||
QString texName = par.getString( "textureName" ).simplified();
|
||||
int pathEnd = std::max( texName.lastIndexOf('/'), texName.lastIndexOf('\\') );
|
||||
if( pathEnd != -1 )
|
||||
texName = texName.right( texName.size()-pathEnd-1 );
|
||||
|
||||
if( (retValue = texName.size()!=0) )
|
||||
{
|
||||
RasterPatchMap patches;
|
||||
PatchVec nullPatches;
|
||||
patchBasedTextureParameterization( patches,
|
||||
nullPatches,
|
||||
md.mm()->id(),
|
||||
mesh,
|
||||
activeRasters,
|
||||
par );
|
||||
|
||||
QImage tex = painter.getTexture();
|
||||
if( tex.save(texName) )
|
||||
TexturePainter painter( *m_Context, par.getInt("textureSize") );
|
||||
if( (retValue = painter.isInitialized()) )
|
||||
{
|
||||
mesh.textures.clear();
|
||||
mesh.textures.push_back( texName.toStdString() );
|
||||
QElapsedTimer t; t.start();
|
||||
painter.paint( patches );
|
||||
if( par.getBool("colorCorrection") )
|
||||
painter.rectifyColor( patches, par.getInt("colorCorrectionFilterSize") );
|
||||
log( "TEXTURE PAINTING: %.3f sec.", 0.001f*t.elapsed() );
|
||||
|
||||
QImage tex = painter.getTexture();
|
||||
if( tex.save(texName) )
|
||||
{
|
||||
mesh.textures.clear();
|
||||
mesh.textures.push_back( texName.toStdString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case FP_RASTER_VERT_COVERAGE:
|
||||
{
|
||||
VisibilityCheck &visibility = *VisibilityCheck::GetInstance( *m_Context );
|
||||
visibility.setMesh(md.mm()->id(),&mesh );
|
||||
visibility.m_plugcontext = glContext;
|
||||
for( CMeshO::VertexIterator vi=mesh.vert.begin(); vi!=mesh.vert.end(); ++vi )
|
||||
vi->Q() = 0.0f;
|
||||
|
||||
foreach( RasterModel *rm, activeRasters )
|
||||
case FP_RASTER_VERT_COVERAGE:
|
||||
{
|
||||
visibility.setRaster( rm );
|
||||
visibility.checkVisibility();
|
||||
VisibilityCheck &visibility = *VisibilityCheck::GetInstance( *m_Context );
|
||||
visibility.setMesh(md.mm()->id(),&mesh );
|
||||
visibility.m_plugcontext = glContext;
|
||||
for( CMeshO::VertexIterator vi=mesh.vert.begin(); vi!=mesh.vert.end(); ++vi )
|
||||
if( visibility.isVertVisible(vi) )
|
||||
vi->Q() += 1.0f;
|
||||
vi->Q() = 0.0f;
|
||||
|
||||
foreach( RasterModel *rm, activeRasters )
|
||||
{
|
||||
visibility.setRaster( rm );
|
||||
visibility.checkVisibility();
|
||||
for( CMeshO::VertexIterator vi=mesh.vert.begin(); vi!=mesh.vert.end(); ++vi )
|
||||
if( visibility.isVertVisible(vi) )
|
||||
vi->Q() += 1.0f;
|
||||
}
|
||||
|
||||
if( par.getBool("normalizeQuality") )
|
||||
{
|
||||
const float normFactor = 1.0f / md.rasterList.size();
|
||||
for( CMeshO::VertexIterator vi=mesh.vert.begin(); vi!=mesh.vert.end(); ++vi )
|
||||
vi->Q() *= normFactor;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if( par.getBool("normalizeQuality") )
|
||||
case FP_RASTER_FACE_COVERAGE:
|
||||
{
|
||||
const float normFactor = 1.0f / md.rasterList.size();
|
||||
for( CMeshO::VertexIterator vi=mesh.vert.begin(); vi!=mesh.vert.end(); ++vi )
|
||||
vi->Q() *= normFactor;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case FP_RASTER_FACE_COVERAGE:
|
||||
{
|
||||
VisibilityCheck &visibility = *VisibilityCheck::GetInstance( *m_Context );
|
||||
visibility.setMesh(md.mm()->id(),&mesh );
|
||||
visibility.m_plugcontext = glContext;
|
||||
|
||||
for( CMeshO::FaceIterator fi=mesh.face.begin(); fi!=mesh.face.end(); ++fi )
|
||||
fi->Q() = 0.0f;
|
||||
|
||||
foreach( RasterModel *rm, activeRasters )
|
||||
{
|
||||
visibility.setRaster( rm );
|
||||
visibility.checkVisibility();
|
||||
VisibilityCheck &visibility = *VisibilityCheck::GetInstance( *m_Context );
|
||||
visibility.setMesh(md.mm()->id(),&mesh );
|
||||
visibility.m_plugcontext = glContext;
|
||||
|
||||
for( CMeshO::FaceIterator fi=mesh.face.begin(); fi!=mesh.face.end(); ++fi )
|
||||
if( visibility.isFaceVisible(fi) )
|
||||
fi->Q() += 1.0f;
|
||||
fi->Q() = 0.0f;
|
||||
|
||||
foreach( RasterModel *rm, activeRasters )
|
||||
{
|
||||
visibility.setRaster( rm );
|
||||
visibility.checkVisibility();
|
||||
for( CMeshO::FaceIterator fi=mesh.face.begin(); fi!=mesh.face.end(); ++fi )
|
||||
if( visibility.isFaceVisible(fi) )
|
||||
fi->Q() += 1.0f;
|
||||
}
|
||||
|
||||
if( par.getBool("normalizeQuality") )
|
||||
{
|
||||
const float normFactor = 1.0f / md.rasterList.size();
|
||||
for( CMeshO::FaceIterator fi=mesh.face.begin(); fi!=mesh.face.end(); ++fi )
|
||||
fi->Q() *= normFactor;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( par.getBool("normalizeQuality") )
|
||||
|
||||
foreach( RasterModel *rm, md.rasterList )
|
||||
{
|
||||
const float normFactor = 1.0f / md.rasterList.size();
|
||||
for( CMeshO::FaceIterator fi=mesh.face.begin(); fi!=mesh.face.end(); ++fi )
|
||||
fi->Q() *= normFactor;
|
||||
rm->shot = *initialShots.begin();
|
||||
initialShots.erase( initialShots.begin() );
|
||||
}
|
||||
|
||||
break;
|
||||
VisibilityCheck::ReleaseInstance();
|
||||
|
||||
|
||||
delete m_Context;
|
||||
m_Context = NULL;
|
||||
|
||||
glPopAttrib();
|
||||
glContext->doneCurrent();
|
||||
|
||||
|
||||
return retValue;
|
||||
}
|
||||
else {
|
||||
errorMessage = "Fatal error: glContext not initialized";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
foreach( RasterModel *rm, md.rasterList )
|
||||
{
|
||||
rm->shot = *initialShots.begin();
|
||||
initialShots.erase( initialShots.begin() );
|
||||
}
|
||||
|
||||
VisibilityCheck::ReleaseInstance();
|
||||
|
||||
|
||||
delete m_Context;
|
||||
m_Context = NULL;
|
||||
|
||||
glPopAttrib();
|
||||
glContext->doneCurrent();
|
||||
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -110,6 +110,7 @@ public:
|
||||
RichParameterList &par );
|
||||
|
||||
virtual int getRequirements(const QAction* act );
|
||||
bool requiresGLContext(const QAction* action) const;
|
||||
//virtual int postCondition( QAction *act ) const;
|
||||
|
||||
virtual bool applyFilter(
|
||||
|
||||
@ -93,7 +93,18 @@ FilterMutualGlobal::FilterClass FilterMutualGlobal::getClass(const QAction *a) c
|
||||
case FP_IMAGE_GLOBALIGN : return FilterPluginInterface::Camera;
|
||||
default : assert(0);
|
||||
}
|
||||
return FilterPluginInterface::Generic;
|
||||
return FilterPluginInterface::Generic;
|
||||
}
|
||||
|
||||
bool FilterMutualGlobal::requiresGLContext(const QAction* action) const
|
||||
{
|
||||
switch(ID(action)) {
|
||||
case FP_IMAGE_GLOBALIGN:
|
||||
return true;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// This function define the needed parameters for each filter. Return true if the filter has some parameters
|
||||
@ -162,6 +173,10 @@ void FilterMutualGlobal::initParameterList(const QAction *action,MeshDocument &
|
||||
// Move Vertex of a random quantity
|
||||
bool FilterMutualGlobal::applyFilter(const QAction *action, MeshDocument &md, std::map<std::string, QVariant>&, unsigned int& /*postConditionMask*/, const RichParameterList & par, vcg::CallBackPos *cb)
|
||||
{
|
||||
if (glContext == nullptr){
|
||||
errorMessage = "Fatal error: glContext not initialized";
|
||||
return false;
|
||||
}
|
||||
QElapsedTimer filterTime;
|
||||
filterTime.start();
|
||||
|
||||
|
||||
@ -58,6 +58,7 @@ public:
|
||||
bool applyFilter(const QAction* filter, MeshDocument &md, std::map<std::string, QVariant>& outputValues, unsigned int& postConditionMask, const RichParameterList & /*parent*/, vcg::CallBackPos * cb) ;
|
||||
int postCondition(const QAction*) const { return MeshModel::MM_NONE; };
|
||||
FilterClass getClass(const QAction* a) const;
|
||||
bool requiresGLContext(const QAction* action) const;
|
||||
QString filterScriptFunctionName(FilterIDType filterID);
|
||||
bool preAlignment(MeshDocument &md, const RichParameterList& par, vcg::CallBackPos *cb);
|
||||
std::vector<SubGraph> buildGraph(MeshDocument &md, bool globalign=true);
|
||||
|
||||
@ -80,6 +80,17 @@ FilterMutualInfoPlugin::FilterClass FilterMutualInfoPlugin::getClass(const QActi
|
||||
}
|
||||
}
|
||||
|
||||
bool FilterMutualInfoPlugin::requiresGLContext(const QAction* action) const
|
||||
{
|
||||
switch(ID(action)) {
|
||||
case FP_IMAGE_MUTUALINFO:
|
||||
return true;
|
||||
default :
|
||||
assert(0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
FilterPluginInterface::FILTER_ARITY FilterMutualInfoPlugin::filterArity(const QAction*) const
|
||||
{
|
||||
return SINGLE_MESH;
|
||||
@ -112,6 +123,10 @@ void FilterMutualInfoPlugin::initParameterList(const QAction *action,MeshDocumen
|
||||
|
||||
bool FilterMutualInfoPlugin::applyFilter(const QAction *action, MeshDocument &md, std::map<std::string, QVariant>&, unsigned int& /*postConditionMask*/, const RichParameterList & par, vcg::CallBackPos* )
|
||||
{
|
||||
if (glContext == nullptr){
|
||||
errorMessage = "Fatal error: glContext not initialized";
|
||||
return false;
|
||||
}
|
||||
switch(ID(action)) {
|
||||
case FP_IMAGE_MUTUALINFO :
|
||||
return imageMutualInfoAlign(
|
||||
|
||||
@ -46,6 +46,7 @@ public:
|
||||
QString filterName(FilterIDType filter) const;
|
||||
QString filterInfo(FilterIDType filter) const;
|
||||
FilterClass getClass(const QAction* a) const;
|
||||
bool requiresGLContext(const QAction* action) const;
|
||||
FILTER_ARITY filterArity(const QAction*) const;
|
||||
void initParameterList(const QAction*, MeshDocument &, RichParameterList & /*parent*/);
|
||||
bool applyFilter(const QAction* filter, MeshDocument &md, std::map<std::string, QVariant>& outputValues, unsigned int& postConditionMask, const RichParameterList & /*parent*/, vcg::CallBackPos * cb) ;
|
||||
|
||||
@ -58,14 +58,27 @@ QString ExtraSampleGPUPlugin::filterName(FilterIDType filterId) const
|
||||
|
||||
// Info() must return the longer string describing each filtering action
|
||||
// (this string is used in the About plugin dialog)
|
||||
QString ExtraSampleGPUPlugin::filterInfo(FilterIDType filterId) const
|
||||
QString ExtraSampleGPUPlugin::filterInfo(FilterIDType filterId) const
|
||||
{
|
||||
switch(filterId) {
|
||||
case FP_GPU_EXAMPLE : return QString("Small useless filter added only to show how to work with a gl render context inside a filter.");
|
||||
default : assert(0);
|
||||
switch(filterId) {
|
||||
case FP_GPU_EXAMPLE :
|
||||
return QString("Small useless filter added only to show how to work with a gl render context inside a filter.");
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return QString("Unknown Filter");
|
||||
}
|
||||
|
||||
bool ExtraSampleGPUPlugin::requiresGLContext(const QAction* action) const
|
||||
{
|
||||
switch(ID(action)){
|
||||
case FP_GPU_EXAMPLE :
|
||||
return true;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// The FilterClass describes in which generic class of filters it fits.
|
||||
// This choice affect the submenu in which each filter will be placed
|
||||
@ -110,6 +123,10 @@ void ExtraSampleGPUPlugin::initParameterList(const QAction * action, MeshModel &
|
||||
// Move Vertex of a random quantity
|
||||
bool ExtraSampleGPUPlugin::applyFilter(const QAction * a, MeshDocument & md , std::map<std::string, QVariant>&, unsigned int& /*postConditionMask*/, const RichParameterList & par, vcg::CallBackPos * /*cb*/)
|
||||
{
|
||||
if (glContext == nullptr){
|
||||
errorMessage = "Fatal error: glContext not initialized";
|
||||
return false;
|
||||
}
|
||||
switch(ID(a))
|
||||
{
|
||||
case FP_GPU_EXAMPLE:
|
||||
|
||||
@ -55,6 +55,7 @@ public:
|
||||
|
||||
QString filterName(FilterIDType filter) const;
|
||||
QString filterInfo(FilterIDType filter) const;
|
||||
bool requiresGLContext(const QAction* action) const;
|
||||
bool applyFilter(const QAction* filter, MeshDocument &md, std::map<std::string, QVariant>& outputValues, unsigned int& postConditionMask, const RichParameterList & /*parent*/, vcg::CallBackPos * cb) ;
|
||||
FilterClass getClass(const QAction* a) const;
|
||||
};
|
||||
|
||||
@ -41,7 +41,6 @@ QString SdfGpuPlugin::pluginName() const
|
||||
|
||||
void SdfGpuPlugin::initParameterList(const QAction *action, MeshModel &/*m*/, RichParameterList &par)
|
||||
{
|
||||
mAction = ID(action);
|
||||
QStringList onPrimitive; onPrimitive.push_back("On vertices"); onPrimitive.push_back("On Faces");
|
||||
par.addParam( RichEnum("onPrimitive", 0, onPrimitive, "Metric:",
|
||||
"Choose whether to trace rays from faces or from vertices. " ));
|
||||
@ -58,12 +57,12 @@ void SdfGpuPlugin::initParameterList(const QAction *action, MeshModel &/*m*/, Ri
|
||||
"Depth tolerance used during depth peeling. This is the threshold used to differentiate layers between each others."
|
||||
"Two elements whose distance is below this value will be considered as belonging to the same layer."));
|
||||
|
||||
if(mAction != SDF_DEPTH_COMPLEXITY)
|
||||
if(ID(action) != SDF_DEPTH_COMPLEXITY)
|
||||
par.addParam(RichFloat("coneAngle",120,"Cone amplitude", "Cone amplitude around normals in degrees. Rays are traced within this cone."));
|
||||
|
||||
|
||||
|
||||
switch(mAction)
|
||||
switch(ID(action))
|
||||
{
|
||||
case SDF_OBSCURANCE:
|
||||
par.addParam(RichFloat("obscuranceExponent", 0.1f, "Obscurance Exponent",
|
||||
@ -80,7 +79,7 @@ void SdfGpuPlugin::initParameterList(const QAction *action, MeshModel &/*m*/, Ri
|
||||
}
|
||||
}
|
||||
|
||||
if(mAction == SDF_SDF)
|
||||
if(ID(action) == SDF_SDF)
|
||||
{
|
||||
par.addParam(RichBool("removeFalse",true,"Remove false intersections","For each"
|
||||
"ray we check the normal at the point of intersection,"
|
||||
@ -143,8 +142,12 @@ QString SdfGpuPlugin::filterInfo(FilterIDType filterId) const
|
||||
return QString("");
|
||||
}
|
||||
|
||||
bool SdfGpuPlugin::applyFilter(const QAction */*filter*/, MeshDocument &md, std::map<std::string, QVariant>&, unsigned int& /*postConditionMask*/, const RichParameterList & pars, vcg::CallBackPos *cb)
|
||||
bool SdfGpuPlugin::applyFilter(const QAction* action, MeshDocument &md, std::map<std::string, QVariant>&, unsigned int& /*postConditionMask*/, const RichParameterList & pars, vcg::CallBackPos *cb)
|
||||
{
|
||||
if (glContext == nullptr){
|
||||
errorMessage = "Fatal error: glContext not initialized";
|
||||
return false;
|
||||
}
|
||||
MeshModel* mm = md.mm();
|
||||
|
||||
//RETRIEVE PARAMETERS
|
||||
@ -155,14 +158,14 @@ bool SdfGpuPlugin::applyFilter(const QAction */*filter*/, MeshDocument &md, std:
|
||||
mTolerance = pars.getFloat("peelingTolerance");
|
||||
mPeelingTextureSize = pars.getInt("DepthTextureSize");
|
||||
|
||||
if(mAction != SDF_DEPTH_COMPLEXITY)
|
||||
if(ID(action) != SDF_DEPTH_COMPLEXITY)
|
||||
mMinCos = vcg::math::Cos(math::ToRad(pars.getFloat("coneAngle")/2.0));
|
||||
|
||||
std::vector<Point3f> coneDirVec;
|
||||
|
||||
if(mAction == SDF_OBSCURANCE)
|
||||
if(ID(action) == SDF_OBSCURANCE)
|
||||
mTau = pars.getFloat("obscuranceExponent");
|
||||
else if(mAction==SDF_SDF)
|
||||
else if(ID(action)==SDF_SDF)
|
||||
{
|
||||
mRemoveFalse = pars.getBool("removeFalse");
|
||||
mRemoveOutliers = pars.getBool("removeOutliers");
|
||||
@ -195,7 +198,7 @@ bool SdfGpuPlugin::applyFilter(const QAction */*filter*/, MeshDocument &md, std:
|
||||
for(vector<vcg::Point3f>::iterator vi = unifDirVec.begin(); vi != unifDirVec.end(); vi++)
|
||||
{
|
||||
(*vi).Normalize();
|
||||
TraceRay(peel, (*vi), md.mm());
|
||||
TraceRay(action, peel, (*vi), md.mm());
|
||||
cb(100*((float)tracedRays/(float)unifDirVec.size()), "Tracing rays...");
|
||||
|
||||
glContext->makeCurrent();
|
||||
@ -208,14 +211,14 @@ bool SdfGpuPlugin::applyFilter(const QAction */*filter*/, MeshDocument &md, std:
|
||||
}
|
||||
|
||||
//read back the result texture and store result in the mesh
|
||||
if(mAction == SDF_OBSCURANCE)
|
||||
if(ID(action) == SDF_OBSCURANCE)
|
||||
{
|
||||
if(mOnPrimitive == ON_VERTICES)
|
||||
applyObscurancePerVertex(*mm,unifDirVec.size());
|
||||
else
|
||||
applyObscurancePerFace(*mm,unifDirVec.size());
|
||||
}
|
||||
else if(mAction == SDF_SDF)
|
||||
else if(ID(action) == SDF_SDF)
|
||||
{
|
||||
if(mOnPrimitive == ON_VERTICES)
|
||||
applySdfPerVertex(*mm);
|
||||
@ -1012,7 +1015,7 @@ bool SdfGpuPlugin::postRender(unsigned int peelingIteration)
|
||||
return true;
|
||||
}
|
||||
|
||||
void SdfGpuPlugin::TraceRay(int peelingIteration,const Point3f& dir, MeshModel* mm )
|
||||
void SdfGpuPlugin::TraceRay(const QAction* action, int peelingIteration,const Point3f& dir, MeshModel* mm )
|
||||
{
|
||||
unsigned int j = 0;
|
||||
|
||||
@ -1048,7 +1051,7 @@ void SdfGpuPlugin::TraceRay(int peelingIteration,const Point3f& dir, MeshModel*
|
||||
if(i%2)
|
||||
{
|
||||
//we use the same method as in sdf, see below
|
||||
if(mAction==SDF_OBSCURANCE )
|
||||
if(ID(action)==SDF_OBSCURANCE )
|
||||
{
|
||||
if(i>1)
|
||||
{
|
||||
@ -1063,7 +1066,7 @@ void SdfGpuPlugin::TraceRay(int peelingIteration,const Point3f& dir, MeshModel*
|
||||
|
||||
}
|
||||
}
|
||||
else if(mAction == SDF_SDF)
|
||||
else if(ID(action) == SDF_SDF)
|
||||
{
|
||||
if(i>1)
|
||||
{
|
||||
@ -1097,7 +1100,20 @@ void SdfGpuPlugin::TraceRay(int peelingIteration,const Point3f& dir, MeshModel*
|
||||
|
||||
FilterPluginInterface::FILTER_ARITY SdfGpuPlugin::filterArity(const QAction *) const
|
||||
{
|
||||
return FilterPluginInterface::SINGLE_MESH;
|
||||
return FilterPluginInterface::SINGLE_MESH;
|
||||
}
|
||||
|
||||
bool SdfGpuPlugin::requiresGLContext(const QAction* action) const
|
||||
{
|
||||
switch(ID(action)){
|
||||
case SDF_SDF:
|
||||
case SDF_DEPTH_COMPLEXITY:
|
||||
case SDF_OBSCURANCE:
|
||||
return true;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
MESHLAB_PLUGIN_NAME_EXPORTER(SdfGpuPlugin)
|
||||
|
||||
@ -13,118 +13,119 @@ enum ONPRIMITIVE{ON_VERTICES=0, ON_FACES=1};
|
||||
|
||||
class SdfGpuPlugin : public QObject, public FilterPluginInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
MESHLAB_PLUGIN_IID_EXPORTER(FILTER_PLUGIN_INTERFACE_IID)
|
||||
Q_INTERFACES(FilterPluginInterface)
|
||||
|
||||
public:
|
||||
|
||||
enum{ SDF_SDF, SDF_DEPTH_COMPLEXITY, SDF_OBSCURANCE };
|
||||
|
||||
SdfGpuPlugin();
|
||||
|
||||
QString pluginName() const;
|
||||
|
||||
QString filterName(FilterIDType filterId) const;
|
||||
|
||||
QString filterInfo(FilterIDType filterId) const;
|
||||
|
||||
FilterClass getClass(const QAction *) const
|
||||
{
|
||||
return FilterPluginInterface::VertexColoring;
|
||||
}
|
||||
|
||||
FILTER_ARITY filterArity(const QAction* act) const;
|
||||
|
||||
//Main plugin function
|
||||
bool applyFilter(const QAction* filter, MeshDocument &md, std::map<std::string, QVariant>& outputValues, unsigned int& postConditionMask, const RichParameterList & par, vcg::CallBackPos *cb);
|
||||
|
||||
//Parameters init for user interface
|
||||
virtual void initParameterList(const QAction* action, MeshModel &m, RichParameterList &parlst);
|
||||
|
||||
//Draw the mesh
|
||||
void fillFrameBuffer(bool front, MeshModel* mm);
|
||||
|
||||
//Mesh setup
|
||||
void setupMesh(MeshDocument& md, ONPRIMITIVE onprim );
|
||||
|
||||
//Init OpenGL context
|
||||
bool initGL(MeshModel& mm);
|
||||
|
||||
//OpenGL clean up
|
||||
void releaseGL(MeshModel &m);
|
||||
|
||||
//Setup camera orientation
|
||||
void setCamera(vcg::Point3f camDir, vcg::Box3f meshBBox);
|
||||
|
||||
//Calculate sdf or obscurance along a ray
|
||||
void TraceRay(int peelingIteration, const vcg::Point3f& dir, MeshModel* mm );
|
||||
|
||||
//Enable depth peeling shader
|
||||
void useDepthPeelingShader(FramebufferObject* fbo);
|
||||
|
||||
//Position and normal of each vertex are copied to two separate texture, to be used in sdf and obscurance GPU calculation
|
||||
void vertexDataToTexture(MeshModel &m);
|
||||
|
||||
void faceDataToTexture(MeshModel &m);
|
||||
|
||||
//Sdf calculation for each depth peeling iteration
|
||||
void calculateSdfHW(FramebufferObject* fboFront, FramebufferObject* fboBack, FramebufferObject* fboPrevBack, const vcg::Point3f& cameraDir );
|
||||
|
||||
//Copy sdf values from result texture to the mesh (vertex quality)
|
||||
void applySdfPerVertex(MeshModel &m);
|
||||
|
||||
//Copy sdf values from result texture to the mesh (face quality)
|
||||
void applySdfPerFace(MeshModel &m);
|
||||
|
||||
|
||||
//Obscurance calculation for each depth peeling iteration
|
||||
void calculateObscurance(FramebufferObject* fboFront, FramebufferObject* fboBack, FramebufferObject* nextFront, const vcg::Point3f& cameraDir, float bbDiag );
|
||||
|
||||
//Copy obscurance values from result texture to the mesh (vertex color)
|
||||
void applyObscurancePerVertex(MeshModel &m, float numberOfRays);
|
||||
|
||||
//Copy obscurance values from result texture to the mesh (face color)
|
||||
void applyObscurancePerFace(MeshModel &m, float numberOfRays);
|
||||
|
||||
void preRender(unsigned int peelingIteration);
|
||||
|
||||
bool postRender(unsigned int peelingIteration);
|
||||
|
||||
protected:
|
||||
|
||||
FilterIDType mAction;
|
||||
ONPRIMITIVE mOnPrimitive;
|
||||
unsigned int mResTextureDim;
|
||||
unsigned int mNumberOfTexRows; //the number of rows of a texture actually used for the result texture
|
||||
FloatTexture2D* mVertexCoordsTexture;
|
||||
FloatTexture2D* mVertexNormalsTexture;
|
||||
FramebufferObject* mFboResult; //Fbo and texture storing the result computation
|
||||
FloatTexture2D* mResultTexture;
|
||||
FloatTexture2D* mDirsResultTexture;
|
||||
FramebufferObject* mFboArray[3]; //Fbos and textures for depth peeling
|
||||
FloatTexture2D* mDepthTextureArray[3];
|
||||
FloatTexture2D* mColorTextureArray[3];
|
||||
unsigned int mPeelingTextureSize;
|
||||
float mTolerance;
|
||||
float mMinCos;
|
||||
float mTau; //obscurance exponent
|
||||
float mMinDist; //min dist between vertices to check too thin parts
|
||||
float mScale; //Scaling factor used to setup camera
|
||||
GPUProgram* mDeepthPeelingProgram;
|
||||
GPUProgram* mSDFProgram;
|
||||
GPUProgram* mObscuranceProgram;
|
||||
bool mRemoveFalse;
|
||||
bool mRemoveOutliers;
|
||||
GLuint mOcclusionQuery;
|
||||
GLuint mPixelCount;
|
||||
unsigned int mTempDepthComplexity;
|
||||
unsigned int mDepthComplexity;
|
||||
bool mDepthComplexityWarning;
|
||||
|
||||
CMeshO::PerFaceAttributeHandle<vcg::Point3f> mMaxQualityDirPerFace;
|
||||
CMeshO::PerVertexAttributeHandle<vcg::Point3f> mMaxQualityDirPerVertex;
|
||||
|
||||
Q_OBJECT
|
||||
MESHLAB_PLUGIN_IID_EXPORTER(FILTER_PLUGIN_INTERFACE_IID)
|
||||
Q_INTERFACES(FilterPluginInterface)
|
||||
|
||||
public:
|
||||
|
||||
enum{ SDF_SDF, SDF_DEPTH_COMPLEXITY, SDF_OBSCURANCE };
|
||||
|
||||
SdfGpuPlugin();
|
||||
|
||||
QString pluginName() const;
|
||||
|
||||
QString filterName(FilterIDType filterId) const;
|
||||
|
||||
QString filterInfo(FilterIDType filterId) const;
|
||||
|
||||
FilterClass getClass(const QAction *) const
|
||||
{
|
||||
return FilterPluginInterface::VertexColoring;
|
||||
}
|
||||
|
||||
FILTER_ARITY filterArity(const QAction* act) const;
|
||||
|
||||
bool requiresGLContext(const QAction* action) const;
|
||||
|
||||
//Main plugin function
|
||||
bool applyFilter(const QAction* filter, MeshDocument &md, std::map<std::string, QVariant>& outputValues, unsigned int& postConditionMask, const RichParameterList & par, vcg::CallBackPos *cb);
|
||||
|
||||
//Parameters init for user interface
|
||||
virtual void initParameterList(const QAction* action, MeshModel &m, RichParameterList &parlst);
|
||||
|
||||
//Draw the mesh
|
||||
void fillFrameBuffer(bool front, MeshModel* mm);
|
||||
|
||||
//Mesh setup
|
||||
void setupMesh(MeshDocument& md, ONPRIMITIVE onprim );
|
||||
|
||||
//Init OpenGL context
|
||||
bool initGL(MeshModel& mm);
|
||||
|
||||
//OpenGL clean up
|
||||
void releaseGL(MeshModel &m);
|
||||
|
||||
//Setup camera orientation
|
||||
void setCamera(vcg::Point3f camDir, vcg::Box3f meshBBox);
|
||||
|
||||
//Calculate sdf or obscurance along a ray
|
||||
void TraceRay(const QAction* action, int peelingIteration, const vcg::Point3f& dir, MeshModel* mm );
|
||||
|
||||
//Enable depth peeling shader
|
||||
void useDepthPeelingShader(FramebufferObject* fbo);
|
||||
|
||||
//Position and normal of each vertex are copied to two separate texture, to be used in sdf and obscurance GPU calculation
|
||||
void vertexDataToTexture(MeshModel &m);
|
||||
|
||||
void faceDataToTexture(MeshModel &m);
|
||||
|
||||
//Sdf calculation for each depth peeling iteration
|
||||
void calculateSdfHW(FramebufferObject* fboFront, FramebufferObject* fboBack, FramebufferObject* fboPrevBack, const vcg::Point3f& cameraDir );
|
||||
|
||||
//Copy sdf values from result texture to the mesh (vertex quality)
|
||||
void applySdfPerVertex(MeshModel &m);
|
||||
|
||||
//Copy sdf values from result texture to the mesh (face quality)
|
||||
void applySdfPerFace(MeshModel &m);
|
||||
|
||||
|
||||
//Obscurance calculation for each depth peeling iteration
|
||||
void calculateObscurance(FramebufferObject* fboFront, FramebufferObject* fboBack, FramebufferObject* nextFront, const vcg::Point3f& cameraDir, float bbDiag );
|
||||
|
||||
//Copy obscurance values from result texture to the mesh (vertex color)
|
||||
void applyObscurancePerVertex(MeshModel &m, float numberOfRays);
|
||||
|
||||
//Copy obscurance values from result texture to the mesh (face color)
|
||||
void applyObscurancePerFace(MeshModel &m, float numberOfRays);
|
||||
|
||||
void preRender(unsigned int peelingIteration);
|
||||
|
||||
bool postRender(unsigned int peelingIteration);
|
||||
|
||||
protected:
|
||||
|
||||
ONPRIMITIVE mOnPrimitive;
|
||||
unsigned int mResTextureDim;
|
||||
unsigned int mNumberOfTexRows; //the number of rows of a texture actually used for the result texture
|
||||
FloatTexture2D* mVertexCoordsTexture;
|
||||
FloatTexture2D* mVertexNormalsTexture;
|
||||
FramebufferObject* mFboResult; //Fbo and texture storing the result computation
|
||||
FloatTexture2D* mResultTexture;
|
||||
FloatTexture2D* mDirsResultTexture;
|
||||
FramebufferObject* mFboArray[3]; //Fbos and textures for depth peeling
|
||||
FloatTexture2D* mDepthTextureArray[3];
|
||||
FloatTexture2D* mColorTextureArray[3];
|
||||
unsigned int mPeelingTextureSize;
|
||||
float mTolerance;
|
||||
float mMinCos;
|
||||
float mTau; //obscurance exponent
|
||||
float mMinDist; //min dist between vertices to check too thin parts
|
||||
float mScale; //Scaling factor used to setup camera
|
||||
GPUProgram* mDeepthPeelingProgram;
|
||||
GPUProgram* mSDFProgram;
|
||||
GPUProgram* mObscuranceProgram;
|
||||
bool mRemoveFalse;
|
||||
bool mRemoveOutliers;
|
||||
GLuint mOcclusionQuery;
|
||||
GLuint mPixelCount;
|
||||
unsigned int mTempDepthComplexity;
|
||||
unsigned int mDepthComplexity;
|
||||
bool mDepthComplexityWarning;
|
||||
|
||||
CMeshO::PerFaceAttributeHandle<vcg::Point3f> mMaxQualityDirPerFace;
|
||||
CMeshO::PerVertexAttributeHandle<vcg::Point3f> mMaxQualityDirPerVertex;
|
||||
|
||||
};
|
||||
|
||||
#endif // FILTER_SDFGPU_H
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user