2 #include "MEM_guardedalloc.h"
4 #include "BLI_memarena.h"
5 #include "BLI_arithb.h"
8 #include "BKE_utildefines.h"
10 #include "BIF_editsima.h"
11 #include "BIF_toolbox.h"
13 #include "ONL_opennl.h"
15 #include "parametrizer.h"
16 #include "parametrizer_intern.h"
24 #define M_PI 3.14159265358979323846
29 static int PHashSizes[] = {
30 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
31 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
32 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459
35 #define PHASH_hash(ph, item) (((unsigned long) (item))%((unsigned int) (ph)->cursize))
37 PHash *phash_new(int sizehint)
39 PHash *ph = (PHash*)MEM_callocN(sizeof(PHash), "PHash");
44 while (PHashSizes[ph->cursize_id] < sizehint)
47 ph->cursize = PHashSizes[ph->cursize_id];
48 ph->buckets = (PHashLink**)MEM_callocN(ph->cursize*sizeof(*ph->buckets), "PHashBuckets");
53 void phash_delete(PHash *ph)
55 MEM_freeN(ph->buckets);
59 void phash_delete_with_links(PHash *ph)
61 PHashLink *link, *next=NULL;
63 for (link = ph->first; link; link = next) {
71 int phash_size(PHash *ph)
76 void phash_insert(PHash *ph, PHashLink *link)
78 int size = ph->cursize;
79 int hash = PHASH_hash(ph, link->key);
80 PHashLink *lookup = ph->buckets[hash];
83 /* insert in front of the list */
84 ph->buckets[hash] = link;
85 link->next = ph->first;
89 /* insert after existing element */
90 link->next = lookup->next;
96 if (ph->size > (size*3)) {
97 PHashLink *next = NULL, *first = ph->first;
99 ph->cursize = PHashSizes[++ph->cursize_id];
100 MEM_freeN(ph->buckets);
101 ph->buckets = (PHashLink**)MEM_callocN(ph->cursize*sizeof(*ph->buckets), "PHashBuckets");
105 for (link = first; link; link = next) {
107 phash_insert(ph, link);
112 PHashLink *phash_lookup(PHash *ph, PHashKey key)
115 int hash = PHASH_hash(ph, key);
117 for (link = ph->buckets[hash]; link; link = link->next)
118 if (link->key == key)
120 else if (PHASH_hash(ph, link->key) != hash)
126 PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link)
128 int hash = PHASH_hash(ph, key);
130 for (link = link->next; link; link = link->next)
131 if (link->key == key)
133 else if (PHASH_hash(ph, link->key) != hash)
141 #define PHEAP_PARENT(i) ((i-1)>>1)
142 #define PHEAP_LEFT(i) ((i<<1)+1)
143 #define PHEAP_RIGHT(i) ((i<<1)+2)
144 #define PHEAP_COMPARE(a, b) (a->value < b->value)
145 #define PHEAP_EQUALS(a, b) (a->value == b->value)
146 #define PHEAP_SWAP(heap, i, j) \
147 { SWAP(int, heap->tree[i]->index, heap->tree[j]->index); \
148 SWAP(PHeapLink*, heap->tree[i], heap->tree[j]); }
150 static void pheap_down(PHeap *heap, int i)
153 int size = heap->size, smallest;
154 int l = PHEAP_LEFT(i);
155 int r = PHEAP_RIGHT(i);
157 smallest = ((l < size) && PHEAP_COMPARE(heap->tree[l], heap->tree[i]))? l: i;
159 if ((r < size) && PHEAP_COMPARE(heap->tree[r], heap->tree[smallest]))
165 PHEAP_SWAP(heap, i, smallest);
170 static void pheap_up(PHeap *heap, int i)
173 int p = PHEAP_PARENT(i);
175 if (PHEAP_COMPARE(heap->tree[p], heap->tree[i]))
178 PHEAP_SWAP(heap, p, i);
185 /* TODO: replace mallocN with something faster */
187 PHeap *heap = (PHeap*)MEM_callocN(sizeof(PHeap), "PHeap");
189 heap->tree = (PHeapLink**)MEM_mallocN(sizeof(PHeapLink*), "PHeapTree");
194 void pheap_delete(PHeap *heap)
196 MEM_freeN(heap->tree);
200 PHeapLink *pheap_insert(PHeap *heap, float value, void *ptr)
204 if ((heap->size + 1) > heap->bufsize) {
205 int newsize = heap->bufsize*2;
207 PHeapLink **ntree = (PHeapLink**)MEM_mallocN(newsize*sizeof(PHeapLink*), "PHeapTree");
208 memcpy(ntree, heap->tree, sizeof(PHeapLink*)*heap->size);
209 MEM_freeN(heap->tree);
212 heap->bufsize = newsize;
215 param_assert(heap->size < heap->bufsize);
217 link = MEM_mallocN(sizeof *link, "PHeapLink");
220 link->index = heap->size;
222 heap->tree[link->index] = link;
226 pheap_up(heap, heap->size-1);
231 int pheap_empty(PHeap *heap)
233 return (heap->size == 0);
236 int pheap_size(PHeap *heap)
241 void *pheap_min(PHeap *heap)
243 return heap->tree[0]->ptr;
246 void *pheap_popmin(PHeap *heap)
248 void *ptr = heap->tree[0]->ptr;
250 MEM_freeN(heap->tree[0]);
255 PHEAP_SWAP(heap, 0, heap->size-1);
264 static void pheap_remove(PHeap *heap, PHeapLink *link)
269 int p = PHEAP_PARENT(i);
271 PHEAP_SWAP(heap, p, i);
280 PEdge *p_wheel_edge_next(PEdge *e)
282 return e->next->next->pair;
285 PEdge *p_wheel_edge_prev(PEdge *e)
287 return (e->pair)? e->pair->next: NULL;
290 static PVert *p_vert_add(PChart *chart, PHashKey key, float *co, PEdge *e)
292 PVert *v = (PVert*)BLI_memarena_alloc(chart->handle->arena, sizeof *v);
298 phash_insert(chart->verts, (PHashLink*)v);
303 static PVert *p_vert_lookup(PChart *chart, PHashKey key, float *co, PEdge *e)
305 PVert *v = (PVert*)phash_lookup(chart->verts, key);
310 return p_vert_add(chart, key, co, e);
313 static PVert *p_vert_copy(PChart *chart, PVert *v)
315 PVert *nv = (PVert*)BLI_memarena_alloc(chart->handle->arena, sizeof *nv);
317 nv->uv[0] = v->uv[0];
318 nv->uv[1] = v->uv[1];
319 nv->link.key = v->link.key;
323 phash_insert(chart->verts, (PHashLink*)nv);
328 static PEdge *p_edge_lookup(PChart *chart, PHashKey *vkeys)
330 PHashKey key = vkeys[0]^vkeys[1];
331 PEdge *e = (PEdge*)phash_lookup(chart->edges, key);
334 if ((e->vert->link.key == vkeys[0]) && (e->next->vert->link.key == vkeys[1]))
336 else if ((e->vert->link.key == vkeys[1]) && (e->next->vert->link.key == vkeys[0]))
339 e = (PEdge*)phash_next(chart->edges, key, (PHashLink*)e);
345 static void p_face_flip(PFace *f)
347 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
348 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
349 int f1 = e1->flag, f2 = e2->flag, f3 = e3->flag;
353 e1->flag = (f1 & ~PEDGE_VERTEX_FLAGS) | (f2 & PEDGE_VERTEX_FLAGS);
357 e2->flag = (f2 & ~PEDGE_VERTEX_FLAGS) | (f3 & PEDGE_VERTEX_FLAGS);
361 e3->flag = (f3 & ~PEDGE_VERTEX_FLAGS) | (f1 & PEDGE_VERTEX_FLAGS);
364 static void p_vert_load_pin_select_uvs(PVert *v)
369 v->uv[0] = v->uv[1] = 0.0f;
373 if (e->orig_uv && (e->flag & PEDGE_PIN)) {
374 if (e->flag & PEDGE_SELECT)
375 v->flag |= PVERT_SELECT;
377 v->flag |= PVERT_PIN;
378 v->uv[0] += e->orig_uv[0];
379 v->uv[1] += e->orig_uv[1];
383 e = p_wheel_edge_next(e);
384 } while (e && e != (v->edge));
392 static void p_vert_load_select_uvs(PVert *v)
397 v->uv[0] = v->uv[1] = 0.0f;
401 if (e->orig_uv && (e->flag & PEDGE_SELECT))
402 v->flag |= PVERT_SELECT;
404 v->uv[0] += e->orig_uv[0];
405 v->uv[1] += e->orig_uv[1];
408 e = p_wheel_edge_next(e);
409 } while (e && e != (v->edge));
417 static void p_extrema_verts(PChart *chart, PVert **v1, PVert **v2)
419 float minv[3], maxv[3], dirlen;
420 PVert *v, *minvert[3], *maxvert[3];
423 /* find minimum and maximum verts over x/y/z axes */
424 minv[0] = minv[1] = minv[2] = 1e20;
425 maxv[0] = maxv[1] = maxv[2] = -1e20;
427 minvert[0] = minvert[1] = minvert[2] = NULL;
428 maxvert[0] = maxvert[1] = maxvert[2] = NULL;
430 for (v = (PVert*)chart->verts->first; v; v=v->link.next) {
431 for (i = 0; i < 3; i++) {
432 if (v->co[i] < minv[i]) {
436 if (v->co[i] > maxv[i]) {
443 /* find axes with longest distance */
447 for (i = 0; i < 3; i++) {
448 if (maxv[i] - minv[i] > dirlen) {
450 dirlen = maxv[i] - minv[i];
454 if (minvert[dir] == maxvert[dir]) {
455 /* degenerate case */
456 PFace *f = (PFace*)chart->faces->first;
458 *v2 = f->edge->next->vert;
469 (*v1)->uv[0] = (*v1)->co[dir];
470 (*v1)->uv[1] = (*v1)->co[(dir+1)%3];
471 (*v2)->uv[0] = (*v2)->co[dir];
472 (*v2)->uv[1] = (*v2)->co[(dir+1)%3];
476 static float p_vec_normalise(float *v)
480 d = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
493 static float p_vec_angle_cos(float *v1, float *v2, float *v3)
497 d1[0] = v1[0] - v2[0];
498 d1[1] = v1[1] - v2[1];
499 d1[2] = v1[2] - v2[2];
501 d2[0] = v3[0] - v2[0];
502 d2[1] = v3[1] - v2[1];
503 d2[2] = v3[2] - v2[2];
508 return d1[0]*d2[0] + d1[1]*d2[1] + d1[2]*d2[2];
511 static float p_vec_angle(float *v1, float *v2, float *v3)
513 float dot = p_vec_angle_cos(v1, v2, v3);
517 else if (dot >= 1.0f)
520 return (float)acos(dot);
523 static void p_face_angles(PFace *f, float *a1, float *a2, float *a3)
525 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
526 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
528 *a1 = p_vec_angle(v3->co, v1->co, v2->co);
529 *a2 = p_vec_angle(v1->co, v2->co, v3->co);
530 *a3 = M_PI - *a2 - *a1;
533 static float p_face_area(PFace *f)
535 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
536 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
538 return AreaT3Dfl(v1->co, v2->co, v3->co);
541 static float p_face_uv_area_signed(PFace *f)
543 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
544 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
546 return 0.5f*(((v2->uv[0]-v1->uv[0]) * (v3->uv[1]-v1->uv[1])) -
547 ((v3->uv[0]-v1->uv[0]) * (v2->uv[1]-v1->uv[1])));
550 static float p_face_uv_area(PFace *f)
552 return fabs(p_face_uv_area_signed(f));
555 static void p_chart_area(PChart *chart, float *uv_area, float *area)
559 *uv_area = *area = 0.0f;
561 for (f=(PFace*)chart->faces->first; f; f=f->link.next) {
562 *uv_area += p_face_uv_area(f);
563 *area += p_face_area(f);
567 static PChart *p_chart_new(PHandle *handle)
569 PChart *chart = (PChart*)MEM_callocN(sizeof*chart, "PChart");
570 chart->verts = phash_new(1);
571 chart->edges = phash_new(1);
572 chart->faces = phash_new(1);
573 chart->handle = handle;
578 static void p_chart_delete(PChart *chart)
580 /* the actual links are free by memarena */
581 phash_delete(chart->verts);
582 phash_delete(chart->edges);
583 phash_delete(chart->faces);
588 static PBool p_edge_implicit_seam(PEdge *e, PEdge *ep)
590 float *uv1, *uv2, *uvp1, *uvp2;
594 uv2 = e->next->orig_uv;
596 if (e->vert->link.key == ep->vert->link.key) {
598 uvp2 = ep->next->orig_uv;
601 uvp1 = ep->next->orig_uv;
605 get_connected_limit_tface_uv(limit);
607 if((fabs(uv1[0]-uvp1[0]) > limit[0]) && (fabs(uv1[1]-uvp1[1]) > limit[1])) {
608 e->flag |= PEDGE_SEAM;
609 ep->flag |= PEDGE_SEAM;
612 if((fabs(uv2[0]-uvp2[0]) > limit[0]) && (fabs(uv2[1]-uvp2[1]) > limit[1])) {
613 e->flag |= PEDGE_SEAM;
614 ep->flag |= PEDGE_SEAM;
621 static PBool p_edge_has_pair(PChart *chart, PEdge *e, PEdge **pair, PBool impl)
626 PHashKey key1 = e->vert->link.key;
627 PHashKey key2 = e->next->vert->link.key;
629 if (e->flag & PEDGE_SEAM)
633 pe = (PEdge*)phash_lookup(chart->edges, key);
641 if (((v1->link.key == key1) && (v2->link.key == key2)) ||
642 ((v1->link.key == key2) && (v2->link.key == key1))) {
644 /* don't connect seams and t-junctions */
645 if ((pe->flag & PEDGE_SEAM) || *pair ||
646 (impl && p_edge_implicit_seam(e, pe))) {
655 pe = (PEdge*)phash_next(chart->edges, key, (PHashLink*)pe);
658 if (*pair && (e->vert == (*pair)->vert)) {
659 if ((*pair)->next->pair || (*pair)->next->next->pair) {
660 /* non unfoldable, maybe mobius ring or klein bottle */
666 return (*pair != NULL);
669 static PBool p_edge_connect_pair(PChart *chart, PEdge *e, PEdge ***stack, PBool impl)
673 if(!e->pair && p_edge_has_pair(chart, e, &pair, impl)) {
674 if (e->vert == pair->vert)
675 p_face_flip(pair->face);
680 if (!(pair->face->flag & PFACE_CONNECTED)) {
686 return (e->pair != NULL);
689 static int p_connect_pairs(PChart *chart, PBool impl)
691 PEdge **stackbase = MEM_mallocN(sizeof*stackbase * phash_size(chart->faces), "Pstackbase");
692 PEdge **stack = stackbase;
697 /* connect pairs, count edges, set vertex-edge pointer to a pairless edge */
698 for (first=(PFace*)chart->faces->first; first; first=first->link.next) {
699 if (first->flag & PFACE_CONNECTED)
702 *stack = first->edge;
705 while (stack != stackbase) {
712 f->flag |= PFACE_CONNECTED;
714 /* assign verts to charts so we can sort them later */
715 f->u.chart = ncharts;
717 if (!p_edge_connect_pair(chart, e, &stack, impl))
719 if (!p_edge_connect_pair(chart, e1, &stack, impl))
721 if (!p_edge_connect_pair(chart, e2, &stack, impl))
728 MEM_freeN(stackbase);
733 static void p_split_vert(PChart *chart, PEdge *e)
735 PEdge *we, *lastwe = NULL;
739 if (e->flag & PEDGE_VERTEX_SPLIT)
742 /* rewind to start */
744 for (we = p_wheel_edge_prev(e); we && (we != e); we = p_wheel_edge_prev(we))
747 /* go over all edges in wheel */
748 for (we = lastwe; we; we = p_wheel_edge_next(we)) {
749 if (we->flag & PEDGE_VERTEX_SPLIT)
752 we->flag |= PEDGE_VERTEX_SPLIT;
755 /* found it, no need to copy */
757 phash_insert(chart->verts, (PHashLink*)v);
762 /* not found, copying */
763 v = p_vert_copy(chart, v);
769 we = p_wheel_edge_next(we);
770 } while (we && (we != lastwe));
774 static PChart **p_split_charts(PHandle *handle, PChart *chart, int ncharts)
776 PChart **charts = MEM_mallocN(sizeof*charts * ncharts, "PCharts"), *nchart;
780 for (i = 0; i < ncharts; i++)
781 charts[i] = p_chart_new(handle);
783 f = (PFace*)chart->faces->first;
785 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
786 nextf = f->link.next;
788 nchart = charts[f->u.chart];
790 phash_insert(nchart->faces, (PHashLink*)f);
791 phash_insert(nchart->edges, (PHashLink*)e1);
792 phash_insert(nchart->edges, (PHashLink*)e2);
793 phash_insert(nchart->edges, (PHashLink*)e3);
795 p_split_vert(nchart, e1);
796 p_split_vert(nchart, e2);
797 p_split_vert(nchart, e3);
805 static void p_face_backup_uvs(PFace *f)
807 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
809 e1->old_uv[0] = e1->orig_uv[0];
810 e1->old_uv[1] = e1->orig_uv[1];
811 e2->old_uv[0] = e2->orig_uv[0];
812 e2->old_uv[1] = e2->orig_uv[1];
813 e3->old_uv[0] = e3->orig_uv[0];
814 e3->old_uv[1] = e3->orig_uv[1];
817 static void p_face_restore_uvs(PFace *f)
819 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
821 e1->orig_uv[0] = e1->old_uv[0];
822 e1->orig_uv[1] = e1->old_uv[1];
823 e2->orig_uv[0] = e2->old_uv[0];
824 e2->orig_uv[1] = e2->old_uv[1];
825 e3->orig_uv[0] = e3->old_uv[0];
826 e3->orig_uv[1] = e3->old_uv[1];
829 static PFace *p_face_add(PChart *chart, ParamKey key, ParamKey *vkeys,
830 float *co[3], float *uv[3], int i1, int i2, int i3,
831 ParamBool *pin, ParamBool *select)
837 f = (PFace*)BLI_memarena_alloc(chart->handle->arena, sizeof *f);
840 e1 = (PEdge*)BLI_memarena_alloc(chart->handle->arena, sizeof *e1);
841 e2 = (PEdge*)BLI_memarena_alloc(chart->handle->arena, sizeof *e2);
842 e3 = (PEdge*)BLI_memarena_alloc(chart->handle->arena, sizeof *e3);
849 e1->face = e2->face = e3->face = f;
865 e1->vert = p_vert_lookup(chart, vkeys[i1], co[i1], e1);
866 e2->vert = p_vert_lookup(chart, vkeys[i2], co[i2], e2);
867 e3->vert = p_vert_lookup(chart, vkeys[i3], co[i3], e3);
869 e1->orig_uv = uv[i1];
870 e2->orig_uv = uv[i2];
871 e3->orig_uv = uv[i3];
875 /* internal call to add face */
876 e1->vert = e2->vert = e3->vert = NULL;
877 e1->orig_uv = e2->orig_uv = e3->orig_uv = NULL;
881 if (pin[i1]) e1->flag |= PEDGE_PIN;
882 if (pin[i2]) e2->flag |= PEDGE_PIN;
883 if (pin[i3]) e3->flag |= PEDGE_PIN;
887 if (select[i1]) e1->flag |= PEDGE_SELECT;
888 if (select[i2]) e2->flag |= PEDGE_SELECT;
889 if (select[i3]) e3->flag |= PEDGE_SELECT;
892 /* insert into hash */
894 phash_insert(chart->faces, (PHashLink*)f);
896 e1->link.key = vkeys[i1]^vkeys[i2];
897 e2->link.key = vkeys[i2]^vkeys[i3];
898 e3->link.key = vkeys[i3]^vkeys[i1];
900 phash_insert(chart->edges, (PHashLink*)e1);
901 phash_insert(chart->edges, (PHashLink*)e2);
902 phash_insert(chart->edges, (PHashLink*)e3);
907 static PBool p_quad_split_direction(float **co)
911 a1 = p_vec_angle_cos(co[0], co[1], co[2]);
912 a1 += p_vec_angle_cos(co[1], co[0], co[2]);
913 a1 += p_vec_angle_cos(co[2], co[0], co[1]);
915 a2 = p_vec_angle_cos(co[0], co[1], co[3]);
916 a2 += p_vec_angle_cos(co[1], co[0], co[3]);
917 a2 += p_vec_angle_cos(co[3], co[0], co[1]);
922 static float p_edge_length(PEdge *e)
924 PVert *v1 = e->vert, *v2 = e->next->vert;
927 d[0] = v2->co[0] - v1->co[0];
928 d[1] = v2->co[1] - v1->co[1];
929 d[2] = v2->co[2] - v1->co[2];
931 return sqrt(d[0]*d[0] + d[1]*d[1] + d[2]*d[2]);
934 static float p_edge_uv_length(PEdge *e)
936 PVert *v1 = e->vert, *v2 = e->next->vert;
939 d[0] = v2->uv[0] - v1->uv[0];
940 d[1] = v2->uv[1] - v1->uv[1];
942 return sqrt(d[0]*d[0] + d[1]*d[1]);
945 void p_chart_uv_bbox(PChart *chart, float *minv, float *maxv)
949 INIT_MINMAX2(minv, maxv);
951 for (v=(PVert*)chart->verts->first; v; v=v->link.next) {
952 DO_MINMAX2(v->uv, minv, maxv);
956 static void p_chart_uv_scale(PChart *chart, float scale)
960 for (v=(PVert*)chart->verts->first; v; v=v->link.next) {
966 static void p_chart_uv_translate(PChart *chart, float trans[2])
970 for (v=(PVert*)chart->verts->first; v; v=v->link.next) {
971 v->uv[0] += trans[0];
972 v->uv[1] += trans[1];
976 static void p_chart_boundaries(PChart *chart, int *nboundaries, PEdge **outer)
979 float len, maxlen = -1.0;
984 for (e=(PEdge*)chart->edges->first; e; e=e->link.next) {
985 if (e->pair || (e->flag & PEDGE_DONE))
993 be->flag |= PEDGE_DONE;
994 len += p_edge_length(be);
995 be = be->next->vert->edge;
1004 for (e=(PEdge*)chart->edges->first; e; e=e->link.next)
1005 e->flag &= ~PEDGE_DONE;
1008 static float p_edge_boundary_angle(PEdge *e)
1017 /* concave angle check -- could be better */
1022 v1 = we->next->vert;
1023 v2 = we->next->next->vert;
1024 angle -= p_vec_angle(v1->co, v->co, v2->co);
1026 we = we->next->next->pair;
1028 } while (we && (we != v->edge));
1033 static PEdge *p_boundary_edge_next(PEdge *e)
1035 return e->next->vert->edge;
1038 static PEdge *p_boundary_edge_prev(PEdge *e)
1040 PEdge *we = e, *last;
1044 we = p_wheel_edge_next(we);
1045 } while (we && (we != e));
1047 return last->next->next;
1050 static void p_chart_fill_boundary(PChart *chart, PEdge *be, int nedges)
1055 struct PHeap *heap = pheap_new(nedges);
1060 angle = p_edge_boundary_angle(e);
1061 e->u.heaplink = pheap_insert(heap, angle, e);
1063 e = e->next->vert->edge;
1067 /* no real boundary, but an isolated seam */
1068 e = be->next->vert->edge;
1072 pheap_remove(heap, e->u.heaplink);
1073 pheap_remove(heap, be->u.heaplink);
1076 while (nedges > 2) {
1077 PEdge *ne, *ne1, *ne2;
1079 e = pheap_popmin(heap);
1081 e1 = p_boundary_edge_prev(e);
1082 e2 = p_boundary_edge_next(e);
1084 pheap_remove(heap, e1->u.heaplink);
1085 pheap_remove(heap, e2->u.heaplink);
1086 e->u.heaplink = e1->u.heaplink = e2->u.heaplink = NULL;
1088 e->flag |= PEDGE_FILLED;
1089 e1->flag |= PEDGE_FILLED;
1091 vkeys[0] = e->vert->link.key;
1092 vkeys[1] = e1->vert->link.key;
1093 vkeys[2] = e2->vert->link.key;
1095 f = p_face_add(chart, -1, vkeys, NULL, NULL, 0, 1, 2, NULL, NULL);
1096 f->flag |= PFACE_FILLED;
1098 ne = f->edge->next->next;
1100 ne2 = f->edge->next;
1102 ne->flag = ne1->flag = ne2->flag = PEDGE_FILLED;
1109 ne->vert = e2->vert;
1110 ne1->vert = e->vert;
1111 ne2->vert = e1->vert;
1118 ne2->vert->edge = ne2;
1120 ne2->u.heaplink = pheap_insert(heap, p_edge_boundary_angle(ne2), ne2);
1121 e2->u.heaplink = pheap_insert(heap, p_edge_boundary_angle(e2), e2);
1131 static void p_chart_fill_boundaries(PChart *chart, PEdge *outer)
1133 PEdge *e, *enext, *be;
1136 for (e=(PEdge*)chart->edges->first; e; e=e->link.next) {
1137 enext = e->link.next;
1139 if (e->pair || (e->flag & PEDGE_FILLED))
1145 be->flag |= PEDGE_FILLED;
1146 be = be->next->vert->edge;
1151 p_chart_fill_boundary(chart, e, nedges);
1155 static void p_flush_uvs(PChart *chart)
1159 for (e=(PEdge*)chart->edges->first; e; e=e->link.next) {
1161 e->orig_uv[0] = e->vert->uv[0];
1162 e->orig_uv[1] = e->vert->uv[1];
1167 static void p_flush_uvs_blend(PChart *chart, float blend)
1170 float invblend = 1.0f - blend;
1172 for (e=(PEdge*)chart->edges->first; e; e=e->link.next) {
1174 e->orig_uv[0] = blend*e->old_uv[0] + invblend*e->vert->uv[0];
1175 e->orig_uv[1] = blend*e->old_uv[1] + invblend*e->vert->uv[1];
1182 ParamHandle *param_construct_begin()
1184 PHandle *handle = MEM_callocN(sizeof*handle, "PHandle");
1185 handle->construction_chart = p_chart_new(handle);
1186 handle->state = PHANDLE_STATE_ALLOCATED;
1187 handle->arena = BLI_memarena_new((1<<16));
1189 return (ParamHandle*)handle;
1192 void param_delete(ParamHandle *handle)
1194 PHandle *phandle = (PHandle*)handle;
1197 param_assert((phandle->state == PHANDLE_STATE_ALLOCATED) ||
1198 (phandle->state == PHANDLE_STATE_CONSTRUCTED));
1200 for (i = 0; i < phandle->ncharts; i++)
1201 p_chart_delete(phandle->charts[i]);
1203 if (phandle->charts)
1204 MEM_freeN(phandle->charts);
1206 if (phandle->construction_chart)
1207 p_chart_delete(phandle->construction_chart);
1209 BLI_memarena_free(phandle->arena);
1213 void param_face_add(ParamHandle *handle, ParamKey key, int nverts,
1214 ParamKey *vkeys, float **co, float **uv,
1215 ParamBool *pin, ParamBool *select)
1217 PHandle *phandle = (PHandle*)handle;
1218 PChart *chart = phandle->construction_chart;
1220 param_assert(phash_lookup(chart->faces, key) == NULL);
1221 param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
1222 param_assert((nverts == 3) || (nverts == 4));
1225 if (!p_quad_split_direction(co)) {
1226 p_face_add(chart, key, vkeys, co, uv, 0, 1, 2, pin, select);
1227 p_face_add(chart, key, vkeys, co, uv, 0, 2, 3, pin, select);
1230 p_face_add(chart, key, vkeys, co, uv, 0, 1, 3, pin, select);
1231 p_face_add(chart, key, vkeys, co, uv, 1, 2, 3, pin, select);
1235 p_face_add(chart, key, vkeys, co, uv, 0, 1, 2, pin, select);
1238 void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys)
1240 PHandle *phandle = (PHandle*)handle;
1241 PChart *chart = phandle->construction_chart;
1244 param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
1246 e = p_edge_lookup(chart, vkeys);
1248 e->flag |= PEDGE_SEAM;
1251 void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool impl)
1253 PHandle *phandle = (PHandle*)handle;
1254 PChart *chart = phandle->construction_chart;
1255 int i, j, nboundaries = 0;
1258 param_assert(phandle->state == PHANDLE_STATE_ALLOCATED);
1260 phandle->ncharts = p_connect_pairs(chart, impl);
1261 phandle->charts = p_split_charts(phandle, chart, phandle->ncharts);
1263 p_chart_delete(chart);
1264 phandle->construction_chart = NULL;
1266 for (i = j = 0; i < phandle->ncharts; i++) {
1267 p_chart_boundaries(phandle->charts[i], &nboundaries, &outer);
1269 if (nboundaries == 0) {
1270 p_chart_delete(phandle->charts[i]);
1274 phandle->charts[j] = phandle->charts[i];
1278 if (fill && (nboundaries > 1))
1279 p_chart_fill_boundaries(phandle->charts[i], outer);
1283 phandle->ncharts = j;
1285 phandle->state = PHANDLE_STATE_CONSTRUCTED;
1288 /* Least Squares Conformal Maps */
1290 static void p_chart_lscm_load_solution(PChart *chart)
1294 for (v=(PVert*)chart->verts->first; v; v=v->link.next) {
1295 v->uv[0] = nlGetVariable(2*v->u.index);
1296 v->uv[1] = nlGetVariable(2*v->u.index + 1);
1300 static void p_chart_lscm_begin(PChart *chart, PBool live)
1302 PVert *v, *pin1, *pin2;
1303 PBool select = P_FALSE;
1304 int npins = 0, id = 0;
1306 /* give vertices matrix indices and count pins */
1307 for (v=(PVert*)chart->verts->first; v; v=v->link.next) {
1308 p_vert_load_pin_select_uvs(v);
1310 if (v->flag & PVERT_PIN)
1313 if (v->flag & PVERT_SELECT)
1319 if ((live && !select) || (npins == 1)) {
1320 chart->u.lscm.context = NULL;
1324 /* not enough pins, lets find some ourself */
1325 p_extrema_verts(chart, &pin1, &pin2);
1327 chart->u.lscm.pin1 = pin1;
1328 chart->u.lscm.pin2 = pin2;
1331 chart->flag |= PCHART_NOPACK;
1335 nlSolverParameteri(NL_NB_VARIABLES, 2*phash_size(chart->verts));
1336 nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
1338 chart->u.lscm.context = nlGetCurrent();
1342 static PBool p_chart_lscm_solve(PChart *chart)
1344 PVert *v, *pin1 = chart->u.lscm.pin1, *pin2 = chart->u.lscm.pin2;
1347 nlMakeCurrent(chart->u.lscm.context);
1351 for (v=(PVert*)chart->verts->first; v; v=v->link.next)
1352 if (v->flag & PVERT_PIN)
1353 p_vert_load_pin_select_uvs(v);
1355 if (chart->u.lscm.pin1) {
1356 nlLockVariable(2*pin1->u.index);
1357 nlLockVariable(2*pin1->u.index + 1);
1358 nlLockVariable(2*pin2->u.index);
1359 nlLockVariable(2*pin2->u.index + 1);
1361 nlSetVariable(2*pin1->u.index, pin1->uv[0]);
1362 nlSetVariable(2*pin1->u.index + 1, pin1->uv[1]);
1363 nlSetVariable(2*pin2->u.index, pin2->uv[0]);
1364 nlSetVariable(2*pin2->u.index + 1, pin2->uv[1]);
1367 /* set and lock the pins */
1368 for (v=(PVert*)chart->verts->first; v; v=v->link.next) {
1369 if (v->flag & PVERT_PIN) {
1370 nlLockVariable(2*v->u.index);
1371 nlLockVariable(2*v->u.index + 1);
1373 nlSetVariable(2*v->u.index, v->uv[0]);
1374 nlSetVariable(2*v->u.index + 1, v->uv[1]);
1379 /* construct matrix */
1383 for (f=(PFace*)chart->faces->first; f; f=f->link.next) {
1384 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
1385 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
1386 float a1, a2, a3, ratio, cosine, sine;
1387 float sina1, sina2, sina3, sinmax;
1389 if (chart->u.lscm.abf_alpha) {
1390 /* use abf angles if passed on */
1391 a1 = *(chart->u.lscm.abf_alpha++);
1392 a2 = *(chart->u.lscm.abf_alpha++);
1393 a3 = *(chart->u.lscm.abf_alpha++);
1396 p_face_angles(f, &a1, &a2, &a3);
1402 sinmax = MAX3(sina1, sina2, sina3);
1404 /* shift vertices to find most stable order */
1405 #define SHIFT3(type, a, b, c) \
1406 { type tmp; tmp = a; a = c; c = b; b = tmp; }
1408 if (sina3 != sinmax) {
1409 SHIFT3(PVert*, v1, v2, v3);
1410 SHIFT3(float, a1, a2, a3);
1411 SHIFT3(float, sina1, sina2, sina3);
1413 if (sina2 == sinmax) {
1414 SHIFT3(PVert*, v1, v2, v3);
1415 SHIFT3(float, a1, a2, a3);
1416 SHIFT3(float, sina1, sina2, sina3);
1420 /* angle based lscm formulation */
1421 ratio = (sina3 == 0.0f)? 0.0f: sina2/sina3;
1422 cosine = cos(a1)*ratio;
1426 nlCoefficient(2*v1->u.index, cosine - 1.0);
1427 nlCoefficient(2*v1->u.index+1, -sine);
1428 nlCoefficient(2*v2->u.index, -cosine);
1429 nlCoefficient(2*v2->u.index+1, sine);
1430 nlCoefficient(2*v3->u.index, 1.0);
1434 nlCoefficient(2*v1->u.index, sine);
1435 nlCoefficient(2*v1->u.index+1, cosine - 1.0);
1436 nlCoefficient(2*v2->u.index, -sine);
1437 nlCoefficient(2*v2->u.index+1, -cosine);
1438 nlCoefficient(2*v3->u.index+1, 1.0);
1446 if (nlSolveAdvanced(NULL, NL_TRUE)) {
1447 p_chart_lscm_load_solution(chart);
1454 static void p_chart_lscm_end(PChart *chart)
1456 if (chart->u.lscm.context)
1457 nlDeleteContext(chart->u.lscm.context);
1459 chart->u.lscm.context = NULL;
1460 chart->u.lscm.pin1 = NULL;
1461 chart->u.lscm.pin2 = NULL;
1464 void param_lscm_begin(ParamHandle *handle, ParamBool live)
1466 PHandle *phandle = (PHandle*)handle;
1469 param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
1470 phandle->state = PHANDLE_STATE_LSCM;
1472 for (i = 0; i < phandle->ncharts; i++)
1473 p_chart_lscm_begin(phandle->charts[i], live);
1476 void param_lscm_solve(ParamHandle *handle)
1478 PHandle *phandle = (PHandle*)handle;
1483 param_assert(phandle->state == PHANDLE_STATE_LSCM);
1485 for (i = 0; i < phandle->ncharts; i++) {
1486 chart = phandle->charts[i];
1488 if (chart->u.lscm.context) {
1489 result = p_chart_lscm_solve(chart);
1491 if (!result || (chart->u.lscm.pin1))
1492 p_chart_lscm_end(chart);
1497 void param_lscm_end(ParamHandle *handle)
1499 PHandle *phandle = (PHandle*)handle;
1502 param_assert(phandle->state == PHANDLE_STATE_LSCM);
1504 for (i = 0; i < phandle->ncharts; i++)
1505 p_chart_lscm_end(phandle->charts[i]);
1507 phandle->state = PHANDLE_STATE_CONSTRUCTED;
1512 #define P_STRETCH_ITER 20
1514 static void p_stretch_pin_boundary(PChart *chart)
1518 for(v=(PVert*)chart->verts->first; v; v=v->link.next)
1519 if (v->edge->pair == NULL)
1520 v->flag |= PVERT_PIN;
1522 v->flag &= ~PVERT_PIN;
1525 static float p_face_stretch(PFace *f)
1530 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
1531 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
1533 area = p_face_uv_area_signed(f);
1535 if (area <= 0.0f) /* flipped face -> infinite stretch */
1538 if (f->flag & PFACE_FILLED)
1541 w= 1.0f/(2.0f*area);
1543 /* compute derivatives */
1544 VecCopyf(Ps, v1->co);
1545 VecMulf(Ps, (v2->uv[1] - v3->uv[1]));
1547 VecCopyf(tmp, v2->co);
1548 VecMulf(tmp, (v3->uv[1] - v1->uv[1]));
1549 VecAddf(Ps, Ps, tmp);
1551 VecCopyf(tmp, v3->co);
1552 VecMulf(tmp, (v1->uv[1] - v2->uv[1]));
1553 VecAddf(Ps, Ps, tmp);
1557 VecCopyf(Pt, v1->co);
1558 VecMulf(Pt, (v3->uv[0] - v2->uv[0]));
1560 VecCopyf(tmp, v2->co);
1561 VecMulf(tmp, (v1->uv[0] - v3->uv[0]));
1562 VecAddf(Pt, Pt, tmp);
1564 VecCopyf(tmp, v3->co);
1565 VecMulf(tmp, (v2->uv[0] - v1->uv[0]));
1566 VecAddf(Pt, Pt, tmp);
1574 T = sqrt(0.5f*(a + c)*f->u.area3d);
1579 static float p_stretch_compute_vertex(PVert *v)
1585 sum += p_face_stretch(e->face);
1586 e = p_wheel_edge_next(e);
1587 } while (e && e != (v->edge));
1592 static void p_chart_stretch_minimize(PChart *chart, RNG *rng)
1597 float orig_stretch, low, stretch_low, high, stretch_high, mid, stretch;
1598 float orig_uv[2], dir[2], random_angle, trusted_radius;
1600 for(v=(PVert*)chart->verts->first; v; v=v->link.next) {
1601 if((v->flag & PVERT_PIN) || !(v->flag & PVERT_SELECT))
1604 orig_stretch = p_stretch_compute_vertex(v);
1605 orig_uv[0] = v->uv[0];
1606 orig_uv[1] = v->uv[1];
1608 /* move vertex in a random direction */
1609 trusted_radius = 0.0f;
1614 trusted_radius += p_edge_uv_length(e);
1617 e = p_wheel_edge_next(e);
1618 } while (e && e != (v->edge));
1620 trusted_radius /= 2 * nedges;
1622 random_angle = rng_getFloat(rng) * 2.0 * M_PI;
1623 dir[0] = trusted_radius * cos(random_angle);
1624 dir[1] = trusted_radius * sin(random_angle);
1626 /* calculate old and new stretch */
1628 stretch_low = orig_stretch;
1630 Vec2Addf(v->uv, orig_uv, dir);
1632 stretch = stretch_high = p_stretch_compute_vertex(v);
1634 /* binary search for lowest stretch position */
1635 for (j = 0; j < P_STRETCH_ITER; j++) {
1636 mid = 0.5 * (low + high);
1637 v->uv[0]= orig_uv[0] + mid*dir[0];
1638 v->uv[1]= orig_uv[1] + mid*dir[1];
1639 stretch = p_stretch_compute_vertex(v);
1641 if (stretch_low < stretch_high) {
1643 stretch_high = stretch;
1647 stretch_low = stretch;
1651 /* no luck, stretch has increased, reset to old values */
1652 if(stretch >= orig_stretch)
1653 Vec2Copyf(v->uv, orig_uv);
1657 void param_stretch_begin(ParamHandle *handle)
1659 PHandle *phandle = (PHandle*)handle;
1665 param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
1666 phandle->state = PHANDLE_STATE_STRETCH;
1668 phandle->rng = rng_new(31415926);
1669 phandle->blend = 0.0f;
1671 for (i = 0; i < phandle->ncharts; i++) {
1672 chart = phandle->charts[i];
1674 for (v=(PVert*)chart->verts->first; v; v=v->link.next)
1675 p_vert_load_select_uvs(v);
1677 p_stretch_pin_boundary(chart);
1679 for (f=(PFace*)chart->faces->first; f; f=f->link.next) {
1680 p_face_backup_uvs(f);
1681 f->u.area3d = p_face_area(f);
1686 void param_stretch_blend(ParamHandle *handle, float blend)
1688 PHandle *phandle = (PHandle*)handle;
1690 param_assert(phandle->state == PHANDLE_STATE_STRETCH);
1691 phandle->blend = blend;
1694 void param_stretch_iter(ParamHandle *handle)
1696 PHandle *phandle = (PHandle*)handle;
1700 param_assert(phandle->state == PHANDLE_STATE_STRETCH);
1702 for (i = 0; i < phandle->ncharts; i++) {
1703 chart = phandle->charts[i];
1704 p_chart_stretch_minimize(chart, phandle->rng);
1708 void param_stretch_end(ParamHandle *handle)
1710 PHandle *phandle = (PHandle*)handle;
1712 param_assert(phandle->state == PHANDLE_STATE_STRETCH);
1713 phandle->state = PHANDLE_STATE_CONSTRUCTED;
1715 rng_free(phandle->rng);
1716 phandle->rng = NULL;
1721 void param_flush(ParamHandle *handle)
1723 PHandle *phandle = (PHandle*)handle;
1727 for (i = 0; i < phandle->ncharts; i++) {
1728 chart = phandle->charts[i];
1730 if ((phandle->state == PHANDLE_STATE_LSCM) && !chart->u.lscm.context)
1733 if (phandle->blend == 0.0f)
1736 p_flush_uvs_blend(chart, phandle->blend);
1740 void param_flush_restore(ParamHandle *handle)
1742 PHandle *phandle = (PHandle*)handle;
1747 for (i = 0; i < phandle->ncharts; i++) {
1748 chart = phandle->charts[i];
1750 for (f=(PFace*)chart->faces->first; f; f=f->link.next)
1751 p_face_restore_uvs(f);
1757 static int compare_chart_area(const void *a, const void *b)
1759 PChart *ca = *((PChart**)a);
1760 PChart *cb = *((PChart**)b);
1762 if (ca->u.pack.area > cb->u.pack.area)
1764 else if (ca->u.pack.area == cb->u.pack.area)
1770 static PBool p_pack_try(PHandle *handle, float side)
1773 float packx, packy, rowh, groupw, w, h;
1778 groupw= 1.0/sqrt(handle->ncharts);
1780 for (i = 0; i < handle->ncharts; i++) {
1781 chart = handle->charts[i];
1783 if (chart->flag & PCHART_NOPACK)
1786 w = chart->u.pack.size[0];
1787 h = chart->u.pack.size[1];
1789 if(w <= (side-packx)) {
1790 chart->u.pack.trans[0] = packx;
1791 chart->u.pack.trans[1] = packy;
1794 rowh= MAX2(rowh, h);
1801 chart->u.pack.trans[0] = 0.0;
1802 chart->u.pack.trans[1] = packy;
1805 if (packy+rowh > side)
1812 #define PACK_SEARCH_DEPTH 15
1814 void param_pack(ParamHandle *handle)
1816 PHandle *phandle = (PHandle*)handle;
1818 float uv_area, area, trans[2], minside, maxside, totarea, side;
1821 /* very simple rectangle packing */
1823 if (phandle->ncharts == 0)
1829 for (i = 0; i < phandle->ncharts; i++) {
1830 chart = phandle->charts[i];
1832 if (chart->flag & PCHART_NOPACK) {
1833 chart->u.pack.area = 0.0f;
1837 p_chart_area(chart, &uv_area, &area);
1838 p_chart_uv_bbox(chart, trans, chart->u.pack.size);
1840 /* translate to origin and make area equal to 3d area */
1841 chart->u.pack.rescale = (uv_area > 0.0f)? sqrt(area)/sqrt(uv_area): 0.0f;
1842 chart->u.pack.area = area;
1845 trans[0] = -trans[0];
1846 trans[1] = -trans[1];
1847 p_chart_uv_translate(chart, trans);
1848 p_chart_uv_scale(chart, chart->u.pack.rescale);
1850 /* compute new dimensions for packing */
1851 chart->u.pack.size[0] += trans[0];
1852 chart->u.pack.size[1] += trans[1];
1853 chart->u.pack.size[0] *= chart->u.pack.rescale;
1854 chart->u.pack.size[1] *= chart->u.pack.rescale;
1856 maxside = MAX3(maxside, chart->u.pack.size[0], chart->u.pack.size[1]);
1859 /* sort by chart area, largest first */
1860 qsort(phandle->charts, phandle->ncharts, sizeof(PChart*), compare_chart_area);
1862 /* binary search over pack region size */
1863 minside = MAX2(sqrt(totarea), maxside);
1864 maxside = (((int)sqrt(phandle->ncharts-1))+1)*maxside;
1866 if (minside < maxside) { /* should always be true */
1868 for (i = 0; i < PACK_SEARCH_DEPTH; i++) {
1869 if (p_pack_try(phandle, (minside+maxside)*0.5f + 1e-5))
1870 maxside = (minside+maxside)*0.5f;
1872 minside = (minside+maxside)*0.5f;
1876 /* do the actual packing */
1877 side = maxside + 1e-5;
1878 if (!p_pack_try(phandle, side))
1879 param_warning("packing failed.\n");
1881 for (i = 0; i < phandle->ncharts; i++) {
1882 chart = phandle->charts[i];
1884 if (chart->flag & PCHART_NOPACK)
1887 p_chart_uv_scale(chart, 1.0f/side);
1888 trans[0] = chart->u.pack.trans[0]/side;
1889 trans[1] = chart->u.pack.trans[1]/side;
1890 p_chart_uv_translate(chart, trans);