Blender  V2.59
uvedit_parametrizer.c
Go to the documentation of this file.
00001 
00005 #include "MEM_guardedalloc.h"
00006 
00007 #include "BLI_memarena.h"
00008 #include "BLI_math.h"
00009 #include "BLI_rand.h"
00010 #include "BLI_heap.h"
00011 #include "BLI_boxpack2d.h"
00012 #include "BLI_utildefines.h"
00013 
00014 
00015 
00016 #include "ONL_opennl.h"
00017 
00018 #include "uvedit_intern.h"
00019 #include "uvedit_parametrizer.h"
00020 
00021 #include <math.h>
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <string.h>
00025 
00026 #include "BLO_sys_types.h" // for intptr_t support
00027 
00028 #if defined(_WIN32)
00029 #define M_PI 3.14159265358979323846
00030 #endif
00031 
00032 /* Utils */
00033 
00034 #if 0
00035         #define param_assert(condition);
00036         #define param_warning(message);
00037         #define param_test_equals_ptr(condition);
00038         #define param_test_equals_int(condition);
00039 #else
00040         #define param_assert(condition) \
00041                 if (!(condition)) \
00042                         { /*printf("Assertion %s:%d\n", __FILE__, __LINE__); abort();*/ }
00043         #define param_warning(message) \
00044                 { /*printf("Warning %s:%d: %s\n", __FILE__, __LINE__, message);*/ }
00045         #define param_test_equals_ptr(str, a, b) \
00046                 if (a != b) \
00047                         { /*printf("Equals %s => %p != %p\n", str, a, b);*/ };
00048         #define param_test_equals_int(str, a, b) \
00049                 if (a != b) \
00050                         { /*printf("Equals %s => %d != %d\n", str, a, b);*/ };
00051 #endif
00052 
00053 typedef enum PBool {
00054         P_TRUE = 1,
00055         P_FALSE = 0
00056 } PBool;
00057 
00058 /* Special Purpose Hash */
00059 
00060 typedef intptr_t PHashKey;
00061 
00062 typedef struct PHashLink {
00063         struct PHashLink *next;
00064         PHashKey key;
00065 } PHashLink;
00066 
00067 typedef struct PHash {
00068         PHashLink **list;
00069         PHashLink **buckets;
00070         int size, cursize, cursize_id;
00071 } PHash;
00072 
00073 
00074 
00075 struct PVert;
00076 struct PEdge;
00077 struct PFace;
00078 struct PChart;
00079 struct PHandle;
00080 
00081 /* Simplices */
00082 
00083 typedef struct PVert {
00084         struct PVert *nextlink;
00085 
00086         union PVertUnion {
00087                 PHashKey key;                   /* construct */
00088                 int id;                                 /* abf/lscm matrix index */
00089                 float distortion;               /* area smoothing */
00090                 HeapNode *heaplink;             /* edge collapsing */
00091         } u;
00092 
00093         struct PEdge *edge;
00094         float *co;
00095         float uv[2];
00096         unsigned char flag;
00097 
00098 } PVert; 
00099 
00100 typedef struct PEdge {
00101         struct PEdge *nextlink;
00102 
00103         union PEdgeUnion {
00104                 PHashKey key;                                   /* construct */
00105                 int id;                                                 /* abf matrix index */
00106                 HeapNode *heaplink;                             /* fill holes */
00107                 struct PEdge *nextcollapse;             /* simplification */
00108         } u;
00109 
00110         struct PVert *vert;
00111         struct PEdge *pair;
00112         struct PEdge *next;
00113         struct PFace *face;
00114         float *orig_uv, old_uv[2];
00115         unsigned short flag;
00116 
00117 } PEdge;
00118 
00119 typedef struct PFace {
00120         struct PFace *nextlink;
00121 
00122         union PFaceUnion {
00123                 PHashKey key;                   /* construct */
00124                 int chart;                              /* construct splitting*/
00125                 float area3d;                   /* stretch */
00126                 int id;                                 /* abf matrix index */
00127         } u;
00128 
00129         struct PEdge *edge;
00130         unsigned char flag;
00131 
00132 } PFace;
00133 
00134 enum PVertFlag {
00135         PVERT_PIN = 1,
00136         PVERT_SELECT = 2,
00137         PVERT_INTERIOR = 4,
00138         PVERT_COLLAPSE = 8,
00139         PVERT_SPLIT = 16
00140 };
00141 
00142 enum PEdgeFlag {
00143         PEDGE_SEAM = 1,
00144         PEDGE_VERTEX_SPLIT = 2,
00145         PEDGE_PIN = 4,
00146         PEDGE_SELECT = 8,
00147         PEDGE_DONE = 16,
00148         PEDGE_FILLED = 32,
00149         PEDGE_COLLAPSE = 64,
00150         PEDGE_COLLAPSE_EDGE = 128,
00151         PEDGE_COLLAPSE_PAIR = 256
00152 };
00153 
00154 /* for flipping faces */
00155 #define PEDGE_VERTEX_FLAGS (PEDGE_PIN)
00156 
00157 enum PFaceFlag {
00158         PFACE_CONNECTED = 1,
00159         PFACE_FILLED = 2,
00160         PFACE_COLLAPSE = 4
00161 };
00162 
00163 /* Chart */
00164 
00165 typedef struct PChart {
00166         PVert *verts;
00167         PEdge *edges;
00168         PFace *faces;
00169         int nverts, nedges, nfaces;
00170 
00171         PVert *collapsed_verts;
00172         PEdge *collapsed_edges;
00173         PFace *collapsed_faces;
00174 
00175         union PChartUnion {
00176                 struct PChartLscm {
00177                         NLContext context;
00178                         float *abf_alpha;
00179                         PVert *pin1, *pin2;
00180                 } lscm;
00181                 struct PChartPack {
00182                         float rescale, area;
00183                         float size[2], trans[2];
00184                 } pack;
00185         } u;
00186 
00187         unsigned char flag;
00188         struct PHandle *handle;
00189 } PChart;
00190 
00191 enum PChartFlag {
00192         PCHART_NOPACK = 1
00193 };
00194 
00195 enum PHandleState {
00196         PHANDLE_STATE_ALLOCATED,
00197         PHANDLE_STATE_CONSTRUCTED,
00198         PHANDLE_STATE_LSCM,
00199         PHANDLE_STATE_STRETCH
00200 };
00201 
00202 typedef struct PHandle {
00203         enum PHandleState state;
00204         MemArena *arena;
00205 
00206         PChart *construction_chart;
00207         PHash *hash_verts;
00208         PHash *hash_edges;
00209         PHash *hash_faces;
00210 
00211         PChart **charts;
00212         int ncharts;
00213 
00214         float aspx, aspy;
00215 
00216         RNG *rng;
00217         float blend;
00218 } PHandle;
00219 
00220 
00221 /* PHash
00222    - special purpose hash that keeps all its elements in a single linked list.
00223    - after construction, this hash is thrown away, and the list remains.
00224    - removing elements is not possible efficiently.
00225 */
00226 
00227 static int PHashSizes[] = {
00228         1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 
00229         16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, 
00230         4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459
00231 };
00232 
00233 #define PHASH_hash(ph, item) (((uintptr_t) (item))%((unsigned int) (ph)->cursize))
00234 #define PHASH_edge(v1, v2)       ((v1)^(v2))
00235 
00236 static PHash *phash_new(PHashLink **list, int sizehint)
00237 {
00238         PHash *ph = (PHash*)MEM_callocN(sizeof(PHash), "PHash");
00239         ph->size = 0;
00240         ph->cursize_id = 0;
00241         ph->list = list;
00242 
00243         while (PHashSizes[ph->cursize_id] < sizehint)
00244                 ph->cursize_id++;
00245 
00246         ph->cursize = PHashSizes[ph->cursize_id];
00247         ph->buckets = (PHashLink**)MEM_callocN(ph->cursize*sizeof(*ph->buckets), "PHashBuckets");
00248 
00249         return ph;
00250 }
00251 
00252 static void phash_delete(PHash *ph)
00253 {
00254         MEM_freeN(ph->buckets);
00255         MEM_freeN(ph);
00256 }
00257 
00258 static int phash_size(PHash *ph)
00259 {
00260         return ph->size;
00261 }
00262 
00263 static void phash_insert(PHash *ph, PHashLink *link)
00264 {
00265         int size = ph->cursize;
00266         uintptr_t hash = PHASH_hash(ph, link->key);
00267         PHashLink *lookup = ph->buckets[hash];
00268 
00269         if (lookup == NULL) {
00270                 /* insert in front of the list */
00271                 ph->buckets[hash] = link;
00272                 link->next = *(ph->list);
00273                 *(ph->list) = link;
00274         }
00275         else {
00276                 /* insert after existing element */
00277                 link->next = lookup->next;
00278                 lookup->next = link;
00279         }
00280                 
00281         ph->size++;
00282 
00283         if (ph->size > (size*3)) {
00284                 PHashLink *next = NULL, *first = *(ph->list);
00285 
00286                 ph->cursize = PHashSizes[++ph->cursize_id];
00287                 MEM_freeN(ph->buckets);
00288                 ph->buckets = (PHashLink**)MEM_callocN(ph->cursize*sizeof(*ph->buckets), "PHashBuckets");
00289                 ph->size = 0;
00290                 *(ph->list) = NULL;
00291 
00292                 for (link = first; link; link = next) {
00293                         next = link->next;
00294                         phash_insert(ph, link);
00295                 }
00296         }
00297 }
00298 
00299 static PHashLink *phash_lookup(PHash *ph, PHashKey key)
00300 {
00301         PHashLink *link;
00302         uintptr_t hash = PHASH_hash(ph, key);
00303 
00304         for (link = ph->buckets[hash]; link; link = link->next)
00305                 if (link->key == key)
00306                         return link;
00307                 else if (PHASH_hash(ph, link->key) != hash)
00308                         return NULL;
00309         
00310         return link;
00311 }
00312 
00313 static PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link)
00314 {
00315         uintptr_t hash = PHASH_hash(ph, key);
00316 
00317         for (link = link->next; link; link = link->next)
00318                 if (link->key == key)
00319                         return link;
00320                 else if (PHASH_hash(ph, link->key) != hash)
00321                         return NULL;
00322         
00323         return link;
00324 }
00325 
00326 /* Geometry */
00327 
00328 static float p_vec_angle_cos(float *v1, float *v2, float *v3)
00329 {
00330         float d1[3], d2[3];
00331 
00332         d1[0] = v1[0] - v2[0];
00333         d1[1] = v1[1] - v2[1];
00334         d1[2] = v1[2] - v2[2];
00335 
00336         d2[0] = v3[0] - v2[0];
00337         d2[1] = v3[1] - v2[1];
00338         d2[2] = v3[2] - v2[2];
00339 
00340         normalize_v3(d1);
00341         normalize_v3(d2);
00342 
00343         return d1[0]*d2[0] + d1[1]*d2[1] + d1[2]*d2[2];
00344 }
00345 
00346 static float p_vec_angle(float *v1, float *v2, float *v3)
00347 {
00348         float dot = p_vec_angle_cos(v1, v2, v3);
00349 
00350         if (dot <= -1.0f)
00351                 return (float)M_PI;
00352         else if (dot >= 1.0f)
00353                 return 0.0f;
00354         else
00355                 return (float)acos(dot);
00356 }
00357 
00358 static float p_vec2_angle(float *v1, float *v2, float *v3)
00359 {
00360         float u1[3], u2[3], u3[3];
00361 
00362         u1[0] = v1[0]; u1[1] = v1[1]; u1[2] = 0.0f;
00363         u2[0] = v2[0]; u2[1] = v2[1]; u2[2] = 0.0f;
00364         u3[0] = v3[0]; u3[1] = v3[1]; u3[2] = 0.0f;
00365 
00366         return p_vec_angle(u1, u2, u3);
00367 }
00368 
00369 static void p_triangle_angles(float *v1, float *v2, float *v3, float *a1, float *a2, float *a3)
00370 {
00371         *a1 = p_vec_angle(v3, v1, v2);
00372         *a2 = p_vec_angle(v1, v2, v3);
00373         *a3 = (float)M_PI - *a2 - *a1;
00374 }
00375 
00376 static void p_face_angles(PFace *f, float *a1, float *a2, float *a3)
00377 {
00378         PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
00379         PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
00380 
00381         p_triangle_angles(v1->co, v2->co, v3->co, a1, a2, a3);
00382 }
00383 
00384 static float p_face_area(PFace *f)
00385 {
00386         PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
00387         PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
00388 
00389         return area_tri_v3(v1->co, v2->co, v3->co);
00390 }
00391 
00392 static float p_area_signed(float *v1, float *v2, float *v3)
00393 {
00394         return 0.5f*(((v2[0] - v1[0])*(v3[1] - v1[1])) - 
00395                                 ((v3[0] - v1[0])*(v2[1] - v1[1])));
00396 }
00397 
00398 static float p_face_uv_area_signed(PFace *f)
00399 {
00400         PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
00401         PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
00402 
00403         return 0.5f*(((v2->uv[0] - v1->uv[0])*(v3->uv[1] - v1->uv[1])) - 
00404                                 ((v3->uv[0] - v1->uv[0])*(v2->uv[1] - v1->uv[1])));
00405 }
00406 
00407 static float p_edge_length(PEdge *e)
00408 {
00409         PVert *v1 = e->vert, *v2 = e->next->vert;
00410         float d[3];
00411 
00412         d[0] = v2->co[0] - v1->co[0];
00413         d[1] = v2->co[1] - v1->co[1];
00414         d[2] = v2->co[2] - v1->co[2];
00415 
00416         return sqrt(d[0]*d[0] + d[1]*d[1] + d[2]*d[2]);
00417 }
00418 
00419 static float p_edge_uv_length(PEdge *e)
00420 {
00421         PVert *v1 = e->vert, *v2 = e->next->vert;
00422         float d[3];
00423 
00424         d[0] = v2->uv[0] - v1->uv[0];
00425         d[1] = v2->uv[1] - v1->uv[1];
00426 
00427         return sqrt(d[0]*d[0] + d[1]*d[1]);
00428 }
00429 
00430 static void p_chart_uv_bbox(PChart *chart, float *minv, float *maxv)
00431 {
00432         PVert *v;
00433 
00434         INIT_MINMAX2(minv, maxv);
00435 
00436         for (v=chart->verts; v; v=v->nextlink) {
00437                 DO_MINMAX2(v->uv, minv, maxv);
00438         }
00439 }
00440 
00441 static void p_chart_uv_scale(PChart *chart, float scale)
00442 {
00443         PVert *v;
00444 
00445         for (v=chart->verts; v; v=v->nextlink) {
00446                 v->uv[0] *= scale;
00447                 v->uv[1] *= scale;
00448         }
00449 }
00450 
00451 static void p_chart_uv_scale_xy(PChart *chart, float x, float y)
00452 {
00453         PVert *v;
00454 
00455         for (v=chart->verts; v; v=v->nextlink) {
00456                 v->uv[0] *= x;
00457                 v->uv[1] *= y;
00458         }
00459 }
00460 
00461 static void p_chart_uv_translate(PChart *chart, float trans[2])
00462 {
00463         PVert *v;
00464 
00465         for (v=chart->verts; v; v=v->nextlink) {
00466                 v->uv[0] += trans[0];
00467                 v->uv[1] += trans[1];
00468         }
00469 }
00470 
00471 static PBool p_intersect_line_2d_dir(float *v1, float *dir1, float *v2, float *dir2, float *isect)
00472 {
00473         float lmbda, div;
00474 
00475         div= dir2[0]*dir1[1] - dir2[1]*dir1[0];
00476 
00477         if (div == 0.0f)
00478                 return P_FALSE;
00479 
00480         lmbda= ((v1[1]-v2[1])*dir1[0]-(v1[0]-v2[0])*dir1[1])/div;
00481         isect[0] = v1[0] + lmbda*dir2[0];
00482         isect[1] = v1[1] + lmbda*dir2[1];
00483 
00484         return P_TRUE;
00485 }
00486 
00487 #if 0
00488 static PBool p_intersect_line_2d(float *v1, float *v2, float *v3, float *v4, float *isect)
00489 {
00490         float dir1[2], dir2[2];
00491 
00492         dir1[0] = v4[0] - v3[0];
00493         dir1[1] = v4[1] - v3[1];
00494 
00495         dir2[0] = v2[0] - v1[0];
00496         dir2[1] = v2[1] - v1[1];
00497 
00498         if (!p_intersect_line_2d_dir(v1, dir1, v2, dir2, isect)) {
00499                 /* parallel - should never happen in theory for polygon kernel, but
00500                    let's give a point nearby in case things go wrong */
00501                 isect[0] = (v1[0] + v2[0])*0.5f;
00502                 isect[1] = (v1[1] + v2[1])*0.5f;
00503                 return P_FALSE;
00504         }
00505 
00506         return P_TRUE;
00507 }
00508 #endif
00509 
00510 /* Topological Utilities */
00511 
00512 static PEdge *p_wheel_edge_next(PEdge *e)
00513 {
00514         return e->next->next->pair;
00515 }
00516 
00517 static PEdge *p_wheel_edge_prev(PEdge *e)
00518 {   
00519         return (e->pair)? e->pair->next: NULL;
00520 }
00521 
00522 static PEdge *p_boundary_edge_next(PEdge *e)
00523 {
00524         return e->next->vert->edge;
00525 }
00526 
00527 static PEdge *p_boundary_edge_prev(PEdge *e)
00528 {
00529         PEdge *we = e, *last;
00530 
00531         do {
00532                 last = we;
00533                 we = p_wheel_edge_next(we);
00534         } while (we && (we != e));
00535 
00536         return last->next->next;
00537 }
00538 
00539 static PBool p_vert_interior(PVert *v)
00540 {
00541         return (v->edge->pair != NULL);
00542 }
00543 
00544 static void p_face_flip(PFace *f)
00545 {
00546         PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
00547         PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
00548         int f1 = e1->flag, f2 = e2->flag, f3 = e3->flag;
00549 
00550         e1->vert = v2;
00551         e1->next = e3;
00552         e1->flag = (f1 & ~PEDGE_VERTEX_FLAGS) | (f2 & PEDGE_VERTEX_FLAGS);
00553 
00554         e2->vert = v3;
00555         e2->next = e1;
00556         e2->flag = (f2 & ~PEDGE_VERTEX_FLAGS) | (f3 & PEDGE_VERTEX_FLAGS);
00557 
00558         e3->vert = v1;
00559         e3->next = e2;
00560         e3->flag = (f3 & ~PEDGE_VERTEX_FLAGS) | (f1 & PEDGE_VERTEX_FLAGS);
00561 }
00562 
00563 #if 0
00564 static void p_chart_topological_sanity_check(PChart *chart)
00565 {
00566         PVert *v;
00567         PEdge *e;
00568 
00569         for (v=chart->verts; v; v=v->nextlink)
00570                 param_test_equals_ptr("v->edge->vert", v, v->edge->vert);
00571         
00572         for (e=chart->edges; e; e=e->nextlink) {
00573                 if (e->pair) {
00574                         param_test_equals_ptr("e->pair->pair", e, e->pair->pair);
00575                         param_test_equals_ptr("pair->vert", e->vert, e->pair->next->vert);
00576                         param_test_equals_ptr("pair->next->vert", e->next->vert, e->pair->vert);
00577                 }
00578         }
00579 }
00580 #endif
00581 
00582 /* Loading / Flushing */
00583 
00584 static void p_vert_load_pin_select_uvs(PHandle *handle, PVert *v)
00585 {
00586         PEdge *e;
00587         int nedges = 0, npins = 0;
00588         float pinuv[2];
00589 
00590         v->uv[0] = v->uv[1] = 0.0f;
00591         pinuv[0] = pinuv[1] = 0.0f;
00592         e = v->edge;
00593         do {
00594                 if (e->orig_uv) {
00595                         if (e->flag & PEDGE_SELECT)
00596                                 v->flag |= PVERT_SELECT;
00597 
00598                         if (e->flag & PEDGE_PIN) {
00599                                 pinuv[0] += e->orig_uv[0]*handle->aspx;
00600                                 pinuv[1] += e->orig_uv[1]*handle->aspy;
00601                                 npins++;
00602                         }
00603                         else {
00604                                 v->uv[0] += e->orig_uv[0]*handle->aspx;
00605                                 v->uv[1] += e->orig_uv[1]*handle->aspy;
00606                         }
00607 
00608                         nedges++;
00609                 }
00610 
00611                 e = p_wheel_edge_next(e);
00612         } while (e && e != (v->edge));
00613 
00614         if (npins > 0) {
00615                 v->uv[0] = pinuv[0]/npins;
00616                 v->uv[1] = pinuv[1]/npins;
00617                 v->flag |= PVERT_PIN;
00618         }
00619         else if (nedges > 0) {
00620                 v->uv[0] /= nedges;
00621                 v->uv[1] /= nedges;
00622         }
00623 }
00624 
00625 static void p_flush_uvs(PHandle *handle, PChart *chart)
00626 {
00627         PEdge *e;
00628 
00629         for (e=chart->edges; e; e=e->nextlink) {
00630                 if (e->orig_uv) {
00631                         e->orig_uv[0] = e->vert->uv[0]/handle->aspx;
00632                         e->orig_uv[1] = e->vert->uv[1]/handle->aspy;
00633                 }
00634         }
00635 }
00636 
00637 static void p_flush_uvs_blend(PHandle *handle, PChart *chart, float blend)
00638 {
00639         PEdge *e;
00640         float invblend = 1.0f - blend;
00641 
00642         for (e=chart->edges; e; e=e->nextlink) {
00643                 if (e->orig_uv) {
00644                         e->orig_uv[0] = blend*e->old_uv[0] + invblend*e->vert->uv[0]/handle->aspx;
00645                         e->orig_uv[1] = blend*e->old_uv[1] + invblend*e->vert->uv[1]/handle->aspy;
00646                 }
00647         }
00648 }
00649 
00650 static void p_face_backup_uvs(PFace *f)
00651 {
00652         PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
00653 
00654         if (e1->orig_uv && e2->orig_uv && e3->orig_uv) {
00655                 e1->old_uv[0] = e1->orig_uv[0];
00656                 e1->old_uv[1] = e1->orig_uv[1];
00657                 e2->old_uv[0] = e2->orig_uv[0];
00658                 e2->old_uv[1] = e2->orig_uv[1];
00659                 e3->old_uv[0] = e3->orig_uv[0];
00660                 e3->old_uv[1] = e3->orig_uv[1];
00661         }
00662 }
00663 
00664 static void p_face_restore_uvs(PFace *f)
00665 {
00666         PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
00667 
00668         if (e1->orig_uv && e2->orig_uv && e3->orig_uv) {
00669                 e1->orig_uv[0] = e1->old_uv[0];
00670                 e1->orig_uv[1] = e1->old_uv[1];
00671                 e2->orig_uv[0] = e2->old_uv[0];
00672                 e2->orig_uv[1] = e2->old_uv[1];
00673                 e3->orig_uv[0] = e3->old_uv[0];
00674                 e3->orig_uv[1] = e3->old_uv[1];
00675         }
00676 }
00677 
00678 /* Construction (use only during construction, relies on u.key being set */
00679 
00680 static PVert *p_vert_add(PHandle *handle, PHashKey key, float *co, PEdge *e)
00681 {
00682         PVert *v = (PVert*)BLI_memarena_alloc(handle->arena, sizeof *v);
00683         v->co = co;
00684         v->u.key = key;
00685         v->edge = e;
00686         v->flag = 0;
00687 
00688         phash_insert(handle->hash_verts, (PHashLink*)v);
00689 
00690         return v;
00691 }
00692 
00693 static PVert *p_vert_lookup(PHandle *handle, PHashKey key, float *co, PEdge *e)
00694 {
00695         PVert *v = (PVert*)phash_lookup(handle->hash_verts, key);
00696 
00697         if (v)
00698                 return v;
00699         else
00700                 return p_vert_add(handle, key, co, e);
00701 }
00702 
00703 static PVert *p_vert_copy(PChart *chart, PVert *v)
00704 {
00705         PVert *nv = (PVert*)BLI_memarena_alloc(chart->handle->arena, sizeof *nv);
00706 
00707         nv->co = v->co;
00708         nv->uv[0] = v->uv[0];
00709         nv->uv[1] = v->uv[1];
00710         nv->u.key = v->u.key;
00711         nv->edge = v->edge;
00712         nv->flag = v->flag;
00713 
00714         return nv;
00715 }
00716 
00717 static PEdge *p_edge_lookup(PHandle *handle, PHashKey *vkeys)
00718 {
00719         PHashKey key = PHASH_edge(vkeys[0], vkeys[1]);
00720         PEdge *e = (PEdge*)phash_lookup(handle->hash_edges, key);
00721 
00722         while (e) {
00723                 if ((e->vert->u.key == vkeys[0]) && (e->next->vert->u.key == vkeys[1]))
00724                         return e;
00725                 else if ((e->vert->u.key == vkeys[1]) && (e->next->vert->u.key == vkeys[0]))
00726                         return e;
00727 
00728                 e = (PEdge*)phash_next(handle->hash_edges, key, (PHashLink*)e);
00729         }
00730 
00731         return NULL;
00732 }
00733 
00734 static PBool p_face_exists(PHandle *handle, PHashKey *vkeys, int i1, int i2, int i3)
00735 {
00736         PHashKey key = PHASH_edge(vkeys[i1], vkeys[i2]);
00737         PEdge *e = (PEdge*)phash_lookup(handle->hash_edges, key);
00738 
00739         while (e) {
00740                 if ((e->vert->u.key == vkeys[i1]) && (e->next->vert->u.key == vkeys[i2])) {
00741                         if (e->next->next->vert->u.key == vkeys[i3])
00742                                 return P_TRUE;
00743                 }
00744                 else if ((e->vert->u.key == vkeys[i2]) && (e->next->vert->u.key == vkeys[i1])) {
00745                         if (e->next->next->vert->u.key == vkeys[i3])
00746                                 return P_TRUE;
00747                 }
00748 
00749                 e = (PEdge*)phash_next(handle->hash_edges, key, (PHashLink*)e);
00750         }
00751 
00752         return P_FALSE;
00753 }
00754 
00755 static PChart *p_chart_new(PHandle *handle)
00756 {
00757         PChart *chart = (PChart*)MEM_callocN(sizeof*chart, "PChart");
00758         chart->handle = handle;
00759 
00760         return chart;
00761 }
00762 
00763 static void p_chart_delete(PChart *chart)
00764 {
00765         /* the actual links are free by memarena */
00766         MEM_freeN(chart);
00767 }
00768 
00769 static PBool p_edge_implicit_seam(PEdge *e, PEdge *ep)
00770 {
00771         float *uv1, *uv2, *uvp1, *uvp2;
00772         float limit[2];
00773 
00774         limit[0] = 0.00001;
00775         limit[1] = 0.00001;
00776 
00777         uv1 = e->orig_uv;
00778         uv2 = e->next->orig_uv;
00779 
00780         if (e->vert->u.key == ep->vert->u.key) {
00781                 uvp1 = ep->orig_uv;
00782                 uvp2 = ep->next->orig_uv;
00783         }
00784         else {
00785                 uvp1 = ep->next->orig_uv;
00786                 uvp2 = ep->orig_uv;
00787         }
00788 
00789         if((fabsf(uv1[0]-uvp1[0]) > limit[0]) || (fabsf(uv1[1]-uvp1[1]) > limit[1])) {
00790                 e->flag |= PEDGE_SEAM;
00791                 ep->flag |= PEDGE_SEAM;
00792                 return P_TRUE;
00793         }
00794         if((fabsf(uv2[0]-uvp2[0]) > limit[0]) || (fabsf(uv2[1]-uvp2[1]) > limit[1])) {
00795                 e->flag |= PEDGE_SEAM;
00796                 ep->flag |= PEDGE_SEAM;
00797                 return P_TRUE;
00798         }
00799         
00800         return P_FALSE;
00801 }
00802 
00803 static PBool p_edge_has_pair(PHandle *handle, PEdge *e, PEdge **pair, PBool impl)
00804 {
00805         PHashKey key;
00806         PEdge *pe;
00807         PVert *v1, *v2;
00808         PHashKey key1 = e->vert->u.key;
00809         PHashKey key2 = e->next->vert->u.key;
00810 
00811         if (e->flag & PEDGE_SEAM)
00812                 return P_FALSE;
00813         
00814         key = PHASH_edge(key1, key2);
00815         pe = (PEdge*)phash_lookup(handle->hash_edges, key);
00816         *pair = NULL;
00817 
00818         while (pe) {
00819                 if (pe != e) {
00820                         v1 = pe->vert;
00821                         v2 = pe->next->vert;
00822 
00823                         if (((v1->u.key == key1) && (v2->u.key == key2)) ||
00824                                 ((v1->u.key == key2) && (v2->u.key == key1))) {
00825 
00826                                 /* don't connect seams and t-junctions */
00827                                 if ((pe->flag & PEDGE_SEAM) || *pair ||
00828                                         (impl && p_edge_implicit_seam(e, pe))) {
00829                                         *pair = NULL;
00830                                         return P_FALSE;
00831                                 }
00832 
00833                                 *pair = pe;
00834                         }
00835                 }
00836 
00837                 pe = (PEdge*)phash_next(handle->hash_edges, key, (PHashLink*)pe);
00838         }
00839 
00840         if (*pair && (e->vert == (*pair)->vert)) {
00841                 if ((*pair)->next->pair || (*pair)->next->next->pair) {
00842                         /* non unfoldable, maybe mobius ring or klein bottle */
00843                         *pair = NULL;
00844                         return P_FALSE;
00845                 }
00846         }
00847 
00848         return (*pair != NULL);
00849 }
00850 
00851 static PBool p_edge_connect_pair(PHandle *handle, PEdge *e, PEdge ***stack, PBool impl)
00852 {
00853         PEdge *pair = NULL;
00854 
00855         if(!e->pair && p_edge_has_pair(handle, e, &pair, impl)) {
00856                 if (e->vert == pair->vert)
00857                         p_face_flip(pair->face);
00858 
00859                 e->pair = pair;
00860                 pair->pair = e;
00861 
00862                 if (!(pair->face->flag & PFACE_CONNECTED)) {
00863                         **stack = pair;
00864                         (*stack)++;
00865                 }
00866         }
00867 
00868         return (e->pair != NULL);
00869 }
00870 
00871 static int p_connect_pairs(PHandle *handle, PBool impl)
00872 {
00873         PEdge **stackbase = MEM_mallocN(sizeof*stackbase*phash_size(handle->hash_faces), "Pstackbase");
00874         PEdge **stack = stackbase;
00875         PFace *f, *first;
00876         PEdge *e, *e1, *e2;
00877         PChart *chart = handle->construction_chart;
00878         int ncharts = 0;
00879 
00880         /* connect pairs, count edges, set vertex-edge pointer to a pairless edge */
00881         for (first=chart->faces; first; first=first->nextlink) {
00882                 if (first->flag & PFACE_CONNECTED)
00883                         continue;
00884 
00885                 *stack = first->edge;
00886                 stack++;
00887 
00888                 while (stack != stackbase) {
00889                         stack--;
00890                         e = *stack;
00891                         e1 = e->next;
00892                         e2 = e1->next;
00893 
00894                         f = e->face;
00895                         f->flag |= PFACE_CONNECTED;
00896 
00897                         /* assign verts to charts so we can sort them later */
00898                         f->u.chart = ncharts;
00899 
00900                         if (!p_edge_connect_pair(handle, e, &stack, impl))
00901                                 e->vert->edge = e;
00902                         if (!p_edge_connect_pair(handle, e1, &stack, impl))
00903                                 e1->vert->edge = e1;
00904                         if (!p_edge_connect_pair(handle, e2, &stack, impl))
00905                                 e2->vert->edge = e2;
00906                 }
00907 
00908                 ncharts++;
00909         }
00910 
00911         MEM_freeN(stackbase);
00912 
00913         return ncharts;
00914 }
00915 
00916 static void p_split_vert(PChart *chart, PEdge *e)
00917 {
00918         PEdge *we, *lastwe = NULL;
00919         PVert *v = e->vert;
00920         PBool copy = P_TRUE;
00921 
00922         if (e->flag & PEDGE_VERTEX_SPLIT)
00923                 return;
00924 
00925         /* rewind to start */
00926         lastwe = e;
00927         for (we = p_wheel_edge_prev(e); we && (we != e); we = p_wheel_edge_prev(we))
00928                 lastwe = we;
00929         
00930         /* go over all edges in wheel */
00931         for (we = lastwe; we; we = p_wheel_edge_next(we)) {
00932                 if (we->flag & PEDGE_VERTEX_SPLIT)
00933                         break;
00934 
00935                 we->flag |= PEDGE_VERTEX_SPLIT;
00936 
00937                 if (we == v->edge) {
00938                         /* found it, no need to copy */
00939                         copy = P_FALSE;
00940                         v->nextlink = chart->verts;
00941                         chart->verts = v;
00942                         chart->nverts++;
00943                 }
00944         }
00945 
00946         if (copy) {
00947                 /* not found, copying */
00948                 v->flag |= PVERT_SPLIT;
00949                 v = p_vert_copy(chart, v);
00950                 v->flag |= PVERT_SPLIT;
00951 
00952                 v->nextlink = chart->verts;
00953                 chart->verts = v;
00954                 chart->nverts++;
00955 
00956                 v->edge = lastwe;
00957 
00958                 we = lastwe;
00959                 do {
00960                         we->vert = v;
00961                         we = p_wheel_edge_next(we);
00962                 } while (we && (we != lastwe));
00963         }
00964 }
00965 
00966 static PChart **p_split_charts(PHandle *handle, PChart *chart, int ncharts)
00967 {
00968         PChart **charts = MEM_mallocN(sizeof*charts * ncharts, "PCharts"), *nchart;
00969         PFace *f, *nextf;
00970         int i;
00971 
00972         for (i = 0; i < ncharts; i++)
00973                 charts[i] = p_chart_new(handle);
00974 
00975         f = chart->faces;
00976         while (f) {
00977                 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
00978                 nextf = f->nextlink;
00979 
00980                 nchart = charts[f->u.chart];
00981 
00982                 f->nextlink = nchart->faces;
00983                 nchart->faces = f;
00984                 e1->nextlink = nchart->edges;
00985                 nchart->edges = e1;
00986                 e2->nextlink = nchart->edges;
00987                 nchart->edges = e2;
00988                 e3->nextlink = nchart->edges;
00989                 nchart->edges = e3;
00990 
00991                 nchart->nfaces++;
00992                 nchart->nedges += 3;
00993 
00994                 p_split_vert(nchart, e1);
00995                 p_split_vert(nchart, e2);
00996                 p_split_vert(nchart, e3);
00997 
00998                 f = nextf;
00999         }
01000 
01001         return charts;
01002 }
01003 
01004 static PFace *p_face_add(PHandle *handle)
01005 {
01006         PFace *f;
01007         PEdge *e1, *e2, *e3;
01008 
01009         /* allocate */
01010         f = (PFace*)BLI_memarena_alloc(handle->arena, sizeof *f);
01011         f->flag=0; // init !
01012 
01013         e1 = (PEdge*)BLI_memarena_alloc(handle->arena, sizeof *e1);
01014         e2 = (PEdge*)BLI_memarena_alloc(handle->arena, sizeof *e2);
01015         e3 = (PEdge*)BLI_memarena_alloc(handle->arena, sizeof *e3);
01016 
01017         /* set up edges */
01018         f->edge = e1;
01019         e1->face = e2->face = e3->face = f;
01020 
01021         e1->next = e2;
01022         e2->next = e3;
01023         e3->next = e1;
01024 
01025         e1->pair = NULL;
01026         e2->pair = NULL;
01027         e3->pair = NULL;
01028    
01029         e1->flag =0;
01030         e2->flag =0;
01031         e3->flag =0;
01032 
01033         return f;
01034 }
01035 
01036 static PFace *p_face_add_construct(PHandle *handle, ParamKey key, ParamKey *vkeys,
01037                                                                    float *co[3], float *uv[3], int i1, int i2, int i3,
01038                                                                    ParamBool *pin, ParamBool *select)
01039 {
01040         PFace *f = p_face_add(handle);
01041         PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
01042 
01043         e1->vert = p_vert_lookup(handle, vkeys[i1], co[i1], e1);
01044         e2->vert = p_vert_lookup(handle, vkeys[i2], co[i2], e2);
01045         e3->vert = p_vert_lookup(handle, vkeys[i3], co[i3], e3);
01046 
01047         e1->orig_uv = uv[i1];
01048         e2->orig_uv = uv[i2];
01049         e3->orig_uv = uv[i3];
01050 
01051         if (pin) {
01052                 if (pin[i1]) e1->flag |= PEDGE_PIN;
01053                 if (pin[i2]) e2->flag |= PEDGE_PIN;
01054                 if (pin[i3]) e3->flag |= PEDGE_PIN;
01055         }
01056 
01057         if (select) {
01058                 if (select[i1]) e1->flag |= PEDGE_SELECT;
01059                 if (select[i2]) e2->flag |= PEDGE_SELECT;
01060                 if (select[i3]) e3->flag |= PEDGE_SELECT;
01061         }
01062 
01063         /* insert into hash */
01064         f->u.key = key;
01065         phash_insert(handle->hash_faces, (PHashLink*)f);
01066 
01067         e1->u.key = PHASH_edge(vkeys[i1], vkeys[i2]);
01068         e2->u.key = PHASH_edge(vkeys[i2], vkeys[i3]);
01069         e3->u.key = PHASH_edge(vkeys[i3], vkeys[i1]);
01070 
01071         phash_insert(handle->hash_edges, (PHashLink*)e1);
01072         phash_insert(handle->hash_edges, (PHashLink*)e2);
01073         phash_insert(handle->hash_edges, (PHashLink*)e3);
01074 
01075         return f;
01076 }
01077 
01078 static PFace *p_face_add_fill(PChart *chart, PVert *v1, PVert *v2, PVert *v3)
01079 {
01080         PFace *f = p_face_add(chart->handle);
01081         PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
01082 
01083         e1->vert = v1;
01084         e2->vert = v2;
01085         e3->vert = v3;
01086 
01087         e1->orig_uv = e2->orig_uv = e3->orig_uv = NULL;
01088 
01089         f->nextlink = chart->faces;
01090         chart->faces = f;
01091         e1->nextlink = chart->edges;
01092         chart->edges = e1;
01093         e2->nextlink = chart->edges;
01094         chart->edges = e2;
01095         e3->nextlink = chart->edges;
01096         chart->edges = e3;
01097 
01098         chart->nfaces++;
01099         chart->nedges += 3;
01100 
01101         return f;
01102 }
01103 
01104 static PBool p_quad_split_direction(PHandle *handle, float **co, PHashKey *vkeys)
01105 {
01106         float fac= len_v3v3(co[0], co[2]) - len_v3v3(co[1], co[3]);
01107         PBool dir = (fac <= 0.0f);
01108 
01109         /* the face exists check is there because of a special case: when
01110            two quads share three vertices, they can each be split into two
01111            triangles, resulting in two identical triangles. for example in
01112            suzanne's nose. */
01113         if (dir) {
01114                 if (p_face_exists(handle,vkeys,0,1,2) || p_face_exists(handle,vkeys,0,2,3))
01115                         return !dir;
01116         }
01117         else {
01118                 if (p_face_exists(handle,vkeys,0,1,3) || p_face_exists(handle,vkeys,1,2,3))
01119                         return !dir;
01120         }
01121 
01122         return dir;
01123 }
01124 
01125 /* Construction: boundary filling */
01126 
01127 static void p_chart_boundaries(PChart *chart, int *nboundaries, PEdge **outer)
01128 {   
01129         PEdge *e, *be;
01130         float len, maxlen = -1.0;
01131 
01132         if (nboundaries)
01133                 *nboundaries = 0;
01134         if (outer)
01135                 *outer = NULL;
01136 
01137         for (e=chart->edges; e; e=e->nextlink) {
01138                 if (e->pair || (e->flag & PEDGE_DONE))
01139                         continue;
01140 
01141                 if (nboundaries)
01142                         (*nboundaries)++;
01143 
01144                 len = 0.0f;
01145 
01146                 be = e;
01147                 do {
01148                         be->flag |= PEDGE_DONE;
01149                         len += p_edge_length(be);
01150                         be = be->next->vert->edge;
01151                 } while(be != e);
01152 
01153                 if (outer && (len > maxlen)) {
01154                         *outer = e;
01155                         maxlen = len;
01156                 }
01157         }
01158 
01159         for (e=chart->edges; e; e=e->nextlink)
01160                 e->flag &= ~PEDGE_DONE;
01161 }
01162 
01163 static float p_edge_boundary_angle(PEdge *e)
01164 {
01165         PEdge *we;
01166         PVert *v, *v1, *v2;
01167         float angle;
01168         int n = 0;
01169 
01170         v = e->vert;
01171 
01172         /* concave angle check -- could be better */
01173         angle = M_PI;
01174 
01175         we = v->edge;
01176         do {
01177                 v1 = we->next->vert;
01178                 v2 = we->next->next->vert;
01179                 angle -= p_vec_angle(v1->co, v->co, v2->co);
01180 
01181                 we = we->next->next->pair;
01182                 n++;
01183         } while (we && (we != v->edge));
01184 
01185         return angle;
01186 }
01187 
01188 static void p_chart_fill_boundary(PChart *chart, PEdge *be, int nedges)
01189 {
01190         PEdge *e, *e1, *e2;
01191 
01192         PFace *f;
01193         struct Heap *heap = BLI_heap_new();
01194         float angle;
01195 
01196         e = be;
01197         do {
01198                 angle = p_edge_boundary_angle(e);
01199                 e->u.heaplink = BLI_heap_insert(heap, angle, e);
01200 
01201                 e = p_boundary_edge_next(e);
01202         } while(e != be);
01203 
01204         if (nedges == 2) {
01205                 /* no real boundary, but an isolated seam */
01206                 e = be->next->vert->edge;
01207                 e->pair = be;
01208                 be->pair = e;
01209 
01210                 BLI_heap_remove(heap, e->u.heaplink);
01211                 BLI_heap_remove(heap, be->u.heaplink);
01212         }
01213         else {
01214                 while (nedges > 2) {
01215                         PEdge *ne, *ne1, *ne2;
01216 
01217                         e = (PEdge*)BLI_heap_popmin(heap);
01218 
01219                         e1 = p_boundary_edge_prev(e);
01220                         e2 = p_boundary_edge_next(e);
01221 
01222                         BLI_heap_remove(heap, e1->u.heaplink);
01223                         BLI_heap_remove(heap, e2->u.heaplink);
01224                         e->u.heaplink = e1->u.heaplink = e2->u.heaplink = NULL;
01225 
01226                         e->flag |= PEDGE_FILLED;
01227                         e1->flag |= PEDGE_FILLED;
01228 
01229 
01230 
01231 
01232 
01233                         f = p_face_add_fill(chart, e->vert, e1->vert, e2->vert);
01234                         f->flag |= PFACE_FILLED;
01235 
01236                         ne = f->edge->next->next;
01237                         ne1 = f->edge;
01238                         ne2 = f->edge->next;
01239 
01240                         ne->flag = ne1->flag = ne2->flag = PEDGE_FILLED;
01241 
01242                         e->pair = ne;
01243                         ne->pair = e;
01244                         e1->pair = ne1;
01245                         ne1->pair = e1;
01246 
01247                         ne->vert = e2->vert;
01248                         ne1->vert = e->vert;
01249                         ne2->vert = e1->vert;
01250 
01251                         if (nedges == 3) {
01252                                 e2->pair = ne2;
01253                                 ne2->pair = e2;
01254                         }
01255                         else {
01256                                 ne2->vert->edge = ne2;
01257                                 
01258                                 ne2->u.heaplink = BLI_heap_insert(heap, p_edge_boundary_angle(ne2), ne2);
01259                                 e2->u.heaplink = BLI_heap_insert(heap, p_edge_boundary_angle(e2), e2);
01260                         }
01261 
01262                         nedges--;
01263                 }
01264         }
01265 
01266         BLI_heap_free(heap, NULL);
01267 }
01268 
01269 static void p_chart_fill_boundaries(PChart *chart, PEdge *outer)
01270 {
01271         PEdge *e, *be; /* *enext - as yet unused */
01272         int nedges;
01273 
01274         for (e=chart->edges; e; e=e->nextlink) {
01275                 /* enext = e->nextlink; - as yet unused */
01276 
01277                 if (e->pair || (e->flag & PEDGE_FILLED))
01278                         continue;
01279 
01280                 nedges = 0;
01281                 be = e;
01282                 do {
01283                         be->flag |= PEDGE_FILLED;
01284                         be = be->next->vert->edge;
01285                         nedges++;
01286                 } while(be != e);
01287 
01288                 if (e != outer)
01289                         p_chart_fill_boundary(chart, e, nedges);
01290         }
01291 }
01292 
01293 #if 0
01294 /* Polygon kernel for inserting uv's non overlapping */
01295 
01296 static int p_polygon_point_in(float *cp1, float *cp2, float *p)
01297 {
01298         if ((cp1[0] == p[0]) && (cp1[1] == p[1]))
01299                 return 2;
01300         else if ((cp2[0] == p[0]) && (cp2[1] == p[1]))
01301                 return 3;
01302         else
01303                 return (p_area_signed(cp1, cp2, p) >= 0.0f);
01304 }
01305 
01306 static void p_polygon_kernel_clip(float (*oldpoints)[2], int noldpoints, float (*newpoints)[2], int *nnewpoints, float *cp1, float *cp2)
01307 {
01308         float *p2, *p1, isect[2];
01309         int i, p2in, p1in;
01310 
01311         p1 = oldpoints[noldpoints-1];
01312         p1in = p_polygon_point_in(cp1, cp2, p1);
01313         *nnewpoints = 0;
01314 
01315         for (i = 0; i < noldpoints; i++) {
01316                 p2 = oldpoints[i];
01317                 p2in = p_polygon_point_in(cp1, cp2, p2);
01318 
01319                 if ((p2in >= 2) || (p1in && p2in)) {
01320                         newpoints[*nnewpoints][0] = p2[0];
01321                         newpoints[*nnewpoints][1] = p2[1];
01322                         (*nnewpoints)++;
01323                 }
01324                 else if (p1in && !p2in) {
01325                         if (p1in != 3) {
01326                                 p_intersect_line_2d(p1, p2, cp1, cp2, isect);
01327                                 newpoints[*nnewpoints][0] = isect[0];
01328                                 newpoints[*nnewpoints][1] = isect[1];
01329                                 (*nnewpoints)++;
01330                         }
01331                 }
01332                 else if (!p1in && p2in) {
01333                         p_intersect_line_2d(p1, p2, cp1, cp2, isect);
01334                         newpoints[*nnewpoints][0] = isect[0];
01335                         newpoints[*nnewpoints][1] = isect[1];
01336                         (*nnewpoints)++;
01337 
01338                         newpoints[*nnewpoints][0] = p2[0];
01339                         newpoints[*nnewpoints][1] = p2[1];
01340                         (*nnewpoints)++;
01341                 }
01342                 
01343                 p1in = p2in;
01344                 p1 = p2;
01345         }
01346 }
01347 
01348 static void p_polygon_kernel_center(float (*points)[2], int npoints, float *center)
01349 {
01350         int i, size, nnewpoints = npoints;
01351         float (*oldpoints)[2], (*newpoints)[2], *p1, *p2;
01352         
01353         size = npoints*3;
01354         oldpoints = MEM_mallocN(sizeof(float)*2*size, "PPolygonOldPoints");
01355         newpoints = MEM_mallocN(sizeof(float)*2*size, "PPolygonNewPoints");
01356 
01357         memcpy(oldpoints, points, sizeof(float)*2*npoints);
01358 
01359         for (i = 0; i < npoints; i++) {
01360                 p1 = points[i];
01361                 p2 = points[(i+1)%npoints];
01362                 p_polygon_kernel_clip(oldpoints, nnewpoints, newpoints, &nnewpoints, p1, p2);
01363 
01364                 if (nnewpoints == 0) {
01365                         /* degenerate case, use center of original polygon */
01366                         memcpy(oldpoints, points, sizeof(float)*2*npoints);
01367                         nnewpoints = npoints;
01368                         break;
01369                 }
01370                 else if (nnewpoints == 1) {
01371                         /* degenerate case, use remaining point */
01372                         center[0] = newpoints[0][0];
01373                         center[1] = newpoints[0][1];
01374 
01375                         MEM_freeN(oldpoints);
01376                         MEM_freeN(newpoints);
01377 
01378                         return;
01379                 }
01380 
01381                 if (nnewpoints*2 > size) {
01382                         size *= 2;
01383                         MEM_freeN(oldpoints);
01384                         oldpoints = MEM_mallocN(sizeof(float)*2*size, "oldpoints");
01385                         memcpy(oldpoints, newpoints, sizeof(float)*2*nnewpoints);
01386                         MEM_freeN(newpoints);
01387                         newpoints = MEM_mallocN(sizeof(float)*2*size, "newpoints");
01388                 }
01389                 else {
01390                         float (*sw_points)[2] = oldpoints;
01391                         oldpoints = newpoints;
01392                         newpoints = sw_points;
01393                 }
01394         }
01395 
01396         center[0] = center[1] = 0.0f;
01397 
01398         for (i = 0; i < nnewpoints; i++) {
01399                 center[0] += oldpoints[i][0];
01400                 center[1] += oldpoints[i][1];
01401         }
01402 
01403         center[0] /= nnewpoints;
01404         center[1] /= nnewpoints;
01405 
01406         MEM_freeN(oldpoints);
01407         MEM_freeN(newpoints);
01408 }
01409 #endif
01410 
01411 #if 0
01412 /* Edge Collapser */
01413 
01414 int NCOLLAPSE = 1;
01415 int NCOLLAPSEX = 0;
01416         
01417 static float p_vert_cotan(float *v1, float *v2, float *v3)
01418 {
01419         float a[3], b[3], c[3], clen;
01420 
01421         sub_v3_v3v3(a, v2, v1);
01422         sub_v3_v3v3(b, v3, v1);
01423         cross_v3_v3v3(c, a, b);
01424 
01425         clen = len_v3(c);
01426 
01427         if (clen == 0.0f)
01428                 return 0.0f;
01429         
01430         return dot_v3v3(a, b)/clen;
01431 }
01432         
01433 static PBool p_vert_flipped_wheel_triangle(PVert *v)
01434 {
01435         PEdge *e = v->edge;
01436 
01437         do {
01438                 if (p_face_uv_area_signed(e->face) < 0.0f)
01439                         return P_TRUE;
01440 
01441                 e = p_wheel_edge_next(e);
01442         } while (e && (e != v->edge));
01443 
01444         return P_FALSE;
01445 }
01446 
01447 static PBool p_vert_map_harmonic_weights(PVert *v)
01448 {
01449         float weightsum, positionsum[2], olduv[2];
01450 
01451         weightsum = 0.0f;
01452         positionsum[0] = positionsum[1] = 0.0f;
01453 
01454         if (p_vert_interior(v)) {
01455                 PEdge *e = v->edge;
01456 
01457                 do {
01458                         float t1, t2, weight;
01459                         PVert *v1, *v2;
01460                         
01461                         v1 = e->next->vert;
01462                         v2 = e->next->next->vert;
01463                         t1 = p_vert_cotan(v2->co, e->vert->co, v1->co);
01464 
01465                         v1 = e->pair->next->vert;
01466                         v2 = e->pair->next->next->vert;
01467                         t2 = p_vert_cotan(v2->co, e->pair->vert->co, v1->co);
01468 
01469                         weight = 0.5f*(t1 + t2);
01470                         weightsum += weight;
01471                         positionsum[0] += weight*e->pair->vert->uv[0];
01472                         positionsum[1] += weight*e->pair->vert->uv[1];
01473 
01474                         e = p_wheel_edge_next(e);
01475                 } while (e && (e != v->edge));
01476         }
01477         else {
01478                 PEdge *e = v->edge;
01479 
01480                 do {
01481                         float t1, t2;
01482                         PVert *v1, *v2;
01483 
01484                         v2 = e->next->vert;
01485                         v1 = e->next->next->vert;
01486 
01487                         t1 = p_vert_cotan(v1->co, v->co, v2->co);
01488                         t2 = p_vert_cotan(v2->co, v->co, v1->co);
01489 
01490                         weightsum += t1 + t2;
01491                         positionsum[0] += (v2->uv[1] - v1->uv[1]) + (t1*v2->uv[0] + t2*v1->uv[0]);
01492                         positionsum[1] += (v1->uv[0] - v2->uv[0]) + (t1*v2->uv[1] + t2*v1->uv[1]);
01493                 
01494                         e = p_wheel_edge_next(e);
01495                 } while (e && (e != v->edge));
01496         }
01497 
01498         if (weightsum != 0.0f) {
01499                 weightsum = 1.0f/weightsum;
01500                 positionsum[0] *= weightsum;
01501                 positionsum[1] *= weightsum;
01502         }
01503 
01504         olduv[0] = v->uv[0];
01505         olduv[1] = v->uv[1];
01506         v->uv[0] = positionsum[0];
01507         v->uv[1] = positionsum[1];
01508 
01509         if (p_vert_flipped_wheel_triangle(v)) {
01510                 v->uv[0] = olduv[0];
01511                 v->uv[1] = olduv[1];
01512 
01513                 return P_FALSE;
01514         }
01515 
01516         return P_TRUE;
01517 }
01518 
01519 static void p_vert_harmonic_insert(PVert *v)
01520 {
01521         PEdge *e;
01522 
01523         if (!p_vert_map_harmonic_weights(v)) {
01524                 /* do polygon kernel center insertion: this is quite slow, but should
01525                    only be needed for 0.01 % of verts or so, when insert with harmonic
01526                    weights fails */
01527 
01528                 int npoints = 0, i;
01529                 float (*points)[2];
01530 
01531                 e = v->edge;
01532                 do {
01533                         npoints++;      
01534                         e = p_wheel_edge_next(e);
01535                 } while (e && (e != v->edge));
01536 
01537                 if (e == NULL)
01538                         npoints++;
01539 
01540                 points = MEM_mallocN(sizeof(float)*2*npoints, "PHarmonicPoints");
01541 
01542                 e = v->edge;
01543                 i = 0;
01544                 do {
01545                         PEdge *nexte = p_wheel_edge_next(e);
01546 
01547                         points[i][0] = e->next->vert->uv[0]; 
01548                         points[i][1] = e->next->vert->uv[1]; 
01549 
01550                         if (nexte == NULL) {
01551                                 i++;
01552                                 points[i][0] = e->next->next->vert->uv[0]; 
01553                                 points[i][1] = e->next->next->vert->uv[1]; 
01554                                 break;
01555                         }
01556 
01557                         e = nexte;
01558                         i++;
01559                 } while (e != v->edge);
01560                 
01561                 p_polygon_kernel_center(points, npoints, v->uv);
01562 
01563                 MEM_freeN(points);
01564         }
01565 
01566         e = v->edge;
01567         do {
01568                 if (!(e->next->vert->flag & PVERT_PIN))
01569                         p_vert_map_harmonic_weights(e->next->vert);
01570                 e = p_wheel_edge_next(e);
01571         } while (e && (e != v->edge));
01572 
01573         p_vert_map_harmonic_weights(v);
01574 }
01575 
01576 static void p_vert_fix_edge_pointer(PVert *v)
01577 {
01578         PEdge *start = v->edge;
01579 
01580         /* set v->edge pointer to the edge with no pair, if there is one */
01581         while (v->edge->pair) {
01582                 v->edge = p_wheel_edge_prev(v->edge);
01583                 
01584                 if (v->edge == start)
01585                         break;
01586         }
01587 }
01588 
01589 static void p_collapsing_verts(PEdge *edge, PEdge *pair, PVert **newv, PVert **keepv)
01590 {
01591         /* the two vertices that are involved in the collapse */
01592         if (edge) {
01593                 *newv = edge->vert;
01594                 *keepv = edge->next->vert;
01595         }
01596         else {
01597                 *newv = pair->next->vert;
01598                 *keepv = pair->vert;
01599         }
01600 }
01601 
01602 static void p_collapse_edge(PEdge *edge, PEdge *pair)
01603 {
01604         PVert *oldv, *keepv;
01605         PEdge *e;
01606 
01607         p_collapsing_verts(edge, pair, &oldv, &keepv);
01608 
01609         /* change e->vert pointers from old vertex to the target vertex */
01610         e = oldv->edge;
01611         do {
01612                 if ((e != edge) && !(pair && pair->next == e))
01613                         e->vert = keepv;
01614 
01615                 e = p_wheel_edge_next(e);
01616         } while (e && (e != oldv->edge));
01617 
01618         /* set keepv->edge pointer */
01619         if ((edge && (keepv->edge == edge->next)) || (keepv->edge == pair)) {
01620                 if (edge && edge->next->pair)
01621                         keepv->edge = edge->next->pair->next;
01622                 else if (pair && pair->next->next->pair)
01623                         keepv->edge = pair->next->next->pair;
01624                 else if (edge && edge->next->next->pair)
01625                         keepv->edge = edge->next->next->pair;
01626                 else
01627                         keepv->edge = pair->next->pair->next;
01628         }
01629         
01630         /* update pairs and v->edge pointers */
01631         if (edge) {
01632                 PEdge *e1 = edge->next, *e2 = e1->next;
01633 
01634                 if (e1->pair)
01635                         e1->pair->pair = e2->pair;
01636 
01637                 if (e2->pair) {
01638                         e2->pair->pair = e1->pair;
01639                         e2->vert->edge = p_wheel_edge_prev(e2);
01640                 }
01641                 else
01642                         e2->vert->edge = p_wheel_edge_next(e2);
01643 
01644                 p_vert_fix_edge_pointer(e2->vert);
01645         }
01646 
01647         if (pair) {
01648                 PEdge *e1 = pair->next, *e2 = e1->next;
01649 
01650                 if (e1->pair)
01651                         e1->pair->pair = e2->pair;
01652 
01653                 if (e2->pair) {
01654                         e2->pair->pair = e1->pair;
01655                         e2->vert->edge = p_wheel_edge_prev(e2);
01656                 }
01657                 else
01658                         e2->vert->edge = p_wheel_edge_next(e2);
01659 
01660                 p_vert_fix_edge_pointer(e2->vert);
01661         }
01662 
01663         p_vert_fix_edge_pointer(keepv);
01664 
01665         /* mark for move to collapsed list later */
01666         oldv->flag |= PVERT_COLLAPSE;
01667 
01668         if (edge) {
01669                 PFace *f = edge->face;
01670                 PEdge *e1 = edge->next, *e2 = e1->next;
01671 
01672                 f->flag |= PFACE_COLLAPSE;
01673                 edge->flag |= PEDGE_COLLAPSE;
01674                 e1->flag |= PEDGE_COLLAPSE;
01675                 e2->flag |= PEDGE_COLLAPSE;
01676         }
01677 
01678         if (pair) {
01679                 PFace *f = pair->face;
01680                 PEdge *e1 = pair->next, *e2 = e1->next;
01681 
01682                 f->flag |= PFACE_COLLAPSE;
01683                 pair->flag |= PEDGE_COLLAPSE;
01684                 e1->flag |= PEDGE_COLLAPSE;
01685                 e2->flag |= PEDGE_COLLAPSE;
01686         }
01687 }
01688 
01689 static void p_split_vertex(PEdge *edge, PEdge *pair)
01690 {
01691         PVert *newv, *keepv;
01692         PEdge *e;
01693 
01694         p_collapsing_verts(edge, pair, &newv, &keepv);
01695 
01696         /* update edge pairs */
01697         if (edge) {
01698                 PEdge *e1 = edge->next, *e2 = e1->next;
01699 
01700                 if (e1->pair)
01701                         e1->pair->pair = e1;
01702                 if (e2->pair)
01703                         e2->pair->pair = e2;
01704 
01705                 e2->vert->edge = e2;
01706                 p_vert_fix_edge_pointer(e2->vert);
01707                 keepv->edge = e1;
01708         }
01709 
01710         if (pair) {
01711                 PEdge *e1 = pair->next, *e2 = e1->next;
01712 
01713                 if (e1->pair)
01714                         e1->pair->pair = e1;
01715                 if (e2->pair)
01716                         e2->pair->pair = e2;
01717 
01718                 e2->vert->edge = e2;
01719                 p_vert_fix_edge_pointer(e2->vert);
01720                 keepv->edge = pair;
01721         }
01722 
01723         p_vert_fix_edge_pointer(keepv);
01724 
01725         /* set e->vert pointers to restored vertex */
01726         e = newv->edge;
01727         do {
01728                 e->vert = newv;
01729                 e = p_wheel_edge_next(e);
01730         } while (e && (e != newv->edge));
01731 }
01732 
01733 static PBool p_collapse_allowed_topologic(PEdge *edge, PEdge *pair)
01734 {
01735         PVert *oldv, *keepv;
01736 
01737         p_collapsing_verts(edge, pair, &oldv, &keepv);
01738 
01739         /* boundary edges */
01740         if (!edge || !pair) {
01741                 /* avoid collapsing chart into an edge */
01742                 if (edge && !edge->next->pair && !edge->next->next->pair)
01743                         return P_FALSE;
01744                 else if (pair && !pair->next->pair && !pair->next->next->pair)
01745                         return P_FALSE;
01746         }
01747         /* avoid merging two boundaries (oldv and keepv are on the 'other side' of
01748            the chart) */
01749         else if (!p_vert_interior(oldv) && !p_vert_interior(keepv))
01750                 return P_FALSE;
01751         
01752         return P_TRUE;
01753 }
01754 
01755 static PBool p_collapse_normal_flipped(float *v1, float *v2, float *vold, float *vnew)
01756 {
01757         float nold[3], nnew[3], sub1[3], sub2[3];
01758 
01759         sub_v3_v3v3(sub1, vold, v1);
01760         sub_v3_v3v3(sub2, vold, v2);
01761         cross_v3_v3v3(nold, sub1, sub2);
01762 
01763         sub_v3_v3v3(sub1, vnew, v1);
01764         sub_v3_v3v3(sub2, vnew, v2);
01765         cross_v3_v3v3(nnew, sub1, sub2);
01766 
01767         return (dot_v3v3(nold, nnew) <= 0.0f);
01768 }
01769 
01770 static PBool p_collapse_allowed_geometric(PEdge *edge, PEdge *pair)
01771 {
01772         PVert *oldv, *keepv;
01773         PEdge *e;
01774         float angulardefect, angle;
01775 
01776         p_collapsing_verts(edge, pair, &oldv, &keepv);
01777 
01778         angulardefect = 2*M_PI;
01779 
01780         e = oldv->edge;
01781         do {
01782                 float a[3], b[3], minangle, maxangle;
01783                 PEdge *e1 = e->next, *e2 = e1->next;
01784                 PVert *v1 = e1->vert, *v2 = e2->vert;
01785                 int i;
01786 
01787                 angle = p_vec_angle(v1->co, oldv->co, v2->co);
01788                 angulardefect -= angle;
01789 
01790                 /* skip collapsing faces */
01791                 if (v1 == keepv || v2 == keepv) {
01792                         e = p_wheel_edge_next(e);
01793                         continue;
01794                 }
01795 
01796                 if (p_collapse_normal_flipped(v1->co, v2->co, oldv->co, keepv->co))
01797                         return P_FALSE;
01798         
01799                 a[0] = angle;
01800                 a[1] = p_vec_angle(v2->co, v1->co, oldv->co);
01801                 a[2] = M_PI - a[0] - a[1];
01802 
01803                 b[0] = p_vec_angle(v1->co, keepv->co, v2->co);
01804                 b[1] = p_vec_angle(v2->co, v1->co, keepv->co);
01805                 b[2] = M_PI - b[0] - b[1];
01806 
01807                 /* abf criterion 1: avoid sharp and obtuse angles */
01808                 minangle = 15.0f*M_PI/180.0f;
01809                 maxangle = M_PI - minangle;
01810 
01811                 for (i = 0; i < 3; i++) {
01812                         if ((b[i] < a[i]) && (b[i] < minangle))
01813                                 return P_FALSE;
01814                         else if ((b[i] > a[i]) && (b[i] > maxangle))
01815                                 return P_FALSE;
01816                 }
01817 
01818                 e = p_wheel_edge_next(e);
01819         } while (e && (e != oldv->edge));
01820 
01821         if (p_vert_interior(oldv)) {
01822                 /* hlscm criterion: angular defect smaller than threshold */
01823                 if (fabs(angulardefect) > (M_PI*30.0/180.0))
01824                         return P_FALSE;
01825         }
01826         else {
01827                 PVert *v1 = p_boundary_edge_next(oldv->edge)->vert;
01828                 PVert *v2 = p_boundary_edge_prev(oldv->edge)->vert;
01829 
01830                 /* abf++ criterion 2: avoid collapsing verts inwards */
01831                 if (p_vert_interior(keepv))
01832                         return P_FALSE;
01833                 
01834                 /* don't collapse significant boundary changes */
01835                 angle = p_vec_angle(v1->co, oldv->co, v2->co);
01836                 if (angle < (M_PI*160.0/180.0))
01837                         return P_FALSE;
01838         }
01839 
01840         return P_TRUE;
01841 }
01842 
01843 static PBool p_collapse_allowed(PEdge *edge, PEdge *pair)
01844 {
01845         PVert *oldv, *keepv;
01846 
01847         p_collapsing_verts(edge, pair, &oldv, &keepv);
01848 
01849         if (oldv->flag & PVERT_PIN)
01850                 return P_FALSE;
01851         
01852         return (p_collapse_allowed_topologic(edge, pair) &&
01853                         p_collapse_allowed_geometric(edge, pair));
01854 }
01855 
01856 static float p_collapse_cost(PEdge *edge, PEdge *pair)
01857 {
01858         /* based on volume and boundary optimization from:
01859           "Fast and Memory Efficient Polygonal Simplification" P. Lindstrom, G. Turk */
01860 
01861         PVert *oldv, *keepv;
01862         PEdge *e;
01863         PFace *oldf1, *oldf2;
01864         float volumecost = 0.0f, areacost = 0.0f, edgevec[3], cost, weight, elen;
01865         float shapecost = 0.0f;
01866         float shapeold = 0.0f, shapenew = 0.0f;
01867         int nshapeold = 0, nshapenew = 0;
01868 
01869         p_collapsing_verts(edge, pair, &oldv, &keepv);
01870         oldf1 = (edge)? edge->face: NULL;
01871         oldf2 = (pair)? pair->face: NULL;
01872 
01873         sub_v3_v3v3(edgevec, keepv->co, oldv->co);
01874 
01875         e = oldv->edge;
01876         do {
01877                 float a1, a2, a3;
01878                 float *co1 = e->next->vert->co;
01879                 float *co2 = e->next->next->vert->co;
01880 
01881                 if ((e->face != oldf1) && (e->face != oldf2)) {
01882                         float tetrav2[3], tetrav3[3], c[3];
01883 
01884                         /* tetrahedron volume = (1/3!)*|a.(b x c)| */
01885                         sub_v3_v3v3(tetrav2, co1, oldv->co);
01886                         sub_v3_v3v3(tetrav3, co2, oldv->co);
01887                         cross_v3_v3v3(c, tetrav2, tetrav3);
01888 
01889                         volumecost += fabs(dot_v3v3(edgevec, c)/6.0f);
01890 #if 0
01891                         shapecost += dot_v3v3(co1, keepv->co);
01892 
01893                         if (p_wheel_edge_next(e) == NULL)
01894                                 shapecost += dot_v3v3(co2, keepv->co);
01895 #endif
01896 
01897                         p_triangle_angles(oldv->co, co1, co2, &a1, &a2, &a3);
01898                         a1 = a1 - M_PI/3.0;
01899                         a2 = a2 - M_PI/3.0;
01900                         a3 = a3 - M_PI/3.0;
01901                         shapeold = (a1*a1 + a2*a2 + a3*a3)/((M_PI/2)*(M_PI/2));
01902 
01903                         nshapeold++;
01904                 }
01905                 else {
01906                         p_triangle_angles(keepv->co, co1, co2, &a1, &a2, &a3);
01907                         a1 = a1 - M_PI/3.0;
01908                         a2 = a2 - M_PI/3.0;
01909                         a3 = a3 - M_PI/3.0;
01910                         shapenew = (a1*a1 + a2*a2 + a3*a3)/((M_PI/2)*(M_PI/2));
01911 
01912                         nshapenew++;
01913                 }
01914 
01915                 e = p_wheel_edge_next(e);
01916         } while (e && (e != oldv->edge));
01917 
01918         if (!p_vert_interior(oldv)) {
01919                 PVert *v1 = p_boundary_edge_prev(oldv->edge)->vert;
01920                 PVert *v2 = p_boundary_edge_next(oldv->edge)->vert;
01921 
01922                 areacost = area_tri_v3(oldv->co, v1->co, v2->co);
01923         }
01924 
01925         elen = len_v3(edgevec);
01926         weight = 1.0f; /* 0.2f */
01927         cost = weight*volumecost*volumecost + elen*elen*areacost*areacost;
01928 #if 0
01929         cost += shapecost;
01930 #else
01931         shapeold /= nshapeold;
01932         shapenew /= nshapenew;
01933         shapecost = (shapeold + 0.00001)/(shapenew + 0.00001);
01934 
01935         cost *= shapecost;
01936 #endif
01937 
01938         return cost;
01939 }
01940         
01941 static void p_collapse_cost_vertex(PVert *vert, float *mincost, PEdge **mine)
01942 {
01943         PEdge *e, *enext, *pair;
01944 
01945         *mine = NULL;
01946         *mincost = 0.0f;
01947         e = vert->edge;
01948         do {
01949                 if (p_collapse_allowed(e, e->pair)) {
01950                         float cost = p_collapse_cost(e, e->pair);
01951 
01952                         if ((*mine == NULL) || (cost < *mincost)) {
01953                                 *mincost = cost;
01954                                 *mine = e;
01955                         }
01956                 }
01957 
01958                 enext = p_wheel_edge_next(e);
01959 
01960                 if (enext == NULL) {
01961                         /* the other boundary edge, where we only have the pair halfedge */
01962                         pair = e->next->next;
01963 
01964                         if (p_collapse_allowed(NULL, pair)) {
01965                                 float cost = p_collapse_cost(NULL, pair);
01966 
01967                                 if ((*mine == NULL) || (cost < *mincost)) {
01968                                         *mincost = cost;
01969                                         *mine = pair;
01970                                 }
01971                         }
01972 
01973                         break;
01974                 }
01975 
01976                 e = enext;
01977         } while (e != vert->edge);
01978 }
01979 
01980 static void p_chart_post_collapse_flush(PChart *chart, PEdge *collapsed)
01981 {
01982         /* move to collapsed_ */
01983 
01984         PVert *v, *nextv = NULL, *verts = chart->verts;
01985         PEdge *e, *nexte = NULL, *edges = chart->edges, *laste = NULL;
01986         PFace *f, *nextf = NULL, *faces = chart->faces;
01987 
01988         chart->verts = chart->collapsed_verts = NULL;
01989         chart->edges = chart->collapsed_edges = NULL;
01990         chart->faces = chart->collapsed_faces = NULL;
01991 
01992         chart->nverts = chart->nedges = chart->nfaces = 0;
01993 
01994         for (v=verts; v; v=nextv) {
01995                 nextv = v->nextlink;
01996 
01997                 if (v->flag & PVERT_COLLAPSE) {
01998                         v->nextlink = chart->collapsed_verts;
01999                         chart->collapsed_verts = v;
02000                 }
02001                 else {
02002                         v->nextlink = chart->verts;
02003                         chart->verts = v;
02004                         chart->nverts++;
02005                 }
02006         }
02007 
02008         for (e=edges; e; e=nexte) {
02009                 nexte = e->nextlink;
02010 
02011                 if (!collapsed || !(e->flag & PEDGE_COLLAPSE_EDGE)) {
02012                         if (e->flag & PEDGE_COLLAPSE) {
02013                                 e->nextlink = chart->collapsed_edges;
02014                                 chart->collapsed_edges = e;
02015                         }
02016                         else {
02017                                 e->nextlink = chart->edges;
02018                                 chart->edges = e;
02019                                 chart->nedges++;
02020                         }
02021                 }
02022         }
02023 
02024         /* these are added last so they can be popped of in the right order
02025            for splitting */
02026         for (e=collapsed; e; e=e->nextlink) {
02027                 e->nextlink = e->u.nextcollapse;
02028                 laste = e;
02029         }
02030         if (laste) {
02031                 laste->nextlink = chart->collapsed_edges;
02032                 chart->collapsed_edges = collapsed;
02033         }
02034 
02035         for (f=faces; f; f=nextf) {
02036                 nextf = f->nextlink;
02037 
02038                 if (f->flag & PFACE_COLLAPSE) {
02039                         f->nextlink = chart->collapsed_faces;
02040                         chart->collapsed_faces = f;
02041                 }
02042                 else {
02043                         f->nextlink = chart->faces;
02044                         chart->faces = f;
02045                         chart->nfaces++;
02046                 }
02047         }
02048 }
02049 
02050 static void p_chart_post_split_flush(PChart *chart)
02051 {
02052         /* move from collapsed_ */
02053 
02054         PVert *v, *nextv = NULL;
02055         PEdge *e, *nexte = NULL;
02056         PFace *f, *nextf = NULL;
02057 
02058         for (v=chart->collapsed_verts; v; v=nextv) {
02059                 nextv = v->nextlink;
02060                 v->nextlink = chart->verts;
02061                 chart->verts = v;
02062                 chart->nverts++;
02063         }
02064 
02065         for (e=chart->collapsed_edges; e; e=nexte) {
02066                 nexte = e->nextlink;
02067                 e->nextlink = chart->edges;
02068                 chart->edges = e;
02069                 chart->nedges++;
02070         }
02071 
02072         for (f=chart->collapsed_faces; f; f=nextf) {
02073                 nextf = f->nextlink;
02074                 f->nextlink = chart->faces;
02075                 chart->faces = f;
02076                 chart->nfaces++;
02077         }
02078 
02079         chart->collapsed_verts = NULL;
02080         chart->collapsed_edges = NULL;
02081         chart->collapsed_faces = NULL;
02082 }
02083 
02084 static void p_chart_simplify_compute(PChart *chart)
02085 {
02086         /* Computes a list of edge collapses / vertex splits. The collapsed
02087            simplices go in the chart->collapsed_* lists, The original and
02088            collapsed may then be view as stacks, where the next collapse/split
02089            is at the top of the respective lists. */
02090 
02091         Heap *heap = BLI_heap_new();
02092         PVert *v, **wheelverts;
02093         PEdge *collapsededges = NULL, *e;
02094         int nwheelverts, i, ncollapsed = 0;
02095 
02096         wheelverts = MEM_mallocN(sizeof(PVert*)*chart->nverts, "PChartWheelVerts");
02097 
02098         /* insert all potential collapses into heap */
02099         for (v=chart->verts; v; v=v->nextlink) {
02100                 float cost;
02101                 PEdge *e = NULL;
02102                 
02103                 p_collapse_cost_vertex(v, &cost, &e);
02104 
02105                 if (e)
02106                         v->u.heaplink = BLI_heap_insert(heap, cost, e);
02107                 else
02108                         v->u.heaplink = NULL;
02109         }
02110 
02111         for (e=chart->edges; e; e=e->nextlink)
02112                 e->u.nextcollapse = NULL;
02113 
02114         /* pop edge collapse out of heap one by one */
02115         while (!BLI_heap_empty(heap)) {
02116                 if (ncollapsed == NCOLLAPSE)
02117                         break;
02118 
02119                 HeapNode *link = BLI_heap_top(heap);
02120                 PEdge *edge = (PEdge*)BLI_heap_popmin(heap), *pair = edge->pair;
02121                 PVert *oldv, *keepv;
02122                 PEdge *wheele, *nexte;
02123 
02124                 /* remember the edges we collapsed */
02125                 edge->u.nextcollapse = collapsededges;
02126                 collapsededges = edge;
02127 
02128                 if (edge->vert->u.heaplink != link) {
02129                         edge->flag |= (PEDGE_COLLAPSE_EDGE|PEDGE_COLLAPSE_PAIR);
02130                         edge->next->vert->u.heaplink = NULL;
02131                         SWAP(PEdge*, edge, pair);
02132                 }
02133                 else {
02134                         edge->flag |= PEDGE_COLLAPSE_EDGE;
02135                         edge->vert->u.heaplink = NULL;
02136                 }
02137 
02138                 p_collapsing_verts(edge, pair, &oldv, &keepv);
02139 
02140                 /* gather all wheel verts and remember them before collapse */
02141                 nwheelverts = 0;
02142                 wheele = oldv->edge;
02143 
02144                 do {
02145                         wheelverts[nwheelverts++] = wheele->next->vert;
02146                         nexte = p_wheel_edge_next(wheele);
02147 
02148                         if (nexte == NULL)
02149                                 wheelverts[nwheelverts++] = wheele->next->next->vert;
02150 
02151                         wheele = nexte;
02152                 } while (wheele && (wheele != oldv->edge));
02153 
02154                 /* collapse */
02155                 p_collapse_edge(edge, pair);
02156 
02157                 for (i = 0; i < nwheelverts; i++) {
02158                         float cost;
02159                         PEdge *collapse = NULL;
02160 
02161                         v = wheelverts[i];
02162 
02163                         if (v->u.heaplink) {
02164                                 BLI_heap_remove(heap, v->u.heaplink);
02165                                 v->u.heaplink = NULL;
02166                         }
02167                 
02168                         p_collapse_cost_vertex(v, &cost, &collapse);
02169 
02170                         if (collapse)
02171                                 v->u.heaplink = BLI_heap_insert(heap, cost, collapse);
02172                 }
02173 
02174                 ncollapsed++;
02175         }
02176 
02177         MEM_freeN(wheelverts);
02178         BLI_heap_free(heap, NULL);
02179 
02180         p_chart_post_collapse_flush(chart, collapsededges);
02181 }
02182 
02183 static void p_chart_complexify(PChart *chart)
02184 {
02185         PEdge *e, *pair, *edge;
02186         PVert *newv, *keepv;
02187         int x = 0;
02188 
02189         for (e=chart->collapsed_edges; e; e=e->nextlink) {
02190                 if (!(e->flag & PEDGE_COLLAPSE_EDGE))
02191                         break;
02192 
02193                 edge = e;
02194                 pair = e->pair;
02195 
02196                 if (edge->flag & PEDGE_COLLAPSE_PAIR) {
02197                         SWAP(PEdge*, edge, pair);
02198                 }
02199 
02200                 p_split_vertex(edge, pair);
02201                 p_collapsing_verts(edge, pair, &newv, &keepv);
02202 
02203                 if (x >= NCOLLAPSEX) {
02204                         newv->uv[0] = keepv->uv[0];
02205                         newv->uv[1] = keepv->uv[1];
02206                 }
02207                 else {
02208                         p_vert_harmonic_insert(newv);
02209                         x++;
02210                 }
02211         }
02212 
02213         p_chart_post_split_flush(chart);
02214 }
02215 
02216 #if 0
02217 static void p_chart_simplify(PChart *chart)
02218 {
02219         /* Not implemented, needs proper reordering in split_flush. */
02220 }
02221 #endif
02222 #endif
02223 
02224 /* ABF */
02225 
02226 #define ABF_MAX_ITER 20
02227 
02228 typedef struct PAbfSystem {
02229         int ninterior, nfaces, nangles;
02230         float *alpha, *beta, *sine, *cosine, *weight;
02231         float *bAlpha, *bTriangle, *bInterior;
02232         float *lambdaTriangle, *lambdaPlanar, *lambdaLength;
02233         float (*J2dt)[3], *bstar, *dstar;
02234         float minangle, maxangle;
02235 } PAbfSystem;
02236 
02237 static void p_abf_setup_system(PAbfSystem *sys)
02238 {
02239         int i;
02240 
02241         sys->alpha = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFalpha");
02242         sys->beta = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFbeta");
02243         sys->sine = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFsine");
02244         sys->cosine = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFcosine");
02245         sys->weight = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFweight");
02246 
02247         sys->bAlpha = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFbalpha");
02248         sys->bTriangle = (float*)MEM_mallocN(sizeof(float)*sys->nfaces, "ABFbtriangle");
02249         sys->bInterior = (float*)MEM_mallocN(sizeof(float)*2*sys->ninterior, "ABFbinterior");
02250 
02251         sys->lambdaTriangle = (float*)MEM_callocN(sizeof(float)*sys->nfaces, "ABFlambdatri");
02252         sys->lambdaPlanar = (float*)MEM_callocN(sizeof(float)*sys->ninterior, "ABFlamdaplane");
02253         sys->lambdaLength = (float*)MEM_mallocN(sizeof(float)*sys->ninterior, "ABFlambdalen");
02254 
02255         sys->J2dt = MEM_mallocN(sizeof(float)*sys->nangles*3, "ABFj2dt");
02256         sys->bstar = (float*)MEM_mallocN(sizeof(float)*sys->nfaces, "ABFbstar");
02257         sys->dstar = (float*)MEM_mallocN(sizeof(float)*sys->nfaces, "ABFdstar");
02258 
02259         for (i = 0; i < sys->ninterior; i++)
02260                 sys->lambdaLength[i] = 1.0;
02261         
02262         sys->minangle = 7.5*M_PI/180.0;
02263         sys->maxangle = (float)M_PI - sys->minangle;
02264 }
02265 
02266 static void p_abf_free_system(PAbfSystem *sys)
02267 {
02268         MEM_freeN(sys->alpha);
02269         MEM_freeN(sys->beta);
02270         MEM_freeN(sys->sine);
02271         MEM_freeN(sys->cosine);
02272         MEM_freeN(sys->weight);
02273         MEM_freeN(sys->bAlpha);
02274         MEM_freeN(sys->bTriangle);
02275         MEM_freeN(sys->bInterior);
02276         MEM_freeN(sys->lambdaTriangle);
02277         MEM_freeN(sys->lambdaPlanar);
02278         MEM_freeN(sys->lambdaLength);
02279         MEM_freeN(sys->J2dt);
02280         MEM_freeN(sys->bstar);
02281         MEM_freeN(sys->dstar);
02282 }
02283 
02284 static void p_abf_compute_sines(PAbfSystem *sys)
02285 {
02286         int i;
02287         float *sine = sys->sine, *cosine = sys->cosine, *alpha = sys->alpha;
02288 
02289         for (i = 0; i < sys->nangles; i++, sine++, cosine++, alpha++) {
02290                 *sine = sin(*alpha);
02291                 *cosine = cos(*alpha);
02292         }
02293 }
02294 
02295 static float p_abf_compute_sin_product(PAbfSystem *sys, PVert *v, int aid)
02296 {
02297         PEdge *e, *e1, *e2;
02298         float sin1, sin2;
02299 
02300         sin1 = sin2 = 1.0;
02301 
02302         e = v->edge;
02303         do {
02304                 e1 = e->next;
02305                 e2 = e->next->next;
02306 
02307                 if (aid == e1->u.id) {
02308                         /* we are computing a derivative for this angle,
02309                            so we use cos and drop the other part */
02310                         sin1 *= sys->cosine[e1->u.id];
02311                         sin2 = 0.0;
02312                 }
02313                 else
02314                         sin1 *= sys->sine[e1->u.id];
02315 
02316                 if (aid == e2->u.id) {
02317                         /* see above */
02318                         sin1 = 0.0;
02319                         sin2 *= sys->cosine[e2->u.id];
02320                 }
02321                 else
02322                         sin2 *= sys->sine[e2->u.id];
02323 
02324                 e = e->next->next->pair;
02325         } while (e && (e != v->edge));
02326 
02327         return (sin1 - sin2);
02328 }
02329 
02330 static float p_abf_compute_grad_alpha(PAbfSystem *sys, PFace *f, PEdge *e)
02331 {
02332         PVert *v = e->vert, *v1 = e->next->vert, *v2 = e->next->next->vert;
02333         float deriv;
02334 
02335         deriv = (sys->alpha[e->u.id] - sys->beta[e->u.id])*sys->weight[e->u.id];
02336         deriv += sys->lambdaTriangle[f->u.id];
02337 
02338         if (v->flag & PVERT_INTERIOR) {
02339                 deriv += sys->lambdaPlanar[v->u.id];
02340         }
02341 
02342         if (v1->flag & PVERT_INTERIOR) {
02343                 float product = p_abf_compute_sin_product(sys, v1, e->u.id);
02344                 deriv += sys->lambdaLength[v1->u.id]*product;
02345         }
02346 
02347         if (v2->flag & PVERT_INTERIOR) {
02348                 float product = p_abf_compute_sin_product(sys, v2, e->u.id);
02349                 deriv += sys->lambdaLength[v2->u.id]*product;
02350         }
02351 
02352         return deriv;
02353 }
02354 
02355 static float p_abf_compute_gradient(PAbfSystem *sys, PChart *chart)
02356 {
02357         PFace *f;
02358         PEdge *e;
02359         PVert *v;
02360         float norm = 0.0;
02361 
02362         for (f=chart->faces; f; f=f->nextlink) {
02363                 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
02364                 float gtriangle, galpha1, galpha2, galpha3;
02365 
02366                 galpha1 = p_abf_compute_grad_alpha(sys, f, e1);
02367                 galpha2 = p_abf_compute_grad_alpha(sys, f, e2);
02368                 galpha3 = p_abf_compute_grad_alpha(sys, f, e3);
02369 
02370                 sys->bAlpha[e1->u.id] = -galpha1;
02371                 sys->bAlpha[e2->u.id] = -galpha2;
02372                 sys->bAlpha[e3->u.id] = -galpha3;
02373 
02374                 norm += galpha1*galpha1 + galpha2*galpha2 + galpha3*galpha3;
02375 
02376                 gtriangle = sys->alpha[e1->u.id] + sys->alpha[e2->u.id] + sys->alpha[e3->u.id] - (float)M_PI;
02377                 sys->bTriangle[f->u.id] = -gtriangle;
02378                 norm += gtriangle*gtriangle;
02379         }
02380 
02381         for (v=chart->verts; v; v=v->nextlink) {
02382                 if (v->flag & PVERT_INTERIOR) {
02383                         float gplanar = -2*M_PI, glength;
02384 
02385                         e = v->edge;
02386                         do {
02387                                 gplanar += sys->alpha[e->u.id];
02388                                 e = e->next->next->pair;
02389                         } while (e && (e != v->edge));
02390 
02391                         sys->bInterior[v->u.id] = -gplanar;
02392                         norm += gplanar*gplanar;
02393 
02394                         glength = p_abf_compute_sin_product(sys, v, -1);
02395                         sys->bInterior[sys->ninterior + v->u.id] = -glength;
02396                         norm += glength*glength;
02397                 }
02398         }
02399 
02400         return norm;
02401 }
02402 
02403 static PBool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
02404 {
02405         PFace *f;
02406         PEdge *e;
02407         int i, j, ninterior = sys->ninterior, nvar = 2*sys->ninterior;
02408         PBool success;
02409 
02410         nlNewContext();
02411         nlSolverParameteri(NL_NB_VARIABLES, nvar);
02412 
02413         nlBegin(NL_SYSTEM);
02414 
02415         nlBegin(NL_MATRIX);
02416 
02417         for (i = 0; i < nvar; i++)
02418                 nlRightHandSideAdd(0, i, sys->bInterior[i]);
02419 
02420         for (f=chart->faces; f; f=f->nextlink) {
02421                 float wi1, wi2, wi3, b, si, beta[3], j2[3][3], W[3][3];
02422                 float row1[6], row2[6], row3[6];
02423                 int vid[6];
02424                 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
02425                 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
02426 
02427                 wi1 = 1.0f/sys->weight[e1->u.id];
02428                 wi2 = 1.0f/sys->weight[e2->u.id];
02429                 wi3 = 1.0f/sys->weight[e3->u.id];
02430 
02431                 /* bstar1 = (J1*dInv*bAlpha - bTriangle) */
02432                 b = sys->bAlpha[e1->u.id]*wi1;
02433                 b += sys->bAlpha[e2->u.id]*wi2;
02434                 b += sys->bAlpha[e3->u.id]*wi3;
02435                 b -= sys->bTriangle[f->u.id];
02436 
02437                 /* si = J1*d*J1t */
02438                 si = 1.0f/(wi1 + wi2 + wi3);
02439 
02440                 /* J1t*si*bstar1 - bAlpha */
02441                 beta[0] = b*si - sys->bAlpha[e1->u.id];
02442                 beta[1] = b*si - sys->bAlpha[e2->u.id];
02443                 beta[2] = b*si - sys->bAlpha[e3->u.id];
02444 
02445                 /* use this later for computing other lambda's */
02446                 sys->bstar[f->u.id] = b;
02447                 sys->dstar[f->u.id] = si;
02448 
02449                 /* set matrix */
02450                 W[0][0] = si - sys->weight[e1->u.id]; W[0][1] = si; W[0][2] = si;
02451                 W[1][0] = si; W[1][1] = si - sys->weight[e2->u.id]; W[1][2] = si;
02452                 W[2][0] = si; W[2][1] = si; W[2][2] = si - sys->weight[e3->u.id];
02453 
02454                 vid[0] = vid[1] = vid[2] = vid[3] = vid[4] = vid[5] = -1;
02455 
02456                 if (v1->flag & PVERT_INTERIOR) {
02457                         vid[0] = v1->u.id;
02458                         vid[3] = ninterior + v1->u.id;
02459 
02460                         sys->J2dt[e1->u.id][0] = j2[0][0] = 1.0f * wi1;
02461                         sys->J2dt[e2->u.id][0] = j2[1][0] = p_abf_compute_sin_product(sys, v1, e2->u.id)*wi2;
02462                         sys->J2dt[e3->u.id][0] = j2[2][0] = p_abf_compute_sin_product(sys, v1, e3->u.id)*wi3;
02463 
02464                         nlRightHandSideAdd(0, v1->u.id, j2[0][0]*beta[0]);
02465                         nlRightHandSideAdd(0, ninterior + v1->u.id, j2[1][0]*beta[1] + j2[2][0]*beta[2]);
02466 
02467                         row1[0] = j2[0][0]*W[0][0];
02468                         row2[0] = j2[0][0]*W[1][0];
02469                         row3[0] = j2[0][0]*W[2][0];
02470 
02471                         row1[3] = j2[1][0]*W[0][1] + j2[2][0]*W[0][2];
02472                         row2[3] = j2[1][0]*W[1][1] + j2[2][0]*W[1][2];
02473                         row3[3] = j2[1][0]*W[2][1] + j2[2][0]*W[2][2];
02474                 }
02475 
02476                 if (v2->flag & PVERT_INTERIOR) {
02477                         vid[1] = v2->u.id;
02478                         vid[4] = ninterior + v2->u.id;
02479 
02480                         sys->J2dt[e1->u.id][1] = j2[0][1] = p_abf_compute_sin_product(sys, v2, e1->u.id)*wi1;
02481                         sys->J2dt[e2->u.id][1] = j2[1][1] = 1.0f*wi2;
02482                         sys->J2dt[e3->u.id][1] = j2[2][1] = p_abf_compute_sin_product(sys, v2, e3->u.id)*wi3;
02483 
02484                         nlRightHandSideAdd(0, v2->u.id, j2[1][1]*beta[1]);
02485                         nlRightHandSideAdd(0, ninterior + v2->u.id, j2[0][1]*beta[0] + j2[2][1]*beta[2]);
02486 
02487                         row1[1] = j2[1][1]*W[0][1];
02488                         row2[1] = j2[1][1]*W[1][1];
02489                         row3[1] = j2[1][1]*W[2][1];
02490 
02491                         row1[4] = j2[0][1]*W[0][0] + j2[2][1]*W[0][2];
02492                         row2[4] = j2[0][1]*W[1][0] + j2[2][1]*W[1][2];
02493                         row3[4] = j2[0][1]*W[2][0] + j2[2][1]*W[2][2];
02494                 }
02495 
02496                 if (v3->flag & PVERT_INTERIOR) {
02497                         vid[2] = v3->u.id;
02498                         vid[5] = ninterior + v3->u.id;
02499 
02500                         sys->J2dt[e1->u.id][2] = j2[0][2] = p_abf_compute_sin_product(sys, v3, e1->u.id)*wi1;
02501                         sys->J2dt[e2->u.id][2] = j2[1][2] = p_abf_compute_sin_product(sys, v3, e2->u.id)*wi2;
02502                         sys->J2dt[e3->u.id][2] = j2[2][2] = 1.0f * wi3;
02503 
02504                         nlRightHandSideAdd(0, v3->u.id, j2[2][2]*beta[2]);
02505                         nlRightHandSideAdd(0, ninterior + v3->u.id, j2[0][2]*beta[0] + j2[1][2]*beta[1]);
02506 
02507                         row1[2] = j2[2][2]*W[0][2];
02508                         row2[2] = j2[2][2]*W[1][2];
02509                         row3[2] = j2[2][2]*W[2][2];
02510 
02511                         row1[5] = j2[0][2]*W[0][0] + j2[1][2]*W[0][1];
02512                         row2[5] = j2[0][2]*W[1][0] + j2[1][2]*W[1][1];
02513                         row3[5] = j2[0][2]*W[2][0] + j2[1][2]*W[2][1];
02514                 }
02515 
02516                 for (i = 0; i < 3; i++) {
02517                         int r = vid[i];
02518 
02519                         if (r == -1)
02520                                 continue;
02521 
02522                         for (j = 0; j < 6; j++) {
02523                                 int c = vid[j];
02524 
02525                                 if (c == -1)
02526                                         continue;
02527 
02528                                 if (i == 0)
02529                                         nlMatrixAdd(r, c, j2[0][i]*row1[j]);
02530                                 else
02531                                         nlMatrixAdd(r + ninterior, c, j2[0][i]*row1[j]);
02532 
02533                                 if (i == 1)
02534                                         nlMatrixAdd(r, c, j2[1][i]*row2[j]);
02535                                 else
02536                                         nlMatrixAdd(r + ninterior, c, j2[1][i]*row2[j]);
02537 
02538 
02539                                 if (i == 2)
02540                                         nlMatrixAdd(r, c, j2[2][i]*row3[j]);
02541                                 else
02542                                         nlMatrixAdd(r + ninterior, c, j2[2][i]*row3[j]);
02543                         }
02544                 }
02545         }
02546 
02547         nlEnd(NL_MATRIX);
02548 
02549         nlEnd(NL_SYSTEM);
02550 
02551         success = nlSolve();
02552 
02553         if (success) {
02554                 for (f=chart->faces; f; f=f->nextlink) {
02555                         float dlambda1, pre[3], dalpha;
02556                         PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
02557                         PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
02558 
02559                         pre[0] = pre[1] = pre[2] = 0.0;
02560 
02561                         if (v1->flag & PVERT_INTERIOR) {
02562                                 float x = nlGetVariable(0, v1->u.id);
02563                                 float x2 = nlGetVariable(0, ninterior + v1->u.id);
02564                                 pre[0] += sys->J2dt[e1->u.id][0]*x;
02565                                 pre[1] += sys->J2dt[e2->u.id][0]*x2;
02566                                 pre[2] += sys->J2dt[e3->u.id][0]*x2;
02567                         }
02568 
02569                         if (v2->flag & PVERT_INTERIOR) {
02570                                 float x = nlGetVariable(0, v2->u.id);
02571                                 float x2 = nlGetVariable(0, ninterior + v2->u.id);
02572                                 pre[0] += sys->J2dt[e1->u.id][1]*x2;
02573                                 pre[1] += sys->J2dt[e2->u.id][1]*x;
02574                                 pre[2] += sys->J2dt[e3->u.id][1]*x2;
02575                         }
02576 
02577                         if (v3->flag & PVERT_INTERIOR) {
02578                                 float x = nlGetVariable(0, v3->u.id);
02579                                 float x2 = nlGetVariable(0, ninterior + v3->u.id);
02580                                 pre[0] += sys->J2dt[e1->u.id][2]*x2;
02581                                 pre[1] += sys->J2dt[e2->u.id][2]*x2;
02582                                 pre[2] += sys->J2dt[e3->u.id][2]*x;
02583                         }
02584 
02585                         dlambda1 = pre[0] + pre[1] + pre[2];
02586                         dlambda1 = sys->dstar[f->u.id]*(sys->bstar[f->u.id] - dlambda1);
02587                         
02588                         sys->lambdaTriangle[f->u.id] += dlambda1;
02589 
02590                         dalpha = (sys->bAlpha[e1->u.id] - dlambda1);
02591                         sys->alpha[e1->u.id] += dalpha/sys->weight[e1->u.id] - pre[0];
02592 
02593                         dalpha = (sys->bAlpha[e2->u.id] - dlambda1);
02594                         sys->alpha[e2->u.id] += dalpha/sys->weight[e2->u.id] - pre[1];
02595 
02596                         dalpha = (sys->bAlpha[e3->u.id] - dlambda1);
02597                         sys->alpha[e3->u.id] += dalpha/sys->weight[e3->u.id] - pre[2];
02598 
02599                         /* clamp */
02600                         e = f->edge;
02601                         do {
02602                                 if (sys->alpha[e->u.id] > (float)M_PI)
02603                                         sys->alpha[e->u.id] = (float)M_PI;
02604                                 else if (sys->alpha[e->u.id] < 0.0f)
02605                                         sys->alpha[e->u.id] = 0.0f;
02606                         } while (e != f->edge);
02607                 }
02608 
02609                 for (i = 0; i < ninterior; i++) {
02610                         sys->lambdaPlanar[i] += nlGetVariable(0, i);
02611                         sys->lambdaLength[i] += nlGetVariable(0, ninterior + i);
02612                 }
02613         }
02614 
02615         nlDeleteContext(nlGetCurrent());
02616 
02617         return success;
02618 }
02619 
02620 static PBool p_chart_abf_solve(PChart *chart)
02621 {
02622         PVert *v;
02623         PFace *f;
02624         PEdge *e, *e1, *e2, *e3;
02625         PAbfSystem sys;
02626         int i;
02627         float lastnorm, limit = (chart->nfaces > 100)? 1.0f: 0.001f;
02628 
02629         /* setup id's */
02630         sys.ninterior = sys.nfaces = sys.nangles = 0;
02631 
02632         for (v=chart->verts; v; v=v->nextlink) {
02633                 if (p_vert_interior(v)) {
02634                         v->flag |= PVERT_INTERIOR;
02635                         v->u.id = sys.ninterior++;
02636                 }
02637                 else
02638                         v->flag &= ~PVERT_INTERIOR;
02639         }
02640 
02641         for (f=chart->faces; f; f=f->nextlink) {
02642                 e1 = f->edge; e2 = e1->next; e3 = e2->next;
02643                 f->u.id = sys.nfaces++;
02644 
02645                 /* angle id's are conveniently stored in half edges */
02646                 e1->u.id = sys.nangles++;
02647                 e2->u.id = sys.nangles++;
02648                 e3->u.id = sys.nangles++;
02649         }
02650 
02651         p_abf_setup_system(&sys);
02652 
02653         /* compute initial angles */
02654         for (f=chart->faces; f; f=f->nextlink) {
02655                 float a1, a2, a3;
02656 
02657                 e1 = f->edge; e2 = e1->next; e3 = e2->next;
02658                 p_face_angles(f, &a1, &a2, &a3);
02659 
02660                 if (a1 < sys.minangle)
02661                         a1 = sys.minangle;
02662                 else if (a1 > sys.maxangle)
02663                         a1 = sys.maxangle;
02664                 if (a2 < sys.minangle)
02665                         a2 = sys.minangle;
02666                 else if (a2 > sys.maxangle)
02667                         a2 = sys.maxangle;
02668                 if (a3 < sys.minangle)
02669                         a3 = sys.minangle;
02670                 else if (a3 > sys.maxangle)
02671                         a3 = sys.maxangle;
02672 
02673                 sys.alpha[e1->u.id] = sys.beta[e1->u.id] = a1;
02674                 sys.alpha[e2->u.id] = sys.beta[e2->u.id] = a2;
02675                 sys.alpha[e3->u.id] = sys.beta[e3->u.id] = a3;
02676 
02677                 sys.weight[e1->u.id] = 2.0f/(a1*a1);
02678                 sys.weight[e2->u.id] = 2.0f/(a2*a2);
02679                 sys.weight[e3->u.id] = 2.0f/(a3*a3);
02680         }
02681 
02682         for (v=chart->verts; v; v=v->nextlink) {
02683                 if (v->flag & PVERT_INTERIOR) {
02684                         float anglesum = 0.0, scale;
02685 
02686                         e = v->edge;
02687                         do {
02688                                 anglesum += sys.beta[e->u.id];
02689                                 e = e->next->next->pair;
02690                         } while (e && (e != v->edge));
02691 
02692                         scale = (anglesum == 0.0f)? 0.0f: 2.0f*(float)M_PI/anglesum;
02693 
02694                         e = v->edge;
02695                         do {
02696                                 sys.beta[e->u.id] = sys.alpha[e->u.id] = sys.beta[e->u.id]*scale;
02697                                 e = e->next->next->pair;
02698                         } while (e && (e != v->edge));
02699                 }
02700         }
02701 
02702         if (sys.ninterior > 0) {
02703                 p_abf_compute_sines(&sys);
02704 
02705                 /* iteration */
02706                 lastnorm = 1e10;
02707 
02708                 for (i = 0; i < ABF_MAX_ITER; i++) {
02709                         float norm = p_abf_compute_gradient(&sys, chart);
02710 
02711                         lastnorm = norm;
02712 
02713                         if (norm < limit)
02714                                 break;
02715 
02716                         if (!p_abf_matrix_invert(&sys, chart)) {
02717                                 param_warning("ABF failed to invert matrix.");
02718                                 p_abf_free_system(&sys);
02719                                 return P_FALSE;
02720                         }
02721 
02722                         p_abf_compute_sines(&sys);
02723                 }
02724 
02725                 if (i == ABF_MAX_ITER) {
02726                         param_warning("ABF maximum iterations reached.");
02727                         p_abf_free_system(&sys);
02728                         return P_FALSE;
02729                 }
02730         }
02731 
02732         chart->u.lscm.abf_alpha = MEM_dupallocN(sys.alpha);
02733         p_abf_free_system(&sys);
02734 
02735         return P_TRUE;
02736 }
02737 
02738 /* Least Squares Conformal Maps */
02739 
02740 static void p_chart_pin_positions(PChart *chart, PVert **pin1, PVert **pin2)
02741 {
02742         if (pin1 == pin2) {
02743                 /* degenerate case */
02744                 PFace *f = chart->faces;
02745                 *pin1 = f->edge->vert;
02746                 *pin2 = f->edge->next->vert;
02747 
02748                 (*pin1)->uv[0] = 0.0f;
02749                 (*pin1)->uv[1] = 0.5f;
02750                 (*pin2)->uv[0] = 1.0f;
02751                 (*pin2)->uv[1] = 0.5f;
02752         }
02753         else {
02754                 int diru, dirv, dirx, diry;
02755                 float sub[3];
02756 
02757                 sub_v3_v3v3(sub, (*pin1)->co, (*pin2)->co);
02758                 sub[0] = fabs(sub[0]);
02759                 sub[1] = fabs(sub[1]);
02760                 sub[2] = fabs(sub[2]);
02761 
02762                 if ((sub[0] > sub[1]) && (sub[0] > sub[2])) {
02763                         dirx = 0;
02764                         diry = (sub[1] > sub[2])? 1: 2;
02765                 }
02766                 else if ((sub[1] > sub[0]) && (sub[1] > sub[2])) {
02767                         dirx = 1;
02768                         diry = (sub[0] > sub[2])? 0: 2;
02769                 }
02770                 else {
02771                         dirx = 2;
02772                         diry = (sub[0] > sub[1])? 0: 1;
02773                 }
02774 
02775                 if (dirx == 2) {
02776                         diru = 1;
02777                         dirv = 0;
02778                 }
02779                 else {
02780                         diru = 0;
02781                         dirv = 1;
02782                 }
02783 
02784                 (*pin1)->uv[diru] = (*pin1)->co[dirx];
02785                 (*pin1)->uv[dirv] = (*pin1)->co[diry];
02786                 (*pin2)->uv[diru] = (*pin2)->co[dirx];
02787                 (*pin2)->uv[dirv] = (*pin2)->co[diry];
02788         }
02789 }
02790 
02791 static PBool p_chart_symmetry_pins(PChart *chart, PEdge *outer, PVert **pin1, PVert **pin2)
02792 {
02793         PEdge *be, *lastbe = NULL, *maxe1 = NULL, *maxe2 = NULL, *be1, *be2;
02794         PEdge *cure = NULL, *firste1 = NULL, *firste2 = NULL, *nextbe;
02795         float maxlen = 0.0f, curlen = 0.0f, totlen = 0.0f, firstlen = 0.0f;
02796         float len1, len2;
02797  
02798          /* find longest series of verts split in the chart itself, these are
02799            marked during construction */
02800         be = outer;
02801         lastbe = p_boundary_edge_prev(be);
02802         do {
02803                 float len = p_edge_length(be);
02804                 totlen += len;
02805 
02806                 nextbe = p_boundary_edge_next(be);
02807 
02808                 if ((be->vert->flag & PVERT_SPLIT) ||
02809                         (lastbe->vert->flag & nextbe->vert->flag & PVERT_SPLIT)) {
02810                         if (!cure) {
02811                                 if (be == outer)
02812                                         firste1 = be;
02813                                 cure = be;
02814                         }
02815                         else
02816                                 curlen += p_edge_length(lastbe);
02817                 }
02818                 else if (cure) {
02819                         if (curlen > maxlen) {
02820                                 maxlen = curlen;
02821                                 maxe1 = cure;
02822                                 maxe2 = lastbe;
02823                         }
02824 
02825                         if (firste1 == cure) {
02826                                 firstlen = curlen;
02827                                 firste2 = lastbe;
02828                         }
02829 
02830                         curlen = 0.0f;
02831                         cure = NULL;
02832                 }
02833 
02834                 lastbe = be;
02835                 be = nextbe;
02836         } while(be != outer);
02837 
02838         /* make sure we also count a series of splits over the starting point */
02839         if (cure && (cure != outer)) {
02840                 firstlen += curlen + p_edge_length(be);
02841 
02842                 if (firstlen > maxlen) {
02843                         maxlen = firstlen;
02844                         maxe1 = cure;
02845                         maxe2 = firste2;
02846                 }
02847         }
02848 
02849         if (!maxe1 || !maxe2 || (maxlen < 0.5f*totlen))
02850                 return P_FALSE;
02851         
02852         /* find pin1 in the split vertices */
02853         be1 = maxe1;
02854         be2 = maxe2;
02855         len1 = 0.0f;
02856         len2 = 0.0f;
02857 
02858         do {
02859                 if (len1 < len2) {
02860                         len1 += p_edge_length(be1);
02861                         be1 = p_boundary_edge_next(be1);
02862                 }
02863                 else {
02864                         be2 = p_boundary_edge_prev(be2);
02865                         len2 += p_edge_length(be2);
02866                 }
02867         } while (be1 != be2);
02868 
02869         *pin1 = be1->vert;
02870 
02871         /* find pin2 outside the split vertices */
02872         be1 = maxe1;
02873         be2 = maxe2;
02874         len1 = 0.0f;
02875         len2 = 0.0f;
02876 
02877         do {
02878                 if (len1 < len2) {
02879                         be1 = p_boundary_edge_prev(be1);
02880                         len1 += p_edge_length(be1);
02881                 }
02882                 else {
02883                         len2 += p_edge_length(be2);
02884                         be2 = p_boundary_edge_next(be2);
02885                 }
02886         } while (be1 != be2);
02887 
02888         *pin2 = be1->vert;
02889 
02890         p_chart_pin_positions(chart, pin1, pin2);
02891 
02892         return P_TRUE;
02893 }
02894 
02895 static void p_chart_extrema_verts(PChart *chart, PVert **pin1, PVert **pin2)
02896 {
02897         float minv[3], maxv[3], dirlen;
02898         PVert *v, *minvert[3], *maxvert[3];
02899         int i, dir;
02900 
02901         /* find minimum and maximum verts over x/y/z axes */
02902         minv[0] = minv[1] = minv[2] = 1e20;
02903         maxv[0] = maxv[1] = maxv[2] = -1e20;
02904 
02905         minvert[0] = minvert[1] = minvert[2] = NULL;
02906         maxvert[0] = maxvert[1] = maxvert[2] = NULL;
02907 
02908         for (v = chart->verts; v; v=v->nextlink) {
02909                 for (i = 0; i < 3; i++) {
02910                         if (v->co[i] < minv[i]) {
02911                                 minv[i] = v->co[i];
02912                                 minvert[i] = v;
02913                         }
02914                         if (v->co[i] > maxv[i]) {
02915                                 maxv[i] = v->co[i];
02916                                 maxvert[i] = v;
02917                         }
02918                 }
02919         }
02920 
02921         /* find axes with longest distance */
02922         dir = 0;
02923         dirlen = -1.0;
02924 
02925         for (i = 0; i < 3; i++) {
02926                 if (maxv[i] - minv[i] > dirlen) {
02927                         dir = i;
02928                         dirlen = maxv[i] - minv[i];
02929                 }
02930         }
02931 
02932         *pin1 = minvert[dir];
02933         *pin2 = maxvert[dir];
02934 
02935         p_chart_pin_positions(chart, pin1, pin2);
02936 }
02937 
02938 static void p_chart_lscm_load_solution(PChart *chart)
02939 {
02940         PVert *v;
02941 
02942         for (v=chart->verts; v; v=v->nextlink) {
02943                 v->uv[0] = nlGetVariable(0, 2*v->u.id);
02944                 v->uv[1] = nlGetVariable(0, 2*v->u.id + 1);
02945         }
02946 }
02947 
02948 static void p_chart_lscm_begin(PChart *chart, PBool live, PBool abf)
02949 {
02950         PVert *v, *pin1, *pin2;
02951         PBool select = P_FALSE, deselect = P_FALSE;
02952         int npins = 0, id = 0;
02953 
02954         /* give vertices matrix indices and count pins */
02955         for (v=chart->verts; v; v=v->nextlink) {
02956                 if (v->flag & PVERT_PIN) {
02957                         npins++;
02958                         if (v->flag & PVERT_SELECT)
02959                                 select = P_TRUE;
02960                 }
02961 
02962                 if (!(v->flag & PVERT_SELECT))
02963                         deselect = P_TRUE;
02964         }
02965 
02966         if ((live && (!select || !deselect)) || (npins == 1)) {
02967                 chart->u.lscm.context = NULL;
02968         }
02969         else {
02970 #if 0
02971                 p_chart_simplify_compute(chart);
02972                 p_chart_topological_sanity_check(chart);
02973 #endif
02974 
02975                 if (abf) {
02976                         if (!p_chart_abf_solve(chart))
02977                                 param_warning("ABF solving failed: falling back to LSCM.\n");
02978                 }
02979 
02980                 if (npins <= 1) {
02981                         /* not enough pins, lets find some ourself */
02982                         PEdge *outer;
02983 
02984                         p_chart_boundaries(chart, NULL, &outer);
02985 
02986                         if (!p_chart_symmetry_pins(chart, outer, &pin1, &pin2))
02987                                 p_chart_extrema_verts(chart, &pin1, &pin2);
02988 
02989                         chart->u.lscm.pin1 = pin1;
02990                         chart->u.lscm.pin2 = pin2;
02991                 }
02992                 else {
02993                         chart->flag |= PCHART_NOPACK;
02994                 }
02995 
02996                 for (v=chart->verts; v; v=v->nextlink)
02997                         v->u.id = id++;
02998 
02999                 nlNewContext();
03000                 nlSolverParameteri(NL_NB_VARIABLES, 2*chart->nverts);
03001                 nlSolverParameteri(NL_NB_ROWS, 2*chart->nfaces);
03002                 nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
03003 
03004                 chart->u.lscm.context = nlGetCurrent();
03005         }
03006 }
03007 
03008 static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
03009 {
03010         PVert *v, *pin1 = chart->u.lscm.pin1, *pin2 = chart->u.lscm.pin2;
03011         PFace *f;
03012         float *alpha = chart->u.lscm.abf_alpha;
03013         int row;
03014 
03015         nlMakeCurrent(chart->u.lscm.context);
03016 
03017         nlBegin(NL_SYSTEM);
03018 
03019 #if 0
03020         /* TODO: make loading pins work for simplify/complexify. */
03021 #endif
03022 
03023         for (v=chart->verts; v; v=v->nextlink)
03024                 if (v->flag & PVERT_PIN)
03025                         p_vert_load_pin_select_uvs(handle, v); /* reload for live */
03026 
03027         if (chart->u.lscm.pin1) {
03028                 nlLockVariable(2*pin1->u.id);
03029                 nlLockVariable(2*pin1->u.id + 1);
03030                 nlLockVariable(2*pin2->u.id);
03031                 nlLockVariable(2*pin2->u.id + 1);
03032         
03033                 nlSetVariable(0, 2*pin1->u.id, pin1->uv[0]);
03034                 nlSetVariable(0, 2*pin1->u.id + 1, pin1->uv[1]);
03035                 nlSetVariable(0, 2*pin2->u.id, pin2->uv[0]);
03036                 nlSetVariable(0, 2*pin2->u.id + 1, pin2->uv[1]);
03037         }
03038         else {
03039                 /* set and lock the pins */
03040                 for (v=chart->verts; v; v=v->nextlink) {
03041                         if (v->flag & PVERT_PIN) {
03042                                 nlLockVariable(2*v->u.id);
03043                                 nlLockVariable(2*v->u.id + 1);
03044 
03045                                 nlSetVariable(0, 2*v->u.id, v->uv[0]);
03046                                 nlSetVariable(0, 2*v->u.id + 1, v->uv[1]);
03047                         }
03048                 }
03049         }
03050 
03051         /* construct matrix */
03052 
03053         nlBegin(NL_MATRIX);
03054 
03055         row = 0;
03056         for (f=chart->faces; f; f=f->nextlink) {
03057                 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
03058                 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
03059                 float a1, a2, a3, ratio, cosine, sine;
03060                 float sina1, sina2, sina3, sinmax;
03061 
03062                 if (alpha) {
03063                         /* use abf angles if passed on */
03064                         a1 = *(alpha++);
03065                         a2 = *(alpha++);
03066                         a3 = *(alpha++);
03067                 }
03068                 else
03069                         p_face_angles(f, &a1, &a2, &a3);
03070 
03071                 sina1 = sin(a1);
03072                 sina2 = sin(a2);
03073                 sina3 = sin(a3);
03074 
03075                 sinmax = MAX3(sina1, sina2, sina3);
03076 
03077                 /* shift vertices to find most stable order */
03078                 if (sina3 != sinmax) {
03079                         SHIFT3(PVert*, v1, v2, v3);
03080                         SHIFT3(float, a1, a2, a3);
03081                         SHIFT3(float, sina1, sina2, sina3);
03082 
03083                         if (sina2 == sinmax) {
03084                                 SHIFT3(PVert*, v1, v2, v3);
03085                                 SHIFT3(float, a1, a2, a3);
03086                                 SHIFT3(float, sina1, sina2, sina3);
03087                         }
03088                 }
03089 
03090                 /* angle based lscm formulation */
03091                 ratio = (sina3 == 0.0f)? 1.0f: sina2/sina3;
03092                 cosine = cosf(a1)*ratio;
03093                 sine = sina1*ratio;
03094 
03095 #if 0
03096                 nlBegin(NL_ROW);
03097                 nlCoefficient(2*v1->u.id,   cosine - 1.0);
03098                 nlCoefficient(2*v1->u.id+1, -sine);
03099                 nlCoefficient(2*v2->u.id,   -cosine);
03100                 nlCoefficient(2*v2->u.id+1, sine);
03101                 nlCoefficient(2*v3->u.id,   1.0);
03102                 nlEnd(NL_ROW);
03103 
03104                 nlBegin(NL_ROW);
03105                 nlCoefficient(2*v1->u.id,   sine);
03106                 nlCoefficient(2*v1->u.id+1, cosine - 1.0);
03107                 nlCoefficient(2*v2->u.id,   -sine);
03108                 nlCoefficient(2*v2->u.id+1, -cosine);
03109                 nlCoefficient(2*v3->u.id+1, 1.0);
03110                 nlEnd(NL_ROW);
03111 #else
03112                 nlMatrixAdd(row, 2*v1->u.id,   cosine - 1.0f);
03113                 nlMatrixAdd(row, 2*v1->u.id+1, -sine);
03114                 nlMatrixAdd(row, 2*v2->u.id,   -cosine);
03115                 nlMatrixAdd(row, 2*v2->u.id+1, sine);
03116                 nlMatrixAdd(row, 2*v3->u.id,   1.0);
03117                 row++;
03118 
03119                 nlMatrixAdd(row, 2*v1->u.id,   sine);
03120                 nlMatrixAdd(row, 2*v1->u.id+1, cosine - 1.0f);
03121                 nlMatrixAdd(row, 2*v2->u.id,   -sine);
03122                 nlMatrixAdd(row, 2*v2->u.id+1, -cosine);
03123                 nlMatrixAdd(row, 2*v3->u.id+1, 1.0);
03124                 row++;
03125 #endif
03126         }
03127 
03128         nlEnd(NL_MATRIX);
03129 
03130         nlEnd(NL_SYSTEM);
03131 
03132         if (nlSolveAdvanced(NULL, NL_TRUE)) {
03133                 p_chart_lscm_load_solution(chart);
03134                 return P_TRUE;
03135         }
03136         else {
03137                 for (v=chart->verts; v; v=v->nextlink) {
03138                         v->uv[0] = 0.0f;
03139                         v->uv[1] = 0.0f;
03140                 }
03141         }
03142 
03143         return P_FALSE;
03144 }
03145 
03146 static void p_chart_lscm_end(PChart *chart)
03147 {
03148         if (chart->u.lscm.context)
03149                 nlDeleteContext(chart->u.lscm.context);
03150         
03151         if (chart->u.lscm.abf_alpha) {
03152                 MEM_freeN(chart->u.lscm.abf_alpha);
03153                 chart->u.lscm.abf_alpha = NULL;
03154         }
03155 
03156         chart->u.lscm.context = NULL;
03157         chart->u.lscm.pin1 = NULL;
03158         chart->u.lscm.pin2 = NULL;
03159 }
03160 
03161 /* Stretch */
03162 
03163 #define P_STRETCH_ITER 20
03164 
03165 static void p_stretch_pin_boundary(PChart *chart)
03166 {
03167         PVert *v;
03168 
03169         for(v=chart->verts; v; v=v->nextlink)
03170                 if (v->edge->pair == NULL)
03171                         v->flag |= PVERT_PIN;
03172                 else
03173                         v->flag &= ~PVERT_PIN;
03174 }
03175 
03176 static float p_face_stretch(PFace *f)
03177 {
03178         float T, w, tmp[3];
03179         float Ps[3], Pt[3];
03180         float a, c, area;
03181         PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
03182         PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
03183 
03184         area = p_face_uv_area_signed(f);
03185 
03186         if (area <= 0.0f) /* flipped face -> infinite stretch */
03187                 return 1e10f;
03188         
03189         w= 1.0f/(2.0f*area);
03190 
03191         /* compute derivatives */
03192         copy_v3_v3(Ps, v1->co);
03193         mul_v3_fl(Ps, (v2->uv[1] - v3->uv[1]));
03194 
03195         copy_v3_v3(tmp, v2->co);
03196         mul_v3_fl(tmp, (v3->uv[1] - v1->uv[1]));
03197         add_v3_v3(Ps, tmp);
03198 
03199         copy_v3_v3(tmp, v3->co);
03200         mul_v3_fl(tmp, (v1->uv[1] - v2->uv[1]));
03201         add_v3_v3(Ps, tmp);
03202 
03203         mul_v3_fl(Ps, w);
03204 
03205         copy_v3_v3(Pt, v1->co);
03206         mul_v3_fl(Pt, (v3->uv[0] - v2->uv[0]));
03207 
03208         copy_v3_v3(tmp, v2->co);
03209         mul_v3_fl(tmp, (v1->uv[0] - v3->uv[0]));
03210         add_v3_v3(Pt, tmp);
03211 
03212         copy_v3_v3(tmp, v3->co);
03213         mul_v3_fl(tmp, (v2->uv[0] - v1->uv[0]));
03214         add_v3_v3(Pt, tmp);
03215 
03216         mul_v3_fl(Pt, w);
03217 
03218         /* Sander Tensor */
03219         a= dot_v3v3(Ps, Ps);
03220         c= dot_v3v3(Pt, Pt);
03221 
03222         T =  sqrt(0.5f*(a + c));
03223         if (f->flag & PFACE_FILLED)
03224                 T *= 0.2f;
03225 
03226         return T;
03227 }
03228 
03229 static float p_stretch_compute_vertex(PVert *v)
03230 {
03231         PEdge *e = v->edge;
03232         float sum = 0.0f;
03233 
03234         do {
03235                 sum += p_face_stretch(e->face);
03236                 e = p_wheel_edge_next(e);
03237         } while (e && e != (v->edge));
03238 
03239         return sum;
03240 }
03241 
03242 static void p_chart_stretch_minimize(PChart *chart, RNG *rng)
03243 {
03244         PVert *v;
03245         PEdge *e;
03246         int j, nedges;
03247         float orig_stretch, low, stretch_low, high, stretch_high, mid, stretch;
03248         float orig_uv[2], dir[2], random_angle, trusted_radius;
03249 
03250         for(v=chart->verts; v; v=v->nextlink) {
03251                 if((v->flag & PVERT_PIN) || !(v->flag & PVERT_SELECT))
03252                         continue;
03253 
03254                 orig_stretch = p_stretch_compute_vertex(v);
03255                 orig_uv[0] = v->uv[0];
03256                 orig_uv[1] = v->uv[1];
03257 
03258                 /* move vertex in a random direction */
03259                 trusted_radius = 0.0f;
03260                 nedges = 0;
03261                 e = v->edge;
03262 
03263                 do {
03264                         trusted_radius += p_edge_uv_length(e);
03265                         nedges++;
03266 
03267                         e = p_wheel_edge_next(e);
03268                 } while (e && e != (v->edge));
03269 
03270                 trusted_radius /= 2 * nedges;
03271 
03272                 random_angle = rng_getFloat(rng) * 2.0f * (float)M_PI;
03273                 dir[0] = trusted_radius * cosf(random_angle);
03274                 dir[1] = trusted_radius * sinf(random_angle);
03275 
03276                 /* calculate old and new stretch */
03277                 low = 0;
03278                 stretch_low = orig_stretch;
03279 
03280                 add_v2_v2v2(v->uv, orig_uv, dir);
03281                 high = 1;
03282                 stretch = stretch_high = p_stretch_compute_vertex(v);
03283 
03284                 /* binary search for lowest stretch position */
03285                 for (j = 0; j < P_STRETCH_ITER; j++) {
03286                         mid = 0.5f * (low + high);
03287                         v->uv[0]= orig_uv[0] + mid*dir[0];
03288                         v->uv[1]= orig_uv[1] + mid*dir[1];
03289                         stretch = p_stretch_compute_vertex(v);
03290 
03291                         if (stretch_low < stretch_high) {
03292                                 high = mid;
03293                                 stretch_high = stretch;
03294                         }
03295                         else {
03296                                 low = mid;
03297                                 stretch_low = stretch;
03298                         }
03299                 }
03300 
03301                 /* no luck, stretch has increased, reset to old values */
03302                 if(stretch >= orig_stretch)
03303                         copy_v2_v2(v->uv, orig_uv);
03304         }
03305 }
03306 
03307 /* Minimum area enclosing rectangle for packing */
03308 
03309 static int p_compare_geometric_uv(const void *a, const void *b)
03310 {
03311         PVert *v1 = *(PVert**)a;
03312         PVert *v2 = *(PVert**)b;
03313 
03314         if (v1->uv[0] < v2->uv[0])
03315                 return -1;
03316         else if (v1->uv[0] == v2->uv[0]) {
03317                 if (v1->uv[1] < v2->uv[1])
03318                         return -1;
03319                 else if (v1->uv[1] == v2->uv[1])
03320                         return 0;
03321                 else
03322                         return 1;
03323         }
03324         else
03325                 return 1;
03326 }
03327 
03328 static PBool p_chart_convex_hull(PChart *chart, PVert ***verts, int *nverts, int *right)
03329 {
03330         /* Graham algorithm, taken from:
03331          * http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/117225 */
03332 
03333         PEdge *be, *e;
03334         int npoints = 0, i, ulen, llen;
03335         PVert **U, **L, **points, **p;
03336 
03337         p_chart_boundaries(chart, NULL, &be);
03338 
03339         if (!be)
03340                 return P_FALSE;
03341 
03342         e = be;
03343         do {
03344                 npoints++;
03345                 e = p_boundary_edge_next(e);
03346         } while(e != be);
03347 
03348         p = points = (PVert**)MEM_mallocN(sizeof(PVert*)*npoints*2, "PCHullpoints");
03349         U = (PVert**)MEM_mallocN(sizeof(PVert*)*npoints, "PCHullU");
03350         L = (PVert**)MEM_mallocN(sizeof(PVert*)*npoints, "PCHullL");
03351 
03352         e = be;
03353         do {
03354                 *p = e->vert;
03355                 p++;
03356                 e = p_boundary_edge_next(e);
03357         } while(e != be);
03358 
03359         qsort(points, npoints, sizeof(PVert*), p_compare_geometric_uv);
03360 
03361         ulen = llen = 0;
03362         for (p=points, i = 0; i < npoints; i++, p++) {
03363                 while ((ulen > 1) && (p_area_signed(U[ulen-2]->uv, (*p)->uv, U[ulen-1]->uv) <= 0))
03364                         ulen--;
03365                 while ((llen > 1) && (p_area_signed(L[llen-2]->uv, (*p)->uv, L[llen-1]->uv) >= 0))
03366                         llen--;
03367 
03368                 U[ulen] = *p;
03369                 ulen++;
03370                 L[llen] = *p;
03371                 llen++;
03372         }
03373 
03374         npoints = 0;
03375         for (p=points, i = 0; i < ulen; i++, p++, npoints++)
03376                 *p = U[i];
03377 
03378         /* the first and last point in L are left out, since they are also in U */
03379         for (i = llen-2; i > 0; i--, p++, npoints++)
03380                 *p = L[i];
03381 
03382         *verts = points;
03383         *nverts = npoints;
03384         *right = ulen - 1;
03385 
03386         MEM_freeN(U);
03387         MEM_freeN(L);
03388 
03389         return P_TRUE;
03390 }
03391 
03392 static float p_rectangle_area(float *p1, float *dir, float *p2, float *p3, float *p4)
03393 {
03394         /* given 4 points on the rectangle edges and the direction of on edge,
03395            compute the area of the rectangle */
03396 
03397         float orthodir[2], corner1[2], corner2[2], corner3[2];
03398 
03399         orthodir[0] = dir[1];
03400         orthodir[1] = -dir[0];
03401 
03402         if (!p_intersect_line_2d_dir(p1, dir, p2, orthodir, corner1))
03403                 return 1e10;
03404 
03405         if (!p_intersect_line_2d_dir(p1, dir, p4, orthodir, corner2))
03406                 return 1e10;
03407 
03408         if (!p_intersect_line_2d_dir(p3, dir, p4, orthodir, corner3))
03409                 return 1e10;
03410 
03411         return len_v2v2(corner1, corner2)*len_v2v2(corner2, corner3);
03412 }
03413 
03414 static float p_chart_minimum_area_angle(PChart *chart)
03415 {
03416         /* minimum area enclosing rectangle with rotating calipers, info:
03417          * http://cgm.cs.mcgill.ca/~orm/maer.html */
03418 
03419         float rotated, minarea, minangle, area, len;
03420         float *angles, miny, maxy, v[2], a[4], mina;
03421         int npoints, right, mini, maxi, i, idx[4], nextidx;
03422         PVert **points, *p1, *p2, *p3, *p4, *p1n;
03423 
03424         /* compute convex hull */
03425         if (!p_chart_convex_hull(chart, &points, &npoints, &right))
03426                 return 0.0;
03427 
03428         /* find left/top/right/bottom points, and compute angle for each point */
03429         angles = MEM_mallocN(sizeof(float)*npoints, "PMinAreaAngles");
03430 
03431         mini = maxi = 0;
03432         miny = 1e10;
03433         maxy = -1e10;
03434 
03435         for (i = 0; i < npoints; i++) {
03436                 p1 = (i == 0)? points[npoints-1]: points[i-1];
03437                 p2 = points[i];
03438                 p3 = (i == npoints-1)? points[0]: points[i+1];
03439 
03440                 angles[i] = (float)M_PI - p_vec2_angle(p1->uv, p2->uv, p3->uv);
03441 
03442                 if (points[i]->uv[1] < miny) {
03443                         miny = points[i]->uv[1];
03444                         mini = i;
03445                 }
03446                 if (points[i]->uv[1] > maxy) {
03447                         maxy = points[i]->uv[1];
03448                         maxi = i;
03449                 }
03450         }
03451 
03452         /* left, top, right, bottom */
03453         idx[0] = 0;
03454         idx[1] = maxi;
03455         idx[2] = right;
03456         idx[3] = mini;
03457 
03458         v[0] = points[idx[0]]->uv[0];
03459         v[1] = points[idx[0]]->uv[1] + 1.0f;
03460         a[0] = p_vec2_angle(points[(idx[0]+1)%npoints]->uv, points[idx[0]]->uv, v);
03461 
03462         v[0] = points[idx[1]]->uv[0] + 1.0f;
03463         v[1] = points[idx[1]]->uv[1];
03464         a[1] = p_vec2_angle(points[(idx[1]+1)%npoints]->uv, points[idx[1]]->uv, v);
03465 
03466         v[0] = points[idx[2]]->uv[0];
03467         v[1] = points[idx[2]]->uv[1] - 1.0f;
03468         a[2] = p_vec2_angle(points[(idx[2]+1)%npoints]->uv, points[idx[2]]->uv, v);
03469 
03470         v[0] = points[idx[3]]->uv[0] - 1.0f;
03471         v[1] = points[idx[3]]->uv[1];
03472         a[3] = p_vec2_angle(points[(idx[3]+1)%npoints]->uv, points[idx[3]]->uv, v);
03473 
03474         /* 4 rotating calipers */
03475 
03476         rotated = 0.0;
03477         minarea = 1e10;
03478         minangle = 0.0;
03479 
03480         while (rotated <= (float)(M_PI/2.0)) { /* INVESTIGATE: how far to rotate? */
03481                 /* rotate with the smallest angle */
03482                 mini = 0;
03483                 mina = 1e10;
03484 
03485                 for (i = 0; i < 4; i++)
03486                         if (a[i] < mina) {
03487                                 mina = a[i];
03488                                 mini = i;
03489                         }
03490 
03491                 rotated += mina;
03492                 nextidx = (idx[mini]+1)%npoints;
03493 
03494                 a[mini] = angles[nextidx];
03495                 a[(mini+1)%4] = a[(mini+1)%4] - mina;
03496                 a[(mini+2)%4] = a[(mini+2)%4] - mina;
03497                 a[(mini+3)%4] = a[(mini+3)%4] - mina;
03498 
03499                 /* compute area */
03500                 p1 = points[idx[mini]];
03501                 p1n = points[nextidx];
03502                 p2 = points[idx[(mini+1)%4]];
03503                 p3 = points[idx[(mini+2)%4]];
03504                 p4 = points[idx[(mini+3)%4]];
03505 
03506                 len = len_v2v2(p1->uv, p1n->uv);
03507 
03508                 if (len > 0.0f) {
03509                         len = 1.0f/len;
03510                         v[0] = (p1n->uv[0] - p1->uv[0])*len;
03511                         v[1] = (p1n->uv[1] - p1->uv[1])*len;
03512 
03513                         area = p_rectangle_area(p1->uv, v, p2->uv, p3->uv, p4->uv);
03514 
03515                         /* remember smallest area */
03516                         if (area < minarea) {
03517                                 minarea = area;
03518                                 minangle = rotated;
03519                         }
03520                 }
03521 
03522                 idx[mini] = nextidx;
03523         }
03524 
03525         /* try keeping rotation as small as possible */
03526         if (minangle > (float)(M_PI/4))
03527                 minangle -= (float)(M_PI/2.0);
03528 
03529         MEM_freeN(angles);
03530         MEM_freeN(points);
03531 
03532         return minangle;
03533 }
03534 
03535 static void p_chart_rotate_minimum_area(PChart *chart)
03536 {
03537         float angle = p_chart_minimum_area_angle(chart);
03538         float sine = sin(angle);
03539         float cosine = cos(angle);
03540         PVert *v;
03541 
03542         for (v = chart->verts; v; v=v->nextlink) {
03543                 float oldu = v->uv[0], oldv = v->uv[1];
03544                 v->uv[0] = cosine*oldu - sine*oldv;
03545                 v->uv[1] = sine*oldu + cosine*oldv;
03546         }
03547 }
03548 
03549 /* Area Smoothing */
03550 
03551 /* 2d bsp tree for inverse mapping - that's a bit silly */
03552 
03553 typedef struct SmoothTriangle {
03554         float co1[2], co2[2], co3[2];
03555         float oco1[2], oco2[2], oco3[2];
03556 } SmoothTriangle;
03557 
03558 typedef struct SmoothNode {
03559         struct SmoothNode *c1, *c2;
03560         SmoothTriangle **tri;
03561         float split;
03562         int axis, ntri;
03563 } SmoothNode;
03564 
03565 static void p_barycentric_2d(float *v1, float *v2, float *v3, float *p, float *b)
03566 {
03567         float a[2], c[2], h[2], div;
03568 
03569         a[0] = v2[0] - v1[0];
03570         a[1] = v2[1] - v1[1];
03571         c[0] = v3[0] - v1[0];
03572         c[1] = v3[1] - v1[1];
03573 
03574         div = a[0]*c[1] - a[1]*c[0];
03575 
03576         if (div == 0.0f) {
03577                 b[0] = 1.0f/3.0f;
03578                 b[1] = 1.0f/3.0f;
03579                 b[2] = 1.0f/3.0f;
03580         }
03581         else {
03582                 h[0] = p[0] - v1[0];
03583                 h[1] = p[1] - v1[1];
03584 
03585                 div = 1.0f/div;
03586 
03587                 b[1] = (h[0]*c[1] - h[1]*c[0])*div;
03588                 b[2] = (a[0]*h[1] - a[1]*h[0])*div;
03589                 b[0] = 1.0f - b[1] - b[2];
03590         }
03591 }
03592 
03593 static PBool p_triangle_inside(SmoothTriangle *t, float *co)
03594 {
03595         float b[3];
03596 
03597         p_barycentric_2d(t->co1, t->co2, t->co3, co, b);
03598 
03599         if ((b[0] >= 0.0f) && (b[1] >= 0.0f) && (b[2] >= 0.0f)) {
03600                 co[0] = t->oco1[0]*b[0] + t->oco2[0]*b[1] + t->oco3[0]*b[2];
03601                 co[1] = t->oco1[1]*b[0] + t->oco2[1]*b[1] + t->oco3[1]*b[2];
03602                 return P_TRUE;
03603         }
03604 
03605         return P_FALSE;
03606 }
03607 
03608 static SmoothNode *p_node_new(MemArena *arena, SmoothTriangle **tri, int ntri, float *bmin, float *bmax, int depth)
03609 {
03610         SmoothNode *node = BLI_memarena_alloc(arena, sizeof *node);
03611         int axis, i, t1size = 0, t2size = 0;
03612         float split, mi, mx;
03613         SmoothTriangle **t1, **t2, *t;
03614 
03615         node->tri = tri;
03616         node->ntri = ntri;
03617 
03618         if (ntri <= 10 || depth >= 15)
03619                 return node;
03620         
03621         t1 = MEM_mallocN(sizeof(SmoothTriangle)*ntri, "PNodeTri1");
03622         t2 = MEM_mallocN(sizeof(SmoothTriangle)*ntri, "PNodeTri1");
03623 
03624         axis = (bmax[0] - bmin[0] > bmax[1] - bmin[1])? 0: 1;
03625         split = 0.5f*(bmin[axis] + bmax[axis]);
03626 
03627         for (i = 0; i < ntri; i++) {
03628                 t = tri[i];
03629 
03630                 if ((t->co1[axis] <= split) || (t->co2[axis] <= split) || (t->co3[axis] <= split)) {
03631                         t1[t1size] = t;
03632                         t1size++;
03633                 }
03634                 if ((t->co1[axis] >= split) || (t->co2[axis] >= split) || (t->co3[axis] >= split)) {
03635                         t2[t2size] = t;
03636                         t2size++;
03637                 }
03638         }
03639 
03640         if ((t1size == t2size) && (t1size == ntri)) {
03641                 MEM_freeN(t1);
03642                 MEM_freeN(t2);
03643                 return node;
03644         }
03645         
03646         node->tri = NULL;
03647         node->ntri = 0;
03648         MEM_freeN(tri);
03649 
03650         node->axis = axis;
03651         node->split = split;
03652 
03653         mi = bmin[axis];
03654         mx = bmax[axis];
03655         bmax[axis] = split;
03656         node->c1 = p_node_new(arena, t1, t1size, bmin, bmax, depth+1);
03657 
03658         bmin[axis] = bmax[axis];
03659         bmax[axis] = mx;
03660         node->c2 = p_node_new(arena, t2, t2size, bmin, bmax, depth+1);
03661 
03662         return node;
03663 }
03664 
03665 static void p_node_delete(SmoothNode *node)
03666 {
03667         if (node->c1)
03668                 p_node_delete(node->c1);
03669         if (node->c2)
03670                 p_node_delete(node->c2);
03671         if (node->tri)
03672                 MEM_freeN(node->tri);
03673 }
03674 
03675 static PBool p_node_intersect(SmoothNode *node, float *co)
03676 {
03677         int i;
03678 
03679         if (node->tri) {
03680                 for (i = 0; i < node->ntri; i++)
03681                         if (p_triangle_inside(node->tri[i], co))
03682                                 return P_TRUE;
03683 
03684                 return P_FALSE;
03685         }
03686         else {
03687                 if (co[node->axis] < node->split)
03688                         return p_node_intersect(node->c1, co);
03689                 else
03690                         return p_node_intersect(node->c2, co);
03691         }
03692 
03693 }
03694 
03695 /* smooothing */
03696 
03697 static int p_compare_float(const void *a, const void *b)
03698 {
03699         if (*((float*)a) < *((float*)b))
03700                 return -1;
03701         else if (*((float*)a) == *((float*)b))
03702                 return 0;
03703         else
03704                 return 1;
03705 }
03706 
03707 static float p_smooth_median_edge_length(PChart *chart)
03708 {
03709         PEdge *e;
03710         float *lengths = MEM_mallocN(sizeof(chart->edges)*chart->nedges, "PMedianLength");
03711         float median;
03712         int i;
03713 
03714         /* ok, so i'm lazy */
03715         for (i=0, e=chart->edges; e; e=e->nextlink, i++)
03716                 lengths[i] = p_edge_length(e);
03717         
03718         qsort(lengths, i, sizeof(float), p_compare_float);
03719 
03720         median = lengths[i/2];
03721         MEM_freeN(lengths);
03722 
03723         return median;
03724 }
03725 
03726 static float p_smooth_distortion(PEdge *e, float avg2d, float avg3d)
03727 {
03728         float len2d = p_edge_uv_length(e)*avg3d;
03729         float len3d = p_edge_length(e)*avg2d;
03730 
03731         return (len3d == 0.0f)? 0.0f: len2d/len3d;
03732 }
03733 
03734 static void p_smooth(PChart *chart)
03735 {
03736         PEdge *e;
03737         PVert *v;
03738         PFace *f;
03739         int j, it2, maxiter2, it;
03740         int nedges = chart->nedges, nwheel, gridx, gridy;
03741         int edgesx, edgesy, nsize, esize, i, x, y, maxiter, totiter;
03742         float minv[2], maxv[2], median, invmedian, avglen2d, avglen3d;
03743         float center[2], dx, dy, *nodes, dlimit, d, *oldnodesx, *oldnodesy;
03744         float *nodesx, *nodesy, *hedges, *vedges, climit, moved, padding;
03745         SmoothTriangle *triangles, *t, *t2, **tri, **trip;
03746         SmoothNode *root;
03747         MemArena *arena;
03748 
03749         if (nedges == 0)
03750                 return;
03751 
03752         p_chart_uv_bbox(chart, minv, maxv);
03753         median = p_smooth_median_edge_length(chart)*0.10f;
03754 
03755         if (median == 0.0f)
03756                 return;
03757 
03758         invmedian = 1.0f/median;
03759 
03760         /* compute edge distortion */
03761         avglen2d = avglen3d = 0.0;
03762 
03763         for (e=chart->edges; e; e=e->nextlink) {
03764                 avglen2d += p_edge_uv_length(e);
03765                 avglen3d += p_edge_length(e);
03766         }
03767 
03768         avglen2d /= nedges;
03769         avglen3d /= nedges;
03770 
03771         for (v=chart->verts; v; v=v->nextlink) {
03772                 v->u.distortion = 0.0;
03773                 nwheel = 0;
03774 
03775                 e = v->edge;
03776                 do {
03777                         v->u.distortion += p_smooth_distortion(e, avglen2d, avglen3d);
03778                         nwheel++;
03779 
03780                         e = e->next->next->pair;
03781                 } while(e && (e != v->edge));
03782 
03783                 v->u.distortion /= nwheel;
03784         }
03785 
03786         /* need to do excessive grid size checking still */
03787         center[0] = 0.5f*(minv[0] + maxv[0]);
03788         center[1] = 0.5f*(minv[1] + maxv[1]);
03789 
03790         dx = 0.5f*(maxv[0] - minv[0]);
03791         dy = 0.5f*(maxv[1] - minv[1]);
03792 
03793         padding = 0.15f;
03794         dx += padding*dx + 2.0f*median;
03795         dy += padding*dy + 2.0f*median;
03796 
03797         gridx = (int)(dx*invmedian);
03798         gridy = (int)(dy*invmedian);
03799 
03800         minv[0] = center[0] - median*gridx;
03801         minv[1] = center[1] - median*gridy;
03802         maxv[0] = center[0] + median*gridx;
03803         maxv[1] = center[1] + median*gridy;
03804 
03805         /* create grid */
03806         gridx = gridx*2 + 1;
03807         gridy = gridy*2 + 1;
03808 
03809         if ((gridx <= 2) || (gridy <= 2))
03810                 return;
03811         
03812         edgesx = gridx-1;
03813         edgesy = gridy-1;
03814         nsize = gridx*gridy;
03815         esize = edgesx*edgesy;
03816         
03817         nodes = MEM_mallocN(sizeof(float)*nsize, "PSmoothNodes");
03818         nodesx = MEM_mallocN(sizeof(float)*nsize, "PSmoothNodesX");
03819         nodesy = MEM_mallocN(sizeof(float)*nsize, "PSmoothNodesY");
03820         oldnodesx = MEM_mallocN(sizeof(float)*nsize, "PSmoothOldNodesX");
03821         oldnodesy = MEM_mallocN(sizeof(float)*nsize, "PSmoothOldNodesY");
03822         hedges = MEM_mallocN(sizeof(float)*esize, "PSmoothHEdges");
03823         vedges = MEM_mallocN(sizeof(float)*esize, "PSmoothVEdges");
03824 
03825         if (!nodes || !nodesx || !nodesy || !oldnodesx || !oldnodesy || !hedges || !vedges) {
03826                 if (nodes) MEM_freeN(nodes);
03827                 if (nodesx) MEM_freeN(nodesx);
03828                 if (nodesy) MEM_freeN(nodesy);
03829                 if (oldnodesx) MEM_freeN(oldnodesx);
03830                 if (oldnodesy) MEM_freeN(oldnodesy);
03831                 if (hedges) MEM_freeN(hedges);
03832                 if (vedges) MEM_freeN(vedges);
03833 
03834                 // printf("Not enough memory for area smoothing grid.");
03835                 return;
03836         }
03837 
03838         for (x = 0; x < gridx; x++) {
03839                 for (y = 0; y < gridy; y++) {
03840                         i = x + y*gridx;
03841 
03842                         nodesx[i] = minv[0] + median*x;
03843                         nodesy[i] = minv[1] + median*y;
03844 
03845                         nodes[i] = 1.0f;
03846                 }
03847         }
03848 
03849         /* embed in grid */
03850         for (f=chart->faces; f; f=f->nextlink) {
03851                 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
03852                 float fmin[2], fmax[2];
03853                 int bx1, by1, bx2, by2;
03854 
03855                 INIT_MINMAX2(fmin, fmax);
03856 
03857                 DO_MINMAX2(e1->vert->uv, fmin, fmax);
03858                 DO_MINMAX2(e2->vert->uv, fmin, fmax);
03859                 DO_MINMAX2(e3->vert->uv, fmin, fmax);
03860 
03861                 bx1 = (int)((fmin[0] - minv[0])*invmedian);
03862                 by1 = (int)((fmin[1] - minv[1])*invmedian);
03863                 bx2 = (int)((fmax[0] - minv[0])*invmedian + 2);
03864                 by2 = (int)((fmax[1] - minv[1])*invmedian + 2);
03865 
03866                 for (x = bx1; x < bx2; x++) {
03867                         for (y = by1; y < by2; y++) {
03868                                 float p[2], b[3];
03869 
03870                                 i = x + y*gridx;
03871                 
03872                                 p[0] = nodesx[i];
03873                                 p[1] = nodesy[i];
03874 
03875                                 p_barycentric_2d(e1->vert->uv, e2->vert->uv, e3->vert->uv, p, b);
03876 
03877                                 if ((b[0] > 0.0f) && (b[1] > 0.0f) && (b[2] > 0.0f)) {
03878                                         nodes[i] = e1->vert->u.distortion*b[0];
03879                                         nodes[i] += e2->vert->u.distortion*b[1];
03880                                         nodes[i] += e3->vert->u.distortion*b[2];
03881                                 }
03882                         }
03883                 }
03884         }
03885 
03886         /* smooth the grid */
03887         maxiter = 10;
03888         totiter = 0;
03889         climit = 0.00001f*nsize;
03890 
03891         for (it = 0; it < maxiter; it++) {
03892                 moved = 0.0f;
03893 
03894                 for (x = 0; x < edgesx; x++) {
03895                         for (y = 0; y < edgesy; y++) {
03896                                 i = x + y*gridx;
03897                                 j = x + y*edgesx;
03898 
03899                                 hedges[j] = (nodes[i] + nodes[i+1])*0.5f;
03900                                 vedges[j] = (nodes[i] + nodes[i+gridx])*0.5f;
03901 
03902                                 /* we do *inverse* mapping */
03903                                 hedges[j] = 1.0f/hedges[j];
03904                                 vedges[j] = 1.0f/vedges[j];
03905                         }
03906                 }
03907 
03908                 maxiter2 = 50;
03909                 dlimit = 0.0001f;
03910 
03911                 for (it2 = 0; it2 < maxiter2; it2++) {
03912                         d = 0.0f;
03913                         totiter += 1;
03914                         
03915                         memcpy(oldnodesx, nodesx, sizeof(float)*nsize);
03916                         memcpy(oldnodesy, nodesy, sizeof(float)*nsize);
03917 
03918                         for (x=1; x < gridx-1; x++) {
03919                                 for (y=1; y < gridy-1; y++) {
03920                                         float p[2], oldp[2], sum1, sum2, diff[2], length;
03921 
03922                                         i = x + gridx*y;
03923                                         j = x + edgesx*y;
03924 
03925                                         oldp[0] = oldnodesx[i];
03926                                         oldp[1] = oldnodesy[i];
03927 
03928                                         sum1 = hedges[j-1]*oldnodesx[i-1];
03929                                         sum1 += hedges[j]*oldnodesx[i+1];
03930                                         sum1 += vedges[j-edgesx]*oldnodesx[i-gridx];
03931                                         sum1 += vedges[j]*oldnodesx[i+gridx];
03932 
03933                                         sum2 = hedges[j-1];
03934                                         sum2 += hedges[j];
03935                                         sum2 += vedges[j-edgesx];
03936                                         sum2 += vedges[j];
03937 
03938                                         nodesx[i] = sum1/sum2;
03939 
03940                                         sum1 = hedges[j-1]*oldnodesy[i-1];
03941                                         sum1 += hedges[j]*oldnodesy[i+1];
03942                                         sum1 += vedges[j-edgesx]*oldnodesy[i-gridx];
03943                                         sum1 += vedges[j]*oldnodesy[i+gridx];
03944 
03945                                         nodesy[i] = sum1/sum2;
03946                                         
03947                                         p[0] = nodesx[i];
03948                                         p[1] = nodesy[i];
03949 
03950                                         diff[0] = p[0] - oldp[0];
03951                                         diff[1] = p[1] - oldp[1];
03952 
03953                                         length = sqrt(diff[0]*diff[0] + diff[1]*diff[1]);
03954                                         d = MAX2(d, length);
03955                                         moved += length;
03956                                 }
03957                         }
03958 
03959                         if (d < dlimit)
03960                                 break;
03961                 }
03962 
03963                 if (moved < climit)
03964                         break;
03965         }
03966 
03967         MEM_freeN(oldnodesx);
03968         MEM_freeN(oldnodesy);
03969         MEM_freeN(hedges);
03970         MEM_freeN(vedges);
03971 
03972         /* create bsp */
03973         t = triangles = MEM_mallocN(sizeof(SmoothTriangle)*esize*2, "PSmoothTris");
03974         trip = tri = MEM_mallocN(sizeof(SmoothTriangle*)*esize*2, "PSmoothTriP");
03975 
03976         if (!triangles || !tri) {
03977                 MEM_freeN(nodes);
03978                 MEM_freeN(nodesx);
03979                 MEM_freeN(nodesy);
03980 
03981                 if (triangles) MEM_freeN(triangles);
03982                 if (tri) MEM_freeN(tri);
03983 
03984                 // printf("Not enough memory for area smoothing grid.");
03985                 return;
03986         }
03987 
03988         for (x = 0; x < edgesx; x++) {
03989                 for (y = 0; y < edgesy; y++) {
03990                         i = x + y*gridx;
03991 
03992                         t->co1[0] = nodesx[i];
03993                         t->co1[1] = nodesy[i];
03994 
03995                         t->co2[0] = nodesx[i+1];
03996                         t->co2[1] = nodesy[i+1];
03997 
03998                         t->co3[0] = nodesx[i+gridx];
03999                         t->co3[1] = nodesy[i+gridx];
04000 
04001                         t->oco1[0] = minv[0] + x*median;
04002                         t->oco1[1] = minv[1] + y*median;
04003 
04004                         t->oco2[0] = minv[0] + (x+1)*median;
04005                         t->oco2[1] = minv[1] + y*median;
04006 
04007                         t->oco3[0] = minv[0] + x*median;
04008                         t->oco3[1] = minv[1] + (y+1)*median;
04009 
04010                         t2 = t+1;
04011 
04012                         t2->co1[0] = nodesx[i+gridx+1];
04013                         t2->co1[1] = nodesy[i+gridx+1];
04014 
04015                         t2->oco1[0] = minv[0] + (x+1)*median;
04016                         t2->oco1[1] = minv[1] + (y+1)*median;
04017 
04018                         t2->co2[0] = t->co2[0]; t2->co2[1] = t->co2[1];
04019                         t2->oco2[0] = t->oco2[0]; t2->oco2[1] = t->oco2[1];
04020 
04021                         t2->co3[0] = t->co3[0]; t2->co3[1] = t->co3[1];
04022                         t2->oco3[0] = t->oco3[0]; t2->oco3[1] = t->oco3[1];
04023 
04024                         *trip = t; trip++; t++; 
04025                         *trip = t; trip++; t++; 
04026                 }
04027         }
04028 
04029         MEM_freeN(nodes);
04030         MEM_freeN(nodesx);
04031         MEM_freeN(nodesy);
04032 
04033         arena = BLI_memarena_new(1<<16, "param smooth arena");
04034         root = p_node_new(arena, tri, esize*2, minv, maxv, 0);
04035 
04036         for (v=chart->verts; v; v=v->nextlink)
04037                 if (!p_node_intersect(root, v->uv))
04038                         param_warning("area smoothing error: couldn't find mapping triangle\n");
04039 
04040         p_node_delete(root);
04041         BLI_memarena_free(arena);
04042         
04043         MEM_freeN(triangles);
04044 }
04045 
04046 /* Exported */
04047 
04048 ParamHandle *param_construct_begin(void)
04049 {
04050         PHandle *handle = MEM_callocN(sizeof*handle, "PHandle");
04051         handle->construction_chart = p_chart_new(handle);
04052         handle->state = PHANDLE_STATE_ALLOCATED;
04053         handle->arena = BLI_memarena_new((1<<16), "param construct arena");
04054         handle->aspx = 1.0f;
04055         handle->aspy = 1.0f;
04056 
04057         handle->hash_verts = phash_new((PHashLink**)&handle->construction_chart->verts, 1);
04058         handle->hash_edges = phash_new((PHashLink**)&handle->construction_chart->edges, 1);
04059         handle->hash_faces = phash_new((PHashLink**)&handle->construction_chart->faces, 1);
04060 
04061         return (ParamHandle*)handle;
04062 }
04063 
04064 void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy)
04065 {
04066         PHandle *phandle = (PHandle*)handle;
04067 
04068         phandle->aspx = aspx;
04069         phandle->aspy = aspy;
04070 }
04071 
04072 void param_delete(ParamHandle *handle)
04073 {
04074         PHandle *phandle = (PHandle*)handle;
04075         int i;
04076 
04077         param_assert((phandle->state == PHANDLE_STATE_ALLOCATED) ||
04078                                  (phandle->state == PHANDLE_STATE_CONSTRUCTED));
04079 
04080         for (i = 0; i < phandle->ncharts; i++)
04081                 p_chart_delete(phandle->charts[i]);
04082         
04083         if (phandle->charts)
04084                 MEM_freeN(phandle->charts);
04085 
04086         if (phandle->construction_chart) {
04087                 p_chart_delete(phandle->construction_chart);
04088 
04089                 phash_delete(phandle->hash_verts);
04090                 phash_delete(phandle->hash_edges);
04091                 phash_delete(phandle->hash_faces);
04092         }
04093 
04094         BLI_memarena_free(phandle->arena);
04095         MEM_freeN(phandle);
04096 }
04097 
04098 void param_face_add(ParamHandle *handle, ParamKey key, int nverts,
04099                                         ParamKey *vkeys, float **co, float **uv,
04100                                         ParamBool *pin, ParamBool *select)
04101 {
04102         PHandle *phandle = (PHandle*)handle;
04103 
04104         param_assert(phash_lookup(phandle->hash_faces, key) == NULL);
04105         param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
04106         param_assert((nverts == 3) || (nverts == 4));
04107 
04108         if (nverts == 4) {
04109                 if (p_quad_split_direction(phandle, co, vkeys)) {
04110                         p_face_add_construct(phandle, key, vkeys, co, uv, 0, 1, 2, pin, select);
04111                         p_face_add_construct(phandle, key, vkeys, co, uv, 0, 2, 3, pin, select);
04112                 }
04113                 else {
04114                         p_face_add_construct(phandle, key, vkeys, co, uv, 0, 1, 3, pin, select);
04115                         p_face_add_construct(phandle, key, vkeys, co, uv, 1, 2, 3, pin, select);
04116                 }
04117         }
04118         else
04119                 p_face_add_construct(phandle, key, vkeys, co, uv, 0, 1, 2, pin, select);
04120 }
04121 
04122 void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys)
04123 {
04124         PHandle *phandle = (PHandle*)handle;
04125         PEdge *e;
04126 
04127         param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
04128 
04129         e = p_edge_lookup(phandle, vkeys);
04130         if (e)
04131                 e->flag |= PEDGE_SEAM;
04132 }
04133 
04134 void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool impl)
04135 {
04136         PHandle *phandle = (PHandle*)handle;
04137         PChart *chart = phandle->construction_chart;
04138         int i, j, nboundaries = 0;
04139         PEdge *outer;
04140 
04141         param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
04142 
04143         phandle->ncharts = p_connect_pairs(phandle, (PBool)impl);
04144         phandle->charts = p_split_charts(phandle, chart, phandle->ncharts);
04145 
04146         p_chart_delete(phandle->construction_chart);
04147         phandle->construction_chart = NULL;
04148 
04149         phash_delete(phandle->hash_verts);
04150         phash_delete(phandle->hash_edges);
04151         phash_delete(phandle->hash_faces);
04152         phandle->hash_verts = phandle->hash_edges = phandle->hash_faces = NULL;
04153 
04154         for (i = j = 0; i < phandle->ncharts; i++) {
04155                 PVert *v;
04156                 chart = phandle->charts[i];
04157 
04158                 p_chart_boundaries(chart, &nboundaries, &outer);
04159 
04160                 if (!impl && nboundaries == 0) {
04161                         p_chart_delete(chart);
04162                         continue;
04163                 }
04164 
04165                 phandle->charts[j] = chart;
04166                 j++;
04167 
04168                 if (fill && (nboundaries > 1))
04169                         p_chart_fill_boundaries(chart, outer);
04170 
04171                 for (v=chart->verts; v; v=v->nextlink)
04172                         p_vert_load_pin_select_uvs(handle, v);
04173         }
04174 
04175         phandle->ncharts = j;
04176 
04177         phandle->state = PHANDLE_STATE_CONSTRUCTED;
04178 }
04179 
04180 void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf)
04181 {
04182         PHandle *phandle = (PHandle*)handle;
04183         PFace *f;
04184         int i;
04185 
04186         param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
04187         phandle->state = PHANDLE_STATE_LSCM;
04188 
04189         for (i = 0; i < phandle->ncharts; i++) {
04190                 for (f=phandle->charts[i]->faces; f; f=f->nextlink)
04191                         p_face_backup_uvs(f);
04192                 p_chart_lscm_begin(phandle->charts[i], (PBool)live, (PBool)abf);
04193         }
04194 }
04195 
04196 void param_lscm_solve(ParamHandle *handle)
04197 {
04198         PHandle *phandle = (PHandle*)handle;
04199         PChart *chart;
04200         int i;
04201         PBool result;
04202 
04203         param_assert(phandle->state == PHANDLE_STATE_LSCM);
04204 
04205         for (i = 0; i < phandle->ncharts; i++) {
04206                 chart = phandle->charts[i];
04207 
04208                 if (chart->u.lscm.context) {
04209                         result = p_chart_lscm_solve(phandle, chart);
04210 
04211                         if (result && !(chart->flag & PCHART_NOPACK))
04212                                 p_chart_rotate_minimum_area(chart);
04213 
04214                         if (!result || (chart->u.lscm.pin1))
04215                                 p_chart_lscm_end(chart);
04216                 }
04217         }
04218 }
04219 
04220 void param_lscm_end(ParamHandle *handle)
04221 {
04222         PHandle *phandle = (PHandle*)handle;
04223         int i;
04224 
04225         param_assert(phandle->state == PHANDLE_STATE_LSCM);
04226 
04227         for (i = 0; i < phandle->ncharts; i++) {
04228                 p_chart_lscm_end(phandle->charts[i]);
04229 #if 0
04230                 p_chart_complexify(phandle->charts[i]);
04231 #endif
04232         }
04233 
04234         phandle->state = PHANDLE_STATE_CONSTRUCTED;
04235 }
04236 
04237 void param_stretch_begin(ParamHandle *handle)
04238 {
04239         PHandle *phandle = (PHandle*)handle;
04240         PChart *chart;
04241         PVert *v;
04242         PFace *f;
04243         int i;
04244 
04245         param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
04246         phandle->state = PHANDLE_STATE_STRETCH;
04247 
04248         phandle->rng = rng_new(31415926);
04249         phandle->blend = 0.0f;
04250 
04251         for (i = 0; i < phandle->ncharts; i++) {
04252                 chart = phandle->charts[i];
04253 
04254                 for (v=chart->verts; v; v=v->nextlink)
04255                         v->flag &= ~PVERT_PIN; /* don't use user-defined pins */
04256 
04257                 p_stretch_pin_boundary(chart);
04258 
04259                 for (f=chart->faces; f; f=f->nextlink) {
04260                         p_face_backup_uvs(f);
04261                         f->u.area3d = p_face_area(f);
04262                 }
04263         }
04264 }
04265 
04266 void param_stretch_blend(ParamHandle *handle, float blend)
04267 {
04268         PHandle *phandle = (PHandle*)handle;
04269 
04270         param_assert(phandle->state == PHANDLE_STATE_STRETCH);
04271         phandle->blend = blend;
04272 }
04273 
04274 void param_stretch_iter(ParamHandle *handle)
04275 {
04276         PHandle *phandle = (PHandle*)handle;
04277         PChart *chart;
04278         int i;
04279 
04280         param_assert(phandle->state == PHANDLE_STATE_STRETCH);
04281 
04282         for (i = 0; i < phandle->ncharts; i++) {
04283                 chart = phandle->charts[i];
04284                 p_chart_stretch_minimize(chart, phandle->rng);
04285         }
04286 }
04287 
04288 void param_stretch_end(ParamHandle *handle)
04289 {
04290         PHandle *phandle = (PHandle*)handle;
04291 
04292         param_assert(phandle->state == PHANDLE_STATE_STRETCH);
04293         phandle->state = PHANDLE_STATE_CONSTRUCTED;
04294 
04295         rng_free(phandle->rng);
04296         phandle->rng = NULL;
04297 }
04298 
04299 void param_smooth_area(ParamHandle *handle)
04300 {
04301         PHandle *phandle = (PHandle*)handle;
04302         int i;
04303 
04304         param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
04305 
04306         for (i = 0; i < phandle->ncharts; i++) {
04307                 PChart *chart = phandle->charts[i];
04308                 PVert *v;
04309 
04310                 for (v=chart->verts; v; v=v->nextlink)
04311                         v->flag &= ~PVERT_PIN;
04312 
04313                 p_smooth(chart);
04314         }
04315 }
04316  
04317 void param_pack(ParamHandle *handle, float margin)
04318 {       
04319         /* box packing variables */
04320         boxPack *boxarray, *box;
04321         float tot_width, tot_height, scale;
04322          
04323         PChart *chart;
04324         int i, unpacked=0;
04325         float trans[2];
04326         double area= 0.0;
04327         
04328         PHandle *phandle = (PHandle*)handle;
04329         
04330         if (phandle->ncharts == 0)
04331                 return;
04332         
04333         if(phandle->aspx != phandle->aspy)
04334                 param_scale(handle, 1.0f/phandle->aspx, 1.0f/phandle->aspy);
04335         
04336         /* we may not use all these boxes */
04337         boxarray = MEM_mallocN( phandle->ncharts*sizeof(boxPack), "boxPack box");
04338         
04339         
04340         for (i = 0; i < phandle->ncharts; i++) {
04341                 chart = phandle->charts[i];
04342                 
04343                 if (chart->flag & PCHART_NOPACK) {
04344                         unpacked++;
04345                         continue;
04346                 }
04347                 
04348                 box = boxarray+(i-unpacked);
04349                 
04350                 p_chart_uv_bbox(chart, trans, chart->u.pack.size);
04351                 
04352                 trans[0] = -trans[0];
04353                 trans[1] = -trans[1];
04354                 
04355                 p_chart_uv_translate(chart, trans);
04356                 
04357                 box->w =  chart->u.pack.size[0] + trans[0];
04358                 box->h =  chart->u.pack.size[1] + trans[1];
04359                 box->index = i; /* warning this index skips PCHART_NOPACK boxes */
04360                 
04361                 if(margin>0.0f)
04362                         area += sqrt(box->w*box->h);
04363         }       
04364         
04365         if(margin>0.0f) {
04366                 /* multiply the margin by the area to give predictable results not dependant on UV scale,
04367                  * ...Without using the area running pack multiple times also gives a bad feedback loop.
04368                  * multiply by 0.1 so the margin value from the UI can be from 0.0 to 1.0 but not give a massive margin */
04369                 margin = (margin*(float)area) * 0.1f;
04370                 unpacked= 0;
04371                 for (i = 0; i < phandle->ncharts; i++) {
04372                         chart = phandle->charts[i];
04373                         
04374                         if (chart->flag & PCHART_NOPACK) {
04375                                 unpacked++;
04376                                 continue;
04377                         }
04378                         
04379                         box = boxarray+(i-unpacked);
04380                         trans[0] = margin;
04381                         trans[1] = margin;
04382                         p_chart_uv_translate(chart, trans);
04383                         box->w += margin*2;
04384                         box->h += margin*2;
04385                 }
04386         }
04387         
04388         boxPack2D(boxarray, phandle->ncharts-unpacked, &tot_width, &tot_height);
04389         
04390         if (tot_height>tot_width)
04391                 scale = 1.0f/tot_height;
04392         else
04393                 scale = 1.0f/tot_width;
04394         
04395         for (i = 0; i < phandle->ncharts-unpacked; i++) {
04396                 box = boxarray+i;
04397                 trans[0] = box->x;
04398                 trans[1] = box->y;
04399                 
04400                 chart = phandle->charts[box->index];
04401                 p_chart_uv_translate(chart, trans);
04402                 p_chart_uv_scale(chart, scale);
04403         }
04404         MEM_freeN(boxarray);
04405 
04406         if(phandle->aspx != phandle->aspy)
04407                 param_scale(handle, phandle->aspx, phandle->aspy);
04408 }
04409 
04410 void param_average(ParamHandle *handle)
04411 {
04412         PChart *chart;
04413         int i;
04414         float tot_uvarea = 0.0f, tot_facearea = 0.0f;
04415         float tot_fac, fac;
04416         float minv[2], maxv[2], trans[2];
04417         PHandle *phandle = (PHandle*)handle;
04418         
04419         if (phandle->ncharts == 0)
04420                 return;
04421         
04422         for (i = 0; i < phandle->ncharts; i++) {
04423                 PFace *f;
04424                 chart = phandle->charts[i];
04425                 
04426                 chart->u.pack.area = 0.0f; /* 3d area */
04427                 chart->u.pack.rescale = 0.0f; /* UV area, abusing rescale for tmp storage, oh well :/ */
04428                 
04429                 for (f=chart->faces; f; f=f->nextlink) {
04430                         chart->u.pack.area += p_face_area(f);
04431                         chart->u.pack.rescale += fabsf(p_face_uv_area_signed(f));
04432                 }
04433                 
04434                 tot_facearea += chart->u.pack.area;
04435                 tot_uvarea += chart->u.pack.rescale;
04436         }
04437         
04438         if (tot_facearea == tot_uvarea || tot_facearea==0.0f || tot_uvarea==0.0f) {
04439                 /* nothing to do */
04440                 return;
04441         }
04442         
04443         tot_fac = tot_facearea/tot_uvarea;
04444         
04445         for (i = 0; i < phandle->ncharts; i++) {
04446                 chart = phandle->charts[i];
04447                 if (chart->u.pack.area != 0.0f && chart->u.pack.rescale != 0.0f) {
04448                         fac = chart->u.pack.area / chart->u.pack.rescale;
04449                         
04450                         /* Get the island center */
04451                         p_chart_uv_bbox(chart, minv, maxv);
04452                         trans[0] = (minv[0] + maxv[0]) /-2.0f;
04453                         trans[1] = (minv[1] + maxv[1]) /-2.0f;
04454                         
04455                         /* Move center to 0,0 */
04456                         p_chart_uv_translate(chart, trans);
04457                         p_chart_uv_scale(chart, sqrt(fac / tot_fac));
04458                         
04459                         /* Move to original center */
04460                         trans[0] = -trans[0];
04461                         trans[1] = -trans[1];
04462                         p_chart_uv_translate(chart, trans);
04463                 }
04464         }
04465 }
04466 
04467 void param_scale(ParamHandle *handle, float x, float y)
04468 {
04469         PHandle *phandle = (PHandle*)handle;
04470         PChart *chart;
04471         int i;
04472 
04473         for (i = 0; i < phandle->ncharts; i++) {
04474                 chart = phandle->charts[i];
04475                 p_chart_uv_scale_xy(chart, x, y);
04476         }
04477 }
04478 
04479 void param_flush(ParamHandle *handle)
04480 {
04481         PHandle *phandle = (PHandle*)handle;
04482         PChart *chart;
04483         int i;
04484 
04485         for (i = 0; i < phandle->ncharts; i++) {
04486                 chart = phandle->charts[i];
04487 
04488                 if ((phandle->state == PHANDLE_STATE_LSCM) && !chart->u.lscm.context)
04489                         continue;
04490 
04491                 if (phandle->blend == 0.0f)
04492                         p_flush_uvs(phandle, chart);
04493                 else
04494                         p_flush_uvs_blend(phandle, chart, phandle->blend);
04495         }
04496 }
04497 
04498 void param_flush_restore(ParamHandle *handle)
04499 {
04500         PHandle *phandle = (PHandle*)handle;
04501         PChart *chart;
04502         PFace *f;
04503         int i;
04504 
04505         for (i = 0; i < phandle->ncharts; i++) {
04506                 chart = phandle->charts[i];
04507 
04508                 for (f=chart->faces; f; f=f->nextlink)
04509                         p_face_restore_uvs(f);
04510         }
04511 }
04512