~ubuntu-branches/ubuntu/gutsy/blender/gutsy-security

« back to all changes in this revision

Viewing changes to source/blender/src/unwrapper.c

  • Committer: Bazaar Package Importer
  • Author(s): Lukas Fittl
  • Date: 2006-09-20 01:57:27 UTC
  • mfrom: (1.2.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20060920015727-gmoqlxwstx9wwqs3
Tags: 2.42a-1ubuntu1
* Merge from Debian unstable (Closes: Malone #55903). Remaining changes:
  - debian/genpot: Add python scripts from Lee June <blender@eyou.com> to
    generate a reasonable PO template from the sources. Since gettext is used
    in a highly nonstandard way, xgettext does not work for this job.
  - debian/rules: Call the scripts, generate po/blender.pot, and clean it up
    in the clean target.
  - Add a proper header to the generated PO template.
* debian/control: Build depend on libavformat-dev >= 3:0.cvs20060823-3.1,
  otherwise this package will FTBFS

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/**
2
 
 * $Id: unwrapper.c,v 1.13 2005/11/22 15:00:32 broken Exp $
 
2
 * $Id: unwrapper.c,v 1.17 2006/06/10 20:35:54 blendix Exp $
3
3
 *
4
4
 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5
5
 *
43
43
#include "DNA_mesh_types.h"
44
44
#include "DNA_meshdata_types.h"
45
45
#include "DNA_scene_types.h"
 
46
#include "DNA_screen_types.h"
 
47
#include "DNA_space_types.h"
46
48
 
47
49
#include "BKE_global.h"
48
50
#include "BKE_mesh.h"
53
55
 
54
56
#include "BIF_editsima.h"
55
57
#include "BIF_space.h"
 
58
#include "BIF_screen.h"
56
59
 
57
60
#include "blendef.h"
58
61
#include "mydevice.h"
59
62
 
60
 
#include "ONL_opennl.h"
61
63
#include "BDR_unwrapper.h"
62
64
 
63
 
/* Implementation Least Squares Conformal Maps parameterization, based on
64
 
 * chapter 2 of:
65
 
 * Bruno Levy, Sylvain Petitjean, Nicolas Ray, Jerome Maillot. Least Squares
66
 
 * Conformal Maps for Automatic Texture Atlas Generation. In Siggraph 2002,
67
 
 * July 2002.
68
 
 */
69
 
 
70
 
/* Data structure defines */
71
 
#define LSCM_SEAM1   1
72
 
#define LSCM_SEAM2   2
73
 
#define LSCM_INDEXED 4
74
 
#define LSCM_PINNED  8
75
 
 
76
 
/* LscmVert = One UV */
77
 
typedef struct LscmVert {
78
 
        int v, v1, v2;            /* vertex indices */
79
 
        int index;                /* index in solver */
80
 
        short tf_index;           /* index in tface (0, 1, 2 or 3) */
81
 
        short flag;               /* see above LSCM constants */
82
 
        TFace *tf;                /* original tface */
83
 
} LscmVert;
84
 
 
85
 
/* QuickSort helper function, sort by vertex id */
86
 
static int comp_lscmvert(const void *u1, const void *u2)
87
 
{
88
 
        LscmVert *v1, *v2;
89
 
        
90
 
        v1= *((LscmVert**)u1);
91
 
        v2= *((LscmVert**)u2);
92
 
 
93
 
        if (v1->v > v2->v) return 1;
94
 
        else if (v1->v < v2->v) return -1;
95
 
        return 0;
96
 
}
97
 
 
98
 
/* Hashed edge table utility */
 
65
#include "PIL_time.h"
 
66
 
 
67
#include "parametrizer.h"
 
68
 
 
69
/* Set tface seams based on edge data, uses hash table to find seam edges. */
99
70
 
100
71
static void hash_add_face(EdgeHash *ehash, MFace *mf)
101
72
{
109
80
                BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL);
110
81
}
111
82
 
112
 
/* divide selected faces in groups, based on seams. note that group numbering
113
 
   starts at 1 */
114
 
static int make_seam_groups(Mesh *me, int **seamgroups)
115
 
{
116
 
        int a, b, gid;
117
 
        TFace *tf, *tface;
118
 
        MFace *mf, *mface;
119
 
        int *gf, *gface, *groups;
120
 
        EdgeHash *ehash;
121
 
        int doit, mark;
122
 
 
123
 
        if(!me || !me->tface) return 0;
124
 
 
125
 
        groups= (int*)MEM_callocN(sizeof(int)*me->totface, "SeamGroups");
126
 
 
127
 
        ehash= BLI_edgehash_new();
128
 
 
129
 
        mface= (MFace*)me->mface;
130
 
        tface= (TFace*)me->tface;
131
 
        gface= groups;
132
 
        gid= 0;
133
 
        for(b=me->totface; b>0; b--, mface++, tface++, gface++) {
134
 
                if(!(tface->flag & TF_SELECT) || *gface!=0) continue;
135
 
 
136
 
                if(gid != 0)
137
 
                        BLI_edgehash_clear(ehash, NULL);
138
 
 
139
 
                gid++;
140
 
                *gface= gid;
141
 
                mark= 0;
142
 
                doit= 1;
143
 
 
144
 
 
145
 
                while(doit) {
146
 
                        doit= 0;
147
 
                
148
 
                        /* select connected: fill array */
149
 
                        tf= tface;
150
 
                        mf= mface;
151
 
                        gf= gface;
152
 
                        a= b;
153
 
                        while(a--) {
154
 
                                if(tf->flag & TF_HIDE);
155
 
                                else if(tf->flag & TF_SELECT && *gf==gid) {
156
 
                                        hash_add_face(ehash, mf);
157
 
                                }
158
 
                                tf++; mf++; gf++;
159
 
                        }
160
 
                
161
 
                        /* select the faces using array
162
 
                         * consider faces connected when they share one non-seam edge */
163
 
                        tf= tface;
164
 
                        mf= mface;
165
 
                        gf= gface;
166
 
                        a= b;
167
 
                        while(a--) {
168
 
                                if(tf->flag & TF_HIDE);
169
 
                                else if(tf->flag & TF_SELECT && *gf==0) {
170
 
                                        mark= 0;
171
 
        
172
 
                                        if(!(tf->unwrap & TF_SEAM1))
173
 
                                                if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2))
174
 
                                                        mark= 1;
175
 
                                        if(!(tf->unwrap & TF_SEAM2))
176
 
                                                if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3))
177
 
                                                        mark= 1;
178
 
                                        if(!(tf->unwrap & TF_SEAM3)) {
179
 
                                                if(mf->v4) {
180
 
                                                        if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4))
181
 
                                                                mark= 1;
182
 
                                                }
183
 
                                                else if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1))
184
 
                                                        mark= 1;
185
 
                                        }
186
 
                                        if(mf->v4 && !(tf->unwrap & TF_SEAM4))
187
 
                                                if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1))
188
 
                                                        mark= 1;
189
 
        
190
 
                                        if(mark) {
191
 
                                                *gf= gid;
192
 
                                                doit= 1;
193
 
                                        }
194
 
                                }
195
 
                                tf++; mf++; gf++;
196
 
                        }
197
 
                }
