109
80
BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL);
112
/* divide selected faces in groups, based on seams. note that group numbering
114
static int make_seam_groups(Mesh *me, int **seamgroups)
119
int *gf, *gface, *groups;
123
if(!me || !me->tface) return 0;
125
groups= (int*)MEM_callocN(sizeof(int)*me->totface, "SeamGroups");
127
ehash= BLI_edgehash_new();
129
mface= (MFace*)me->mface;
130
tface= (TFace*)me->tface;
133
for(b=me->totface; b>0; b--, mface++, tface++, gface++) {
134
if(!(tface->flag & TF_SELECT) || *gface!=0) continue;
137
BLI_edgehash_clear(ehash, NULL);
148
/* select connected: fill array */
154
if(tf->flag & TF_HIDE);
155
else if(tf->flag & TF_SELECT && *gf==gid) {
156
hash_add_face(ehash, mf);
161
/* select the faces using array
162
* consider faces connected when they share one non-seam edge */
168
if(tf->flag & TF_HIDE);
169
else if(tf->flag & TF_SELECT && *gf==0) {
172
if(!(tf->unwrap & TF_SEAM1))
173
if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2))
175
if(!(tf->unwrap & TF_SEAM2))
176
if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3))
178
if(!(tf->unwrap & TF_SEAM3)) {
180
if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4))
183
else if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1))
186
if(mf->v4 && !(tf->unwrap & TF_SEAM4))
187
if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1))
200
BLI_edgehash_free(ehash, NULL);
206
static void lscm_rotate_vert(int a, LscmVert **sortvert, int v2, int index)
211
/* starting from edge sortvert->v,v2, rotate around vertex and set
212
* index until a seam or an already marked tri is encountered */
219
for(b=a; b>0 && ((*sv)->v == (*sortvert)->v) && !found; b--, sv++) {
222
if(v->flag & LSCM_INDEXED);
223
else if(v->v1 == v2) {
226
if(v->flag & LSCM_SEAM1) break;
229
v->flag |= LSCM_INDEXED;
236
if(v->flag & LSCM_SEAM2) break;
239
v->flag |= LSCM_INDEXED;
247
static int lscm_vertex_set_index(int a, LscmVert **sortvert, int totindex)
252
/* rotate over 'wheel' of faces around vertex, incrementing the index
253
everytime we meet a seam, or no next connected face is found.
254
repeat this until we have and id for all verts.
255
if mesh is non-manifold, non-manifold edges will be cut randomly */
260
for(b=a; b>0 && ((*sv)->v == (*sortvert)->v); b--, sv++) {
263
if(v->flag & LSCM_INDEXED) continue;
266
v->flag |= LSCM_INDEXED;
268
lscm_rotate_vert(b, sv, v->v1, index);
269
lscm_rotate_vert(b, sv, v->v2, index);
277
static int lscm_set_indices(LscmVert **sortvert, int totvert)
280
int a, lastvert, totindex;
286
for(a=totvert; a>0; a--, sv++) {
288
if(v->v != lastvert) {
289
totindex= lscm_vertex_set_index(a, sv, totindex);
297
static void lscm_normalize(float *co, float *center, float radius)
299
/* normalize relative to complete surface */
300
VecSubf(co, co, center);
301
VecMulf(co, (float)1.0/radius);
304
static void lscm_add_triangle(float *v1, float *v2, float *v3, int vid1, int vid2, int vid3, float *center, float radius)
306
float x[3], y[3], z[3], sub[3], z1[2], z2[2];
307
int id0[2], id1[2], id2[2];
309
/* project 3d triangle
310
* edge length is lost, as this algorithm is angle based */
311
lscm_normalize(v1, center, radius);
312
lscm_normalize(v2, center, radius);
313
lscm_normalize(v3, center, radius);
318
VecSubf(sub, v3, v1);
324
/* reduce to two 2d vectors */
325
VecSubf(sub, v2, v1);
326
z1[0]= Normalise(sub);
329
VecSubf(sub, v3, v1);
333
/* split id's up for u and v
334
id = u, id + 1 = v */
342
/* The LSCM Equation:
344
* (u,v) are the uv coords we are looking for -> complex number u + i*v
345
* (x,y) are the above calculated local coords -> complex number x + i*y
347
* Zk = xk + i*yk (= zk[0] + i*zk[1] in the code)
349
* That makes the equation:
350
* (Z1 - Z0)(U2 - U0) = (Z2 - Z0)(U1 - U0)
352
* x0, y0 and y1 were made zero by projecting the triangle:
353
* (x1 + i*y1)(u2 + i*v2 - u0 - i*v0) = (x2 + i*y2)(u1 + i*v1 - u0 - i*v0)
355
* this gives the following coefficients:
356
* u0 * ((-x1 + x2) + i*(y2))
357
* v0 * ((-y2) + i*(-x1 + x2))
358
* u1 * ((-x2) + i*(-y2))
359
* v1 * ((y2) + i*(-x2))
366
nlCoefficient(id0[0], -z1[0] + z2[0]);
367
nlCoefficient(id0[1], -z2[1] );
368
nlCoefficient(id1[0], -z2[0] );
369
nlCoefficient(id1[1], z2[1] );
370
nlCoefficient(id2[0], z1[0] );
375
nlCoefficient(id0[0], z2[1] );
376
nlCoefficient(id0[1], -z1[0] + z2[0]);
377
nlCoefficient(id1[0], -z2[1] );
378
nlCoefficient(id1[1], -z2[0] );
379
nlCoefficient(id2[1], z1[0] );
383
static float lscm_angle_cos(float *v1, float *v2, float *v3)
385
float vec1[3], vec2[3];
387
VecSubf(vec1, v2, v1);
388
VecSubf(vec2, v3, v1);
392
return vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2];
395
static int lscm_build_vertex_data(Mesh *me, int *groups, int gid, LscmVert **lscm_vertices, LscmVert ***sort_vertices)
401
LscmVert *lscmvert, **sortvert;
402
LscmVert *v1, *v2, *v3, **sv1, **sv2, **sv3;
405
/* determine size for malloc */
413
for(a=me->totface; a>0; a--) {
417
if(mf->v4) totvert +=3;
422
/* a list per face vertices */
423
lscmvert= (LscmVert*)MEM_mallocN(sizeof(LscmVert)*totvert,"LscmVerts");
424
/* the above list sorted by vertex id */
425
sortvert= (LscmVert**)MEM_mallocN(sizeof(LscmVert*)*totvert, "LscmVSort");
427
/* actually build the list (including virtual triangulation) */
440
/* warning: ugly code :) */
441
for(a=me->totface; a>0; a--) {
443
/* determine triangulation direction, to avoid degenerate
444
triangles (small cos = degenerate). */
446
a1 = lscm_angle_cos((mv+mf->v1)->co, (mv+mf->v2)->co, (mv+mf->v3)->co);
447
a1 += lscm_angle_cos((mv+mf->v2)->co, (mv+mf->v1)->co, (mv+mf->v3)->co);
448
a1 += lscm_angle_cos((mv+mf->v3)->co, (mv+mf->v1)->co, (mv+mf->v2)->co);
450
a2 = lscm_angle_cos((mv+mf->v1)->co, (mv+mf->v2)->co, (mv+mf->v4)->co);
451
a2 += lscm_angle_cos((mv+mf->v2)->co, (mv+mf->v1)->co, (mv+mf->v4)->co);
452
a2 += lscm_angle_cos((mv+mf->v4)->co, (mv+mf->v1)->co, (mv+mf->v2)->co);
457
if(!mf->v4 || a1 > a2) {
466
v1->flag= v2->flag= v3->flag= 0;
477
v1->tf= v2->tf= v3->tf= tf;
483
if(tf->unwrap & TF_SEAM1) {
484
v1->flag |= LSCM_SEAM1;
485
v2->flag |= LSCM_SEAM1;
488
if(tf->unwrap & TF_SEAM2) {
489
v2->flag |= LSCM_SEAM2;
490
v3->flag |= LSCM_SEAM2;
493
if(!mf->v4 && tf->unwrap & TF_SEAM3) {
494
v1->flag |= LSCM_SEAM2;
495
v3->flag |= LSCM_SEAM1;
498
v1 += 3; v2 += 3; v3 += 3;
499
sv1 += 3; sv2 += 3; sv3 += 3;
502
if(mf->v4 && a1 > a2) {
511
v1->flag= v2->flag= v3->flag= 0;
522
v1->tf= v2->tf= v3->tf= tf;
528
if(tf->unwrap & TF_SEAM3) {
529
v2->flag |= LSCM_SEAM1;
530
v3->flag |= LSCM_SEAM2;
533
if(tf->unwrap & TF_SEAM4) {
534
v1->flag |= LSCM_SEAM2;
535
v3->flag |= LSCM_SEAM1;
538
v1 += 3; v2 += 3; v3 += 3;
539
sv1 += 3; sv2 += 3; sv3 += 3;
542
if(mf->v4 && a1 <= a2) {
551
v1->flag= v2->flag= v3->flag= 0;
562
v1->tf= v2->tf= v3->tf= tf;
568
if(tf->unwrap & TF_SEAM1) {
569
v1->flag |= LSCM_SEAM1;
570
v2->flag |= LSCM_SEAM1;
573
if(tf->unwrap & TF_SEAM4) {
574
v1->flag |= LSCM_SEAM2;
575
v3->flag |= LSCM_SEAM1;
578
v1 += 3; v2 += 3; v3 += 3;
579
sv1 += 3; sv2 += 3; sv3 += 3;
591
v1->flag= v2->flag= v3->flag= 0;
602
v1->tf= v2->tf= v3->tf= tf;
608
if(tf->unwrap & TF_SEAM2) {
609
v1->flag |= LSCM_SEAM1;
610
v2->flag |= LSCM_SEAM1;
613
if(tf->unwrap & TF_SEAM3) {
614
v2->flag |= LSCM_SEAM2;
615
v3->flag |= LSCM_SEAM2;
618
v1 += 3; v2 += 3; v3 += 3;
619
sv1 += 3; sv2 += 3; sv3 += 3;
626
/* sort by vertex id */
627
qsort(sortvert, totvert, sizeof(LscmVert*), comp_lscmvert);
629
*lscm_vertices= lscmvert;
630
*sort_vertices= sortvert;
634
static void lscm_min_max_cent_rad(Mesh *me, LscmVert **sortvert, int totvert, float *min, float *max, float *center, float *radius)
636
MVert *mv= me->mvert;
638
int a, lastvert, vertcount;
641
/* find min, max and center */
642
center[0]= center[1]= center[2]= 0.0;
643
INIT_MINMAX(min, max);
649
for(a=totvert; a>0; a--, sv++) {
651
if(v->v != lastvert) {
654
VecAddf(center, center, (mv+v->v)->co);
655
DO_MINMAX(co, min, max);
662
VecMulf(center, (float)1.0/(float)vertcount);
665
VecSubf(sub, center, max);
666
*radius= Normalise(sub);
672
static void lscm_projection_axes(float *min, float *max, float *p1, float *p2)
680
p1[0]= p1[1]= p1[2]= 0.0;
681
p2[0]= p2[1]= p2[2]= 0.0;
683
if(dx < dy && dx < dz) {
684
if(dy > dz) p1[1]= p2[2]= 1.0; /* y, z */
685
else p1[2]= p2[1]= 1.0; /* z, y */
687
else if(dy < dx && dy < dz) {
688
if(dx > dz) p1[0]= p2[2]= 1.0; /* x, z */
689
else p1[2]= p2[0]= 1.0; /* z, x */
692
if(dx > dy) p1[0]= p2[1]= 1.0; /* x, y */
693
else p1[1]= p2[0]= 1.0; /* y, x */
697
static void lscm_set_initial_solution(Mesh *me, LscmVert **sortvert, int totvert, float *p1, float *p2, int *vertex_min, int *vertex_max)
699
float umin, umax, *uv, *co;
702
MVert *mv= me->mvert;
712
for(a=totvert; a>0; a--, sv++) {
715
uv= v->tf->uv[v->tf_index];
729
nlSetVariable(2*v->index, uv[0]);
730
nlSetVariable(2*v->index + 1, uv[1]);
737
static void lscm_set_pinned_solution(Mesh *me, LscmVert **sortvert, int totvert, int *pinned)
739
float min[2], max[2], *uv, *co;
742
MVert *mv= me->mvert;
744
INIT_MINMAX2(min, max);
749
for(a=totvert; a>0; a--, sv++) {
752
uv= v->tf->uv[v->tf_index];
754
pin = ((v->tf->unwrap & TF_PIN1) && (v->tf_index == 0)) ||
755
((v->tf->unwrap & TF_PIN2) && (v->tf_index == 1)) ||
756
((v->tf->unwrap & TF_PIN3) && (v->tf_index == 2)) ||
757
((v->tf->unwrap & TF_PIN4) && (v->tf_index == 3));
759
nlSetVariable(2*v->index, uv[0]);
760
nlSetVariable(2*v->index + 1, uv[1]);
763
DO_MINMAX2(uv, min, max);
767
nlLockVariable(2*v->index);
768
nlLockVariable(2*v->index + 1);
773
/* abuse umax vmax for caculating euclidian distance */
777
/* check for degenerated pinning box */
778
if (((max[0]*max[0])+(max[1]*max[1])) < 1e-10)
784
static void lscm_build_matrix(Mesh *me, LscmVert *lscmvert, int *groups, int gid, float *center, float radius)
786
MVert *mv= me->mvert;
789
int *gf, a, id1, id2, id3;
791
float co1[3], co2[3], co3[3];
800
for(a=me->totface; a>0; a--) {
802
VecCopyf(co1, (mv+v->v)->co);
804
VecCopyf(co2, (mv+v->v)->co);
806
VecCopyf(co3, (mv+v->v)->co);
808
lscm_add_triangle(co1, co2, co3, id1, id2, id3, center, radius);
811
VecCopyf(co1, (mv+v->v)->co);
813
VecCopyf(co2, (mv+v->v)->co);
815
VecCopyf(co3, (mv+v->v)->co);
817
lscm_add_triangle(co1, co2, co3, id1, id2, id3, center, radius);
826
static void lscm_load_solution(Mesh *me, LscmVert *lscmvert, int *groups, int gid)
839
for(a=me->totface; a>0; a--) {
845
/* index= u, index + 1= v */
847
uv= v->tf->uv[v->tf_index];
849
uv[0]= nlGetVariable(2*v->index);
850
uv[1]= nlGetVariable(2*v->index + 1);
860
static int unwrap_lscm_face_group(Mesh *me, int *groups, int gid)
862
LscmVert *lscmvert, **sortvert;
863
int totindex, totvert, vmin, vmax,pinned;
864
float min[3], max[3], center[3], radius, p1[3], p2[3];
866
/* build the data structures */
867
totvert= lscm_build_vertex_data(me, groups, gid, &lscmvert, &sortvert);
869
/* calculate min, max, center and radius */
870
lscm_min_max_cent_rad(me, sortvert, totvert, min, max, center, &radius);
872
/* index distinct vertices */
873
totindex= lscm_set_indices(sortvert, totvert);
877
nlSolverParameteri(NL_NB_VARIABLES, 2*totindex);
878
nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
882
/* find axes for projecting initial solutions on */
883
lscm_projection_axes(min, max, p1, p2);
884
/* see if pinned data is avail and set on fly */
885
lscm_set_pinned_solution(me, sortvert, totvert, &pinned);
887
if(pinned < 0); /* really small pinned uv's: won't see difference anyway */
892
/* set initial solution and locate two extrema vertices to pin */
893
lscm_set_initial_solution(me,sortvert,totvert,p1,p2,&vmin,&vmax);
896
nlLockVariable(2*vmin);
897
nlLockVariable(2*vmin + 1);
898
nlLockVariable(2*vmax);
899
nlLockVariable(2*vmax + 1);
902
/* add triangles to the solver */
903
lscm_build_matrix(me, lscmvert, groups, gid, center, radius);
907
/* LSCM solver magic! */
910
/* load new uv's: will be projected uv's if solving failed */
911
lscm_load_solution(me, lscmvert, groups, gid);
914
nlDeleteContext(nlGetCurrent());
920
static void seam_group_bbox(Mesh *me, int *groups, int gid, float *min, float *max)
926
INIT_MINMAX2(min, max);
932
for(a=me->totface; a>0; a--) {
933
if((gid!=0 && *gf==gid) || (gid==0 && *gf)) {
935
DO_MINMAX2(tf->uv[0], min, max)
936
DO_MINMAX2(tf->uv[1], min, max)
937
DO_MINMAX2(tf->uv[2], min, max)
940
DO_MINMAX2(tf->uv[3], min, max)
947
static void seam_group_scale(Mesh *me, int *groups, int gid, float scale)
957
for(a=me->totface; a>0; a--) {
958
if((gid!=0 && *gf==gid) || (gid==0 && *gf)) {
960
Vec2Mulf(tf->uv[0], scale);
961
Vec2Mulf(tf->uv[1], scale);
962
Vec2Mulf(tf->uv[2], scale);
963
if(mf->v4) Vec2Mulf(tf->uv[3], scale);
969
static void seam_group_move(Mesh *me, int *groups, int gid, float add[2])
979
for(a=me->totface; a>0; a--) {
980
if((gid!=0 && *gf==gid) || (gid==0 && *gf)) {
982
Vec2Addf(tf->uv[0], tf->uv[0], add);
983
Vec2Addf(tf->uv[1], tf->uv[1], add);
984
Vec2Addf(tf->uv[2], tf->uv[2], add);
985
if(mf->v4) Vec2Addf(tf->uv[3], tf->uv[3], add);
991
/* put group withing (0,0)->(1,1) boundbox */
992
static void seam_group_normalize(Mesh *me, int *groups, int gid)
994
float min[2], max[2], sx, sy, scale, add[2];
996
seam_group_bbox(me, groups, gid, min, max);
1001
scale= MAX2(sx, sy);
1007
seam_group_move(me, groups, gid, add);
1008
seam_group_scale(me, groups, gid, scale);
1011
/* get scale relative to mesh */
1012
static float seam_group_relative_scale(Mesh *me, int *groups, int gid)
1014
MVert *mv= me->mvert;
1018
float len_xyz, len_uv;
1026
for(a=me->totface; a>0; a--) {
1029
len_uv += Vec2Lenf(tf->uv[0], tf->uv[1]);
1030
len_xyz += VecLenf((mv+mf->v1)->co, (mv+mf->v2)->co);
1032
len_uv += Vec2Lenf(tf->uv[1], tf->uv[2]);
1033
len_xyz += VecLenf((mv+mf->v2)->co, (mv+mf->v3)->co);
1037
len_uv += Vec2Lenf(tf->uv[2], tf->uv[3]);
1038
len_xyz += VecLenf((mv+mf->v3)->co, (mv+mf->v4)->co);
1040
len_uv += Vec2Lenf(tf->uv[3], tf->uv[0]);
1041
len_xyz += VecLenf((mv+mf->v4)->co, (mv+mf->v1)->co);
1044
len_uv += Vec2Lenf(tf->uv[2], tf->uv[0]);
1045
len_xyz += VecLenf((mv+mf->v3)->co, (mv+mf->v1)->co);
1051
return (len_uv/len_xyz);
1054
/* very primitive packing */
1055
static void pack_seam_groups(Mesh *me, int *groups, int totgroup)
1057
float *groupscale, minscale, scale, add[2], groupw;
1058
float dx, dy, packx, packy, min[2], max[2], rowh;
1061
groupscale = (float*)MEM_mallocN(sizeof(float)*totgroup, "SeamGroupScale");
1065
for(a=0; a<totgroup; a++) {
1066
groupscale[a]= seam_group_relative_scale(me, groups, a+1);
1067
minscale= MIN2(groupscale[a], minscale);
1072
groupw= 1.0/sqrt(totgroup);
1074
for(a=0; a<totgroup; a++) {
1076
/* scale so all groups have the same size relative to the mesh */
1077
scale = minscale/groupscale[a];
1080
seam_group_bbox(me, groups, a+1, min, max);
1081
dx= (max[0]-min[0])*scale;
1082
dy= (max[1]-min[1])*scale;
1088
add[0]= add[1]= 0.0;
1098
else if(dx <= (1.0-packx)) {
1103
rowh= MAX2(rowh, dy);
1118
seam_group_scale(me, groups, a+1, scale);
1119
seam_group_move(me, groups, a+1, add);
1122
MEM_freeN(groupscale);
1124
seam_group_normalize(me, groups, 0);
1125
seam_group_scale(me, groups, 0, 0.98);
1126
add[0]= add[1]= 0.01;
1127
seam_group_move(me, groups, 0, add);
1130
void unwrap_lscm(void)
1135
int totgroup, *groups=NULL, a;
1137
me= get_mesh(OBACT);
1138
if(me==0 || me->tface==0) return;
1140
totgroup= make_seam_groups(me, &groups);
1142
if(totgroup==0) return;
1144
for(a=totgroup; a>0; a--) {
1145
res= unwrap_lscm_face_group(me, groups, a);
1146
if((res < 3) && (res > -1)) {
1147
seam_group_normalize(me, groups, a);
1155
if(dopack) pack_seam_groups(me, groups, totgroup);
1159
BIF_undo_push("UV lscm unwrap");
1161
object_uvs_changed(OBACT);
1163
allqueue(REDRAWVIEW3D, 0);
1164
allqueue(REDRAWIMAGE, 0);
1167
/* note; to make it quick work, brecht/jens: you can make it nice later! (ton) */
1168
void unwrap_lscm_live(void)
1173
int totgroup, *groups=NULL, a;
1175
me= get_mesh(OBACT);
1176
if(me==0 || me->tface==0) return;
1178
totgroup= make_seam_groups(me, &groups);
1180
if(totgroup==0) return;
1182
for(a=totgroup; a>0; a--) {
1183
res= unwrap_lscm_face_group(me, groups, a);
1184
if((res < 3) && (res > -1)) {
1185
seam_group_normalize(me, groups, a);
1193
if(dopack) pack_seam_groups(me, groups, totgroup);
1199
/* Set tface seams based on edge data, uses hash table to find seam edges. */
1201
void set_seamtface()
1210
me= get_mesh(OBACT);
1211
if(!me || !me->tface || !(G.f & G_FACESELECT)) return;
1213
ehash= BLI_edgehash_new();
1215
for(medge=me->medge, a=me->totedge; a>0; a--, medge++)
1216
if(medge->flag & ME_SEAM)
1217
BLI_edgehash_insert(ehash, medge->v1, medge->v2, NULL);
1221
for(a=me->totface; a>0; a--, mf++, tf++) {
1222
tf->unwrap &= ~(TF_SEAM1|TF_SEAM2|TF_SEAM3|TF_SEAM4);
1224
if(!ehash) continue;
1226
if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2)) tf->unwrap |= TF_SEAM1;
1227
if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3)) tf->unwrap |= TF_SEAM2;
1230
if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4)) tf->unwrap |= TF_SEAM3;
1231
if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1)) tf->unwrap |= TF_SEAM4;
1233
else if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1)) tf->unwrap |= TF_SEAM3;
1236
BLI_edgehash_free(ehash, NULL);
1239
83
void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index)
1243
87
int a, doit=1, mark=0;
89
EdgeHash *ehash, *seamhash;
1247
92
ehash= BLI_edgehash_new();
93
seamhash = BLI_edgehash_new();
1248
94
linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv");
96
for(med=me->medge, a=0; a < me->totedge; a++, med++)
97
if(med->flag & ME_SEAM)
98
BLI_edgehash_insert(seamhash, med->v1, med->v2, NULL);
1250
100
if (mode==0 || mode==1) {
1251
101
/* only put face under cursor in array */
1252
102
mf= ((MFace*)me->mface) + index;
1332
BLI_edgehash_free(ehash, NULL);
1333
187
MEM_freeN(linkflag);
1335
189
BIF_undo_push("Select linked UV face");
1336
190
object_tface_flags_changed(OBACT, 0);
195
ParamHandle *construct_param_handle(Mesh *me, short implicit, short fill, short sel)
204
handle = param_construct_begin();
209
for (a=0; a<me->totface; a++, mf++, tf++) {
210
ParamKey key, vkeys[4];
211
ParamBool pin[4], select[4];
216
if (tf->flag & TF_HIDE)
219
if (sel && !(tf->flag & TF_SELECT))
222
if (implicit && !(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
226
vkeys[0] = (ParamKey)mf->v1;
227
vkeys[1] = (ParamKey)mf->v2;
228
vkeys[2] = (ParamKey)mf->v3;
230
co[0] = (mv+mf->v1)->co;
231
co[1] = (mv+mf->v2)->co;
232
co[2] = (mv+mf->v3)->co;
238
pin[0] = ((tf->unwrap & TF_PIN1) != 0);
239
pin[1] = ((tf->unwrap & TF_PIN2) != 0);
240
pin[2] = ((tf->unwrap & TF_PIN3) != 0);
242
select[0] = ((tf->flag & TF_SEL1) != 0);
243
select[1] = ((tf->flag & TF_SEL2) != 0);
244
select[2] = ((tf->flag & TF_SEL3) != 0);
247
vkeys[3] = (ParamKey)mf->v4;
248
co[3] = (mv+mf->v4)->co;
250
pin[3] = ((tf->unwrap & TF_PIN4) != 0);
251
select[3] = ((tf->flag & TF_SEL4) != 0);
257
param_face_add(handle, key, nverts, vkeys, co, uv, pin, select);
261
for(medge=me->medge, a=me->totedge; a>0; a--, medge++) {
262
if(medge->flag & ME_SEAM) {
265
vkeys[0] = (ParamKey)medge->v1;
266
vkeys[1] = (ParamKey)medge->v2;
267
param_edge_set_seam(handle, vkeys);
272
param_construct_end(handle, fill, implicit);
277
void unwrap_lscm(short seamcut)
281
short abf = G.scene->toolsettings->unwrapper == 1;
282
short fillholes = G.scene->toolsettings->uvcalc_flag & 1;
285
if(me==0 || me->tface==0) return;
287
handle = construct_param_handle(me, 0, fillholes, seamcut == 0);
289
param_lscm_begin(handle, PARAM_FALSE, abf);
290
param_lscm_solve(handle);
291
param_lscm_end(handle);
297
param_delete(handle);
300
BIF_undo_push("UV unwrap");
302
object_uvs_changed(OBACT);
304
allqueue(REDRAWVIEW3D, 0);
305
allqueue(REDRAWIMAGE, 0);
308
void minimize_stretch_tface_uv(void)
313
short doit = 1, escape = 0, val, blend = 0;
314
unsigned short event = 0;
315
short fillholes = G.scene->toolsettings->uvcalc_flag & 1;
317
me = get_mesh(OBACT);
318
if(me==0 || me->tface==0) return;
320
handle = construct_param_handle(me, 1, fillholes, 1);
322
lasttime = PIL_check_seconds_timer();
324
param_stretch_begin(handle);
327
param_stretch_iter(handle);
330
event= extern_qread(&val);
344
param_stretch_blend(handle, blend*0.1f);
353
param_stretch_blend(handle, blend*0.1f);
360
else if ((event == LEFTMOUSE) || (event == RIGHTMOUSE)) {
361
escape = (event == RIGHTMOUSE);
369
if (PIL_check_seconds_timer() - lasttime > 0.5) {
374
sprintf(str, "Stretch minimize. Blend %.2f.", blend*0.1f);
377
lasttime = PIL_check_seconds_timer();
378
object_uvs_changed(OBACT);
379
if(G.sima->lock) force_draw_plus(SPACE_VIEW3D, 0);
385
param_flush_restore(handle);
389
param_stretch_end(handle);
391
param_delete(handle);
393
BIF_undo_push("UV stretch minimize");
395
object_uvs_changed(OBACT);
397
allqueue(REDRAWVIEW3D, 0);
398
allqueue(REDRAWIMAGE, 0);
403
static ParamHandle *liveHandle = NULL;
405
void unwrap_lscm_live_begin(void)
408
short abf = G.scene->toolsettings->unwrapper == 1;
409
short fillholes = G.scene->toolsettings->uvcalc_flag & 1;
412
if(me==0 || me->tface==0) return;
414
liveHandle = construct_param_handle(me, 0, fillholes, 1);
416
param_lscm_begin(liveHandle, PARAM_TRUE, abf);
419
void unwrap_lscm_live_re_solve(void)
422
param_lscm_solve(liveHandle);
423
param_flush(liveHandle);
427
void unwrap_lscm_live_end(short cancel)
430
param_lscm_end(liveHandle);
432
param_flush_restore(liveHandle);
433
param_delete(liveHandle);