00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __MIQ_PARAMETRIZATION_H
00025 #define __MIQ_PARAMETRIZATION_H
00026
00027
00028 #include <igl/cross_field_missmatch.h>
00029 #include <igl/line_field_missmatch.h>
00030 #include <igl/comb_line_field.h>
00031 #include <igl/cut_mesh_from_singularities.h>
00032 #include <igl/find_cross_field_singularities.h>
00033 #include <igl/compute_frame_field_bisectors.h>
00034 #include <igl/comiso/miq.h>
00035 #include <vcg/complex/algorithms/parametrization/uv_utils.h>
00036 #include <vcg/complex/algorithms/mesh_to_matrix.h>
00037
00038 namespace vcg {
00039 namespace tri {
00040 template < class MeshType>
00041 class MiQParametrizer
00042 {
00043
00044 typedef typename MeshType::CoordType CoordType;
00045 typedef typename MeshType::VertexType VertexType;
00046 typedef typename MeshType::FaceType FaceType;
00047 typedef typename MeshType::ScalarType ScalarType;
00048 typedef typename MeshType::VertexType PolyVertexType;
00049
00050 public:
00051 struct MIQParameters
00052 {
00053
00054 double gradient;
00055
00056 bool doRound;
00057
00058 bool directRound;
00059
00060 double stiffness;
00061
00062 int stiffness_iter;
00063
00064 int local_iter;
00065
00066 bool hexaLine;
00067
00068 double crease_thr;
00069
00070 int Ndir;
00071
00072 bool round_singularities;
00073
00074 bool crease_as_feature;
00075
00076 bool round_selected;
00077
00078 MIQParameters()
00079 {
00080 gradient=80;
00081 doRound=true;
00082 directRound=true;
00083 round_singularities=true;
00084 crease_as_feature=false;
00085 round_selected=true;
00086 stiffness=5;
00087 stiffness_iter=10;
00088 local_iter=5;
00089 Ndir=4;
00090 crease_thr=0.2;
00091 hexaLine=false;
00092 }
00093 };
00094
00095
00096 static void GetFeatureLines(MeshType &trimesh,
00097 std::vector<std::vector<int> > &feature_lines)
00098 {
00099 feature_lines.clear();
00100
00101 for (size_t i=0;i<trimesh.face.size();i++)
00102 {
00103 for (int j=0;j<3;j++)
00104 {
00105
00106 if (!trimesh.face[i].IsCrease(j))continue;
00107
00108 feature_lines.push_back(std::vector<int>());
00109 feature_lines.back().push_back(i);
00110 feature_lines.back().push_back(j);
00111
00112 }
00113 }
00114 }
00115
00116 private:
00117
00118
00119
00120 static void CrossFieldParam(MeshType &trimesh,
00121 MIQParameters &MiqP)
00122 {
00123
00124 Eigen::MatrixXi F;
00125 Eigen::MatrixXd V;
00126 vcg::tri::MeshToMatrix<MeshType>::GetTriMeshData(trimesh,F,V);
00127
00128
00129 Eigen::MatrixXd X1,X2;
00130 X1=Eigen::MatrixXd(trimesh.FN(), 3);
00131 for (size_t i=0;i<trimesh.face.size();i++)
00132 {
00133 CoordType Dir1=trimesh.face[i].PD1();
00134 Dir1.Normalize();
00135 for (int j=0;j<3;j++)
00136 {
00137 X1(i,j)=Dir1[j];
00138 }
00139 }
00140
00141 Eigen::MatrixXd B1,B2,B3;
00142 igl::local_basis(V,F,B1,B2,B3);
00143 X2 = igl::rotate_vectors(X1, Eigen::VectorXd::Constant(1,M_PI/2), B1, B2);
00144
00145 Eigen::MatrixXd UV;
00146 Eigen::MatrixXi FUV;
00147
00148
00149
00150 std::vector<std::vector<int> > hard_features;
00151
00152 if (MiqP.crease_as_feature)
00153 GetFeatureLines(trimesh,hard_features);
00154
00155 std::vector<int> extra_round;
00156
00157 if (MiqP.round_selected)
00158 {
00159 for (int i=0;i<trimesh.vert.size();i++)
00160 {
00161 if (!trimesh.vert[i].IsS())continue;
00162 extra_round.push_back(i);
00163 }
00164 }
00165
00166 igl::miq(V,F,X1,X2,UV,FUV,MiqP.gradient,MiqP.stiffness,MiqP.directRound,
00167 MiqP.stiffness_iter,MiqP.local_iter,MiqP.doRound,MiqP.round_singularities,
00168 extra_round,hard_features);
00169
00170
00171 for (size_t i=0;i<trimesh.face.size();i++)
00172 {
00173 for (int j=0;j<3;j++)
00174 {
00175 int index=FUV(i,j);
00176 trimesh.face[i].WT(j).P()[0]=UV(index,0);
00177 trimesh.face[i].WT(j).P()[1]=UV(index,1);
00178 }
00179 }
00180 }
00181
00182 static void LineFieldParam(MeshType &trimesh,
00183 MIQParameters &MiqP)
00184 {
00185
00186 Eigen::MatrixXi F;
00187 Eigen::MatrixXd V;
00188 vcg::tri::MeshToMatrix<MeshType>::GetTriMeshData(trimesh,F,V);
00189
00190
00191 Eigen::MatrixXd X1,X2;
00192 X1=Eigen::MatrixXd(trimesh.FN(), 3);
00193 for (size_t i=0;i<trimesh.face.size();i++)
00194 {
00195 CoordType Dir1=trimesh.face[i].PD1();
00196 Dir1.Normalize();
00197 for (int j=0;j<3;j++)
00198 {
00199 X1(i,j)=Dir1[j];
00200 }
00201 }
00202
00203 Eigen::MatrixXd B1,B2,B3;
00204 igl::local_basis(V,F,B1,B2,B3);
00205 X2 = igl::rotate_vectors(X1, Eigen::VectorXd::Constant(1,M_PI/2), B1, B2);
00206
00207
00208 Eigen::MatrixXd BIS1, BIS2;
00209
00210
00211 Eigen::MatrixXd BIS1_combed, BIS2_combed;
00212
00213
00214 Eigen::MatrixXi MMatch;
00215
00216
00217 Eigen::VectorXi isSingularity, singularityIndex;
00218
00219
00220 Eigen::MatrixXi Seams;
00221
00222
00223 Eigen::MatrixXd X1_combed, X2_combed;
00224
00225
00226
00227 Eigen::MatrixXd UV_seams;
00228 Eigen::MatrixXi FUV_seams;
00229
00230
00231 Eigen::MatrixXd UV;
00232 Eigen::MatrixXi FUV;
00233
00234
00235 igl::compute_frame_field_bisectors(V, F, X1, X2, BIS1, BIS2);
00236
00237
00238 igl::comb_line_field(V, F, BIS1, BIS1_combed);
00239 igl::local_basis(V,F,B1,B2,B3);
00240 BIS2_combed = igl::rotate_vectors(BIS1_combed, Eigen::VectorXd::Constant(1,M_PI/2), B1, B2);
00241
00242
00243 igl::line_field_missmatch(V, F, BIS1_combed, true, MMatch);
00244
00245
00246 igl::find_cross_field_singularities(V, F, MMatch, isSingularity, singularityIndex);
00247
00248
00249
00250 igl::cut_mesh_from_singularities(V, F, MMatch,Seams);
00251
00252
00253 igl::comb_frame_field(V, F, X1, X2, BIS1_combed, BIS2_combed, X1_combed, X2_combed);
00254
00255 std::vector<std::vector<int> > hard_features;
00256
00257
00258 std::vector<int> extra_round;
00259
00260 if (MiqP.round_selected)
00261 {
00262 for (int i=0;i<trimesh.vert.size();i++)
00263 {
00264 if (!trimesh.vert[i].IsS())continue;
00265 extra_round.push_back(i);
00266 }
00267 }
00268 if (MiqP.crease_as_feature)
00269 GetFeatureLines(trimesh,hard_features);
00270
00271
00272 ScalarType sqrt3=1.732050807568877;
00273
00274 ScalarType GradX=0.5;
00275 ScalarType GradY=1;
00276
00277 if (MiqP.hexaLine)
00278 {
00279 for (int i=0;i<X1_combed.rows();i++)
00280 {
00281 X1_combed(i)*=GradX;
00282 X2_combed(i)*=GradY;
00283 }
00284 }
00285
00286
00287
00288
00289
00290 igl::miq(V,F,X1_combed,X2_combed,
00291 UV,FUV,MiqP.gradient,MiqP.stiffness,MiqP.directRound,
00292 MiqP.stiffness_iter,MiqP.local_iter,MiqP.doRound,MiqP.round_singularities,extra_round,hard_features);
00293
00294
00295 for (size_t i=0;i<trimesh.face.size();i++)
00296 {
00297 for (int j=0;j<3;j++)
00298 {
00299 int index=FUV(i,j);
00300 trimesh.face[i].WT(j).P()[0]=UV(index,0);
00301 trimesh.face[i].WT(j).P()[1]=UV(index,1);
00302 }
00303 }
00304 }
00305
00306 public:
00307
00308 static void SetCreases(MeshType & mesh,
00309 const ScalarType &thr=0.2,
00310 bool setBorder=true)
00311 {
00312 for (size_t i=0;i<mesh.face.size();i++)
00313 for (int j=0;j<mesh.face[i].VN();j++)
00314 {
00315 FaceType *f0=&mesh.face[i];
00316 f0->ClearCrease(j);
00317 }
00318
00319
00320 for (size_t i=0;i<mesh.face.size();i++)
00321 for (int j=0;j<mesh.face[i].VN();j++)
00322 {
00323 FaceType *f0=&mesh.face[i];
00324 FaceType *f1=f0->FFp(j);
00325
00326 if (f0==f1){f0->SetCrease(j);continue;}
00327
00328 CoordType N0=f0->N();
00329 CoordType N1=f1->N();
00330 if ((N0*N1)>thr)continue;
00331 f0->SetCrease(j);
00332
00333 }
00334 }
00335
00336 static void MIQParametrize(MeshType &trimesh,
00337 MIQParameters &MiqP)
00338 {
00339 if (MiqP.crease_as_feature)
00340 SetCreases(trimesh,MiqP.crease_thr);
00341
00342 if (MiqP.Ndir==4)
00343 CrossFieldParam(trimesh,MiqP);
00344 else
00345 LineFieldParam(trimesh,MiqP);
00346 }
00347 };
00348
00349 }
00350 }
00351 #endif // VORO_CLUSTER_H