198
 
        }
199
 
 
200
 
        BLI_edgehash_free(ehash, NULL);
201
 
        *seamgroups= groups;
202
 
 
203
 
        return gid;
204
 
}
205
 
 
206
 
static void lscm_rotate_vert(int a, LscmVert **sortvert, int v2, int index)
207
 
{
208
 
        LscmVert **sv, *v;
209
 
        int found, b;
210
 
 
211
 
        /* starting from edge sortvert->v,v2, rotate around vertex and set
212
 
         * index until a seam or an already marked tri is encountered */
213
 
        found = 1;
214
 
 
215
 
        while(found) {
216
 
                found= 0;
217
 
                sv=sortvert;
218
 
 
219
 
                for(b=a; b>0 && ((*sv)->v == (*sortvert)->v) && !found; b--, sv++) {
220
 
                        v= *sv;
221
 
 
222
 
                        if(v->flag & LSCM_INDEXED);
223
 
                        else if(v->v1 == v2) {
224
 
                                v2= v->v2;
225
 
 
226
 
                                if(v->flag & LSCM_SEAM1) break;
227
 
 
228
 
                                v->index= index;
229
 
                                v->flag |= LSCM_INDEXED;
230
 
                                found= 1;
231
 
                                break;
232
 
                        }
233
 
                        else if(v->v2==v2) {
234
 
                                v2= v->v1;
235
 
 
236
 
                                if(v->flag & LSCM_SEAM2) break;
237
 
 
238
 
                                v->index= index;
239
 
                                v->flag |= LSCM_INDEXED;
240
 
                                found= 1;
241
 
                                break;
242
 
                        }
243
 
                }
244
 
        }
245
 
}
246
 
 
247
 
static int lscm_vertex_set_index(int a, LscmVert **sortvert, int totindex)
248
 
{
249
 
        LscmVert **sv, *v;
250
 
        int index, b;
251
 
 
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 */
256
 
 
257
 
        index= totindex;
258
 
        sv= sortvert;
259
 
 
260
 
        for(b=a; b>0 && ((*sv)->v == (*sortvert)->v); b--, sv++) {
261
 
                v= *sv;
262
 
 
263
 
                if(v->flag & LSCM_INDEXED) continue;
264
 
 
265
 
                v->index= index;
266
 
                v->flag |= LSCM_INDEXED;
267
 
 
268
 
                lscm_rotate_vert(b, sv, v->v1, index);
269
 
                lscm_rotate_vert(b, sv, v->v2, index);
270
 
 
271
 
                index++;
272
 
        }
273
 
 
274
 
        return index;
275
 
}
276
 
 
277
 
static int lscm_set_indices(LscmVert **sortvert, int totvert)
278
 
{
279
 
        LscmVert *v, **sv;
280
 
        int a, lastvert, totindex;
281
 
 
282
 
        totindex= 0;
283
 
        lastvert= -1;
284
 
        sv= sortvert;
285
 
 
286
 
        for(a=totvert; a>0; a--, sv++) {
287
 
                v= *sv;
288
 
                if(v->v != lastvert) {
289
 
                        totindex= lscm_vertex_set_index(a, sv, totindex);
290
 
                        lastvert= v->v;
291
 
                }
292
 
        }
293
 
 
294
 
        return totindex;
295
 
}
296
 
 
297
 
static void lscm_normalize(float *co, float *center, float radius)
298
 
{
299
 
        /* normalize relative to complete surface */
300
 
        VecSubf(co, co, center);
301
 
        VecMulf(co, (float)1.0/radius);
302
 
}
303
 
 
304
 
static void lscm_add_triangle(float *v1, float *v2, float *v3, int vid1, int vid2, int vid3, float *center, float radius)
305
 
{
306
 
        float x[3], y[3], z[3], sub[3], z1[2], z2[2];
307
 
        int id0[2], id1[2], id2[2];
308
 
 
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);
314
 
 
315
 
        VecSubf(x, v2, v1);
316
 
        Normalise(x);
317
 
 
318
 
        VecSubf(sub, v3, v1);
319
 
        Crossf(z, x, sub);
320
 
        Normalise(z);
321
 
 
322
 
        Crossf(y, z, x);
323
 
 
324
 
        /* reduce to two 2d vectors */
325
 
        VecSubf(sub, v2, v1);
326
 
        z1[0]= Normalise(sub);
327
 
        z1[1]= 0;
328
 
 
329
 
        VecSubf(sub, v3, v1);
330
 
        z2[0]= Inpf(sub, x);
331
 
        z2[1]= Inpf(sub, y);
332
 
 
333
 
        /* split id's up for u and v
334
 
           id = u, id + 1 = v */
335
 
        id0[0]= 2*vid1;
336
 
        id0[1]= 2*vid1 + 1;
337
 
        id1[0]= 2*vid2;
338
 
        id1[1]= 2*vid2 + 1;
339
 
        id2[0]= 2*vid3;
340
 
        id2[1]= 2*vid3 + 1;
341
 
 
342
 
        /* The LSCM Equation:
343
 
         * ------------------
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
346
 
         * Uk = uk + i*vk
347
 
         * Zk = xk + i*yk (= zk[0] + i*zk[1] in the code)
348
 
         * 
349
 
         * That makes the equation:
350
 
         * (Z1 - Z0)(U2 - U0) = (Z2 - Z0)(U1 - U0)
351
 
         *
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)
354
 
         *
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))
360
 
         * u2 * (x1)
361
 
         * v2 * (i*(x1))
362
 
         */
363
 
 
364
 
        /* real part */
365
 
        nlBegin(NL_ROW);
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]        );
371
 
        nlEnd(NL_ROW);
372
 
 
373
 
        /* imaginary  part */
374
 
        nlBegin(NL_ROW);
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]        );
380
 
        nlEnd(NL_ROW);
381
 
}
382
 
 
383
 
static float lscm_angle_cos(float *v1, float *v2, float *v3)
384
 
{
385
 
    float vec1[3], vec2[3];
386
 
 
387
 
        VecSubf(vec1, v2, v1);
388
 
        VecSubf(vec2, v3, v1);
389
 
        Normalise(vec1);
390
 
        Normalise(vec2);
391
 
 
392
 
        return vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2];
393
 
}
394
 
 
395
 
static int lscm_build_vertex_data(Mesh *me, int *groups, int gid, LscmVert **lscm_vertices, LscmVert ***sort_vertices)
396
 
