Blender V2.61 - r43446

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