removed a few point3f and changed into coordTypes

This commit is contained in:
Paolo Cignoni 2014-06-17 13:42:10 +00:00
parent 3e4c020642
commit b389e3a314
1 changed files with 444 additions and 442 deletions

View File

@ -46,15 +46,15 @@ namespace tri{
/* /*
Metodo di Loop dalla documentazione "Siggraph 2000 course on subdivision" Metodo di Loop dalla documentazione "Siggraph 2000 course on subdivision"
d4------d3 d4------d3 d4------d3 d4------d3
/ \ / \ / \ / \ u / \ / \ / \ / \ u
/ \ / \ / e4--e3 \ / \ / \ / \ / e4--e3 \ / \
/ \/ \ / / \/ \ \ / \ / \/ \ / / \/ \ \ / \
d5------d1------d2 -> d5--e5--d1--e2--d2 l--M--r d5------d1------d2 -> d5--e5--d1--e2--d2 l--M--r
\ /\ / \ \ /\ / / \ / \ /\ / \ \ /\ / / \ /
\ / \ / \ e6--e7 / \ / \ / \ / \ e6--e7 / \ /
\ / \ / \ / \ / d \ / \ / \ / \ / d
d6------d7 d6------d7 d6------d7 d6------d7
******************************************************* *******************************************************
@ -67,19 +67,19 @@ d5------d1------d2 -> d5--e5--d1--e2--d2 l--M--r
*/ */
template<class SCALAR_TYPE> template<class SCALAR_TYPE>
struct LoopWeight { struct LoopWeight {
inline SCALAR_TYPE beta(int k) { inline SCALAR_TYPE beta(int k) {
return (k>3)?(5.0/8.0 - std::pow((3.0/8.0 + std::cos(2.0*M_PI/SCALAR_TYPE(k))/4.0),2))/SCALAR_TYPE(k):3.0/16.0; return (k>3)?(5.0/8.0 - std::pow((3.0/8.0 + std::cos(2.0*M_PI/SCALAR_TYPE(k))/4.0),2))/SCALAR_TYPE(k):3.0/16.0;
} }
inline SCALAR_TYPE incidentRegular(int) { inline SCALAR_TYPE incidentRegular(int) {
return 3.0/8.0; return 3.0/8.0;
} }
inline SCALAR_TYPE incidentIrregular(int) { inline SCALAR_TYPE incidentIrregular(int) {
return 3.0/8.0; return 3.0/8.0;
} }
inline SCALAR_TYPE opposite(int) { inline SCALAR_TYPE opposite(int) {
return 1.0/8.0; return 1.0/8.0;
} }
}; };
/*! /*!
@ -89,114 +89,114 @@ struct LoopWeight {
*/ */
template<class SCALAR_TYPE> template<class SCALAR_TYPE>
struct RegularLoopWeight { struct RegularLoopWeight {
inline SCALAR_TYPE beta(int k) { inline SCALAR_TYPE beta(int k) {
static SCALAR_TYPE bkPolar[] = { static SCALAR_TYPE bkPolar[] = {
.32517, .32517,
.49954, .49954,
.59549, .59549,
.625, .625,
.63873, .63873,
.64643, .64643,
.65127, .65127,
.67358, .67358,
.68678, .68678,
.69908 .69908
}; };
return (k<=12)?(1.0-bkPolar[k-3])/k:LoopWeight<SCALAR_TYPE>().beta(k); return (k<=12)?(1.0-bkPolar[k-3])/k:LoopWeight<SCALAR_TYPE>().beta(k);
} }
inline SCALAR_TYPE incidentRegular(int k) { inline SCALAR_TYPE incidentRegular(int k) {
return 1.0 - incidentIrregular(k) - opposite(k)*2; return 1.0 - incidentIrregular(k) - opposite(k)*2;
} }
inline SCALAR_TYPE incidentIrregular(int k) { inline SCALAR_TYPE incidentIrregular(int k) {
static SCALAR_TYPE bkPolar[] = { static SCALAR_TYPE bkPolar[] = {
.15658, .15658,
.25029, .25029,
.34547, .34547,
.375, .375,
.38877, .38877,
.39644, .39644,
.40132, .40132,
.42198, .42198,
.43423, .43423,
.44579 .44579
}; };
return (k<=12)?bkPolar[k-3]:LoopWeight<SCALAR_TYPE>().incidentIrregular(k); return (k<=12)?bkPolar[k-3]:LoopWeight<SCALAR_TYPE>().incidentIrregular(k);
} }
inline SCALAR_TYPE opposite(int k) { inline SCALAR_TYPE opposite(int k) {
static SCALAR_TYPE bkPolar[] = { static SCALAR_TYPE bkPolar[] = {
.14427, .14427,
.12524, .12524,
.11182, .11182,
.125, .125,
.14771, .14771,
.1768, .1768,
.21092, .21092,
.20354, .20354,
.20505, .20505,
.19828 .19828
}; };
return (k<=12)?bkPolar[k-3]:LoopWeight<SCALAR_TYPE>().opposite(k); return (k<=12)?bkPolar[k-3]:LoopWeight<SCALAR_TYPE>().opposite(k);
} }
}; };
template<class SCALAR_TYPE> template<class SCALAR_TYPE>
struct ContinuityLoopWeight { struct ContinuityLoopWeight {
inline SCALAR_TYPE beta(int k) { inline SCALAR_TYPE beta(int k) {
static SCALAR_TYPE bkPolar[] = { static SCALAR_TYPE bkPolar[] = {
.32517, .32517,
.50033, .50033,
.59464, .59464,
.625, .625,
.63903, .63903,
.67821, .67821,
.6866, .6866,
.69248, .69248,
.69678, .69678,
.70014 .70014
}; };
return (k<=12)?(1.0-bkPolar[k-3])/k:LoopWeight<SCALAR_TYPE>().beta(k); return (k<=12)?(1.0-bkPolar[k-3])/k:LoopWeight<SCALAR_TYPE>().beta(k);
} }
inline SCALAR_TYPE incidentRegular(int k) { inline SCALAR_TYPE incidentRegular(int k) {
return 1.0 - incidentIrregular(k) - opposite(k)*2; return 1.0 - incidentIrregular(k) - opposite(k)*2;
} }
inline SCALAR_TYPE incidentIrregular(int k) { inline SCALAR_TYPE incidentIrregular(int k) {
static SCALAR_TYPE bkPolar[] = { static SCALAR_TYPE bkPolar[] = {
.15658, .15658,
.26721, .26721,
.33539, .33539,
.375, .375,
.36909, .36909,
.25579, .25579,
.2521, .2521,
.24926, .24926,
.24706, .24706,
.2452 .2452
}; };
return (k<=12)?bkPolar[k-3]:LoopWeight<SCALAR_TYPE>().incidentIrregular(k); return (k<=12)?bkPolar[k-3]:LoopWeight<SCALAR_TYPE>().incidentIrregular(k);
} }
inline SCALAR_TYPE opposite(int k) { inline SCALAR_TYPE opposite(int k) {
static SCALAR_TYPE bkPolar[] = { static SCALAR_TYPE bkPolar[] = {
.14427, .14427,
.12495, .12495,
.11252, .11252,
.125, .125,
.14673, .14673,
.16074, .16074,
.18939, .18939,
.2222, .2222,
.25894, .25894,
.29934 .29934
}; };
return (k<=12)?bkPolar[k-3]:LoopWeight<SCALAR_TYPE>().opposite(k); return (k<=12)?bkPolar[k-3]:LoopWeight<SCALAR_TYPE>().opposite(k);
} }
}; };
// Centroid and LS3Projection classes may be pettre placed in an other file. (which one ?) // Centroid and LS3Projection classes may be pettre placed in an other file. (which one ?)
@ -206,28 +206,28 @@ struct ContinuityLoopWeight {
*/ */
template<class MESH_TYPE, class LSCALAR_TYPE = typename MESH_TYPE::ScalarType> template<class MESH_TYPE, class LSCALAR_TYPE = typename MESH_TYPE::ScalarType>
struct Centroid { struct Centroid {
typedef typename MESH_TYPE::ScalarType Scalar; typedef typename MESH_TYPE::ScalarType Scalar;
typedef typename MESH_TYPE::CoordType Coord; typedef typename MESH_TYPE::CoordType CoordType;
typedef LSCALAR_TYPE LScalar; typedef LSCALAR_TYPE LScalar;
typedef vcg::Point3<LScalar> LVector; typedef vcg::Point3<LScalar> LVector;
LVector sumP; LVector sumP;
LScalar sumW; LScalar sumW;
Centroid() { reset(); } Centroid() { reset(); }
inline void reset() { inline void reset() {
sumP.SetZero(); sumP.SetZero();
sumW = 0.; sumW = 0.;
} }
inline void addVertex(const typename MESH_TYPE::VertexType &v, LScalar w) { inline void addVertex(const typename MESH_TYPE::VertexType &v, LScalar w) {
LVector p(v.cP().X(), v.cP().Y(), v.cP().Z()); LVector p(v.cP().X(), v.cP().Y(), v.cP().Z());
sumP += p * w; sumP += p * w;
sumW += w; sumW += w;
} }
inline void project(std::pair<Point3f,Point3f> &nv) const { inline void project(std::pair<CoordType,CoordType> &nv) const {
LVector position = sumP / sumW; LVector position = sumP / sumW;
nv.first = Coord(position.X(), position.Y(), position.Z()); nv.first = CoordType(position.X(), position.Y(), position.Z());
} }
}; };
/*! Implementation of the APSS projection for the LS3 scheme. /*! Implementation of the APSS projection for the LS3 scheme.
@ -241,291 +241,293 @@ struct Centroid {
*/ */
template<class MESH_TYPE, class LSCALAR_TYPE = typename MESH_TYPE::ScalarType> template<class MESH_TYPE, class LSCALAR_TYPE = typename MESH_TYPE::ScalarType>
struct LS3Projection { struct LS3Projection {
typedef typename MESH_TYPE::ScalarType Scalar; typedef typename MESH_TYPE::ScalarType Scalar;
typedef typename MESH_TYPE::CoordType Coord; typedef typename MESH_TYPE::CoordType CoordType;
typedef LSCALAR_TYPE LScalar; typedef LSCALAR_TYPE LScalar;
typedef vcg::Point3<LScalar> LVector; typedef vcg::Point3<LScalar> LVector;
Scalar beta; Scalar beta;
LVector sumP; LVector sumP;
LVector sumN; LVector sumN;
LScalar sumDotPN; LScalar sumDotPN;
LScalar sumDotPP; LScalar sumDotPP;
LScalar sumW; LScalar sumW;
inline LS3Projection(Scalar beta = 1.0) : beta(beta) { reset(); } inline LS3Projection(Scalar beta = 1.0) : beta(beta) { reset(); }
inline void reset() { inline void reset() {
sumP.SetZero(); sumP.SetZero();
sumN.SetZero(); sumN.SetZero();
sumDotPN = 0.; sumDotPN = 0.;
sumDotPP = 0.; sumDotPP = 0.;
sumW = 0.; sumW = 0.;
} }
inline void addVertex(const typename MESH_TYPE::VertexType &v, LScalar w) { inline void addVertex(const typename MESH_TYPE::VertexType &v, LScalar w) {
LVector p(v.cP().X(), v.cP().Y(), v.cP().Z()); LVector p(v.cP().X(), v.cP().Y(), v.cP().Z());
LVector n(v.cN().X(), v.cN().Y(), v.cN().Z()); LVector n(v.cN().X(), v.cN().Y(), v.cN().Z());
sumP += p * w; sumP += p * w;
sumN += n * w; sumN += n * w;
sumDotPN += w * n.dot(p); sumDotPN += w * n.dot(p);
sumDotPP += w * vcg::SquaredNorm(p); sumDotPP += w * vcg::SquaredNorm(p);
sumW += w; sumW += w;
} }
void project(std::pair<Point3f,Point3f> &nv) const { void project(std::pair<CoordType,CoordType> &nv) const {
LScalar invSumW = Scalar(1)/sumW; LScalar invSumW = Scalar(1)/sumW;
LScalar aux4 = beta * LScalar(0.5) * LScalar aux4 = beta * LScalar(0.5) *
(sumDotPN - invSumW*sumP.dot(sumN)) (sumDotPN - invSumW*sumP.dot(sumN))
/(sumDotPP - invSumW*vcg::SquaredNorm(sumP)); /(sumDotPP - invSumW*vcg::SquaredNorm(sumP));
LVector uLinear = (sumN-sumP*(Scalar(2)*aux4))*invSumW; LVector uLinear = (sumN-sumP*(Scalar(2)*aux4))*invSumW;
LScalar uConstant = -invSumW*(uLinear.dot(sumP) + sumDotPP*aux4); LScalar uConstant = -invSumW*(uLinear.dot(sumP) + sumDotPP*aux4);
LScalar uQuad = aux4; LScalar uQuad = aux4;
LVector orig = sumP*invSumW; LVector orig = sumP*invSumW;
// finalize // finalize
LVector position; LVector position;
LVector normal; LVector normal;
if (fabs(uQuad)>1e-7) if (fabs(uQuad)>1e-7)
{ {
LScalar b = 1./uQuad; LScalar b = 1./uQuad;
LVector center = uLinear*(-0.5*b); LVector center = uLinear*(-0.5*b);
LScalar radius = sqrt( vcg::SquaredNorm(center) - b*uConstant ); LScalar radius = sqrt( vcg::SquaredNorm(center) - b*uConstant );
normal = orig - center; normal = orig - center;
normal.Normalize(); normal.Normalize();
position = center + normal * radius; position = center + normal * radius;
normal = uLinear + position * (LScalar(2) * uQuad); normal = uLinear + position * (LScalar(2) * uQuad);
normal.Normalize(); normal.Normalize();
} }
else if (uQuad==0.) else if (uQuad==0.)
{ {
LScalar s = LScalar(1)/vcg::Norm(uLinear); LScalar s = LScalar(1)/vcg::Norm(uLinear);
assert(!vcg::math::IsNAN(s) && "normal should not have zero len!"); assert(!vcg::math::IsNAN(s) && "normal should not have zero len!");
uLinear *= s; uLinear *= s;
uConstant *= s; uConstant *= s;
normal = uLinear; normal = uLinear;
position = orig - uLinear * (orig.dot(uLinear) + uConstant); position = orig - uLinear * (orig.dot(uLinear) + uConstant);
} }
else else
{ {
// normalize the gradient // normalize the gradient
LScalar f = 1./sqrt(vcg::SquaredNorm(uLinear) - Scalar(4)*uConstant*uQuad); LScalar f = 1./sqrt(vcg::SquaredNorm(uLinear) - Scalar(4)*uConstant*uQuad);
uConstant *= f; uConstant *= f;
uLinear *= f; uLinear *= f;
uQuad *= f; uQuad *= f;
// Newton iterations // Newton iterations
LVector grad; LVector grad;
LVector dir = uLinear+orig*(2.*uQuad); LVector dir = uLinear+orig*(2.*uQuad);
LScalar ilg = 1./vcg::Norm(dir); LScalar ilg = 1./vcg::Norm(dir);
dir *= ilg; dir *= ilg;
LScalar ad = uConstant + uLinear.dot(orig) + uQuad * vcg::SquaredNorm(orig); LScalar ad = uConstant + uLinear.dot(orig) + uQuad * vcg::SquaredNorm(orig);
LScalar delta = -ad*std::min<Scalar>(ilg,1.); LScalar delta = -ad*std::min<Scalar>(ilg,1.);
LVector p = orig + dir*delta; LVector p = orig + dir*delta;
for (int i=0 ; i<2 ; ++i) for (int i=0 ; i<2 ; ++i)
{ {
grad = uLinear+p*(2.*uQuad); grad = uLinear+p*(2.*uQuad);
ilg = 1./vcg::Norm(grad); ilg = 1./vcg::Norm(grad);
delta = -(uConstant + uLinear.dot(p) + uQuad * vcg::SquaredNorm(p))*std::min<Scalar>(ilg,1.); delta = -(uConstant + uLinear.dot(p) + uQuad * vcg::SquaredNorm(p))*std::min<Scalar>(ilg,1.);
p += dir*delta; p += dir*delta;
} }
position = p; position = p;
normal = uLinear + position * (Scalar(2) * uQuad); normal = uLinear + position * (Scalar(2) * uQuad);
normal.Normalize(); normal.Normalize();
} }
nv.first = Coord(position.X(), position.Y(), position.Z()); nv.first = Coord(position.X(), position.Y(), position.Z());
nv.second = Coord(normal.X(), normal.Y(), normal.Z()); nv.second = Coord(normal.X(), normal.Y(), normal.Z());
} }
}; };
template<class MESH_TYPE, class METHOD_TYPE=Centroid<MESH_TYPE>, class WEIGHT_TYPE=LoopWeight<typename MESH_TYPE::ScalarType> > template<class MESH_TYPE, class METHOD_TYPE=Centroid<MESH_TYPE>, class WEIGHT_TYPE=LoopWeight<typename MESH_TYPE::ScalarType> >
struct OddPointLoopGeneric : public std::unary_function<face::Pos<typename MESH_TYPE::FaceType> , typename MESH_TYPE::VertexType> struct OddPointLoopGeneric : public std::unary_function<face::Pos<typename MESH_TYPE::FaceType> , typename MESH_TYPE::VertexType>
{ {
typedef METHOD_TYPE Projection; typedef METHOD_TYPE Projection;
typedef WEIGHT_TYPE Weight; typedef WEIGHT_TYPE Weight;
typedef typename MESH_TYPE::template PerVertexAttributeHandle<int> ValenceAttr; typedef typename MESH_TYPE::template PerVertexAttributeHandle<int> ValenceAttr;
typedef typename MESH_TYPE::CoordType CoordType;
MESH_TYPE &m; MESH_TYPE &m;
Projection proj; Projection proj;
Weight weight; Weight weight;
ValenceAttr *valence; ValenceAttr *valence;
inline OddPointLoopGeneric(MESH_TYPE &_m, Projection proj = Projection(), Weight weight = Weight()) : inline OddPointLoopGeneric(MESH_TYPE &_m, Projection proj = Projection(), Weight weight = Weight()) :
m(_m), proj(proj), weight(weight), valence(0) {} m(_m), proj(proj), weight(weight), valence(0) {}
void operator()(typename MESH_TYPE::VertexType &nv, face::Pos<typename MESH_TYPE::FaceType> ep) { void operator()(typename MESH_TYPE::VertexType &nv, face::Pos<typename MESH_TYPE::FaceType> ep) {
proj.reset(); proj.reset();
face::Pos<typename MESH_TYPE::FaceType> he(ep.f,ep.z,ep.f->V(ep.z)); face::Pos<typename MESH_TYPE::FaceType> he(ep.f,ep.z,ep.f->V(ep.z));
typename MESH_TYPE::VertexType *l,*r,*u,*d; typename MESH_TYPE::VertexType *l,*r,*u,*d;
l = he.v; l = he.v;
he.FlipV(); he.FlipV();
r = he.v; r = he.v;
if( tri::HasPerVertexColor(m)) if( tri::HasPerVertexColor(m))
nv.C().lerp(ep.f->V(ep.z)->C(),ep.f->V1(ep.z)->C(),.5f); nv.C().lerp(ep.f->V(ep.z)->C(),ep.f->V1(ep.z)->C(),.5f);
if (he.IsBorder()) { if (he.IsBorder()) {
proj.addVertex(*l, 0.5); proj.addVertex(*l, 0.5);
proj.addVertex(*r, 0.5); proj.addVertex(*r, 0.5);
std::pair<Point3f,Point3f>pp; std::pair<CoordType,CoordType>pp;
proj.project(pp); proj.project(pp);
nv.P()=pp.first; nv.P()=pp.first;
nv.N()=pp.second; nv.N()=pp.second;
} }
else { else {
he.FlipE(); he.FlipV(); he.FlipE(); he.FlipV();
u = he.v; u = he.v;
he.FlipV(); he.FlipE(); he.FlipV(); he.FlipE();
assert(he.v == r); // back to r assert(he.v == r); // back to r
he.FlipF(); he.FlipE(); he.FlipV(); he.FlipF(); he.FlipE(); he.FlipV();
d = he.v; d = he.v;
if(valence && ((*valence)[l]==6 || (*valence)[r]==6)) { if(valence && ((*valence)[l]==6 || (*valence)[r]==6)) {
int extra = ((*valence)[l]==6)?(*valence)[r]:(*valence)[l]; int extra = ((*valence)[l]==6)?(*valence)[r]:(*valence)[l];
proj.addVertex(*l, ((*valence)[l]==6)?weight.incidentRegular(extra):weight.incidentIrregular(extra)); proj.addVertex(*l, ((*valence)[l]==6)?weight.incidentRegular(extra):weight.incidentIrregular(extra));
proj.addVertex(*r, ((*valence)[r]==6)?weight.incidentRegular(extra):weight.incidentIrregular(extra)); proj.addVertex(*r, ((*valence)[r]==6)?weight.incidentRegular(extra):weight.incidentIrregular(extra));
proj.addVertex(*u, weight.opposite(extra)); proj.addVertex(*u, weight.opposite(extra));
proj.addVertex(*d, weight.opposite(extra)); proj.addVertex(*d, weight.opposite(extra));
} }
// unhandled case that append only at first subdivision step: use Loop's weights // unhandled case that append only at first subdivision step: use Loop's weights
else { else {
proj.addVertex(*l, 3.0/8.0); proj.addVertex(*l, 3.0/8.0);
proj.addVertex(*r, 3.0/8.0); proj.addVertex(*r, 3.0/8.0);
proj.addVertex(*u, 1.0/8.0); proj.addVertex(*u, 1.0/8.0);
proj.addVertex(*d, 1.0/8.0); proj.addVertex(*d, 1.0/8.0);
} }
std::pair<Point3f,Point3f>pp; std::pair<CoordType,CoordType>pp;
proj.project(pp); proj.project(pp);
nv.P()=pp.first; nv.P()=pp.first;
nv.N()=pp.second; nv.N()=pp.second;
// proj.project(nv); // proj.project(nv);
} }
} }
Color4<typename MESH_TYPE::ScalarType> WedgeInterp(Color4<typename MESH_TYPE::ScalarType> &c0, Color4<typename MESH_TYPE::ScalarType> &c1) Color4<typename MESH_TYPE::ScalarType> WedgeInterp(Color4<typename MESH_TYPE::ScalarType> &c0, Color4<typename MESH_TYPE::ScalarType> &c1)
{ {
Color4<typename MESH_TYPE::ScalarType> cc; Color4<typename MESH_TYPE::ScalarType> cc;
return cc.lerp(c0,c1,0.5f); return cc.lerp(c0,c1,0.5f);
} }
template<class FL_TYPE> template<class FL_TYPE>
TexCoord2<FL_TYPE,1> WedgeInterp(TexCoord2<FL_TYPE,1> &t0, TexCoord2<FL_TYPE,1> &t1) TexCoord2<FL_TYPE,1> WedgeInterp(TexCoord2<FL_TYPE,1> &t0, TexCoord2<FL_TYPE,1> &t1)
{ {
TexCoord2<FL_TYPE,1> tmp; TexCoord2<FL_TYPE,1> tmp;
tmp.n()=t0.n(); tmp.n()=t0.n();
tmp.t()=(t0.t()+t1.t())/2.0; tmp.t()=(t0.t()+t1.t())/2.0;
return tmp; return tmp;
} }
inline void setValenceAttr(ValenceAttr *valence) { inline void setValenceAttr(ValenceAttr *valence) {
this->valence = valence; this->valence = valence;
} }
}; };
template<class MESH_TYPE, class METHOD_TYPE=Centroid<MESH_TYPE>, class WEIGHT_TYPE=LoopWeight<typename MESH_TYPE::ScalarType> > template<class MESH_TYPE, class METHOD_TYPE=Centroid<MESH_TYPE>, class WEIGHT_TYPE=LoopWeight<typename MESH_TYPE::ScalarType> >
struct EvenPointLoopGeneric : public std::unary_function<face::Pos<typename MESH_TYPE::FaceType> , typename MESH_TYPE::VertexType> struct EvenPointLoopGeneric : public std::unary_function<face::Pos<typename MESH_TYPE::FaceType> , typename MESH_TYPE::VertexType>
{ {
typedef METHOD_TYPE Projection; typedef METHOD_TYPE Projection;
typedef WEIGHT_TYPE Weight; typedef WEIGHT_TYPE Weight;
typedef typename MESH_TYPE::template PerVertexAttributeHandle<int> ValenceAttr; typedef typename MESH_TYPE::template PerVertexAttributeHandle<int> ValenceAttr;
typedef typename MESH_TYPE::CoordType CoordType;
Projection proj; Projection proj;
Weight weight; Weight weight;
ValenceAttr *valence; ValenceAttr *valence;
inline EvenPointLoopGeneric(Projection proj = Projection(), Weight weight = Weight()) : inline EvenPointLoopGeneric(Projection proj = Projection(), Weight weight = Weight()) :
proj(proj), weight(weight), valence(0) {} proj(proj), weight(weight), valence(0) {}
void operator()(std::pair<Point3f,Point3f> &nv, face::Pos<typename MESH_TYPE::FaceType> ep) { void operator()(std::pair<CoordType,CoordType> &nv, face::Pos<typename MESH_TYPE::FaceType> ep) {
proj.reset(); proj.reset();
face::Pos<typename MESH_TYPE::FaceType> he(ep.f,ep.z,ep.f->V(ep.z)); face::Pos<typename MESH_TYPE::FaceType> he(ep.f,ep.z,ep.f->V(ep.z));
typename MESH_TYPE::VertexType *r, *l, *curr; typename MESH_TYPE::VertexType *r, *l, *curr;
curr = he.v; curr = he.v;
face::Pos<typename MESH_TYPE::FaceType> heStart = he; face::Pos<typename MESH_TYPE::FaceType> heStart = he;
// compute valence of this vertex or find a border // compute valence of this vertex or find a border
int k = 0; int k = 0;
do { do {
he.NextE(); he.NextE();
k++; k++;
} while(!he.IsBorder() && he != heStart); } while(!he.IsBorder() && he != heStart);
if (he.IsBorder()) { // Border rule if (he.IsBorder()) { // Border rule
// consider valence of borders as if they are half+1 of an inner vertex. not perfect, but better than nothing. // consider valence of borders as if they are half+1 of an inner vertex. not perfect, but better than nothing.
if(valence) { if(valence) {
k = 0; k = 0;
do { do {
he.NextE(); he.NextE();
k++; k++;
} while(!he.IsBorder()); } while(!he.IsBorder());
(*valence)[he.V()] = std::max(2*(k-1), 3); (*valence)[he.V()] = std::max(2*(k-1), 3);
// (*valence)[he.V()] = 6; // (*valence)[he.V()] = 6;
} }
he.FlipV(); he.FlipV();
r = he.v; r = he.v;
he.FlipV(); he.FlipV();
he.NextB(); he.NextB();
l = he.v; l = he.v;
proj.addVertex(*curr, 3.0/4.0); proj.addVertex(*curr, 3.0/4.0);
proj.addVertex(*l, 1.0/8.0); proj.addVertex(*l, 1.0/8.0);
proj.addVertex(*r, 1.0/8.0); proj.addVertex(*r, 1.0/8.0);
// std::pair<Point3f,Point3f>pp; // std::pair<Point3f,Point3f>pp;
proj.project(nv); proj.project(nv);
// nv.P()=pp.first; // nv.P()=pp.first;
// nv.N()=pp.second; // nv.N()=pp.second;
// proj.project(nv); // proj.project(nv);
} }
else { // Inner rule else { // Inner rule
// assert(!he.v->IsB()); border flag no longer updated (useless) // assert(!he.v->IsB()); border flag no longer updated (useless)
if(valence) if(valence)
(*valence)[he.V()] = k; (*valence)[he.V()] = k;
typename MESH_TYPE::ScalarType beta = weight.beta(k); typename MESH_TYPE::ScalarType beta = weight.beta(k);
proj.addVertex(*curr, 1.0 - (typename MESH_TYPE::ScalarType)(k) * beta); proj.addVertex(*curr, 1.0 - (typename MESH_TYPE::ScalarType)(k) * beta);
do { do {
proj.addVertex(*he.VFlip(), beta); proj.addVertex(*he.VFlip(), beta);
he.NextE(); he.NextE();
} while(he != heStart); } while(he != heStart);
proj.project(nv); proj.project(nv);
} }
} // end of operator() } // end of operator()
Color4<typename MESH_TYPE::ScalarType> WedgeInterp(Color4<typename MESH_TYPE::ScalarType> &c0, Color4<typename MESH_TYPE::ScalarType> &c1) Color4<typename MESH_TYPE::ScalarType> WedgeInterp(Color4<typename MESH_TYPE::ScalarType> &c0, Color4<typename MESH_TYPE::ScalarType> &c1)
{ {
Color4<typename MESH_TYPE::ScalarType> cc; Color4<typename MESH_TYPE::ScalarType> cc;
return cc.lerp(c0,c1,0.5f); return cc.lerp(c0,c1,0.5f);
} }
Color4b WedgeInterp(Color4b &c0, Color4b &c1) Color4b WedgeInterp(Color4b &c0, Color4b &c1)
{ {
Color4b cc; Color4b cc;
cc.lerp(c0,c1,0.5f); cc.lerp(c0,c1,0.5f);
return cc; return cc;
} }
template<class FL_TYPE> template<class FL_TYPE>
TexCoord2<FL_TYPE,1> WedgeInterp(TexCoord2<FL_TYPE,1> &t0, TexCoord2<FL_TYPE,1> &t1) TexCoord2<FL_TYPE,1> WedgeInterp(TexCoord2<FL_TYPE,1> &t0, TexCoord2<FL_TYPE,1> &t1)
{ {
TexCoord2<FL_TYPE,1> tmp; TexCoord2<FL_TYPE,1> tmp;
// assert(t0.n()== t1.n()); // assert(t0.n()== t1.n());
tmp.n()=t0.n(); tmp.n()=t0.n();
tmp.t()=(t0.t()+t1.t())/2.0; tmp.t()=(t0.t()+t1.t())/2.0;
return tmp; return tmp;
} }
inline void setValenceAttr(ValenceAttr *valence) { inline void setValenceAttr(ValenceAttr *valence) {
this->valence = valence; this->valence = valence;
} }
}; };
template<class MESH_TYPE> template<class MESH_TYPE>
@ -552,73 +554,73 @@ bool RefineOddEven(MESH_TYPE &m, ODD_VERT odd, EVEN_VERT even,float length,
*/ */
template<class MESH_TYPE, class ODD_VERT, class EVEN_VERT, class PREDICATE> template<class MESH_TYPE, class ODD_VERT, class EVEN_VERT, class PREDICATE>
bool RefineOddEvenE(MESH_TYPE &m, ODD_VERT odd, EVEN_VERT even, PREDICATE edgePred, bool RefineOddEvenE(MESH_TYPE &m, ODD_VERT odd, EVEN_VERT even, PREDICATE edgePred,
bool RefineSelected=false, CallBackPos *cbOdd = 0, CallBackPos *cbEven = 0) bool RefineSelected=false, CallBackPos *cbOdd = 0, CallBackPos *cbEven = 0)
{ {
typedef typename MESH_TYPE::template PerVertexAttributeHandle<int> ValenceAttr; typedef typename MESH_TYPE::template PerVertexAttributeHandle<int> ValenceAttr;
// momentaneamente le callback sono identiche, almeno cbOdd deve essere passata // momentaneamente le callback sono identiche, almeno cbOdd deve essere passata
cbEven = cbOdd; cbEven = cbOdd;
// to mark visited vertices // to mark visited vertices
int evenFlag = MESH_TYPE::VertexType::NewBitFlag(); int evenFlag = MESH_TYPE::VertexType::NewBitFlag();
for (int i = 0; i < m.vn ; i++ ) { for (int i = 0; i < m.vn ; i++ ) {
m.vert[i].ClearUserBit(evenFlag); m.vert[i].ClearUserBit(evenFlag);
} }
int j = 0; int j = 0;
// di texture per wedge (uno per ogni edge) // di texture per wedge (uno per ogni edge)
ValenceAttr valence = vcg::tri::Allocator<MESH_TYPE>:: template AddPerVertexAttribute<int>(m); ValenceAttr valence = vcg::tri::Allocator<MESH_TYPE>:: template AddPerVertexAttribute<int>(m);
odd.setValenceAttr(&valence); odd.setValenceAttr(&valence);
even.setValenceAttr(&valence); even.setValenceAttr(&valence);
// store updated vertices // store updated vertices
std::vector<bool> updatedList(m.vn, false); std::vector<bool> updatedList(m.vn, false);
//std::vector<typename MESH_TYPE::VertexType> newEven(m.vn); //std::vector<typename MESH_TYPE::VertexType> newEven(m.vn);
std::vector<std::pair<Point3f,Point3f> > newEven(m.vn); std::vector<std::pair<typename MESH_TYPE::CoordType, typename MESH_TYPE::CoordType> > newEven(m.vn);
typename MESH_TYPE::VertexIterator vi; typename MESH_TYPE::VertexIterator vi;
typename MESH_TYPE::FaceIterator fi; typename MESH_TYPE::FaceIterator fi;
for (fi = m.face.begin(); fi != m.face.end(); fi++) if(!(*fi).IsD() && (!RefineSelected || (*fi).IsS())){ //itero facce for (fi = m.face.begin(); fi != m.face.end(); fi++) if(!(*fi).IsD() && (!RefineSelected || (*fi).IsS())){ //itero facce
for (int i = 0; i < 3; i++) { //itero vert for (int i = 0; i < 3; i++) { //itero vert
if ( !(*fi).V(i)->IsUserBit(evenFlag) && ! (*fi).V(i)->IsD() ) { if ( !(*fi).V(i)->IsUserBit(evenFlag) && ! (*fi).V(i)->IsD() ) {
(*fi).V(i)->SetUserBit(evenFlag); (*fi).V(i)->SetUserBit(evenFlag);
// use face selection, not vertex selection, to be coherent with RefineE // use face selection, not vertex selection, to be coherent with RefineE
//if (RefineSelected && !(*fi).V(i)->IsS() ) //if (RefineSelected && !(*fi).V(i)->IsS() )
// break; // break;
face::Pos<typename MESH_TYPE::FaceType>aux (&(*fi),i); face::Pos<typename MESH_TYPE::FaceType>aux (&(*fi),i);
if( tri::HasPerVertexColor(m) ) { if( tri::HasPerVertexColor(m) ) {
(*fi).V(i)->C().lerp((*fi).V0(i)->C() , (*fi).V1(i)->C(),0.5f); (*fi).V(i)->C().lerp((*fi).V0(i)->C() , (*fi).V1(i)->C(),0.5f);
} }
if (cbEven) { if (cbEven) {
(*cbEven)(int(100.0f * (float)j / (float)m.fn),"Refining"); (*cbEven)(int(100.0f * (float)j / (float)m.fn),"Refining");
j++; j++;
} }
int index = tri::Index(m, (*fi).V(i)); int index = tri::Index(m, (*fi).V(i));
updatedList[index] = true; updatedList[index] = true;
even(newEven[index], aux); even(newEven[index], aux);
} }
} }
} }
MESH_TYPE::VertexType::DeleteBitFlag(evenFlag); MESH_TYPE::VertexType::DeleteBitFlag(evenFlag);
// Now apply the stored normal and position to the initial vertex set (note that newEven is << m.vert) // Now apply the stored normal and position to the initial vertex set (note that newEven is << m.vert)
RefineE< MESH_TYPE, ODD_VERT > (m, odd, edgePred, RefineSelected, cbOdd); RefineE< MESH_TYPE, ODD_VERT > (m, odd, edgePred, RefineSelected, cbOdd);
for(size_t i=0;i<newEven.size();++i) { for(size_t i=0;i<newEven.size();++i) {
if(updatedList[i]) { if(updatedList[i]) {
m.vert[i].P()=newEven[i].first; m.vert[i].P()=newEven[i].first;
m.vert[i].N()=newEven[i].second; m.vert[i].N()=newEven[i].second;
} }
} }
odd.setValenceAttr(0); odd.setValenceAttr(0);
even.setValenceAttr(0); even.setValenceAttr(0);
vcg::tri::Allocator<MESH_TYPE>::DeletePerVertexAttribute(m, valence); vcg::tri::Allocator<MESH_TYPE>::DeletePerVertexAttribute(m, valence);
return true; return true;
} }
} // namespace tri } // namespace tri