{
397
 
        MVert *mv;
398
 
        MFace *mf;
399
 
        TFace *tf;
400
 
        int *gf, totvert, a;
401
 
        LscmVert *lscmvert, **sortvert;
402
 
        LscmVert *v1, *v2, *v3, **sv1, **sv2, **sv3;
403
 
        float a1, a2;
404
 
 
405
 
        /* determine size for malloc */
406
 
        totvert= 0;
407
 
        mv = me->mvert;
408
 
        mf= me->mface;
409
 
        tf= me->tface;
410
 
        gf= groups;
411
 
        a1 = a2 = 0;
412
 
 
413
 
        for(a=me->totface; a>0; a--) {
414
 
                if(*gf==gid) {
415
 
 
416
 
                        totvert += 3;
417
 
                        if(mf->v4) totvert +=3; 
418
 
                }
419
 
                tf++; mf++; gf++;
420
 
        }
421
 
 
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");
426
 
 
427
 
        /* actually build the list (including virtual triangulation) */
428
 
        mf= me->mface;
429
 
        tf= me->tface;
430
 
        gf= groups;
431
 
 
432
 
        v1= lscmvert;
433
 
        v2= lscmvert + 1;
434
 
        v3= lscmvert + 2;
435
 
 
436
 
        sv1= sortvert;
437
 
        sv2= sortvert + 1;
438
 
        sv3= sortvert + 2;
439
 
 
440
 
        /* warning: ugly code :) */
441
 
        for(a=me->totface; a>0; a--) {
442
 
                if(*gf==gid) {
443
 
                        /* determine triangulation direction, to avoid degenerate
444
 
                           triangles (small cos = degenerate). */
445
 
                        if(mf->v4) {
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);
449
 
 
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);
453
 
                        }
454
 
 
455
 
                        a1 = 0.0; a2 = 1.0;
456
 
 
457
 
                        if(!mf->v4 || a1 > a2) {
458
 
                                v1->v= mf->v1;
459
 
                                v2->v= mf->v2;
460
 
                                v3->v= mf->v3;
461
 
 
462
 
                                v1->tf_index= 0;
463
 
                                v2->tf_index= 1;
464
 
                                v3->tf_index= 2;
465
 
 
466
 
                                v1->flag= v2->flag= v3->flag= 0;
467
 
 
468
 
                                v1->v1= v2->v;
469
 
                                v1->v2= v3->v;
470
 
 
471
 
                                v2->v1= v1->v;
472
 
                                v2->v2= v3->v;
473
 
 
474
 
                                v3->v1= v1->v;
475
 
                                v3->v2= v2->v;
476
 
 
477
 
                                v1->tf= v2->tf= v3->tf= tf;
478
 
 
479
 
                                *sv1= v1;
480
 
                                *sv2= v2;
481
 
                                *sv3= v3;
482
 
 
483
 
                                if(tf->unwrap & TF_SEAM1) {
484
 
                                        v1->flag |= LSCM_SEAM1;
485
 
                                        v2->flag |= LSCM_SEAM1;
486
 
                                }
487
 
        
488
 
                                if(tf->unwrap & TF_SEAM2) {
489
 
                                        v2->flag |= LSCM_SEAM2;
490
 
                                        v3->flag |= LSCM_SEAM2;
491
 
                                }
492
 
 
493
 
                                if(!mf->v4 && tf->unwrap & TF_SEAM3) {
494
 
                                        v1->flag |= LSCM_SEAM2;
495
 
                                        v3->flag |= LSCM_SEAM1;
496
 
                                }
497
 
 
498
 
                                v1 += 3; v2 += 3; v3 += 3;
499
 
                                sv1 += 3; sv2 += 3; sv3 += 3;
500
 
                        }
501
 
 
502
 
                        if(mf->v4 && a1 > a2) {
503
 
                                v1->v= mf->v1;
504
 
                                v2->v= mf->v3;
505
 
                                v3->v= mf->v4;
506
 
 
507
 
                                v1->tf_index= 0;
508
 
                                v2->tf_index= 2;
509
 
                                v3->tf_index= 3;
510
 
 
511
 
                                v1->flag= v2->flag= v3->flag= 0;
512
 
 
513
 
                                v1->v1= v2->v;
514
 
                                v1->v2= v3->v;
515
 
 
516
 
                                v2->v1= v3->v;
517
 
                                v2->v2= v1->v;
518
 
        
519
 
                                v3->v1= v1->v;
520
 
                                v3->v2= v2->v;
521
 
 
522
 
                                v1->tf= v2->tf= v3->tf= tf;
523
 
 
524
 
                                *sv1= v1;
525
 
                                *sv2= v2;
526
 
                                *sv3= v3;
527
 
 
528
 
                                if(tf->unwrap & TF_SEAM3) {
529
 
                                        v2->flag |= LSCM_SEAM1;
530
 
                                        v3->flag |= LSCM_SEAM2;
531
 
                                }
532
 
        
533
 
                                if(tf->unwrap & TF_SEAM4) {
534
 
                                        v1->flag |= LSCM_SEAM2;
535
 
                                        v3->flag |= LSCM_SEAM1;
536
 
                                }
537
 
 
538
 
                                v1 += 3; v2 += 3; v3 += 3;
539
 
                                sv1 += 3; sv2 += 3; sv3 += 3;
540
 
                        }
541
 
 
542
 
                        if(mf->v4 && a1 <= a2) {
543
 
                                v1->v= mf->v1;
544
 
                                v2->v= mf->v2;
545
 
                                v3->v= mf->v4;
546
 
 
547
 
                                v1->tf_index= 0;
548
 
                                v2->tf_index= 1;
549
 
                                v3->tf_index= 3;
550
 
 
551
 
                                v1->flag= v2->flag= v3->flag= 0;
552
 
 
553
 
                                v1->v1= v2->v;
554
 
                                v1->v2= v3->v;
555
 
 
556
 
                                v2->v1= v1->v;
557
 
                                v2->v2= v3->v;
558
 
 
559
 
                                v3->v1= v1->v;
560
 
                                v3->v2= v2->v;
561
 
 
562
 
                                v1->tf= v2->tf= v3->tf= tf;
563
 
 
564
 
                                *sv1= v1;
565
 
                                *sv2= v2;
566
 
                                *sv3= v3;
567
 
 
568
 
                                if(tf->unwrap & TF_SEAM1) {
569
 
                                        v1->flag |= LSCM_SEAM1;
570
 
                                        v2->flag |= LSCM_SEAM1;
571
 
                                }
572
 
        
573
 
                                if(tf->unwrap & TF_SEAM4) {
574
 
                                        v1->flag |= LSCM_SEAM2;
575
 
                                        v3->flag |= LSCM_SEAM1;
576
 
                                }
577
 
 
578
 
                                v1 += 3; v2 += 3; v3 += 3;
579
 
                                sv1 += 3; sv2 += 3; sv3 += 3;
580
 
 
581
 
                                /* -- */
582
 
 
583
 
                                v1->v= mf->v2;
584
 
                                v2->v= mf->v3;
585
 
                                v3->v= mf->v4;
586
 
 
587
 
                                v1->tf_index= 1;
588
 
                                v2->tf_index= 2;
589
 
                                v3->tf_index= 3;
590
 
 
591
 
                                v1->flag= v2->flag= v3->flag= 0;
592
 
 
593
 
                                v1->v1= v2->v;
594
 
                                v1->v2= v3->v;
595
 
 
596
 
                                v2->v1= v1->v;
597
 
                                v2->v2= v3->v;
598
 
        
599
 
                                v3->v1= v1->v;
600
 
                                v3->v2= v2->v;
601
 
 
602
 
                                v1->tf= v2->tf= v3->tf= tf;
603
 
 
604
 
                                *sv1= v1;
605
 
                                *sv2= v2;
606
 
                                *sv3= v3;
607
 
 
608
 
                                if(tf->unwrap & TF_SEAM2) {
609
 
                                        v1->flag |= LSCM_SEAM1;
610
 
                                        v2->flag |= LSCM_SEAM1;
611
 
                                }
612
 
        
613
 
                                if(tf->unwrap & TF_SEAM3) {
614
 
                                        v2->flag |= LSCM_SEAM2;
615
 
                                        v3->flag |= LSCM_SEAM2;
616
 
                                }
617
 
 
618
 
                                v1 += 3; v2 += 3; v3 += 3;
619
 
                                sv1 += 3; sv2 += 3; sv3 += 3;
620
 
                        }
621
 
 
622
 
                }
