mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-20 03:16:10 +00:00
refactored the code and made the edge splitting predicate robust to non symmetric equations (with a non trascurable overhead)
This commit is contained in:
parent
74982c1a4f
commit
1d71ce2db5
@ -1,256 +1,267 @@
|
||||
/****************************************************************************
|
||||
* 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. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include <meshlab/meshmodel.h>
|
||||
|
||||
using namespace vcg;
|
||||
using namespace mu;
|
||||
|
||||
// MidPoint Function Object used by RefineE() to find new vertex position on splitted edge
|
||||
// Sets new attributes values on created vertex.
|
||||
template<class MESH_TYPE>
|
||||
struct MidPointCustom : public std::unary_function<face::Pos<typename MESH_TYPE::FaceType> , typename MESH_TYPE::CoordType >
|
||||
{
|
||||
public :
|
||||
MidPointCustom(std::string expr1, std::string expr2, std::string expr3, bool &error, std::string &msg)
|
||||
{
|
||||
// expr1, expr2, expr3 are parameters for x,y and z coord respectively
|
||||
this->p1.SetExpr(expr1);
|
||||
this->p2.SetExpr(expr2);
|
||||
this->p3.SetExpr(expr3);
|
||||
|
||||
this->setVars(p1);
|
||||
this->setVars(p2);
|
||||
this->setVars(p3);
|
||||
this->varDefined = false;
|
||||
|
||||
// this piece of code is used only to test expressions and
|
||||
// return a message in case of muparser's error
|
||||
try {
|
||||
p1.Eval();
|
||||
p2.Eval();
|
||||
p3.Eval();
|
||||
} catch(Parser::exception_type &e) {
|
||||
msg = e.GetMsg().c_str();
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(typename MESH_TYPE::VertexType &nv, face::Pos<typename MESH_TYPE::FaceType> ep)
|
||||
{
|
||||
// set variables only the first time. parser doesn't work otherwise
|
||||
if(!varDefined)
|
||||
{
|
||||
this->setVars(p1);
|
||||
this->setVars(p2);
|
||||
this->setVars(p3);
|
||||
this->varDefined = true;
|
||||
}
|
||||
|
||||
// first and second vertex of current edge
|
||||
x0 = ep.f->V(ep.z)->P()[0];
|
||||
y0 = ep.f->V(ep.z)->P()[1];
|
||||
z0 = ep.f->V(ep.z)->P()[2];
|
||||
|
||||
x1 = ep.f->V1(ep.z)->P()[0];
|
||||
y1 = ep.f->V1(ep.z)->P()[1];
|
||||
z1 = ep.f->V1(ep.z)->P()[2];
|
||||
|
||||
// new midpoint
|
||||
nv.P() = Point3f(p1.Eval(),p2.Eval(),p3.Eval());
|
||||
|
||||
|
||||
if( MESH_TYPE::HasPerVertexColor())
|
||||
{
|
||||
// calculate new R,G,B component for midpoint based on the distance of two vertices
|
||||
// and color distance.
|
||||
float distance_r = math::Abs((float)ep.f->V(ep.z)->C()[0] - (float)ep.f->V1(ep.z)->C()[0]);
|
||||
float distance_g = math::Abs((float)ep.f->V(ep.z)->C()[1] - (float)ep.f->V1(ep.z)->C()[1]);
|
||||
float distance_b = math::Abs((float)ep.f->V(ep.z)->C()[2] - (float)ep.f->V1(ep.z)->C()[2]);
|
||||
double clength = Distance(ep.f->V(ep.z)->P(), ep.f->V1(ep.z)->P());
|
||||
|
||||
double r = Distance(ep.f->V(ep.z)->P(),nv.P()) * (distance_r / clength);
|
||||
double g = Distance(ep.f->V(ep.z)->P(),nv.P()) * (distance_g / clength);
|
||||
double b = Distance(ep.f->V(ep.z)->P(),nv.P()) * (distance_b / clength);
|
||||
|
||||
// set R component
|
||||
if(ep.f->V(ep.z)->C()[0] < ep.f->V1(ep.z)->C()[0])
|
||||
nv.C()[0] = ep.f->V(ep.z)->C()[0] +r;
|
||||
else nv.C()[0] = ep.f->V(ep.z)->C()[0] -r;
|
||||
|
||||
// set G component
|
||||
if(ep.f->V(ep.z)->C()[1] < ep.f->V1(ep.z)->C()[1])
|
||||
nv.C()[1] = ep.f->V(ep.z)->C()[1] +g;
|
||||
else nv.C()[1] = ep.f->V(ep.z)->C()[1] -g;
|
||||
|
||||
// set B component
|
||||
if(ep.f->V(ep.z)->C()[2] < ep.f->V1(ep.z)->C()[2])
|
||||
nv.C()[2] = ep.f->V(ep.z)->C()[2] +b;
|
||||
else nv.C()[2] = ep.f->V(ep.z)->C()[2] -b;
|
||||
}
|
||||
|
||||
if( MESH_TYPE::HasPerVertexQuality())
|
||||
{
|
||||
// calculate new quality for midpoint based on the distance of two vertices
|
||||
// and quality distance
|
||||
double f = Distance(ep.f->V(ep.z)->P(),nv.P()) *
|
||||
(math::Abs(ep.f->V(ep.z)->Q() - ep.f->V1(ep.z)->Q()) / Distance(ep.f->V(ep.z)->P(), ep.f->V1(ep.z)->P()));
|
||||
|
||||
if(ep.f->V(ep.z)->Q() < ep.f->V1(ep.z)->Q())
|
||||
nv.Q() = ep.f->V(ep.z)->Q() + f;
|
||||
else nv.Q() = ep.f->V(ep.z)->Q() - f;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// raw calculation for wedgeinterp
|
||||
Color4<typename MESH_TYPE::ScalarType> WedgeInterp(Color4<typename MESH_TYPE::ScalarType> &c0, Color4<typename MESH_TYPE::ScalarType> &c1)
|
||||
{
|
||||
Color4<CMeshO::ScalarType> cc;
|
||||
return cc.lerp(c0,c1,0.5f);
|
||||
}
|
||||
|
||||
template<class FL_TYPE>
|
||||
TexCoord2<FL_TYPE,1> WedgeInterp(TexCoord2<FL_TYPE,1> &t0, TexCoord2<FL_TYPE,1> &t1)
|
||||
{
|
||||
TexCoord2<FL_TYPE,1> tmp;
|
||||
assert(t0.n()== t1.n());
|
||||
tmp.n()=t0.n();
|
||||
tmp.t()=(t0.t()+t1.t())/2.0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
protected:
|
||||
Parser p1,p2,p3;
|
||||
bool varDefined;
|
||||
double x0,y0,z0,x1,y1,z1;
|
||||
|
||||
// parser variables
|
||||
void setVars(Parser &p)
|
||||
{
|
||||
p.DefineVar("x0", &x0);
|
||||
p.DefineVar("y0", &y0);
|
||||
p.DefineVar("z0", &z0);
|
||||
p.DefineVar("x1", &x1);
|
||||
p.DefineVar("y1", &y1);
|
||||
p.DefineVar("z1", &z1);
|
||||
}
|
||||
};
|
||||
|
||||
// Edge pred function object used by RefineE() to choose which edges are selected to refine.
|
||||
// expr is a string that represents a boolean function evaluated by muparser
|
||||
template <class MESH_TYPE>
|
||||
class CustomEdge
|
||||
{
|
||||
public:
|
||||
CustomEdge(std::string expr, bool &error, std::string &msg)
|
||||
{
|
||||
// set expression and variables needed by parser
|
||||
this->p.SetExpr(expr);
|
||||
this->setVars(p);
|
||||
this->varDefined = false;
|
||||
|
||||
// check error
|
||||
try {
|
||||
p.Eval();
|
||||
} catch(Parser::exception_type &e) {
|
||||
msg = e.GetMsg().c_str();
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator()(face::Pos<typename MESH_TYPE::FaceType> ep)
|
||||
{
|
||||
// set variables only the first time. parser doesn't work otherwise
|
||||
if(!varDefined)
|
||||
{
|
||||
this->setVars(p);
|
||||
this->varDefined = true;
|
||||
}
|
||||
|
||||
// parser variables are related to vertex attributes
|
||||
// set coords, normals, quality for the two edge's vertices
|
||||
x0 = ep.f->V(ep.z)->P()[0];
|
||||
y0 = ep.f->V(ep.z)->P()[1];
|
||||
z0 = ep.f->V(ep.z)->P()[2];
|
||||
|
||||
x1 = ep.f->V1(ep.z)->P()[0];
|
||||
y1 = ep.f->V1(ep.z)->P()[1];
|
||||
z1 = ep.f->V1(ep.z)->P()[2];
|
||||
|
||||
nx0 = ep.f->V(ep.z)->N()[0];
|
||||
ny0 = ep.f->V(ep.z)->N()[1];
|
||||
nz0 = ep.f->V(ep.z)->N()[2];
|
||||
|
||||
nx1 = ep.f->V1(ep.z)->N()[0];
|
||||
ny1 = ep.f->V1(ep.z)->N()[1];
|
||||
nz1 = ep.f->V1(ep.z)->N()[2];
|
||||
|
||||
r0 = ep.f->V(ep.z)->C()[0];
|
||||
g0 = ep.f->V(ep.z)->C()[1];
|
||||
b0 = ep.f->V(ep.z)->C()[2];
|
||||
|
||||
r1 = ep.f->V1(ep.z)->C()[0];
|
||||
g1 = ep.f->V1(ep.z)->C()[1];
|
||||
b1 = ep.f->V1(ep.z)->C()[2];
|
||||
|
||||
q0 = ep.f->V(ep.z)->Q();
|
||||
q1 = ep.f->V1(ep.z)->Q();
|
||||
|
||||
return p.Eval();
|
||||
}
|
||||
protected:
|
||||
Parser p;
|
||||
bool varDefined;
|
||||
double x0,y0,z0,x1,y1,z1,nx0,ny0,nz0,nx1,ny1,nz1,r0,g0,b0,r1,g1,b1,q0,q1;
|
||||
|
||||
// parser variables
|
||||
void setVars(Parser &p)
|
||||
{
|
||||
p.DefineVar("x0", &x0);
|
||||
p.DefineVar("y0", &y0);
|
||||
p.DefineVar("z0", &z0);
|
||||
p.DefineVar("x1", &x1);
|
||||
p.DefineVar("y1", &y1);
|
||||
p.DefineVar("z1", &z1);
|
||||
|
||||
p.DefineVar("nx0", &nx0);
|
||||
p.DefineVar("ny0", &ny0);
|
||||
p.DefineVar("nz0", &nz0);
|
||||
|
||||
p.DefineVar("nx1", &nx1);
|
||||
p.DefineVar("ny1", &ny1);
|
||||
p.DefineVar("nz1", &nz1);
|
||||
|
||||
p.DefineVar("r0", &r0);
|
||||
p.DefineVar("g0", &g0);
|
||||
p.DefineVar("b0", &b0);
|
||||
|
||||
p.DefineVar("r1", &r1);
|
||||
p.DefineVar("g1", &g1);
|
||||
p.DefineVar("b1", &b1);
|
||||
|
||||
p.DefineVar("q0", &q0);
|
||||
p.DefineVar("q1", &q1);
|
||||
}
|
||||
/****************************************************************************
|
||||
* 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. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include <meshlab/meshmodel.h>
|
||||
|
||||
using namespace vcg;
|
||||
using namespace mu;
|
||||
|
||||
// MidPoint Function Object used by RefineE() to find new vertex position on splitted edge
|
||||
// Sets new attributes values on created vertex.
|
||||
template<class MESH_TYPE>
|
||||
struct MidPointCustom : public std::unary_function<face::Pos<typename MESH_TYPE::FaceType> , typename MESH_TYPE::CoordType >
|
||||
{
|
||||
public :
|
||||
MidPointCustom(std::string expr1, std::string expr2, std::string expr3, bool &error, std::string &msg)
|
||||
{
|
||||
// expr1, expr2, expr3 are parameters for x,y and z coord respectively
|
||||
this->p1.SetExpr(expr1);
|
||||
this->p2.SetExpr(expr2);
|
||||
this->p3.SetExpr(expr3);
|
||||
|
||||
this->setVars(p1);
|
||||
this->setVars(p2);
|
||||
this->setVars(p3);
|
||||
this->varDefined = false;
|
||||
|
||||
// this piece of code is used only to test expressions and
|
||||
// return a message in case of muparser's error
|
||||
try {
|
||||
p1.Eval();
|
||||
p2.Eval();
|
||||
p3.Eval();
|
||||
} catch(Parser::exception_type &e) {
|
||||
msg = e.GetMsg().c_str();
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(typename MESH_TYPE::VertexType &nv, face::Pos<typename MESH_TYPE::FaceType> ep)
|
||||
{
|
||||
// set variables only the first time. parser doesn't work otherwise
|
||||
if(!varDefined)
|
||||
{
|
||||
this->setVars(p1);
|
||||
this->setVars(p2);
|
||||
this->setVars(p3);
|
||||
this->varDefined = true;
|
||||
}
|
||||
|
||||
// first and second vertex of current edge
|
||||
x0 = ep.V()->P()[0];
|
||||
y0 = ep.V()->P()[1];
|
||||
z0 = ep.V()->P()[2];
|
||||
|
||||
x1 = ep.VFlip()->P()[0];
|
||||
y1 = ep.VFlip()->P()[1];
|
||||
z1 = ep.VFlip()->P()[2];
|
||||
|
||||
// new midpoint
|
||||
nv.P() = Point3f(p1.Eval(),p2.Eval(),p3.Eval());
|
||||
|
||||
|
||||
if( MESH_TYPE::HasPerVertexColor())
|
||||
{
|
||||
// calculate new R,G,B component for midpoint based on the distance of two vertices
|
||||
// and color distance.
|
||||
float distance_r = math::Abs((float)ep.V()->C()[0] - (float)ep.VFlip()->C()[0]);
|
||||
float distance_g = math::Abs((float)ep.V()->C()[1] - (float)ep.VFlip()->C()[1]);
|
||||
float distance_b = math::Abs((float)ep.V()->C()[2] - (float)ep.VFlip()->C()[2]);
|
||||
double clength = Distance(ep.V()->P(), ep.VFlip()->P());
|
||||
|
||||
double r = Distance(ep.V()->P(),nv.P()) * (distance_r / clength);
|
||||
double g = Distance(ep.V()->P(),nv.P()) * (distance_g / clength);
|
||||
double b = Distance(ep.V()->P(),nv.P()) * (distance_b / clength);
|
||||
|
||||
// set R component
|
||||
if(ep.V()->C()[0] < ep.VFlip()->C()[0])
|
||||
nv.C()[0] = ep.V()->C()[0] +r;
|
||||
else nv.C()[0] = ep.V()->C()[0] -r;
|
||||
|
||||
// set G component
|
||||
if(ep.V()->C()[1] < ep.VFlip()->C()[1])
|
||||
nv.C()[1] = ep.V()->C()[1] +g;
|
||||
else nv.C()[1] = ep.V()->C()[1] -g;
|
||||
|
||||
// set B component
|
||||
if(ep.V()->C()[2] < ep.VFlip()->C()[2])
|
||||
nv.C()[2] = ep.V()->C()[2] +b;
|
||||
else nv.C()[2] = ep.V()->C()[2] -b;
|
||||
}
|
||||
|
||||
if( MESH_TYPE::HasPerVertexQuality())
|
||||
{
|
||||
// calculate new quality for midpoint based on the distance of two vertices
|
||||
// and quality distance
|
||||
double f = Distance(ep.V()->P(),nv.P()) *
|
||||
(math::Abs(ep.V()->Q() - ep.VFlip()->Q()) / Distance(ep.V()->P(), ep.VFlip()->P()));
|
||||
|
||||
if(ep.V()->Q() < ep.VFlip()->Q())
|
||||
nv.Q() = ep.V()->Q() + f;
|
||||
else nv.Q() = ep.V()->Q() - f;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// raw calculation for wedgeinterp
|
||||
Color4<typename MESH_TYPE::ScalarType> WedgeInterp(Color4<typename MESH_TYPE::ScalarType> &c0, Color4<typename MESH_TYPE::ScalarType> &c1)
|
||||
{
|
||||
Color4<CMeshO::ScalarType> cc;
|
||||
return cc.lerp(c0,c1,0.5f);
|
||||
}
|
||||
|
||||
template<class FL_TYPE>
|
||||
TexCoord2<FL_TYPE,1> WedgeInterp(TexCoord2<FL_TYPE,1> &t0, TexCoord2<FL_TYPE,1> &t1)
|
||||
{
|
||||
TexCoord2<FL_TYPE,1> tmp;
|
||||
assert(t0.n()== t1.n());
|
||||
tmp.n()=t0.n();
|
||||
tmp.t()=(t0.t()+t1.t())/2.0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
protected:
|
||||
Parser p1,p2,p3;
|
||||
bool varDefined;
|
||||
double x0,y0,z0,x1,y1,z1;
|
||||
|
||||
// parser variables
|
||||
void setVars(Parser &p)
|
||||
{
|
||||
p.DefineVar("x0", &x0);
|
||||
p.DefineVar("y0", &y0);
|
||||
p.DefineVar("z0", &z0);
|
||||
p.DefineVar("x1", &x1);
|
||||
p.DefineVar("y1", &y1);
|
||||
p.DefineVar("z1", &z1);
|
||||
}
|
||||
};
|
||||
|
||||
// Edge pred function object used by RefineE() to choose which edges are selected to refine.
|
||||
// expr is a string that represents a boolean function evaluated by muparser
|
||||
template <class MESH_TYPE>
|
||||
class CustomEdge
|
||||
{
|
||||
public:
|
||||
CustomEdge(std::string expr, bool &error, std::string &msg)
|
||||
{
|
||||
// set expression and variables needed by parser
|
||||
this->p.SetExpr(expr);
|
||||
this->setVars(p);
|
||||
this->varDefined = false;
|
||||
|
||||
// check error
|
||||
try {
|
||||
p.Eval();
|
||||
} catch(Parser::exception_type &e) {
|
||||
msg = e.GetMsg().c_str();
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator()(face::Pos<typename MESH_TYPE::FaceType> ep)
|
||||
{
|
||||
// set variables only the first time. parser doesn't work otherwise
|
||||
if(!varDefined)
|
||||
{
|
||||
this->setVars(p);
|
||||
this->varDefined = true;
|
||||
}
|
||||
|
||||
setVarVal(ep);
|
||||
|
||||
bool ret = p.Eval();
|
||||
ep.FlipV();
|
||||
setVarVal(ep);
|
||||
ret = ret | bool(p.Eval());
|
||||
|
||||
qDebug("Eval returned %i (%f %f",ret?1:0,x0,x1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void setVarVal(face::Pos<typename MESH_TYPE::FaceType> &ep)
|
||||
{
|
||||
// parser variables are related to vertex attributes
|
||||
// set coords, normals, quality for the two edge's vertices
|
||||
x0 = ep.V()->P()[0];
|
||||
y0 = ep.V()->P()[1];
|
||||
z0 = ep.V()->P()[2];
|
||||
|
||||
x1 = ep.VFlip()->P()[0];
|
||||
y1 = ep.VFlip()->P()[1];
|
||||
z1 = ep.VFlip()->P()[2];
|
||||
|
||||
nx0 = ep.V()->N()[0];
|
||||
ny0 = ep.V()->N()[1];
|
||||
nz0 = ep.V()->N()[2];
|
||||
|
||||
nx1 = ep.VFlip()->N()[0];
|
||||
ny1 = ep.VFlip()->N()[1];
|
||||
nz1 = ep.VFlip()->N()[2];
|
||||
|
||||
r0 = ep.V()->C()[0];
|
||||
g0 = ep.V()->C()[1];
|
||||
b0 = ep.V()->C()[2];
|
||||
|
||||
r1 = ep.VFlip()->C()[0];
|
||||
g1 = ep.VFlip()->C()[1];
|
||||
b1 = ep.VFlip()->C()[2];
|
||||
|
||||
q0 = ep.V()->Q();
|
||||
q1 = ep.VFlip()->Q();
|
||||
}
|
||||
protected:
|
||||
Parser p;
|
||||
bool varDefined;
|
||||
double x0,y0,z0,x1,y1,z1,nx0,ny0,nz0,nx1,ny1,nz1,r0,g0,b0,r1,g1,b1,q0,q1;
|
||||
|
||||
// parser variables
|
||||
void setVars(Parser &p)
|
||||
{
|
||||
p.DefineVar("x0", &x0);
|
||||
p.DefineVar("y0", &y0);
|
||||
p.DefineVar("z0", &z0);
|
||||
p.DefineVar("x1", &x1);
|
||||
p.DefineVar("y1", &y1);
|
||||
p.DefineVar("z1", &z1);
|
||||
|
||||
p.DefineVar("nx0", &nx0);
|
||||
p.DefineVar("ny0", &ny0);
|
||||
p.DefineVar("nz0", &nz0);
|
||||
|
||||
p.DefineVar("nx1", &nx1);
|
||||
p.DefineVar("ny1", &ny1);
|
||||
p.DefineVar("nz1", &nz1);
|
||||
|
||||
p.DefineVar("r0", &r0);
|
||||
p.DefineVar("g0", &g0);
|
||||
p.DefineVar("b0", &b0);
|
||||
|
||||
p.DefineVar("r1", &r1);
|
||||
p.DefineVar("g1", &g1);
|
||||
p.DefineVar("b1", &b1);
|
||||
|
||||
p.DefineVar("q0", &q0);
|
||||
p.DefineVar("q1", &q1);
|
||||
}
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user