You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
248 lines
9.1 KiB
248 lines
9.1 KiB
/**************************************************************************** |
|
* VCGLib o o * |
|
* Visual and Computer Graphics Library o o * |
|
* _ O _ * |
|
* Copyright(C) 2004-2016 \/)\/ * |
|
* Visual Computing Lab /\/| * |
|
* ISTI - Italian National Research Council | * |
|
* \ * |
|
* All rights reserved. * |
|
* * |
|
* This program is free software; you can redistribute it and/or modify * |
|
* it under the terms of the GNU General Public License as published by * |
|
* the Free Software Foundation; either version 2 of the License, or * |
|
* (at your option) any later version. * |
|
* * |
|
* This program is distributed in the hope that it will be useful, * |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of * |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
|
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * |
|
* for more details. * |
|
* * |
|
****************************************************************************/ |
|
|
|
#ifndef VCG_COMPLEX_ALGORITHMS_PARAMETRIZATION_UV_UTILS_H |
|
#define VCG_COMPLEX_ALGORITHMS_PARAMETRIZATION_UV_UTILS_H |
|
|
|
#include <vcg/space/point2.h> |
|
#include <vcg/space/box2.h> |
|
#include <vcg/space/triangle2.h> |
|
#include <vcg/space/triangle3.h> |
|
|
|
namespace vcg { |
|
namespace tri { |
|
template <class MeshType> |
|
class UV_Utils |
|
{ |
|
typedef typename MeshType::CoordType CoordType; |
|
typedef typename MeshType::ScalarType ScalarType; |
|
typedef typename MeshType::FaceType FaceType; |
|
typedef typename MeshType::VertexType VertexType; |
|
typedef typename MeshType::VertexIterator VertexIterator; |
|
typedef typename MeshType::FaceIterator FaceIterator; |
|
typedef typename vcg::Point2<ScalarType> UVCoordType; |
|
|
|
public: |
|
|
|
/// calculate the area in UV space |
|
static ScalarType PerVertUVArea(MeshType &m) |
|
{ |
|
FaceIterator fi; |
|
ScalarType Area=0; |
|
for (fi=m.face.begin();fi!=m.face.end();fi++) |
|
{ |
|
if ((*fi).IsD()) continue; |
|
UVCoordType E0= (*fi).V(1)->T().P()-(*fi).V(0)->T().P(); |
|
UVCoordType E1= (*fi).V(2)->T().P()-(*fi).V(0)->T().P(); |
|
ScalarType doubleA=fabs(E0^E1); |
|
Area+=doubleA/2; |
|
} |
|
return Area; |
|
} |
|
|
|
///scale vert UV to match 3D area |
|
static void ScaleVertUVToMatchArea(MeshType &m) |
|
{ |
|
FaceIterator fi; |
|
ScalarType Area3D=0; |
|
for (fi=m.face.begin();fi!=m.face.end();fi++) |
|
{ |
|
if ((*fi).IsD()) continue; |
|
Area3D+=vcg::DoubleArea((*fi))/2; |
|
} |
|
ScalarType Area2D=PerVertUVArea(m); |
|
ScalarType ScaleFact=sqrt( Area3D / Area2D ); |
|
|
|
VertexIterator vi; |
|
for (vi=m.vert.begin();vi!=m.vert.end();vi++) |
|
{ |
|
if ((*vi).IsD()) continue; |
|
(*vi).T().P()*=ScaleFact; |
|
} |
|
} |
|
|
|
///calculate the BBox in UV space |
|
static vcg::Box2<ScalarType> PerWedgeUVBox(MeshType &m) |
|
{ |
|
vcg::Box2<ScalarType> UVBox; |
|
FaceIterator fi; |
|
for (fi=m.face.begin();fi!=m.face.end();fi++) |
|
{ |
|
if ((*fi).IsD()) continue; |
|
for (int i=0;i<3;i++) |
|
UVBox.Add((*fi).WT(i).P()); |
|
} |
|
return UVBox; |
|
} |
|
|
|
///calculate the BBox in UV space |
|
static vcg::Box2<ScalarType> PerVertUVBox(const MeshType &m) |
|
{ |
|
vcg::Box2<ScalarType> UVBox; |
|
for (auto vi=m.vert.begin();vi!=m.vert.end();vi++) |
|
{ |
|
if ((*vi).IsD()) continue; |
|
UVBox.Add((*vi).T().P()); |
|
} |
|
return UVBox; |
|
} |
|
|
|
void PerWedgeMakeUnitaryUV(MeshType &m) |
|
{ |
|
vcg::Box2<typename MeshType::ScalarType> UVBox = PerWedgeUVBox(m); |
|
|
|
typename MeshType::FaceIterator fi; |
|
Point2f boxSize(UVBox.max-UVBox.min); |
|
for (fi=m.face.begin();fi!=m.face.end();fi++) |
|
{ |
|
if ((*fi).IsD()) continue; |
|
for (int i=0;i<3;i++) |
|
{ |
|
(*fi).WT(i).U() = ((*fi).WT(i).U()-UVBox.min[0])/boxSize[0] ; |
|
(*fi).WT(i).V() = ((*fi).WT(i).V()-UVBox.min[1])/boxSize[1] ; |
|
} |
|
} |
|
} |
|
///transform curvature to UV space |
|
static UVCoordType Coord3DtoUV(FaceType &f,const CoordType &dir) |
|
{ |
|
///then transform to UV |
|
CoordType bary3d=(f.P(0)+f.P(1)+f.P(2))/3.0; |
|
UVCoordType baryUV=(f.WT(0).P()+f.WT(1).P()+f.WT(2).P())/3.0; |
|
CoordType dir3d=bary3d+dir; |
|
CoordType baryCoordsUV; |
|
vcg::InterpolationParameters<FaceType,ScalarType>(f,dir3d,baryCoordsUV); |
|
UVCoordType dirUV=baryCoordsUV.X()*f.WT(0).P()+ |
|
baryCoordsUV.Y()*f.WT(1).P()+ |
|
baryCoordsUV.Z()*f.WT(2).P()-baryUV; |
|
dirUV.Normalize(); |
|
return dirUV; |
|
} |
|
|
|
static void GloballyMirrorX(MeshType &m) |
|
{ |
|
vcg::Box2<ScalarType> BBuv=PerVertUVBox(m); |
|
ScalarType Xmin=BBuv.min.X(); |
|
ScalarType Xmax=BBuv.max.X(); |
|
ScalarType XAv=(Xmax+Xmin)/2; |
|
VertexIterator vi; |
|
for (vi=m.vert.begin();vi!=m.vert.end();vi++) |
|
{ |
|
ScalarType distAV=(*vi).T().P().X()-XAv; |
|
(*vi).T().P().X()=XAv-distAV; |
|
} |
|
} |
|
|
|
static void GloballyRotate(MeshType &m,ScalarType Angle) |
|
{ |
|
vcg::Box2<ScalarType> BB=PerWedgeUVBox(m); |
|
UVCoordType Origin=BB.Center(); |
|
typename MeshType::FaceIterator fi; |
|
for (fi=m.face.begin();fi!=m.face.end();fi++) |
|
{ |
|
if ((*fi).IsD()) continue; |
|
for (int i=0;i<3;i++) |
|
{ |
|
(*fi).WT(i).P()-=Origin; |
|
ScalarType X1=(*fi).WT(i).P().X()*cos(Angle)-(*fi).WT(i).P().Y()*sin(Angle); |
|
ScalarType Y1=(*fi).WT(i).P().X()*cos(Angle)+(*fi).WT(i).P().Y()*sin(Angle); |
|
(*fi).WT(i).P().X()=X1; |
|
(*fi).WT(i).P().Y()=Y1; |
|
(*fi).WT(i).P()+=Origin; |
|
} |
|
} |
|
} |
|
|
|
static void GloballyRotatePerVert(MeshType &m,ScalarType Angle) |
|
{ |
|
vcg::Box2<ScalarType> BB=PerVertUVBox(m); |
|
UVCoordType Origin=BB.Center(); |
|
typename MeshType::VertexIterator vi; |
|
for (vi=m.vert.begin();vi!=m.vert.end();vi++) |
|
{ |
|
if ((*vi).IsD()) continue; |
|
(*vi).T().P()-=Origin; |
|
ScalarType X1=(*vi).T().P().X()*cos(Angle)-(*vi).T().P().Y()*sin(Angle); |
|
ScalarType Y1=(*vi).T().P().X()*cos(Angle)+(*vi).T().P().Y()*sin(Angle); |
|
(*vi).T().P().X()=X1; |
|
(*vi).T().P().Y()=Y1; |
|
(*vi).T().P()+=Origin; |
|
} |
|
} |
|
|
|
static void LaplacianUVVert(MeshType &m,bool fix_borders=false,int steps=3) |
|
{ |
|
FaceIterator fi; |
|
for (int s=0;s<steps;s++) |
|
{ |
|
std::vector<int> num(m.vert.size(),0); |
|
std::vector<UVCoordType> UVpos(m.vert.size(),UVCoordType(0,0)); |
|
for (fi=m.face.begin();fi!=m.face.end();fi++) |
|
{ |
|
for (int j=0;j<3;j++) |
|
{ |
|
VertexType *v0=(*fi).V(0); |
|
VertexType *v1=(*fi).V1(0); |
|
VertexType *v2=(*fi).V2(0); |
|
assert(v0!=v1); |
|
assert(v1!=v2); |
|
assert(v0!=v2); |
|
UVCoordType uv1=v1->T().P(); |
|
UVCoordType uv2=v2->T().P(); |
|
int index=v0-&(m.vert[0]); |
|
num[index]+=2; |
|
UVpos[index]+=uv1; |
|
UVpos[index]+=uv2; |
|
} |
|
} |
|
VertexIterator vi; |
|
for (int i=0;i<m.vert.size();i++) |
|
{ |
|
if ((fix_borders)&&(m.vert[i].IsB()))continue; |
|
if (num[i]==0)continue; |
|
m.vert[i].T().P()=UVpos[i]/(ScalarType)num[i]; |
|
} |
|
} |
|
} |
|
|
|
static void CopyVertUVWedge(MeshType &m) |
|
{ |
|
for (size_t i=0;i<m.face.size();i++) |
|
for (size_t j=0;j<3;j++) |
|
m.face[i].WT(j).P()=m.face[i].V(j)->T().P(); |
|
} |
|
|
|
static void CopyWedgeVertUV(MeshType &m,bool onlyS=false) |
|
{ |
|
for (size_t i=0;i<m.face.size();i++) |
|
{ |
|
if ((onlyS)&&(!m.face[i].IsS()))continue; |
|
for (int j=0;j<3;j++) |
|
m.face[i].V(j)->T().P()=m.face[i].WT(j).P(); |
|
} |
|
} |
|
}; |
|
|
|
} // end Namespace tri |
|
} // end Namespace vcg |
|
#endif // VCG_COMPLEX_ALGORITHMS_PARAMETRIZATION_UV_UTILS_H
|
|
|