623
 
                tf++; mf++; gf++;
624
 
        }
625
 
 
626
 
        /* sort by vertex id */
627
 
        qsort(sortvert, totvert, sizeof(LscmVert*), comp_lscmvert);
628
 
        
629
 
        *lscm_vertices= lscmvert;
630
 
        *sort_vertices= sortvert;
631
 
        return totvert;
632
 
}
633
 
 
634
 
static void lscm_min_max_cent_rad(Mesh *me, LscmVert **sortvert, int totvert, float *min, float *max, float *center, float *radius)
635
 
{
636
 
        MVert *mv= me->mvert;
637
 
        LscmVert *v, **sv;
638
 
        int a, lastvert, vertcount;
639
 
        float *co, sub[3];
640
 
        
641
 
        /* find min, max and center */
642
 
        center[0]= center[1]= center[2]= 0.0;
643
 
        INIT_MINMAX(min, max);
644
 
 
645
 
        vertcount= 0;
646
 
        lastvert= -1;
647
 
        sv= sortvert;
648
 
 
649
 
        for(a=totvert; a>0; a--, sv++) {
650
 
                v= *sv;
651
 
                if(v->v != lastvert) {
652
 
                        co= (mv+v->v)->co;
653
 
 
654
 
                        VecAddf(center, center, (mv+v->v)->co);
655
 
                        DO_MINMAX(co, min, max);
656
 
 
657
 
                        vertcount++;
658
 
                        lastvert= v->v;
659
 
                }
660
 
        }
661
 
 
662
 
        VecMulf(center, (float)1.0/(float)vertcount);
663
 
 
664
 
        /* find radius */
665
 
        VecSubf(sub, center, max);
666
 
        *radius= Normalise(sub);
667
 
 
668
 
        if(*radius < 1e-20)
669
 
                *radius= 1.0;
670
 
}
671
 
 
672
 
static void lscm_projection_axes(float *min, float *max, float *p1, float *p2)
673
 
{
674
 
        float dx, dy, dz;
675
 
 
676
 
        dx= max[0] - min[0];
677
 
        dy= max[1] - min[1];
678
 
        dz= max[2] - min[2];
679
 
 
680
 
        p1[0]= p1[1]= p1[2]= 0.0;
681
 
        p2[0]= p2[1]= p2[2]= 0.0;
682
 
 
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 */
686
 
        }
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 */
690
 
        }
691
 
        else {
692
 
                if(dx > dy) p1[0]= p2[1]= 1.0;   /* x, y */
693
 
                else p1[1]= p2[0]= 1.0;          /* y, x */
694
 
        }
695
 
}
696
 
 
697
 
static void lscm_set_initial_solution(Mesh *me, LscmVert **sortvert, int totvert, float *p1, float *p2, int *vertex_min, int *vertex_max)
698
 
{
699
 
        float umin, umax, *uv, *co;
700
 
        int vmin, vmax, a;
701
 
        LscmVert **sv, *v;
702
 
        MVert *mv= me->mvert;
703
 
 
704
 
        umin= 1.0e30;
705
 
        umax= -1.0e30;
706
 
 
707
 
        vmin= 0;
708
 
        vmax= 2;
709
 
 
710
 
        sv= sortvert;
711
 
 
712
 
        for(a=totvert; a>0; a--, sv++) {
713
 
                v= *sv;
714
 
                co= (mv+v->v)->co;
715
 
                uv= v->tf->uv[v->tf_index];
716
 
 
717
 
                uv[0]= Inpf(co, p1);
718
 
                uv[1]= Inpf(co, p2);
719
 
                
720
 
                if(uv[0] < umin) {
721
 
                        vmin= v->index;
722
 
                        umin= uv[0];
723
 
                }
724
 
                if(uv[0] > umax) {
725
 
                        vmax= v->index;
726
 
                        umax= uv[0];
727
 
                }
728
 
 
729
 
                nlSetVariable(2*v->index, uv[0]);
730
 
                nlSetVariable(2*v->index + 1, uv[1]);
731
 
        }
732
 
 
733
 
        *vertex_min= vmin;
734
 
        *vertex_max= vmax;
735
 
}
736
 
 
737
 
static void lscm_set_pinned_solution(Mesh *me, LscmVert **sortvert, int totvert, int *pinned)
738
 
{
739
 
        float min[2], max[2], *uv, *co;
740
 
        int a, pin;
741
 
        LscmVert **sv, *v;
742
 
        MVert *mv= me->mvert;
743
 
 
744
 
        INIT_MINMAX2(min, max);
745
 
        *pinned= 0;
746
 
 
747
 
        sv= sortvert;
748
 
 
749
 
        for(a=totvert; a>0; a--, sv++) {
750
 
                v= *sv;
751
 
                co= (mv+v->v)->co;
752
 
                uv= v->tf->uv[v->tf_index];
753
 
 
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)); 
758
 
 
759
 
                nlSetVariable(2*v->index, uv[0]);
760
 
                nlSetVariable(2*v->index + 1, uv[1]);
761
 
 
762
 
        if(pin){
763
 
                        DO_MINMAX2(uv, min, max);
764
 
 
765
 
                        *pinned += 1;
766
 
 
767
 
                        nlLockVariable(2*v->index);
768
 
                        nlLockVariable(2*v->index + 1);
769
 
                }
770
 
        }
771
 
 
772
 
        if (*pinned){
773
 
                /* abuse umax vmax for caculating euclidian distance */
774
 
                max[0] -= min[0];
775
 
                max[1] -= min[1];
776
 
 
777
 
                /* check for degenerated pinning box */
778
 
                if (((max[0]*max[0])+(max[1]*max[1])) < 1e-10)
779
 
                        *pinned = -1;
780
 
        }
781
 
}
782
 
 
783
 
 
784
 
static void lscm_build_matrix(Mesh *me, LscmVert *lscmvert, int *groups, int gid, float *center, float radius)
785
 
{
786
 
        MVert *mv= me->mvert;
787
 
        MFace *mf;
788
 
        TFace *tf;
789
 
        int *gf, a, id1, id2, id3;
790
 
        LscmVert *v;
791
 
        float co1[3], co2[3], co3[3];
792
 
 
793
 
        nlBegin(NL_MATRIX);
794
 
 
795
 
        mf= me->mface;
796
 
        tf= me->tface;
797
 
        gf= groups;
798
 
        v= lscmvert;
799
 
 
800
 
        for(a=me->totface; a>0; a--) {
801
 
                if(*gf==gid) {
802
 
                        VecCopyf(co1, (mv+v->v)->co);
803
 
                        id1= v->index; v++;
804
 
                        VecCopyf(co2, (mv+v->v)->co);
805
 
                        id2= v->index; v++;
806
 
                        VecCopyf(co3, (mv+v->v)->co);
807
 
                        id3= v->index; v++;
808
 
                        lscm_add_triangle(co1, co2, co3, id1, id2, id3, center, radius);
809
 
 
810
 
                        if(mf->v4) {
811
 
                                VecCopyf(co1, (mv+v->v)->co);
812
 
                                id1= v->index; v++;
813
 
                                VecCopyf(co2, (mv+v->v)->co);
814
 
                                id2= v->index; v++;
815
 
                                VecCopyf(co3, (mv+v->v)->co);
816
 
                                id3= v->index; v++;
817
 
                                lscm_add_triangle(co1, co2, co3, id1, id2, id3, center, radius);
818
 
                        } 
819
 
                }
820
 
                tf++; mf++; gf++;
821
 
        }
822
 
 
823
 
        nlEnd(NL_MATRIX);
824
 
}
825
 
 
826
 
static void lscm_load_solution(Mesh *me, LscmVert *lscmvert, int *groups, int gid)
827
 
{
828
 
        MFace *mf;
829
 
        TFace *tf;
830
 
        int *gf, a, b;
831
 
        LscmVert *v;
832
 
        float *uv;
833
 
 
834
 
        mf= me->mface;
835
 
        tf= me->tface;
836
 
        gf= groups;
837
 
        v= lscmvert;
838
 
 
839
 
        for(a=me->totface; a>0; a--) {
840
 
                if(*gf==gid) {
841
 
 
842
 
                        if(mf->v4) b= 6;
843
 
                        else b=3;
844
 
 
845
 
                        /* index= u, index + 1= v */
846
 
                        while(b > 0) {
847
 
                                uv= v->tf->uv[v->tf_index];
848
 
 
849
 
                                uv[0]= nlGetVariable(2*v->index);
850
 
                                uv[1]= nlGetVariable(2*v->index + 1);
851
 
 
852
 
                                v++;
853
 
                                b--;
854
 
                        }
855
 
                }
856
 
                tf++; mf++; gf++;
857
 
        }
858
 
}
859
 
 
860
 
static int unwrap_lscm_face_group(Mesh *me, int *groups, int gid)
861
 
{
862
 
        LscmVert *lscmvert, **sortvert;
863
 
        int totindex, totvert, vmin, vmax,pinned;
864
 
        float min[3], max[3], center[3], radius, p1[3], p2[3];
865
 
 
866
 
        /* build the data structures */
867
 
        totvert= lscm_build_vertex_data(me, groups, gid, &lscmvert, &sortvert);
868
 
 
869
 
        /* calculate min, max, center and radius */
870
 
        lscm_min_max_cent_rad(me, sortvert, totvert, min, max, center, &radius);
871
 
 
872
 
        /* index distinct vertices */
873
 
        totindex= lscm_set_indices(sortvert, totvert);
874
 
 
875
 
        /* create solver */
876
 
        nlNewContext();
877
 
        nlSolverParameteri(NL_NB_VARIABLES, 2*totindex);
878
 
        nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
879
 
 
880
 
        nlBegin(NL_SYSTEM);
881
 
 
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);
886
 
 
887
 
    if(pinned < 0); /* really small pinned uv's: won't see difference anyway */
888
 
        else { 
889
 
                /* auto pinning */
890
 
                if(pinned < 2) 
891
 
                {
892
 
                        /* set initial solution and locate two extrema vertices to pin */
893
 
                        lscm_set_initial_solution(me,sortvert,totvert,p1,p2,&vmin,&vmax);
894
 
 
895
 
                        /* pin 2 uv's */
896
 
                        nlLockVariable(2*vmin);
897
 
                        nlLockVariable(2*vmin + 1);
898
 
                        nlLockVariable(2*vmax);
899
 
                        nlLockVariable(2*vmax + 1);
900
 
                }
901
 
 
902
 
                /* add triangles to the solver */
903
 
                lscm_build_matrix(me, lscmvert, groups, gid, center, radius);
904
 
                
905
 
                nlEnd(NL_SYSTEM);
906
 
                
907
 
                /* LSCM solver magic! */
908
 
                nlSolve();
909
 
                
910
 
                /* load new uv's: will be projected uv's if solving failed  */
911
 
                lscm_load_solution(me, lscmvert, groups, gid);
912
 
    }
913
 
 
914
 
        nlDeleteContext(nlGetCurrent());
915
 
        MEM_freeN(lscmvert);
916
 
        MEM_freeN(sortvert);
917
 
        return (pinned);
918
 
}
919
 
 
920
 
static void seam_group_bbox(Mesh *me, int *groups, int gid, float *min, float *max)
921
 
{
922
 
        MFace *mf;
923
 
        TFace *tf;
924
 
        int *gf, a;
925
 
 
926
 
        INIT_MINMAX2(min, max);
927
 
 
928
 
        mf= me->mface;
929
 
        tf= me->tface;
930
 
        gf= groups;
931
 
 
932
 
        for(a=me->totface; a>0; a--) {
933
 
                if((gid!=0 && *gf==gid) || (gid==0 && *gf)) {
934
 
                        
935
 
                        DO_MINMAX2(tf->uv[0], min, max)
936
 
                        DO_MINMAX2(tf->uv[1], min, max)
937
 
                        DO_MINMAX2(tf->uv[2], min, max)
938
 
 
939
 
                        if(mf->v4) { 
940
 
                                DO_MINMAX2(tf->uv[3], min, max)
941
 
                        }
942
 
                }
943
 
                tf++; mf++; gf++;
944
 
        }
945
 
}
946
 
 
947
 
static void seam_group_scale(Mesh *me, int *groups, int gid, float scale)
948
 
{
949
 
        MFace *mf;
950
 
        TFace *tf;
951
 
        int *gf, a;
952
 
 
953
 
        mf= me->mface;
954
 
        tf= me->tface;
955
 
        gf= groups;
956
 
 
957
 
        for(a=me->totface; a>0; a--) {
958
 
                if((gid!=0 && *gf==gid) || (gid==0 && *gf)) {
959
 
                        
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);
964
 
                }
965
 
                tf++; mf++; gf++;
966
 
        }
967
 
}
968
 
 
969
 
static void seam_group_move(Mesh *me, int *groups, int gid, float add[2])
970
 
{
971
 
        MFace *mf;
972
 
        TFace *tf;
973
 
        int *gf, a;
974
 
 
975
 
        mf= me->mface;
976
 
        tf= me->tface;
977
 
        gf= groups;
978
 
 
979
 
        for(a=me->totface; a>0; a--) {
980
 
                if((gid!=0 && *gf==gid) || (gid==0 && *gf)) {
981
 
                        
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);
986
 
                }
987
 
                tf++; mf++; gf++;
988
 
        }
989
 
}
990
 
 
991
 
/* put group withing (0,0)->(1,1) boundbox */
992
 
static void seam_group_normalize(Mesh *me, int *groups, int gid)
993
 
{
994
 
        float min[2], max[2], sx, sy, scale, add[2];
995
 
 
996
 
        seam_group_bbox(me, groups, gid, min, max);
997
 
 
998
 
        sx= (max[0]-min[0]);
999
 
        sy= (max[1]-min[1]);
1000
 
 
1001
 
        scale= MAX2(sx, sy);
1002
 
        scale= (1.0/scale);
1003
 
 
1004
 
        add[0]= -min[0];
1005
 
        add[1]= -min[1];
1006
 
 
1007
 
        seam_group_move(me, groups, gid, add);
1008
 
        seam_group_scale(me, groups, gid, scale);
1009
 
}
1010
 
 
1011
 
/* get scale relative to mesh */
1012
 
static float seam_group_relative_scale(Mesh *me, int *groups, int gid)
1013
 
{
1014
 
        MVert *mv= me->mvert;
1015
 
        MFace *mf;
1016
 
        TFace *tf;
1017
 
        int *gf, a;
1018
 
        float len_xyz, len_uv;
1019
 
 
1020
 
        len_xyz= 0.0;
1021
 
        len_uv= 0.0;
1022
 
        mf= me->mface;
1023
 
        tf= me->tface;
1024
 
        gf= groups;
1025
 
 
1026
 
        for(a=me->totface; a>0; a--) {
1027
 
                if(*gf==gid) {
1028
 
                        
1029
 
                        len_uv += Vec2Lenf(tf->uv[0], tf->uv[1]);
1030
 
                        len_xyz += VecLenf((mv+mf->v1)->co, (mv+mf->v2)->co);
1031
 
 
1032
 
                        len_uv += Vec2Lenf(tf->uv[1], tf->uv[2]);
1033
 
                        len_xyz += VecLenf((mv+mf->v2)->co, (mv+mf->v3)->co);
1034
 
 
1035
 
                        if(mf->v4) { 
1036
 
 
1037
 
                                len_uv += Vec2Lenf(tf->uv[2], tf->uv[3]);
1038
 
                                len_xyz += VecLenf((mv+mf->v3)->co, (mv+mf->v4)->co);
1039
 
                                
1040
 
                                len_uv += Vec2Lenf(tf->uv[3], tf->uv[0]);
1041
 
                                len_xyz += VecLenf((mv+mf->v4)->co, (mv+mf->v1)->co);
1042
 
                        }
1043
 
                        else {
1044
 
                                len_uv += Vec2Lenf(tf->uv[2], tf->uv[0]);
1045
 
                                len_xyz += VecLenf((mv+mf->v3)->co, (mv+mf->v1)->co);
1046
 
                        }
1047
 
                }
1048
 
                tf++; mf++; gf++;
1049
 
        }
1050
 
 
1051
 
        return (len_uv/len_xyz);
1052
 
}
1053
 
 
1054
 
/* very primitive packing */
1055
 
static void pack_seam_groups(Mesh *me, int *groups, int totgroup)
1056
 
{
1057
 
        float *groupscale, minscale, scale, add[2], groupw;
1058
 
        float dx, dy, packx, packy, min[2], max[2], rowh;
1059
 
        int a;
1060
 
 
1061
 
        groupscale = (float*)MEM_mallocN(sizeof(float)*totgroup, "SeamGroupScale");
1062
 
 
1063
 
        minscale= 1e30;
1064
 
 
1065
 
        for(a=0; a<totgroup; a++) {
1066
 
                groupscale[a]= seam_group_relative_scale(me, groups, a+1);
1067
 
                minscale= MIN2(groupscale[a], minscale);
1068
 
        }
1069
 
 
1070
 
        packx= packy= 0.0;
1071
 
        rowh= 0.0;
1072
 
        groupw= 1.0/sqrt(totgroup);
1073
 
 
1074
 
        for(a=0; a<totgroup; a++) {
1075
 
 
1076
 
                /* scale so all groups have the same size relative to the mesh */
1077
 
                scale = minscale/groupscale[a];
1078
 
                scale *= groupw;
1079
 
 
1080
 
                seam_group_bbox(me, groups, a+1, min, max);
1081
 
                dx= (max[0]-min[0])*scale;
1082
 
                dy= (max[1]-min[1])*scale;
1083
 
 
1084
 
                /* for padding */
1085
 
                dx += 0.01;
1086
 
                dy += 0.01;
1087
 
 
1088
 
                add[0]= add[1]= 0.0;
1089
 
 
1090
 
                if(dx > 1.0) {
1091
 
                        add[0]= 0.0;
1092
 
                        add[1]= packy;
1093
 
 
1094
 
                        packy += dy;
1095
 
                        packx= 0.0;
1096
 
                        rowh= 0.0;
1097
 
                }
1098
 
                else if(dx <= (1.0-packx)) {
1099
 
                        add[0]= packx;
1100
 
                        add[1]= packy;
1101
 
 
1102
 
                        packx += dx;
1103
 
                        rowh= MAX2(rowh, dy);
1104
 
                }
1105
 
                else {
1106
 
                        packy += rowh;
1107
 
                        packx= dx;
1108
 
                        rowh= dy;
1109
 
 
1110
 
                        add[0]= 0.0;
1111
 
                        add[1]= packy;
1112
 
                }
1113
 
 
1114
 
                /* for padding */
1115
 
                add[0] += 0.005;
1116
 
                add[1] += 0.005;
1117
 
 
1118
 
                seam_group_scale(me, groups, a+1, scale);
1119
 
                seam_group_move(me, groups, a+1, add);
1120
 
        }
1121
 
 
1122
 
        MEM_freeN(groupscale);
1123
 
 
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);
1128
 
}
1129
 
 
1130
 
void unwrap_lscm(void)
1131
 
{
1132
 
    int dopack = 1;
1133
 
        int res;
1134
 
        Mesh *me;
1135
 
        int totgroup, *groups=NULL, a;
1136
 
        
1137
 
        me= get_mesh(OBACT);
1138
 
        if(me==0 || me->tface==0) return;
1139
 
        
1140
 
        totgroup= make_seam_groups(me, &groups);
1141
 
        
1142
 
        if(totgroup==0) return;
1143
 
        
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);
1148
 
                }
1149
 
                else {
1150
 
                        dopack = 0;
1151
 
                }
1152
 
                
1153
 
        }
1154
 
        
1155
 
        if(dopack) pack_seam_groups(me, groups, totgroup);
1156
 
        
1157
 
        MEM_freeN(groups);
1158
 
 
1159
 
        BIF_undo_push("UV lscm unwrap");
1160
 
 
1161
 
        object_uvs_changed(OBACT);
1162
 
 
1163
 
        allqueue(REDRAWVIEW3D, 0);
1164
 
        allqueue(REDRAWIMAGE, 0);
1165
 
}
1166
 
 
1167
 
/* note; to make it quick work, brecht/jens: you can make it nice later! (ton) */
1168
 
void unwrap_lscm_live(void)
1169
 
{
1170
 
    int dopack = 1;
1171
 
        int res;
1172
 
        Mesh *me;
1173
 
        int totgroup, *groups=NULL, a;
1174
 
        
1175
 
        me= get_mesh(OBACT);
1176
 
        if(me==0 || me->tface==0) return;
1177
 
        
1178
 
        totgroup= make_seam_groups(me, &groups);
1179
 
        
1180
 
        if(totgroup==0) return;
1181
 
        
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);
1186
 
                }
1187
 
                else {
1188
 
                        dopack = 0;
1189
 
                }
1190
 
                
1191
 
        }
1192
 
        
1193
 
        if(dopack) pack_seam_groups(me, groups, totgroup);
1194
 
        
1195
 
        MEM_freeN(groups);
1196
 
 
1197
 
}
1198
 
 
1199
 
/* Set tface seams based on edge data, uses hash table to find seam edges. */
1200
 
 
1201
 
void set_seamtface()
1202
 
{
1203
 
        Mesh *me;
1204
 
        EdgeHash *ehash;
1205
 
        int a;
1206
 
        MFace *mf;
1207
 
        TFace *tf;
1208
 
        MEdge *medge;
1209
 
 
1210
 
        me= get_mesh(OBACT);
1211
 
        if(!me || !me->tface || !(G.f & G_FACESELECT)) return;
1212
 
        
1213
 
        ehash= BLI_edgehash_new();
1214
 
 
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);
1218
 
 
1219
 
        mf= me->mface;
1220
 
        tf= me->tface;
1221
 
        for(a=me->totface; a>0; a--, mf++, tf++) {
1222
 
                tf->unwrap &= ~(TF_SEAM1|TF_SEAM2|TF_SEAM3|TF_SEAM4);
1223
 
 
1224
 
                if(!ehash) continue;
1225
 
 
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;
1228
 
 
1229
 
                if(mf->v4) {
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;
1232
 
                }
1233
 
                else if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1)) tf->unwrap |= TF_SEAM3;
1234
 
        }
1235
 
 
1236
 
        BLI_edgehash_free(ehash, NULL);
1237
 
}
1238
 
 
1239
83
void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index)
1240
84
{
1241
85
        TFace *tf;
1242
86
        MFace *mf;
1243
87
        int a, doit=1, mark=0;
1244
88
        char *linkflag;
1245
 
        EdgeHash *ehash;
 
89
        EdgeHash *ehash, *seamhash;
 
90
        MEdge *med;
1246
91
 
1247
92
        ehash= BLI_edgehash_new();
 
93
        seamhash = BLI_edgehash_new();
1248
94
        linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv");
1249
95
 
 
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);
 
99
 
1250
100
        if (mode==0 || mode==1) {
1251
101
                /* only put face under cursor in array */
1252
102
                mf= ((MFace*)me->mface) + index;
1273
123
                tf= me->tface;
1274
124
                mf= me->mface;
1275
125
                for(a=0; a<me->totface; a++, tf++, mf++) {
1276
 
                        if(tf->flag & TF_HIDE);
1277
 
                        else if(!linkflag[a]) {
 
126
                        if(tf->flag & TF_HIDE)
 
127
                                continue;
 
128
 
 
129
                        if(!linkflag[a]) {
1278
130
                                mark= 0;
1279
131
 
1280
 
                                if(!(tf->unwrap & TF_SEAM1))
 
132
                                if(!BLI_edgehash_haskey(seamhash, mf->v1, mf->v2))
1281
133
                                        if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2))
1282
134
                                                mark= 1;
1283
 
                                if(!(tf->unwrap & TF_SEAM2))
 
135
                                if(!BLI_edgehash_haskey(seamhash, mf->v2, mf->v3))
1284
136
                                        if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3))
1285
137
                                                mark= 1;
1286
 
                                if(!(tf->unwrap & TF_SEAM3)) {
1287
 
                                        if(mf->v4) {
 
138
                                if(mf->v4) {
 
139
                                        if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v4))
1288
140
                                                if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4))
1289
141
                                                        mark= 1;
1290
 
                                        }
1291
 
                                        else if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1))
1292
 
                                                mark= 1;
 
142
                                        if(!BLI_edgehash_haskey(seamhash, mf->v4, mf->v1))
 
143
                                                if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1))
 
144
                                                        mark= 1;
1293
145
                                }
1294
 
                                if(mf->v4 && !(tf->unwrap & TF_SEAM4))
1295
 
                                        if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1))
1296
 
                                                mark= 1;
 
146
                                else if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v1))
 
147
                                        if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1))
 
148
                                                mark = 1;
1297
149
 
1298
150
                                if(mark) {
1299
151
                                        linkflag[a]= 1;
1305
157
                
1306
158
        }
1307
159
 
 
160
        BLI_edgehash_free(ehash, NULL);
 
161
        BLI_edgehash_free(seamhash, NULL);
 
162
 
1308
163
        if(mode==0 || mode==2) {
1309
164
                for(a=0, tf=me->tface; a<me->totface; a++, tf++)
1310
165
                        if(linkflag[a])
1329
184
                }
1330
185
        }
1331
186
        
1332
 
        BLI_edgehash_free(ehash, NULL);
1333
187
        MEM_freeN(linkflag);
1334
188
        
1335
189
        BIF_undo_push("Select linked UV face");
1336
190
        object_tface_flags_changed(OBACT, 0);
1337
191
}
1338
192
 
 
193
/* Parametrizer */
 
194
 
 
195
ParamHandle *construct_param_handle(Mesh *me, short implicit, short fill, short sel)
 
196
{
 
197
        int a;
 
198
        TFace *tf;
 
199
        MFace *mf;
 
200
        MVert *mv;
 
201
        MEdge *medge;
 
202
        ParamHandle *handle;
 
203
        
 
204
        handle = param_construct_begin();
 
205
        
 
206
        mv= me->mvert;
 
207
        mf= me->mface;
 
208
        tf= me->tface;
 
209
        for (a=0; a<me->totface; a++, mf++, tf++) {
 
210
                ParamKey key, vkeys[4];
 
211
                ParamBool pin[4], select[4];
 
212
                float *co[4];
 
213
                float *uv[4];
 
214
                int nverts;
 
215
 
 
216
                if (tf->flag & TF_HIDE)
 
217
                        continue;
 
218
 
 
219
                if (sel && !(tf->flag & TF_SELECT))
 
220
                        continue;
 
221
 
 
222
                if (implicit && !(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
 
223
                        continue;
 
224
 
 
225
                key = (ParamKey)mf;
 
226
                vkeys[0] = (ParamKey)mf->v1;
 
227
                vkeys[1] = (ParamKey)mf->v2;
 
228
                vkeys[2] = (ParamKey)mf->v3;
 
229
 
 
230
                co[0] = (mv+mf->v1)->co;
 
231
                co[1] = (mv+mf->v2)->co;
 
232
                co[2] = (mv+mf->v3)->co;
 
233
 
 
234
                uv[0] = tf->uv[0];
 
235
                uv[1] = tf->uv[1];
 
236
                uv[2] = tf->uv[2];
 
237
 
 
238
                pin[0] = ((tf->unwrap & TF_PIN1) != 0);
 
239
                pin[1] = ((tf->unwrap & TF_PIN2) != 0);
 
240
                pin[2] = ((tf->unwrap & TF_PIN3) != 0);
 
241
 
 
242
                select[0] = ((tf->flag & TF_SEL1) != 0);
 
243
                select[1] = ((tf->flag & TF_SEL2) != 0);
 
244
                select[2] = ((tf->flag & TF_SEL3) != 0);
 
245
 
 
246
                if (mf->v4) {
 
247
                        vkeys[3] = (ParamKey)mf->v4;
 
248
                        co[3] = (mv+mf->v4)->co;
 
249
                        uv[3] = tf->uv[3];
 
250
                        pin[3] = ((tf->unwrap & TF_PIN4) != 0);
 
251
                        select[3] = ((tf->flag & TF_SEL4) != 0);
 
252
                        nverts = 4;
 
253
                }
 
254
                else
 
255
                        nverts = 3;
 
256
 
 
257
                param_face_add(handle, key, nverts, vkeys, co, uv, pin, select);
 
258
        }
 
259
 
 
260
        if (!implicit) {
 
261
                for(medge=me->medge, a=me->totedge; a>0; a--, medge++) {
 
262
                        if(medge->flag & ME_SEAM) {
 
263
                                ParamKey vkeys[2];
 
264
 
 
265
                                vkeys[0] = (ParamKey)medge->v1;
 
266
                                vkeys[1] = (ParamKey)medge->v2;
 
267
                                param_edge_set_seam(handle, vkeys);
 
268
                        }
 
269
                }
 
270
        }
 
271
 
 
272
        param_construct_end(handle, fill, implicit);
 
273
 
 
274
        return handle;
 
275
}
 
276
 
 
277
void unwrap_lscm(short seamcut)
 
278
{
 
279
        Mesh *me;
 
280
        ParamHandle *handle;
 
281
        short abf = G.scene->toolsettings->unwrapper == 1;
 
282
        short fillholes = G.scene->toolsettings->uvcalc_flag & 1;
 
283
        
 
284
        me= get_mesh(OBACT);
 
285
        if(me==0 || me->tface==0) return;
 
286
 
 
287
        handle = construct_param_handle(me, 0, fillholes, seamcut == 0);
 
288
 
 
289
        param_lscm_begin(handle, PARAM_FALSE, abf);
 
290
        param_lscm_solve(handle);
 
291
        param_lscm_end(handle);
 
292
 
 
293
        param_pack(handle);
 
294
 
 
295
        param_flush(handle);
 
296
 
 
297
        param_delete(handle);
 
298
 
 
299
        if (!seamcut)
 
300
                BIF_undo_push("UV unwrap");
 
301
 
 
302
        object_uvs_changed(OBACT);
 
303
 
 
304
        allqueue(REDRAWVIEW3D, 0);
 
305
        allqueue(REDRAWIMAGE, 0);
 
306
}
 
307
 
 
308
void minimize_stretch_tface_uv(void)
 
309
{
 
310
        Mesh *me;
 
311
        ParamHandle *handle;
 
312
        double lasttime;
 
313
        short doit = 1, escape = 0, val, blend = 0;
 
314
        unsigned short event = 0;
 
315
        short fillholes = G.scene->toolsettings->uvcalc_flag & 1;
 
316
        
 
317
        me = get_mesh(OBACT);
 
318
        if(me==0 || me->tface==0) return;
 
319
 
 
320
        handle = construct_param_handle(me, 1, fillholes, 1);
 
321
 
 
322
        lasttime = PIL_check_seconds_timer();
 
323
 
 
324
        param_stretch_begin(handle);
 
325
 
 
326
        while (doit) {
 
327
                param_stretch_iter(handle);
 
328
 
 
329
                while (qtest()) {
 
330
                        event= extern_qread(&val);
 
331
 
 
332
                        if (val) {
 
333
                                switch (event) {
 
334
                                        case ESCKEY:
 
335
                                                escape = 1;
 
336
                                        case RETKEY:
 
337
                                        case PADENTER:
 
338
                                                doit = 0;
 
339
                                                break;
 
340
                                        case PADPLUSKEY:
 
341
                                        case WHEELUPMOUSE:
 
342
                                                if (blend < 10) {
 
343
                                                        blend++;
 
344
                                                        param_stretch_blend(handle, blend*0.1f);
 
345
                                                        param_flush(handle);
 
346
                                                        lasttime = 0.0f;
 
347
                                                }
 
348
                                                break;
 
349
                                        case PADMINUS:
 
350
                                        case WHEELDOWNMOUSE:
 
351
                                                if (blend > 0) {
 
352
                                                        blend--;
 
353
                                                        param_stretch_blend(handle, blend*0.1f);
 
354
                                                        param_flush(handle);
 
355
                                                        lasttime = 0.0f;
 
356
                                                }
 
357
                                                break;
 
358
                                }
 
359
                        }
 
360
                        else if ((event == LEFTMOUSE) || (event == RIGHTMOUSE)) {
 
361
                                        escape = (event == RIGHTMOUSE);
 
362
                                        doit = 0;
 
363
                        }
 
364
                }
 
365
                
 
366
                if (!doit)
 
367
                        break;
 
368
 
 
369
                if (PIL_check_seconds_timer() - lasttime > 0.5) {
 
370
                        char str[100];
 
371
 
 
372
                        param_flush(handle);
 
373
 
 
374
                        sprintf(str, "Stretch minimize. Blend %.2f.", blend*0.1f);
 
375
                        headerprint(str);
 
376
 
 
377
                        lasttime = PIL_check_seconds_timer();
 
378
                        object_uvs_changed(OBACT);
 
379
                        if(G.sima->lock) force_draw_plus(SPACE_VIEW3D, 0);
 
380
                        else force_draw(0);
 
381
                }
 
382
        }
 
383
 
 
384
        if (escape)
 
385
                param_flush_restore(handle);
 
386
        else
 
387
                param_flush(handle);
 
388
 
 
389
        param_stretch_end(handle);
 
390
 
 
391
        param_delete(handle);
 
392
 
 
393
        BIF_undo_push("UV stretch minimize");
 
394
 
 
395
        object_uvs_changed(OBACT);
 
396
 
 
397
        allqueue(REDRAWVIEW3D, 0);
 
398
        allqueue(REDRAWIMAGE, 0);
 
399
}
 
400
 
 
401
/* LSCM live mode */
 
402
 
 
403
static ParamHandle *liveHandle = NULL;
 
404
 
 
405
void unwrap_lscm_live_begin(void)
 
406
{
 
407
        Mesh *me;
 
408
        short abf = G.scene->toolsettings->unwrapper == 1;
 
409
        short fillholes = G.scene->toolsettings->uvcalc_flag & 1;
 
410
 
 
411
        me= get_mesh(OBACT);
 
412
        if(me==0 || me->tface==0) return;
 
413
 
 
414
        liveHandle = construct_param_handle(me, 0, fillholes, 1);
 
415
 
 
416
        param_lscm_begin(liveHandle, PARAM_TRUE, abf);
 
417
}
 
418
 
 
419
void unwrap_lscm_live_re_solve(void)
 
420
{
 
421
        if (liveHandle) {
 
422
                param_lscm_solve(liveHandle);
 
423
                param_flush(liveHandle);
 
424
        }
 
425
}
 
426
        
 
427
void unwrap_lscm_live_end(short cancel)
 
428
{
 
429
        if (liveHandle) {
 
430
                param_lscm_end(liveHandle);
 
431
                if (cancel)
 
432
                        param_flush_restore(liveHandle);
 
433
                param_delete(liveHandle);
 
434
                liveHandle = NULL;
 
435
        }
 
436
}
 
437