2 #include "MEM_guardedalloc.h"
4 #include "BLI_memarena.h"
5 #include "BLI_arithb.h"
8 #include "BLI_boxpack2d.h"
10 #include "BKE_utildefines.h"
12 #include "BIF_editsima.h"
13 #include "BIF_toolbox.h"
15 #include "ONL_opennl.h"
17 #include "parametrizer.h"
18 #include "parametrizer_intern.h"
25 #include "BLO_sys_types.h" // for intptr_t support
28 #define M_PI 3.14159265358979323846
32 - special purpose hash that keeps all its elements in a single linked list.
33 - after construction, this hash is thrown away, and the list remains.
34 - removing elements is not possible efficiently.
37 static int PHashSizes[] = {
38 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
39 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
40 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459
43 #define PHASH_hash(ph, item) (((uintptr_t) (item))%((unsigned int) (ph)->cursize))
44 #define PHASH_edge(v1, v2) ((v1)^(v2))
46 static PHash *phash_new(PHashLink **list, int sizehint)
48 PHash *ph = (PHash*)MEM_callocN(sizeof(PHash), "PHash");
53 while (PHashSizes[ph->cursize_id] < sizehint)
56 ph->cursize = PHashSizes[ph->cursize_id];
57 ph->buckets = (PHashLink**)MEM_callocN(ph->cursize*sizeof(*ph->buckets), "PHashBuckets");
62 static void phash_delete(PHash *ph)
64 MEM_freeN(ph->buckets);
68 static int phash_size(PHash *ph)
73 static void phash_insert(PHash *ph, PHashLink *link)
75 int size = ph->cursize;
76 int hash = PHASH_hash(ph, link->key);
77 PHashLink *lookup = ph->buckets[hash];
80 /* insert in front of the list */
81 ph->buckets[hash] = link;
82 link->next = *(ph->list);
86 /* insert after existing element */
87 link->next = lookup->next;
93 if (ph->size > (size*3)) {
94 PHashLink *next = NULL, *first = *(ph->list);
96 ph->cursize = PHashSizes[++ph->cursize_id];
97 MEM_freeN(ph->buckets);
98 ph->buckets = (PHashLink**)MEM_callocN(ph->cursize*sizeof(*ph->buckets), "PHashBuckets");
102 for (link = first; link; link = next) {
104 phash_insert(ph, link);
109 static PHashLink *phash_lookup(PHash *ph, PHashKey key)
112 int hash = PHASH_hash(ph, key);
114 for (link = ph->buckets[hash]; link; link = link->next)
115 if (link->key == key)
117 else if (PHASH_hash(ph, link->key) != hash)
123 static PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link)
125 int hash = PHASH_hash(ph, key);
127 for (link = link->next; link; link = link->next)
128 if (link->key == key)
130 else if (PHASH_hash(ph, link->key) != hash)
138 static float p_vec_angle_cos(float *v1, float *v2, float *v3)
142 d1[0] = v1[0] - v2[0];
143 d1[1] = v1[1] - v2[1];
144 d1[2] = v1[2] - v2[2];
146 d2[0] = v3[0] - v2[0];
147 d2[1] = v3[1] - v2[1];
148 d2[2] = v3[2] - v2[2];
153 return d1[0]*d2[0] + d1[1]*d2[1] + d1[2]*d2[2];
156 static float p_vec_angle(float *v1, float *v2, float *v3)
158 float dot = p_vec_angle_cos(v1, v2, v3);
162 else if (dot >= 1.0f)
165 return (float)acos(dot);
168 static float p_vec2_angle(float *v1, float *v2, float *v3)
170 float u1[3], u2[3], u3[3];
172 u1[0] = v1[0]; u1[1] = v1[1]; u1[2] = 0.0f;
173 u2[0] = v2[0]; u2[1] = v2[1]; u2[2] = 0.0f;
174 u3[0] = v3[0]; u3[1] = v3[1]; u3[2] = 0.0f;
176 return p_vec_angle(u1, u2, u3);
179 static void p_triangle_angles(float *v1, float *v2, float *v3, float *a1, float *a2, float *a3)
181 *a1 = p_vec_angle(v3, v1, v2);
182 *a2 = p_vec_angle(v1, v2, v3);
183 *a3 = M_PI - *a2 - *a1;
186 static void p_face_angles(PFace *f, float *a1, float *a2, float *a3)
188 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
189 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
191 p_triangle_angles(v1->co, v2->co, v3->co, a1, a2, a3);
194 static float p_face_area(PFace *f)
196 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
197 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
199 return AreaT3Dfl(v1->co, v2->co, v3->co);
202 static float p_area_signed(float *v1, float *v2, float *v3)
204 return 0.5f*(((v2[0] - v1[0])*(v3[1] - v1[1])) -
205 ((v3[0] - v1[0])*(v2[1] - v1[1])));
208 static float p_face_uv_area_signed(PFace *f)
210 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
211 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
213 return 0.5f*(((v2->uv[0] - v1->uv[0])*(v3->uv[1] - v1->uv[1])) -
214 ((v3->uv[0] - v1->uv[0])*(v2->uv[1] - v1->uv[1])));
217 static float p_edge_length(PEdge *e)
219 PVert *v1 = e->vert, *v2 = e->next->vert;
222 d[0] = v2->co[0] - v1->co[0];
223 d[1] = v2->co[1] - v1->co[1];
224 d[2] = v2->co[2] - v1->co[2];
226 return sqrt(d[0]*d[0] + d[1]*d[1] + d[2]*d[2]);
229 static float p_edge_uv_length(PEdge *e)
231 PVert *v1 = e->vert, *v2 = e->next->vert;
234 d[0] = v2->uv[0] - v1->uv[0];
235 d[1] = v2->uv[1] - v1->uv[1];
237 return sqrt(d[0]*d[0] + d[1]*d[1]);
240 static void p_chart_uv_bbox(PChart *chart, float *minv, float *maxv)
244 INIT_MINMAX2(minv, maxv);
246 for (v=chart->verts; v; v=v->nextlink) {
247 DO_MINMAX2(v->uv, minv, maxv);
251 static void p_chart_uv_scale(PChart *chart, float scale)
255 for (v=chart->verts; v; v=v->nextlink) {
261 static void p_chart_uv_scale_xy(PChart *chart, float x, float y)
265 for (v=chart->verts; v; v=v->nextlink) {
271 static void p_chart_uv_translate(PChart *chart, float trans[2])
275 for (v=chart->verts; v; v=v->nextlink) {
276 v->uv[0] += trans[0];
277 v->uv[1] += trans[1];
281 static PBool p_intersect_line_2d_dir(float *v1, float *dir1, float *v2, float *dir2, float *isect)
285 div= dir2[0]*dir1[1] - dir2[1]*dir1[0];
290 lmbda= ((v1[1]-v2[1])*dir1[0]-(v1[0]-v2[0])*dir1[1])/div;
291 isect[0] = v1[0] + lmbda*dir2[0];
292 isect[1] = v1[1] + lmbda*dir2[1];
298 static PBool p_intersect_line_2d(float *v1, float *v2, float *v3, float *v4, float *isect)
300 float dir1[2], dir2[2];
302 dir1[0] = v4[0] - v3[0];
303 dir1[1] = v4[1] - v3[1];
305 dir2[0] = v2[0] - v1[0];
306 dir2[1] = v2[1] - v1[1];
308 if (!p_intersect_line_2d_dir(v1, dir1, v2, dir2, isect)) {
309 /* parallel - should never happen in theory for polygon kernel, but
310 let's give a point nearby in case things go wrong */
311 isect[0] = (v1[0] + v2[0])*0.5f;
312 isect[1] = (v1[1] + v2[1])*0.5f;
320 /* Topological Utilities */
322 static PEdge *p_wheel_edge_next(PEdge *e)
324 return e->next->next->pair;
327 static PEdge *p_wheel_edge_prev(PEdge *e)
329 return (e->pair)? e->pair->next: NULL;
332 static PEdge *p_boundary_edge_next(PEdge *e)
334 return e->next->vert->edge;
337 static PEdge *p_boundary_edge_prev(PEdge *e)
339 PEdge *we = e, *last;
343 we = p_wheel_edge_next(we);
344 } while (we && (we != e));
346 return last->next->next;
349 static PBool p_vert_interior(PVert *v)
351 return (v->edge->pair != NULL);
354 static void p_face_flip(PFace *f)
356 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
357 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
358 int f1 = e1->flag, f2 = e2->flag, f3 = e3->flag;
362 e1->flag = (f1 & ~PEDGE_VERTEX_FLAGS) | (f2 & PEDGE_VERTEX_FLAGS);
366 e2->flag = (f2 & ~PEDGE_VERTEX_FLAGS) | (f3 & PEDGE_VERTEX_FLAGS);
370 e3->flag = (f3 & ~PEDGE_VERTEX_FLAGS) | (f1 & PEDGE_VERTEX_FLAGS);
374 static void p_chart_topological_sanity_check(PChart *chart)
379 for (v=chart->verts; v; v=v->nextlink)
380 param_test_equals_ptr("v->edge->vert", v, v->edge->vert);
382 for (e=chart->edges; e; e=e->nextlink) {
384 param_test_equals_ptr("e->pair->pair", e, e->pair->pair);
385 param_test_equals_ptr("pair->vert", e->vert, e->pair->next->vert);
386 param_test_equals_ptr("pair->next->vert", e->next->vert, e->pair->vert);
392 /* Loading / Flushing */
394 static void p_vert_load_pin_select_uvs(PHandle *handle, PVert *v)
397 int nedges = 0, npins = 0;
400 v->uv[0] = v->uv[1] = 0.0f;
401 pinuv[0] = pinuv[1] = 0.0f;
405 if (e->flag & PEDGE_SELECT)
406 v->flag |= PVERT_SELECT;
408 if (e->flag & PEDGE_PIN) {
409 pinuv[0] += e->orig_uv[0]*handle->aspx;
410 pinuv[1] += e->orig_uv[1]*handle->aspy;
414 v->uv[0] += e->orig_uv[0]*handle->aspx;
415 v->uv[1] += e->orig_uv[1]*handle->aspy;
421 e = p_wheel_edge_next(e);
422 } while (e && e != (v->edge));
425 v->uv[0] = pinuv[0]/npins;
426 v->uv[1] = pinuv[1]/npins;
427 v->flag |= PVERT_PIN;
429 else if (nedges > 0) {
435 static void p_flush_uvs(PHandle *handle, PChart *chart)
439 for (e=chart->edges; e; e=e->nextlink) {
441 e->orig_uv[0] = e->vert->uv[0]/handle->aspx;
442 e->orig_uv[1] = e->vert->uv[1]/handle->aspy;
447 static void p_flush_uvs_blend(PHandle *handle, PChart *chart, float blend)
450 float invblend = 1.0f - blend;
452 for (e=chart->edges; e; e=e->nextlink) {
454 e->orig_uv[0] = blend*e->old_uv[0] + invblend*e->vert->uv[0]/handle->aspx;
455 e->orig_uv[1] = blend*e->old_uv[1] + invblend*e->vert->uv[1]/handle->aspy;
460 static void p_face_backup_uvs(PFace *f)
462 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
464 if (e1->orig_uv && e2->orig_uv && e3->orig_uv) {
465 e1->old_uv[0] = e1->orig_uv[0];
466 e1->old_uv[1] = e1->orig_uv[1];
467 e2->old_uv[0] = e2->orig_uv[0];
468 e2->old_uv[1] = e2->orig_uv[1];
469 e3->old_uv[0] = e3->orig_uv[0];
470 e3->old_uv[1] = e3->orig_uv[1];
474 static void p_face_restore_uvs(PFace *f)
476 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
478 if (e1->orig_uv && e2->orig_uv && e3->orig_uv) {
479 e1->orig_uv[0] = e1->old_uv[0];
480 e1->orig_uv[1] = e1->old_uv[1];
481 e2->orig_uv[0] = e2->old_uv[0];
482 e2->orig_uv[1] = e2->old_uv[1];
483 e3->orig_uv[0] = e3->old_uv[0];
484 e3->orig_uv[1] = e3->old_uv[1];
488 /* Construction (use only during construction, relies on u.key being set */
490 static PVert *p_vert_add(PHandle *handle, PHashKey key, float *co, PEdge *e)
492 PVert *v = (PVert*)BLI_memarena_alloc(handle->arena, sizeof *v);
498 phash_insert(handle->hash_verts, (PHashLink*)v);
503 static PVert *p_vert_lookup(PHandle *handle, PHashKey key, float *co, PEdge *e)
505 PVert *v = (PVert*)phash_lookup(handle->hash_verts, key);
510 return p_vert_add(handle, key, co, e);
513 static PVert *p_vert_copy(PChart *chart, PVert *v)
515 PVert *nv = (PVert*)BLI_memarena_alloc(chart->handle->arena, sizeof *nv);
518 nv->uv[0] = v->uv[0];
519 nv->uv[1] = v->uv[1];
520 nv->u.key = v->u.key;
527 static PEdge *p_edge_lookup(PHandle *handle, PHashKey *vkeys)
529 PHashKey key = PHASH_edge(vkeys[0], vkeys[1]);
530 PEdge *e = (PEdge*)phash_lookup(handle->hash_edges, key);
533 if ((e->vert->u.key == vkeys[0]) && (e->next->vert->u.key == vkeys[1]))
535 else if ((e->vert->u.key == vkeys[1]) && (e->next->vert->u.key == vkeys[0]))
538 e = (PEdge*)phash_next(handle->hash_edges, key, (PHashLink*)e);
544 static PBool p_face_exists(PHandle *handle, PHashKey *vkeys, int i1, int i2, int i3)
546 PHashKey key = PHASH_edge(vkeys[i1], vkeys[i2]);
547 PEdge *e = (PEdge*)phash_lookup(handle->hash_edges, key);
550 if ((e->vert->u.key == vkeys[i1]) && (e->next->vert->u.key == vkeys[i2])) {
551 if (e->next->next->vert->u.key == vkeys[i3])
554 else if ((e->vert->u.key == vkeys[i2]) && (e->next->vert->u.key == vkeys[i1])) {
555 if (e->next->next->vert->u.key == vkeys[i3])
559 e = (PEdge*)phash_next(handle->hash_edges, key, (PHashLink*)e);
565 static PChart *p_chart_new(PHandle *handle)
567 PChart *chart = (PChart*)MEM_callocN(sizeof*chart, "PChart");
568 chart->handle = handle;
573 static void p_chart_delete(PChart *chart)
575 /* the actual links are free by memarena */
579 static PBool p_edge_implicit_seam(PEdge *e, PEdge *ep)
581 float *uv1, *uv2, *uvp1, *uvp2;
588 uv2 = e->next->orig_uv;
590 if (e->vert->u.key == ep->vert->u.key) {
592 uvp2 = ep->next->orig_uv;
595 uvp1 = ep->next->orig_uv;
599 if((fabs(uv1[0]-uvp1[0]) > limit[0]) || (fabs(uv1[1]-uvp1[1]) > limit[1])) {
600 e->flag |= PEDGE_SEAM;
601 ep->flag |= PEDGE_SEAM;
604 if((fabs(uv2[0]-uvp2[0]) > limit[0]) || (fabs(uv2[1]-uvp2[1]) > limit[1])) {
605 e->flag |= PEDGE_SEAM;
606 ep->flag |= PEDGE_SEAM;
613 static PBool p_edge_has_pair(PHandle *handle, PEdge *e, PEdge **pair, PBool impl)
618 PHashKey key1 = e->vert->u.key;
619 PHashKey key2 = e->next->vert->u.key;
621 if (e->flag & PEDGE_SEAM)
624 key = PHASH_edge(key1, key2);
625 pe = (PEdge*)phash_lookup(handle->hash_edges, key);
633 if (((v1->u.key == key1) && (v2->u.key == key2)) ||
634 ((v1->u.key == key2) && (v2->u.key == key1))) {
636 /* don't connect seams and t-junctions */
637 if ((pe->flag & PEDGE_SEAM) || *pair ||
638 (impl && p_edge_implicit_seam(e, pe))) {
647 pe = (PEdge*)phash_next(handle->hash_edges, key, (PHashLink*)pe);
650 if (*pair && (e->vert == (*pair)->vert)) {
651 if ((*pair)->next->pair || (*pair)->next->next->pair) {
652 /* non unfoldable, maybe mobius ring or klein bottle */
658 return (*pair != NULL);
661 static PBool p_edge_connect_pair(PHandle *handle, PEdge *e, PEdge ***stack, PBool impl)
665 if(!e->pair && p_edge_has_pair(handle, e, &pair, impl)) {
666 if (e->vert == pair->vert)
667 p_face_flip(pair->face);
672 if (!(pair->face->flag & PFACE_CONNECTED)) {
678 return (e->pair != NULL);
681 static int p_connect_pairs(PHandle *handle, PBool impl)
683 PEdge **stackbase = MEM_mallocN(sizeof*stackbase*phash_size(handle->hash_faces), "Pstackbase");
684 PEdge **stack = stackbase;
687 PChart *chart = handle->construction_chart;
690 /* connect pairs, count edges, set vertex-edge pointer to a pairless edge */
691 for (first=chart->faces; first; first=first->nextlink) {
692 if (first->flag & PFACE_CONNECTED)
695 *stack = first->edge;
698 while (stack != stackbase) {
705 f->flag |= PFACE_CONNECTED;
707 /* assign verts to charts so we can sort them later */
708 f->u.chart = ncharts;
710 if (!p_edge_connect_pair(handle, e, &stack, impl))
712 if (!p_edge_connect_pair(handle, e1, &stack, impl))
714 if (!p_edge_connect_pair(handle, e2, &stack, impl))
721 MEM_freeN(stackbase);
726 static void p_split_vert(PChart *chart, PEdge *e)
728 PEdge *we, *lastwe = NULL;
732 if (e->flag & PEDGE_VERTEX_SPLIT)
735 /* rewind to start */
737 for (we = p_wheel_edge_prev(e); we && (we != e); we = p_wheel_edge_prev(we))
740 /* go over all edges in wheel */
741 for (we = lastwe; we; we = p_wheel_edge_next(we)) {
742 if (we->flag & PEDGE_VERTEX_SPLIT)
745 we->flag |= PEDGE_VERTEX_SPLIT;
748 /* found it, no need to copy */
750 v->nextlink = chart->verts;
757 /* not found, copying */
758 v->flag |= PVERT_SPLIT;
759 v = p_vert_copy(chart, v);
760 v->flag |= PVERT_SPLIT;
762 v->nextlink = chart->verts;
771 we = p_wheel_edge_next(we);
772 } while (we && (we != lastwe));
776 static PChart **p_split_charts(PHandle *handle, PChart *chart, int ncharts)
778 PChart **charts = MEM_mallocN(sizeof*charts * ncharts, "PCharts"), *nchart;
782 for (i = 0; i < ncharts; i++)
783 charts[i] = p_chart_new(handle);
787 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
790 nchart = charts[f->u.chart];
792 f->nextlink = nchart->faces;
794 e1->nextlink = nchart->edges;
796 e2->nextlink = nchart->edges;
798 e3->nextlink = nchart->edges;
804 p_split_vert(nchart, e1);
805 p_split_vert(nchart, e2);
806 p_split_vert(nchart, e3);
814 static PFace *p_face_add(PHandle *handle)
820 f = (PFace*)BLI_memarena_alloc(handle->arena, sizeof *f);
823 e1 = (PEdge*)BLI_memarena_alloc(handle->arena, sizeof *e1);
824 e2 = (PEdge*)BLI_memarena_alloc(handle->arena, sizeof *e2);
825 e3 = (PEdge*)BLI_memarena_alloc(handle->arena, sizeof *e3);
829 e1->face = e2->face = e3->face = f;
846 static PFace *p_face_add_construct(PHandle *handle, ParamKey key, ParamKey *vkeys,
847 float *co[3], float *uv[3], int i1, int i2, int i3,
848 ParamBool *pin, ParamBool *select)
850 PFace *f = p_face_add(handle);
851 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
853 e1->vert = p_vert_lookup(handle, vkeys[i1], co[i1], e1);
854 e2->vert = p_vert_lookup(handle, vkeys[i2], co[i2], e2);
855 e3->vert = p_vert_lookup(handle, vkeys[i3], co[i3], e3);
857 e1->orig_uv = uv[i1];
858 e2->orig_uv = uv[i2];
859 e3->orig_uv = uv[i3];
862 if (pin[i1]) e1->flag |= PEDGE_PIN;
863 if (pin[i2]) e2->flag |= PEDGE_PIN;
864 if (pin[i3]) e3->flag |= PEDGE_PIN;
868 if (select[i1]) e1->flag |= PEDGE_SELECT;
869 if (select[i2]) e2->flag |= PEDGE_SELECT;
870 if (select[i3]) e3->flag |= PEDGE_SELECT;
873 /* insert into hash */
875 phash_insert(handle->hash_faces, (PHashLink*)f);
877 e1->u.key = PHASH_edge(vkeys[i1], vkeys[i2]);
878 e2->u.key = PHASH_edge(vkeys[i2], vkeys[i3]);
879 e3->u.key = PHASH_edge(vkeys[i3], vkeys[i1]);
881 phash_insert(handle->hash_edges, (PHashLink*)e1);
882 phash_insert(handle->hash_edges, (PHashLink*)e2);
883 phash_insert(handle->hash_edges, (PHashLink*)e3);
888 static PFace *p_face_add_fill(PChart *chart, PVert *v1, PVert *v2, PVert *v3)
890 PFace *f = p_face_add(chart->handle);
891 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
897 e1->orig_uv = e2->orig_uv = e3->orig_uv = NULL;
899 f->nextlink = chart->faces;
901 e1->nextlink = chart->edges;
903 e2->nextlink = chart->edges;
905 e3->nextlink = chart->edges;
914 static PBool p_quad_split_direction(PHandle *handle, float **co, PHashKey *vkeys)
916 float fac= VecLenf(co[0], co[2]) - VecLenf(co[1], co[3]);
917 PBool dir = (fac <= 0.0f);
919 /* the face exists check is there because of a special case: when
920 two quads share three vertices, they can each be split into two
921 triangles, resulting in two identical triangles. for example in
924 if (p_face_exists(handle,vkeys,0,1,2) || p_face_exists(handle,vkeys,0,2,3))
928 if (p_face_exists(handle,vkeys,0,1,3) || p_face_exists(handle,vkeys,1,2,3))
935 /* Construction: boundary filling */
937 static void p_chart_boundaries(PChart *chart, int *nboundaries, PEdge **outer)
940 float len, maxlen = -1.0;
947 for (e=chart->edges; e; e=e->nextlink) {
948 if (e->pair || (e->flag & PEDGE_DONE))
958 be->flag |= PEDGE_DONE;
959 len += p_edge_length(be);
960 be = be->next->vert->edge;
963 if (outer && (len > maxlen)) {
969 for (e=chart->edges; e; e=e->nextlink)
970 e->flag &= ~PEDGE_DONE;
973 static float p_edge_boundary_angle(PEdge *e)
982 /* concave angle check -- could be better */
988 v2 = we->next->next->vert;
989 angle -= p_vec_angle(v1->co, v->co, v2->co);
991 we = we->next->next->pair;
993 } while (we && (we != v->edge));
998 static void p_chart_fill_boundary(PChart *chart, PEdge *be, int nedges)
1003 struct Heap *heap = BLI_heap_new();
1008 angle = p_edge_boundary_angle(e);
1009 e->u.heaplink = BLI_heap_insert(heap, angle, e);
1011 e = p_boundary_edge_next(e);
1015 /* no real boundary, but an isolated seam */
1016 e = be->next->vert->edge;
1020 BLI_heap_remove(heap, e->u.heaplink);
1021 BLI_heap_remove(heap, be->u.heaplink);
1024 while (nedges > 2) {
1025 PEdge *ne, *ne1, *ne2;
1027 e = (PEdge*)BLI_heap_popmin(heap);
1029 e1 = p_boundary_edge_prev(e);
1030 e2 = p_boundary_edge_next(e);
1032 BLI_heap_remove(heap, e1->u.heaplink);
1033 BLI_heap_remove(heap, e2->u.heaplink);
1034 e->u.heaplink = e1->u.heaplink = e2->u.heaplink = NULL;
1036 e->flag |= PEDGE_FILLED;
1037 e1->flag |= PEDGE_FILLED;
1043 f = p_face_add_fill(chart, e->vert, e1->vert, e2->vert);
1044 f->flag |= PFACE_FILLED;
1046 ne = f->edge->next->next;
1048 ne2 = f->edge->next;
1050 ne->flag = ne1->flag = ne2->flag = PEDGE_FILLED;
1057 ne->vert = e2->vert;
1058 ne1->vert = e->vert;
1059 ne2->vert = e1->vert;
1066 ne2->vert->edge = ne2;
1068 ne2->u.heaplink = BLI_heap_insert(heap, p_edge_boundary_angle(ne2), ne2);
1069 e2->u.heaplink = BLI_heap_insert(heap, p_edge_boundary_angle(e2), e2);
1076 BLI_heap_free(heap, NULL);
1079 static void p_chart_fill_boundaries(PChart *chart, PEdge *outer)
1081 PEdge *e, *be; /* *enext - as yet unused */
1084 for (e=chart->edges; e; e=e->nextlink) {
1085 /* enext = e->nextlink; - as yet unused */
1087 if (e->pair || (e->flag & PEDGE_FILLED))
1093 be->flag |= PEDGE_FILLED;
1094 be = be->next->vert->edge;
1099 p_chart_fill_boundary(chart, e, nedges);
1104 /* Polygon kernel for inserting uv's non overlapping */
1106 static int p_polygon_point_in(float *cp1, float *cp2, float *p)
1108 if ((cp1[0] == p[0]) && (cp1[1] == p[1]))
1110 else if ((cp2[0] == p[0]) && (cp2[1] == p[1]))
1113 return (p_area_signed(cp1, cp2, p) >= 0.0f);
1116 static void p_polygon_kernel_clip(float (*oldpoints)[2], int noldpoints, float (*newpoints)[2], int *nnewpoints, float *cp1, float *cp2)
1118 float *p2, *p1, isect[2];
1121 p1 = oldpoints[noldpoints-1];
1122 p1in = p_polygon_point_in(cp1, cp2, p1);
1125 for (i = 0; i < noldpoints; i++) {
1127 p2in = p_polygon_point_in(cp1, cp2, p2);
1129 if ((p2in >= 2) || (p1in && p2in)) {
1130 newpoints[*nnewpoints][0] = p2[0];
1131 newpoints[*nnewpoints][1] = p2[1];
1134 else if (p1in && !p2in) {
1136 p_intersect_line_2d(p1, p2, cp1, cp2, isect);
1137 newpoints[*nnewpoints][0] = isect[0];
1138 newpoints[*nnewpoints][1] = isect[1];
1142 else if (!p1in && p2in) {
1143 p_intersect_line_2d(p1, p2, cp1, cp2, isect);
1144 newpoints[*nnewpoints][0] = isect[0];
1145 newpoints[*nnewpoints][1] = isect[1];
1148 newpoints[*nnewpoints][0] = p2[0];
1149 newpoints[*nnewpoints][1] = p2[1];
1158 static void p_polygon_kernel_center(float (*points)[2], int npoints, float *center)
1160 int i, size, nnewpoints = npoints;
1161 float (*oldpoints)[2], (*newpoints)[2], *p1, *p2;
1164 oldpoints = MEM_mallocN(sizeof(float)*2*size, "PPolygonOldPoints");
1165 newpoints = MEM_mallocN(sizeof(float)*2*size, "PPolygonNewPoints");
1167 memcpy(oldpoints, points, sizeof(float)*2*npoints);
1169 for (i = 0; i < npoints; i++) {
1171 p2 = points[(i+1)%npoints];
1172 p_polygon_kernel_clip(oldpoints, nnewpoints, newpoints, &nnewpoints, p1, p2);
1174 if (nnewpoints == 0) {
1175 /* degenerate case, use center of original polygon */
1176 memcpy(oldpoints, points, sizeof(float)*2*npoints);
1177 nnewpoints = npoints;
1180 else if (nnewpoints == 1) {
1181 /* degenerate case, use remaining point */
1182 center[0] = newpoints[0][0];
1183 center[1] = newpoints[0][1];
1185 MEM_freeN(oldpoints);
1186 MEM_freeN(newpoints);
1191 if (nnewpoints*2 > size) {
1194 oldpoints = malloc(sizeof(float)*2*size);
1195 memcpy(oldpoints, newpoints, sizeof(float)*2*nnewpoints);
1197 newpoints = malloc(sizeof(float)*2*size);
1200 float (*sw_points)[2] = oldpoints;
1201 oldpoints = newpoints;
1202 newpoints = sw_points;
1206 center[0] = center[1] = 0.0f;
1208 for (i = 0; i < nnewpoints; i++) {
1209 center[0] += oldpoints[i][0];
1210 center[1] += oldpoints[i][1];
1213 center[0] /= nnewpoints;
1214 center[1] /= nnewpoints;
1216 MEM_freeN(oldpoints);
1217 MEM_freeN(newpoints);
1222 /* Edge Collapser */
1227 static float p_vert_cotan(float *v1, float *v2, float *v3)
1229 float a[3], b[3], c[3], clen;
1235 clen = VecLength(c);
1240 return Inpf(a, b)/clen;
1243 static PBool p_vert_flipped_wheel_triangle(PVert *v)
1248 if (p_face_uv_area_signed(e->face) < 0.0f)
1251 e = p_wheel_edge_next(e);
1252 } while (e && (e != v->edge));
1257 static PBool p_vert_map_harmonic_weights(PVert *v)
1259 float weightsum, positionsum[2], olduv[2];
1262 positionsum[0] = positionsum[1] = 0.0f;
1264 if (p_vert_interior(v)) {
1268 float t1, t2, weight;
1272 v2 = e->next->next->vert;
1273 t1 = p_vert_cotan(v2->co, e->vert->co, v1->co);
1275 v1 = e->pair->next->vert;
1276 v2 = e->pair->next->next->vert;
1277 t2 = p_vert_cotan(v2->co, e->pair->vert->co, v1->co);
1279 weight = 0.5f*(t1 + t2);
1280 weightsum += weight;
1281 positionsum[0] += weight*e->pair->vert->uv[0];
1282 positionsum[1] += weight*e->pair->vert->uv[1];
1284 e = p_wheel_edge_next(e);
1285 } while (e && (e != v->edge));
1295 v1 = e->next->next->vert;
1297 t1 = p_vert_cotan(v1->co, v->co, v2->co);
1298 t2 = p_vert_cotan(v2->co, v->co, v1->co);
1300 weightsum += t1 + t2;
1301 positionsum[0] += (v2->uv[1] - v1->uv[1]) + (t1*v2->uv[0] + t2*v1->uv[0]);
1302 positionsum[1] += (v1->uv[0] - v2->uv[0]) + (t1*v2->uv[1] + t2*v1->uv[1]);
1304 e = p_wheel_edge_next(e);
1305 } while (e && (e != v->edge));
1308 if (weightsum != 0.0f) {
1309 weightsum = 1.0f/weightsum;
1310 positionsum[0] *= weightsum;
1311 positionsum[1] *= weightsum;
1314 olduv[0] = v->uv[0];
1315 olduv[1] = v->uv[1];
1316 v->uv[0] = positionsum[0];
1317 v->uv[1] = positionsum[1];
1319 if (p_vert_flipped_wheel_triangle(v)) {
1320 v->uv[0] = olduv[0];
1321 v->uv[1] = olduv[1];
1329 static void p_vert_harmonic_insert(PVert *v)
1333 if (!p_vert_map_harmonic_weights(v)) {
1334 /* do polygon kernel center insertion: this is quite slow, but should
1335 only be needed for 0.01 % of verts or so, when insert with harmonic
1344 e = p_wheel_edge_next(e);
1345 } while (e && (e != v->edge));
1350 points = MEM_mallocN(sizeof(float)*2*npoints, "PHarmonicPoints");
1355 PEdge *nexte = p_wheel_edge_next(e);
1357 points[i][0] = e->next->vert->uv[0];
1358 points[i][1] = e->next->vert->uv[1];
1360 if (nexte == NULL) {
1362 points[i][0] = e->next->next->vert->uv[0];
1363 points[i][1] = e->next->next->vert->uv[1];
1369 } while (e != v->edge);
1371 p_polygon_kernel_center(points, npoints, v->uv);
1378 if (!(e->next->vert->flag & PVERT_PIN))
1379 p_vert_map_harmonic_weights(e->next->vert);
1380 e = p_wheel_edge_next(e);
1381 } while (e && (e != v->edge));
1383 p_vert_map_harmonic_weights(v);
1386 static void p_vert_fix_edge_pointer(PVert *v)
1388 PEdge *start = v->edge;
1390 /* set v->edge pointer to the edge with no pair, if there is one */
1391 while (v->edge->pair) {
1392 v->edge = p_wheel_edge_prev(v->edge);
1394 if (v->edge == start)
1399 static void p_collapsing_verts(PEdge *edge, PEdge *pair, PVert **newv, PVert **keepv)
1401 /* the two vertices that are involved in the collapse */
1404 *keepv = edge->next->vert;
1407 *newv = pair->next->vert;
1408 *keepv = pair->vert;
1412 static void p_collapse_edge(PEdge *edge, PEdge *pair)
1414 PVert *oldv, *keepv;
1417 p_collapsing_verts(edge, pair, &oldv, &keepv);
1419 /* change e->vert pointers from old vertex to the target vertex */
1422 if ((e != edge) && !(pair && pair->next == e))
1425 e = p_wheel_edge_next(e);
1426 } while (e && (e != oldv->edge));
1428 /* set keepv->edge pointer */
1429 if ((edge && (keepv->edge == edge->next)) || (keepv->edge == pair)) {
1430 if (edge && edge->next->pair)
1431 keepv->edge = edge->next->pair->next;
1432 else if (pair && pair->next->next->pair)
1433 keepv->edge = pair->next->next->pair;
1434 else if (edge && edge->next->next->pair)
1435 keepv->edge = edge->next->next->pair;
1437 keepv->edge = pair->next->pair->next;
1440 /* update pairs and v->edge pointers */
1442 PEdge *e1 = edge->next, *e2 = e1->next;
1445 e1->pair->pair = e2->pair;
1448 e2->pair->pair = e1->pair;
1449 e2->vert->edge = p_wheel_edge_prev(e2);
1452 e2->vert->edge = p_wheel_edge_next(e2);
1454 p_vert_fix_edge_pointer(e2->vert);
1458 PEdge *e1 = pair->next, *e2 = e1->next;
1461 e1->pair->pair = e2->pair;
1464 e2->pair->pair = e1->pair;
1465 e2->vert->edge = p_wheel_edge_prev(e2);
1468 e2->vert->edge = p_wheel_edge_next(e2);
1470 p_vert_fix_edge_pointer(e2->vert);
1473 p_vert_fix_edge_pointer(keepv);
1475 /* mark for move to collapsed list later */
1476 oldv->flag |= PVERT_COLLAPSE;
1479 PFace *f = edge->face;
1480 PEdge *e1 = edge->next, *e2 = e1->next;
1482 f->flag |= PFACE_COLLAPSE;
1483 edge->flag |= PEDGE_COLLAPSE;
1484 e1->flag |= PEDGE_COLLAPSE;
1485 e2->flag |= PEDGE_COLLAPSE;
1489 PFace *f = pair->face;
1490 PEdge *e1 = pair->next, *e2 = e1->next;
1492 f->flag |= PFACE_COLLAPSE;
1493 pair->flag |= PEDGE_COLLAPSE;
1494 e1->flag |= PEDGE_COLLAPSE;
1495 e2->flag |= PEDGE_COLLAPSE;
1499 static void p_split_vertex(PEdge *edge, PEdge *pair)
1501 PVert *newv, *keepv;
1504 p_collapsing_verts(edge, pair, &newv, &keepv);
1506 /* update edge pairs */
1508 PEdge *e1 = edge->next, *e2 = e1->next;
1511 e1->pair->pair = e1;
1513 e2->pair->pair = e2;
1515 e2->vert->edge = e2;
1516 p_vert_fix_edge_pointer(e2->vert);
1521 PEdge *e1 = pair->next, *e2 = e1->next;
1524 e1->pair->pair = e1;
1526 e2->pair->pair = e2;
1528 e2->vert->edge = e2;
1529 p_vert_fix_edge_pointer(e2->vert);
1533 p_vert_fix_edge_pointer(keepv);
1535 /* set e->vert pointers to restored vertex */
1539 e = p_wheel_edge_next(e);
1540 } while (e && (e != newv->edge));
1543 static PBool p_collapse_allowed_topologic(PEdge *edge, PEdge *pair)
1545 PVert *oldv, *keepv;
1547 p_collapsing_verts(edge, pair, &oldv, &keepv);
1549 /* boundary edges */
1550 if (!edge || !pair) {
1551 /* avoid collapsing chart into an edge */
1552 if (edge && !edge->next->pair && !edge->next->next->pair)
1554 else if (pair && !pair->next->pair && !pair->next->next->pair)
1557 /* avoid merging two boundaries (oldv and keepv are on the 'other side' of
1559 else if (!p_vert_interior(oldv) && !p_vert_interior(keepv))
1565 static PBool p_collapse_normal_flipped(float *v1, float *v2, float *vold, float *vnew)
1567 float nold[3], nnew[3], sub1[3], sub2[3];
1569 VecSubf(sub1, vold, v1);
1570 VecSubf(sub2, vold, v2);
1571 Crossf(nold, sub1, sub2);
1573 VecSubf(sub1, vnew, v1);
1574 VecSubf(sub2, vnew, v2);
1575 Crossf(nnew, sub1, sub2);
1577 return (Inpf(nold, nnew) <= 0.0f);
1580 static PBool p_collapse_allowed_geometric(PEdge *edge, PEdge *pair)
1582 PVert *oldv, *keepv;
1584 float angulardefect, angle;
1586 p_collapsing_verts(edge, pair, &oldv, &keepv);
1588 angulardefect = 2*M_PI;
1592 float a[3], b[3], minangle, maxangle;
1593 PEdge *e1 = e->next, *e2 = e1->next;
1594 PVert *v1 = e1->vert, *v2 = e2->vert;
1597 angle = p_vec_angle(v1->co, oldv->co, v2->co);
1598 angulardefect -= angle;
1600 /* skip collapsing faces */
1601 if (v1 == keepv || v2 == keepv) {
1602 e = p_wheel_edge_next(e);
1606 if (p_collapse_normal_flipped(v1->co, v2->co, oldv->co, keepv->co))
1610 a[1] = p_vec_angle(v2->co, v1->co, oldv->co);
1611 a[2] = M_PI - a[0] - a[1];
1613 b[0] = p_vec_angle(v1->co, keepv->co, v2->co);
1614 b[1] = p_vec_angle(v2->co, v1->co, keepv->co);
1615 b[2] = M_PI - b[0] - b[1];
1617 /* abf criterion 1: avoid sharp and obtuse angles */
1618 minangle = 15.0f*M_PI/180.0f;
1619 maxangle = M_PI - minangle;
1621 for (i = 0; i < 3; i++) {
1622 if ((b[i] < a[i]) && (b[i] < minangle))
1624 else if ((b[i] > a[i]) && (b[i] > maxangle))
1628 e = p_wheel_edge_next(e);
1629 } while (e && (e != oldv->edge));
1631 if (p_vert_interior(oldv)) {
1632 /* hlscm criterion: angular defect smaller than threshold */
1633 if (fabs(angulardefect) > (M_PI*30.0/180.0))
1637 PVert *v1 = p_boundary_edge_next(oldv->edge)->vert;
1638 PVert *v2 = p_boundary_edge_prev(oldv->edge)->vert;
1640 /* abf++ criterion 2: avoid collapsing verts inwards */
1641 if (p_vert_interior(keepv))
1644 /* don't collapse significant boundary changes */
1645 angle = p_vec_angle(v1->co, oldv->co, v2->co);
1646 if (angle < (M_PI*160.0/180.0))
1653 static PBool p_collapse_allowed(PEdge *edge, PEdge *pair)
1655 PVert *oldv, *keepv;
1657 p_collapsing_verts(edge, pair, &oldv, &keepv);
1659 if (oldv->flag & PVERT_PIN)
1662 return (p_collapse_allowed_topologic(edge, pair) &&
1663 p_collapse_allowed_geometric(edge, pair));
1666 static float p_collapse_cost(PEdge *edge, PEdge *pair)
1668 /* based on volume and boundary optimization from:
1669 "Fast and Memory Efficient Polygonal Simplification" P. Lindstrom, G. Turk */
1671 PVert *oldv, *keepv;
1673 PFace *oldf1, *oldf2;
1674 float volumecost = 0.0f, areacost = 0.0f, edgevec[3], cost, weight, elen;
1675 float shapecost = 0.0f;
1676 float shapeold = 0.0f, shapenew = 0.0f;
1677 int nshapeold = 0, nshapenew = 0;
1679 p_collapsing_verts(edge, pair, &oldv, &keepv);
1680 oldf1 = (edge)? edge->face: NULL;
1681 oldf2 = (pair)? pair->face: NULL;
1683 VecSubf(edgevec, keepv->co, oldv->co);
1688 float *co1 = e->next->vert->co;
1689 float *co2 = e->next->next->vert->co;
1691 if ((e->face != oldf1) && (e->face != oldf2)) {
1692 float tetrav2[3], tetrav3[3], c[3];
1694 /* tetrahedron volume = (1/3!)*|a.(b x c)| */
1695 VecSubf(tetrav2, co1, oldv->co);
1696 VecSubf(tetrav3, co2, oldv->co);
1697 Crossf(c, tetrav2, tetrav3);
1699 volumecost += fabs(Inpf(edgevec, c)/6.0f);
1701 shapecost += Inpf(co1, keepv->co);
1703 if (p_wheel_edge_next(e) == NULL)
1704 shapecost += Inpf(co2, keepv->co);
1707 p_triangle_angles(oldv->co, co1, co2, &a1, &a2, &a3);
1711 shapeold = (a1*a1 + a2*a2 + a3*a3)/((M_PI/2)*(M_PI/2));
1716 p_triangle_angles(keepv->co, co1, co2, &a1, &a2, &a3);
1720 shapenew = (a1*a1 + a2*a2 + a3*a3)/((M_PI/2)*(M_PI/2));
1725 e = p_wheel_edge_next(e);
1726 } while (e && (e != oldv->edge));
1728 if (!p_vert_interior(oldv)) {
1729 PVert *v1 = p_boundary_edge_prev(oldv->edge)->vert;
1730 PVert *v2 = p_boundary_edge_next(oldv->edge)->vert;
1732 areacost = AreaT3Dfl(oldv->co, v1->co, v2->co);
1735 elen = VecLength(edgevec);
1736 weight = 1.0f; /* 0.2f */
1737 cost = weight*volumecost*volumecost + elen*elen*areacost*areacost;
1741 shapeold /= nshapeold;
1742 shapenew /= nshapenew;
1743 shapecost = (shapeold + 0.00001)/(shapenew + 0.00001);
1751 static void p_collapse_cost_vertex(PVert *vert, float *mincost, PEdge **mine)
1753 PEdge *e, *enext, *pair;
1759 if (p_collapse_allowed(e, e->pair)) {
1760 float cost = p_collapse_cost(e, e->pair);
1762 if ((*mine == NULL) || (cost < *mincost)) {
1768 enext = p_wheel_edge_next(e);
1770 if (enext == NULL) {
1771 /* the other boundary edge, where we only have the pair halfedge */
1772 pair = e->next->next;
1774 if (p_collapse_allowed(NULL, pair)) {
1775 float cost = p_collapse_cost(NULL, pair);
1777 if ((*mine == NULL) || (cost < *mincost)) {
1787 } while (e != vert->edge);
1790 static void p_chart_post_collapse_flush(PChart *chart, PEdge *collapsed)
1792 /* move to collapsed_ */
1794 PVert *v, *nextv = NULL, *verts = chart->verts;
1795 PEdge *e, *nexte = NULL, *edges = chart->edges, *laste = NULL;
1796 PFace *f, *nextf = NULL, *faces = chart->faces;
1798 chart->verts = chart->collapsed_verts = NULL;
1799 chart->edges = chart->collapsed_edges = NULL;
1800 chart->faces = chart->collapsed_faces = NULL;
1802 chart->nverts = chart->nedges = chart->nfaces = 0;
1804 for (v=verts; v; v=nextv) {
1805 nextv = v->nextlink;
1807 if (v->flag & PVERT_COLLAPSE) {
1808 v->nextlink = chart->collapsed_verts;
1809 chart->collapsed_verts = v;
1812 v->nextlink = chart->verts;
1818 for (e=edges; e; e=nexte) {
1819 nexte = e->nextlink;
1821 if (!collapsed || !(e->flag & PEDGE_COLLAPSE_EDGE)) {
1822 if (e->flag & PEDGE_COLLAPSE) {
1823 e->nextlink = chart->collapsed_edges;
1824 chart->collapsed_edges = e;
1827 e->nextlink = chart->edges;
1834 /* these are added last so they can be popped of in the right order
1836 for (e=collapsed; e; e=e->nextlink) {
1837 e->nextlink = e->u.nextcollapse;
1841 laste->nextlink = chart->collapsed_edges;
1842 chart->collapsed_edges = collapsed;
1845 for (f=faces; f; f=nextf) {
1846 nextf = f->nextlink;
1848 if (f->flag & PFACE_COLLAPSE) {
1849 f->nextlink = chart->collapsed_faces;
1850 chart->collapsed_faces = f;
1853 f->nextlink = chart->faces;
1860 static void p_chart_post_split_flush(PChart *chart)
1862 /* move from collapsed_ */
1864 PVert *v, *nextv = NULL;
1865 PEdge *e, *nexte = NULL;
1866 PFace *f, *nextf = NULL;
1868 for (v=chart->collapsed_verts; v; v=nextv) {
1869 nextv = v->nextlink;
1870 v->nextlink = chart->verts;
1875 for (e=chart->collapsed_edges; e; e=nexte) {
1876 nexte = e->nextlink;
1877 e->nextlink = chart->edges;
1882 for (f=chart->collapsed_faces; f; f=nextf) {
1883 nextf = f->nextlink;
1884 f->nextlink = chart->faces;
1889 chart->collapsed_verts = NULL;
1890 chart->collapsed_edges = NULL;
1891 chart->collapsed_faces = NULL;
1894 static void p_chart_simplify_compute(PChart *chart)
1896 /* Computes a list of edge collapses / vertex splits. The collapsed
1897 simplices go in the chart->collapsed_* lists, The original and
1898 collapsed may then be view as stacks, where the next collapse/split
1899 is at the top of the respective lists. */
1901 Heap *heap = BLI_heap_new();
1902 PVert *v, **wheelverts;
1903 PEdge *collapsededges = NULL, *e;
1904 int nwheelverts, i, ncollapsed = 0;
1906 wheelverts = MEM_mallocN(sizeof(PVert*)*chart->nverts, "PChartWheelVerts");
1908 /* insert all potential collapses into heap */
1909 for (v=chart->verts; v; v=v->nextlink) {
1913 p_collapse_cost_vertex(v, &cost, &e);
1916 v->u.heaplink = BLI_heap_insert(heap, cost, e);
1918 v->u.heaplink = NULL;
1921 for (e=chart->edges; e; e=e->nextlink)
1922 e->u.nextcollapse = NULL;
1924 /* pop edge collapse out of heap one by one */
1925 while (!BLI_heap_empty(heap)) {
1926 if (ncollapsed == NCOLLAPSE)
1929 HeapNode *link = BLI_heap_top(heap);
1930 PEdge *edge = (PEdge*)BLI_heap_popmin(heap), *pair = edge->pair;
1931 PVert *oldv, *keepv;
1932 PEdge *wheele, *nexte;
1934 /* remember the edges we collapsed */
1935 edge->u.nextcollapse = collapsededges;
1936 collapsededges = edge;
1938 if (edge->vert->u.heaplink != link) {
1939 edge->flag |= (PEDGE_COLLAPSE_EDGE|PEDGE_COLLAPSE_PAIR);
1940 edge->next->vert->u.heaplink = NULL;
1941 SWAP(PEdge*, edge, pair);
1944 edge->flag |= PEDGE_COLLAPSE_EDGE;
1945 edge->vert->u.heaplink = NULL;
1948 p_collapsing_verts(edge, pair, &oldv, &keepv);
1950 /* gather all wheel verts and remember them before collapse */
1952 wheele = oldv->edge;
1955 wheelverts[nwheelverts++] = wheele->next->vert;
1956 nexte = p_wheel_edge_next(wheele);
1959 wheelverts[nwheelverts++] = wheele->next->next->vert;
1962 } while (wheele && (wheele != oldv->edge));
1965 p_collapse_edge(edge, pair);
1967 for (i = 0; i < nwheelverts; i++) {
1969 PEdge *collapse = NULL;
1973 if (v->u.heaplink) {
1974 BLI_heap_remove(heap, v->u.heaplink);
1975 v->u.heaplink = NULL;
1978 p_collapse_cost_vertex(v, &cost, &collapse);
1981 v->u.heaplink = BLI_heap_insert(heap, cost, collapse);
1987 MEM_freeN(wheelverts);
1988 BLI_heap_free(heap, NULL);
1990 p_chart_post_collapse_flush(chart, collapsededges);
1993 static void p_chart_complexify(PChart *chart)
1995 PEdge *e, *pair, *edge;
1996 PVert *newv, *keepv;
1999 for (e=chart->collapsed_edges; e; e=e->nextlink) {
2000 if (!(e->flag & PEDGE_COLLAPSE_EDGE))
2006 if (edge->flag & PEDGE_COLLAPSE_PAIR) {
2007 SWAP(PEdge*, edge, pair);
2010 p_split_vertex(edge, pair);
2011 p_collapsing_verts(edge, pair, &newv, &keepv);
2013 if (x >= NCOLLAPSEX) {
2014 newv->uv[0] = keepv->uv[0];
2015 newv->uv[1] = keepv->uv[1];
2018 p_vert_harmonic_insert(newv);
2023 p_chart_post_split_flush(chart);
2027 static void p_chart_simplify(PChart *chart)
2029 /* Not implemented, needs proper reordering in split_flush. */
2036 #define ABF_MAX_ITER 20
2038 typedef struct PAbfSystem {
2039 int ninterior, nfaces, nangles;
2040 float *alpha, *beta, *sine, *cosine, *weight;
2041 float *bAlpha, *bTriangle, *bInterior;
2042 float *lambdaTriangle, *lambdaPlanar, *lambdaLength;
2043 float (*J2dt)[3], *bstar, *dstar;
2044 float minangle, maxangle;
2047 static void p_abf_setup_system(PAbfSystem *sys)
2051 sys->alpha = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFalpha");
2052 sys->beta = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFbeta");
2053 sys->sine = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFsine");
2054 sys->cosine = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFcosine");
2055 sys->weight = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFweight");
2057 sys->bAlpha = (float*)MEM_mallocN(sizeof(float)*sys->nangles, "ABFbalpha");
2058 sys->bTriangle = (float*)MEM_mallocN(sizeof(float)*sys->nfaces, "ABFbtriangle");
2059 sys->bInterior = (float*)MEM_mallocN(sizeof(float)*2*sys->ninterior, "ABFbinterior");
2061 sys->lambdaTriangle = (float*)MEM_callocN(sizeof(float)*sys->nfaces, "ABFlambdatri");
2062 sys->lambdaPlanar = (float*)MEM_callocN(sizeof(float)*sys->ninterior, "ABFlamdaplane");
2063 sys->lambdaLength = (float*)MEM_mallocN(sizeof(float)*sys->ninterior, "ABFlambdalen");
2065 sys->J2dt = MEM_mallocN(sizeof(float)*sys->nangles*3, "ABFj2dt");
2066 sys->bstar = (float*)MEM_mallocN(sizeof(float)*sys->nfaces, "ABFbstar");
2067 sys->dstar = (float*)MEM_mallocN(sizeof(float)*sys->nfaces, "ABFdstar");
2069 for (i = 0; i < sys->ninterior; i++)
2070 sys->lambdaLength[i] = 1.0;
2072 sys->minangle = 7.5f*M_PI/180.0f;
2073 sys->maxangle = M_PI - sys->minangle;
2076 static void p_abf_free_system(PAbfSystem *sys)
2078 MEM_freeN(sys->alpha);
2079 MEM_freeN(sys->beta);
2080 MEM_freeN(sys->sine);
2081 MEM_freeN(sys->cosine);
2082 MEM_freeN(sys->weight);
2083 MEM_freeN(sys->bAlpha);
2084 MEM_freeN(sys->bTriangle);
2085 MEM_freeN(sys->bInterior);
2086 MEM_freeN(sys->lambdaTriangle);
2087 MEM_freeN(sys->lambdaPlanar);
2088 MEM_freeN(sys->lambdaLength);
2089 MEM_freeN(sys->J2dt);
2090 MEM_freeN(sys->bstar);
2091 MEM_freeN(sys->dstar);
2094 static void p_abf_compute_sines(PAbfSystem *sys)
2097 float *sine = sys->sine, *cosine = sys->cosine, *alpha = sys->alpha;
2099 for (i = 0; i < sys->nangles; i++, sine++, cosine++, alpha++) {
2100 *sine = sin(*alpha);
2101 *cosine = cos(*alpha);
2105 static float p_abf_compute_sin_product(PAbfSystem *sys, PVert *v, int aid)
2117 if (aid == e1->u.id) {
2118 /* we are computing a derivative for this angle,
2119 so we use cos and drop the other part */
2120 sin1 *= sys->cosine[e1->u.id];
2124 sin1 *= sys->sine[e1->u.id];
2126 if (aid == e2->u.id) {
2129 sin2 *= sys->cosine[e2->u.id];
2132 sin2 *= sys->sine[e2->u.id];
2134 e = e->next->next->pair;
2135 } while (e && (e != v->edge));
2137 return (sin1 - sin2);
2140 static float p_abf_compute_grad_alpha(PAbfSystem *sys, PFace *f, PEdge *e)
2142 PVert *v = e->vert, *v1 = e->next->vert, *v2 = e->next->next->vert;
2145 deriv = (sys->alpha[e->u.id] - sys->beta[e->u.id])*sys->weight[e->u.id];
2146 deriv += sys->lambdaTriangle[f->u.id];
2148 if (v->flag & PVERT_INTERIOR) {
2149 deriv += sys->lambdaPlanar[v->u.id];
2152 if (v1->flag & PVERT_INTERIOR) {
2153 float product = p_abf_compute_sin_product(sys, v1, e->u.id);
2154 deriv += sys->lambdaLength[v1->u.id]*product;
2157 if (v2->flag & PVERT_INTERIOR) {
2158 float product = p_abf_compute_sin_product(sys, v2, e->u.id);
2159 deriv += sys->lambdaLength[v2->u.id]*product;
2165 static float p_abf_compute_gradient(PAbfSystem *sys, PChart *chart)
2172 for (f=chart->faces; f; f=f->nextlink) {
2173 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
2174 float gtriangle, galpha1, galpha2, galpha3;
2176 galpha1 = p_abf_compute_grad_alpha(sys, f, e1);
2177 galpha2 = p_abf_compute_grad_alpha(sys, f, e2);
2178 galpha3 = p_abf_compute_grad_alpha(sys, f, e3);
2180 sys->bAlpha[e1->u.id] = -galpha1;
2181 sys->bAlpha[e2->u.id] = -galpha2;
2182 sys->bAlpha[e3->u.id] = -galpha3;
2184 norm += galpha1*galpha1 + galpha2*galpha2 + galpha3*galpha3;
2186 gtriangle = sys->alpha[e1->u.id] + sys->alpha[e2->u.id] + sys->alpha[e3->u.id] - M_PI;
2187 sys->bTriangle[f->u.id] = -gtriangle;
2188 norm += gtriangle*gtriangle;
2191 for (v=chart->verts; v; v=v->nextlink) {
2192 if (v->flag & PVERT_INTERIOR) {
2193 float gplanar = -2*M_PI, glength;
2197 gplanar += sys->alpha[e->u.id];
2198 e = e->next->next->pair;
2199 } while (e && (e != v->edge));
2201 sys->bInterior[v->u.id] = -gplanar;
2202 norm += gplanar*gplanar;
2204 glength = p_abf_compute_sin_product(sys, v, -1);
2205 sys->bInterior[sys->ninterior + v->u.id] = -glength;
2206 norm += glength*glength;
2213 static PBool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
2217 int i, j, ninterior = sys->ninterior, nvar = 2*sys->ninterior;
2221 nlSolverParameteri(NL_NB_VARIABLES, nvar);
2227 for (i = 0; i < nvar; i++)
2228 nlRightHandSideAdd(0, i, sys->bInterior[i]);
2230 for (f=chart->faces; f; f=f->nextlink) {
2231 float wi1, wi2, wi3, b, si, beta[3], j2[3][3], W[3][3];
2232 float row1[6], row2[6], row3[6];
2234 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
2235 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
2237 wi1 = 1.0/sys->weight[e1->u.id];
2238 wi2 = 1.0/sys->weight[e2->u.id];
2239 wi3 = 1.0/sys->weight[e3->u.id];
2241 /* bstar1 = (J1*dInv*bAlpha - bTriangle) */
2242 b = sys->bAlpha[e1->u.id]*wi1;
2243 b += sys->bAlpha[e2->u.id]*wi2;
2244 b += sys->bAlpha[e3->u.id]*wi3;
2245 b -= sys->bTriangle[f->u.id];
2248 si = 1.0/(wi1 + wi2 + wi3);
2250 /* J1t*si*bstar1 - bAlpha */
2251 beta[0] = b*si - sys->bAlpha[e1->u.id];
2252 beta[1] = b*si - sys->bAlpha[e2->u.id];
2253 beta[2] = b*si - sys->bAlpha[e3->u.id];
2255 /* use this later for computing other lambda's */
2256 sys->bstar[f->u.id] = b;
2257 sys->dstar[f->u.id] = si;
2260 W[0][0] = si - sys->weight[e1->u.id]; W[0][1] = si; W[0][2] = si;
2261 W[1][0] = si; W[1][1] = si - sys->weight[e2->u.id]; W[1][2] = si;
2262 W[2][0] = si; W[2][1] = si; W[2][2] = si - sys->weight[e3->u.id];
2264 vid[0] = vid[1] = vid[2] = vid[3] = vid[4] = vid[5] = -1;
2266 if (v1->flag & PVERT_INTERIOR) {
2268 vid[3] = ninterior + v1->u.id;
2270 sys->J2dt[e1->u.id][0] = j2[0][0] = 1.0*wi1;
2271 sys->J2dt[e2->u.id][0] = j2[1][0] = p_abf_compute_sin_product(sys, v1, e2->u.id)*wi2;
2272 sys->J2dt[e3->u.id][0] = j2[2][0] = p_abf_compute_sin_product(sys, v1, e3->u.id)*wi3;
2274 nlRightHandSideAdd(0, v1->u.id, j2[0][0]*beta[0]);
2275 nlRightHandSideAdd(0, ninterior + v1->u.id, j2[1][0]*beta[1] + j2[2][0]*beta[2]);
2277 row1[0] = j2[0][0]*W[0][0];
2278 row2[0] = j2[0][0]*W[1][0];
2279 row3[0] = j2[0][0]*W[2][0];
2281 row1[3] = j2[1][0]*W[0][1] + j2[2][0]*W[0][2];
2282 row2[3] = j2[1][0]*W[1][1] + j2[2][0]*W[1][2];
2283 row3[3] = j2[1][0]*W[2][1] + j2[2][0]*W[2][2];
2286 if (v2->flag & PVERT_INTERIOR) {
2288 vid[4] = ninterior + v2->u.id;
2290 sys->J2dt[e1->u.id][1] = j2[0][1] = p_abf_compute_sin_product(sys, v2, e1->u.id)*wi1;
2291 sys->J2dt[e2->u.id][1] = j2[1][1] = 1.0*wi2;
2292 sys->J2dt[e3->u.id][1] = j2[2][1] = p_abf_compute_sin_product(sys, v2, e3->u.id)*wi3;
2294 nlRightHandSideAdd(0, v2->u.id, j2[1][1]*beta[1]);
2295 nlRightHandSideAdd(0, ninterior + v2->u.id, j2[0][1]*beta[0] + j2[2][1]*beta[2]);
2297 row1[1] = j2[1][1]*W[0][1];
2298 row2[1] = j2[1][1]*W[1][1];
2299 row3[1] = j2[1][1]*W[2][1];
2301 row1[4] = j2[0][1]*W[0][0] + j2[2][1]*W[0][2];
2302 row2[4] = j2[0][1]*W[1][0] + j2[2][1]*W[1][2];
2303 row3[4] = j2[0][1]*W[2][0] + j2[2][1]*W[2][2];
2306 if (v3->flag & PVERT_INTERIOR) {
2308 vid[5] = ninterior + v3->u.id;
2310 sys->J2dt[e1->u.id][2] = j2[0][2] = p_abf_compute_sin_product(sys, v3, e1->u.id)*wi1;
2311 sys->J2dt[e2->u.id][2] = j2[1][2] = p_abf_compute_sin_product(sys, v3, e2->u.id)*wi2;
2312 sys->J2dt[e3->u.id][2] = j2[2][2] = 1.0*wi3;
2314 nlRightHandSideAdd(0, v3->u.id, j2[2][2]*beta[2]);
2315 nlRightHandSideAdd(0, ninterior + v3->u.id, j2[0][2]*beta[0] + j2[1][2]*beta[1]);
2317 row1[2] = j2[2][2]*W[0][2];
2318 row2[2] = j2[2][2]*W[1][2];
2319 row3[2] = j2[2][2]*W[2][2];
2321 row1[5] = j2[0][2]*W[0][0] + j2[1][2]*W[0][1];
2322 row2[5] = j2[0][2]*W[1][0] + j2[1][2]*W[1][1];
2323 row3[5] = j2[0][2]*W[2][0] + j2[1][2]*W[2][1];
2326 for (i = 0; i < 3; i++) {
2332 for (j = 0; j < 6; j++) {
2339 nlMatrixAdd(r, c, j2[0][i]*row1[j]);
2341 nlMatrixAdd(r + ninterior, c, j2[0][i]*row1[j]);
2344 nlMatrixAdd(r, c, j2[1][i]*row2[j]);
2346 nlMatrixAdd(r + ninterior, c, j2[1][i]*row2[j]);
2350 nlMatrixAdd(r, c, j2[2][i]*row3[j]);
2352 nlMatrixAdd(r + ninterior, c, j2[2][i]*row3[j]);
2361 success = nlSolve();
2364 for (f=chart->faces; f; f=f->nextlink) {
2365 float dlambda1, pre[3], dalpha;
2366 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
2367 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
2369 pre[0] = pre[1] = pre[2] = 0.0;
2371 if (v1->flag & PVERT_INTERIOR) {
2372 float x = nlGetVariable(0, v1->u.id);
2373 float x2 = nlGetVariable(0, ninterior + v1->u.id);
2374 pre[0] += sys->J2dt[e1->u.id][0]*x;
2375 pre[1] += sys->J2dt[e2->u.id][0]*x2;
2376 pre[2] += sys->J2dt[e3->u.id][0]*x2;
2379 if (v2->flag & PVERT_INTERIOR) {
2380 float x = nlGetVariable(0, v2->u.id);
2381 float x2 = nlGetVariable(0, ninterior + v2->u.id);
2382 pre[0] += sys->J2dt[e1->u.id][1]*x2;
2383 pre[1] += sys->J2dt[e2->u.id][1]*x;
2384 pre[2] += sys->J2dt[e3->u.id][1]*x2;
2387 if (v3->flag & PVERT_INTERIOR) {
2388 float x = nlGetVariable(0, v3->u.id);
2389 float x2 = nlGetVariable(0, ninterior + v3->u.id);
2390 pre[0] += sys->J2dt[e1->u.id][2]*x2;
2391 pre[1] += sys->J2dt[e2->u.id][2]*x2;
2392 pre[2] += sys->J2dt[e3->u.id][2]*x;
2395 dlambda1 = pre[0] + pre[1] + pre[2];
2396 dlambda1 = sys->dstar[f->u.id]*(sys->bstar[f->u.id] - dlambda1);
2398 sys->lambdaTriangle[f->u.id] += dlambda1;
2400 dalpha = (sys->bAlpha[e1->u.id] - dlambda1);
2401 sys->alpha[e1->u.id] += dalpha/sys->weight[e1->u.id] - pre[0];
2403 dalpha = (sys->bAlpha[e2->u.id] - dlambda1);
2404 sys->alpha[e2->u.id] += dalpha/sys->weight[e2->u.id] - pre[1];
2406 dalpha = (sys->bAlpha[e3->u.id] - dlambda1);
2407 sys->alpha[e3->u.id] += dalpha/sys->weight[e3->u.id] - pre[2];
2412 if (sys->alpha[e->u.id] > M_PI)
2413 sys->alpha[e->u.id] = M_PI;
2414 else if (sys->alpha[e->u.id] < 0.0f)
2415 sys->alpha[e->u.id] = 0.0f;
2416 } while (e != f->edge);
2419 for (i = 0; i < ninterior; i++) {
2420 sys->lambdaPlanar[i] += nlGetVariable(0, i);
2421 sys->lambdaLength[i] += nlGetVariable(0, ninterior + i);
2425 nlDeleteContext(nlGetCurrent());
2430 static PBool p_chart_abf_solve(PChart *chart)
2434 PEdge *e, *e1, *e2, *e3;
2437 float lastnorm, limit = (chart->nfaces > 100)? 1.0f: 0.001f;
2440 sys.ninterior = sys.nfaces = sys.nangles = 0;
2442 for (v=chart->verts; v; v=v->nextlink) {
2443 if (p_vert_interior(v)) {
2444 v->flag |= PVERT_INTERIOR;
2445 v->u.id = sys.ninterior++;
2448 v->flag &= ~PVERT_INTERIOR;
2451 for (f=chart->faces; f; f=f->nextlink) {
2452 e1 = f->edge; e2 = e1->next; e3 = e2->next;
2453 f->u.id = sys.nfaces++;
2455 /* angle id's are conveniently stored in half edges */
2456 e1->u.id = sys.nangles++;
2457 e2->u.id = sys.nangles++;
2458 e3->u.id = sys.nangles++;
2461 p_abf_setup_system(&sys);
2463 /* compute initial angles */
2464 for (f=chart->faces; f; f=f->nextlink) {
2467 e1 = f->edge; e2 = e1->next; e3 = e2->next;
2468 p_face_angles(f, &a1, &a2, &a3);
2470 if (a1 < sys.minangle)
2472 else if (a1 > sys.maxangle)
2474 if (a2 < sys.minangle)
2476 else if (a2 > sys.maxangle)
2478 if (a3 < sys.minangle)
2480 else if (a3 > sys.maxangle)
2483 sys.alpha[e1->u.id] = sys.beta[e1->u.id] = a1;
2484 sys.alpha[e2->u.id] = sys.beta[e2->u.id] = a2;
2485 sys.alpha[e3->u.id] = sys.beta[e3->u.id] = a3;
2487 sys.weight[e1->u.id] = 2.0/(a1*a1);
2488 sys.weight[e2->u.id] = 2.0/(a2*a2);
2489 sys.weight[e3->u.id] = 2.0/(a3*a3);
2492 for (v=chart->verts; v; v=v->nextlink) {
2493 if (v->flag & PVERT_INTERIOR) {
2494 float anglesum = 0.0, scale;
2498 anglesum += sys.beta[e->u.id];
2499 e = e->next->next->pair;
2500 } while (e && (e != v->edge));
2502 scale = (anglesum == 0.0f)? 0.0f: 2*M_PI/anglesum;
2506 sys.beta[e->u.id] = sys.alpha[e->u.id] = sys.beta[e->u.id]*scale;
2507 e = e->next->next->pair;
2508 } while (e && (e != v->edge));
2512 if (sys.ninterior > 0) {
2513 p_abf_compute_sines(&sys);
2518 for (i = 0; i < ABF_MAX_ITER; i++) {
2519 float norm = p_abf_compute_gradient(&sys, chart);
2526 if (!p_abf_matrix_invert(&sys, chart)) {
2527 param_warning("ABF failed to invert matrix.");
2528 p_abf_free_system(&sys);
2532 p_abf_compute_sines(&sys);
2535 if (i == ABF_MAX_ITER) {
2536 param_warning("ABF maximum iterations reached.");
2537 p_abf_free_system(&sys);
2542 chart->u.lscm.abf_alpha = MEM_dupallocN(sys.alpha);
2543 p_abf_free_system(&sys);
2548 /* Least Squares Conformal Maps */
2550 static void p_chart_pin_positions(PChart *chart, PVert **pin1, PVert **pin2)
2553 /* degenerate case */
2554 PFace *f = chart->faces;
2555 *pin1 = f->edge->vert;
2556 *pin2 = f->edge->next->vert;
2558 (*pin1)->uv[0] = 0.0f;
2559 (*pin1)->uv[1] = 0.5f;
2560 (*pin2)->uv[0] = 1.0f;
2561 (*pin2)->uv[1] = 0.5f;
2564 int diru, dirv, dirx, diry;
2567 VecSubf(sub, (*pin1)->co, (*pin2)->co);
2568 sub[0] = fabs(sub[0]);
2569 sub[1] = fabs(sub[1]);
2570 sub[2] = fabs(sub[2]);
2572 if ((sub[0] > sub[1]) && (sub[0] > sub[2])) {
2574 diry = (sub[1] > sub[2])? 1: 2;
2576 else if ((sub[1] > sub[0]) && (sub[1] > sub[2])) {
2578 diry = (sub[0] > sub[2])? 0: 2;
2582 diry = (sub[0] > sub[1])? 0: 1;
2594 (*pin1)->uv[diru] = (*pin1)->co[dirx];
2595 (*pin1)->uv[dirv] = (*pin1)->co[diry];
2596 (*pin2)->uv[diru] = (*pin2)->co[dirx];
2597 (*pin2)->uv[dirv] = (*pin2)->co[diry];
2601 static PBool p_chart_symmetry_pins(PChart *chart, PEdge *outer, PVert **pin1, PVert **pin2)
2603 PEdge *be, *lastbe = NULL, *maxe1 = NULL, *maxe2 = NULL, *be1, *be2;
2604 PEdge *cure = NULL, *firste1 = NULL, *firste2 = NULL, *nextbe;
2605 float maxlen = 0.0f, curlen = 0.0f, totlen = 0.0f, firstlen = 0.0f;
2608 /* find longest series of verts split in the chart itself, these are
2609 marked during construction */
2611 lastbe = p_boundary_edge_prev(be);
2613 float len = p_edge_length(be);
2616 nextbe = p_boundary_edge_next(be);
2618 if ((be->vert->flag & PVERT_SPLIT) ||
2619 (lastbe->vert->flag & nextbe->vert->flag & PVERT_SPLIT)) {
2626 curlen += p_edge_length(lastbe);
2629 if (curlen > maxlen) {
2635 if (firste1 == cure) {
2646 } while(be != outer);
2648 /* make sure we also count a series of splits over the starting point */
2649 if (cure && (cure != outer)) {
2650 firstlen += curlen + p_edge_length(be);
2652 if (firstlen > maxlen) {
2659 if (!maxe1 || !maxe2 || (maxlen < 0.5f*totlen))
2662 /* find pin1 in the split vertices */
2670 len1 += p_edge_length(be1);
2671 be1 = p_boundary_edge_next(be1);
2674 be2 = p_boundary_edge_prev(be2);
2675 len2 += p_edge_length(be2);
2677 } while (be1 != be2);
2681 /* find pin2 outside the split vertices */
2689 be1 = p_boundary_edge_prev(be1);
2690 len1 += p_edge_length(be1);
2693 len2 += p_edge_length(be2);
2694 be2 = p_boundary_edge_next(be2);
2696 } while (be1 != be2);
2700 p_chart_pin_positions(chart, pin1, pin2);
2705 static void p_chart_extrema_verts(PChart *chart, PVert **pin1, PVert **pin2)
2707 float minv[3], maxv[3], dirlen;
2708 PVert *v, *minvert[3], *maxvert[3];
2711 /* find minimum and maximum verts over x/y/z axes */
2712 minv[0] = minv[1] = minv[2] = 1e20;
2713 maxv[0] = maxv[1] = maxv[2] = -1e20;
2715 minvert[0] = minvert[1] = minvert[2] = NULL;
2716 maxvert[0] = maxvert[1] = maxvert[2] = NULL;
2718 for (v = chart->verts; v; v=v->nextlink) {
2719 for (i = 0; i < 3; i++) {
2720 if (v->co[i] < minv[i]) {
2724 if (v->co[i] > maxv[i]) {
2731 /* find axes with longest distance */
2735 for (i = 0; i < 3; i++) {
2736 if (maxv[i] - minv[i] > dirlen) {
2738 dirlen = maxv[i] - minv[i];
2742 *pin1 = minvert[dir];
2743 *pin2 = maxvert[dir];
2745 p_chart_pin_positions(chart, pin1, pin2);
2748 static void p_chart_lscm_load_solution(PChart *chart)
2752 for (v=chart->verts; v; v=v->nextlink) {
2753 v->uv[0] = nlGetVariable(0, 2*v->u.id);
2754 v->uv[1] = nlGetVariable(0, 2*v->u.id + 1);
2758 static void p_chart_lscm_begin(PChart *chart, PBool live, PBool abf)
2760 PVert *v, *pin1, *pin2;
2761 PBool select = P_FALSE, deselect = P_FALSE;
2762 int npins = 0, id = 0;
2764 /* give vertices matrix indices and count pins */
2765 for (v=chart->verts; v; v=v->nextlink) {
2766 if (v->flag & PVERT_PIN) {
2768 if (v->flag & PVERT_SELECT)
2772 if (!(v->flag & PVERT_SELECT))
2776 if ((live && (!select || !deselect)) || (npins == 1)) {
2777 chart->u.lscm.context = NULL;
2781 p_chart_simplify_compute(chart);
2782 p_chart_topological_sanity_check(chart);
2786 if (!p_chart_abf_solve(chart))
2787 param_warning("ABF solving failed: falling back to LSCM.\n");
2791 /* not enough pins, lets find some ourself */
2794 p_chart_boundaries(chart, NULL, &outer);
2796 if (!p_chart_symmetry_pins(chart, outer, &pin1, &pin2))
2797 p_chart_extrema_verts(chart, &pin1, &pin2);
2799 chart->u.lscm.pin1 = pin1;
2800 chart->u.lscm.pin2 = pin2;
2803 chart->flag |= PCHART_NOPACK;
2806 for (v=chart->verts; v; v=v->nextlink)
2810 nlSolverParameteri(NL_NB_VARIABLES, 2*chart->nverts);
2811 nlSolverParameteri(NL_NB_ROWS, 2*chart->nfaces);
2812 nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
2814 chart->u.lscm.context = nlGetCurrent();
2818 static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
2820 PVert *v, *pin1 = chart->u.lscm.pin1, *pin2 = chart->u.lscm.pin2;
2822 float *alpha = chart->u.lscm.abf_alpha;
2825 nlMakeCurrent(chart->u.lscm.context);
2830 /* TODO: make loading pins work for simplify/complexify. */
2833 for (v=chart->verts; v; v=v->nextlink)
2834 if (v->flag & PVERT_PIN)
2835 p_vert_load_pin_select_uvs(handle, v); /* reload for live */
2837 if (chart->u.lscm.pin1) {
2838 nlLockVariable(2*pin1->u.id);
2839 nlLockVariable(2*pin1->u.id + 1);
2840 nlLockVariable(2*pin2->u.id);
2841 nlLockVariable(2*pin2->u.id + 1);
2843 nlSetVariable(0, 2*pin1->u.id, pin1->uv[0]);
2844 nlSetVariable(0, 2*pin1->u.id + 1, pin1->uv[1]);
2845 nlSetVariable(0, 2*pin2->u.id, pin2->uv[0]);
2846 nlSetVariable(0, 2*pin2->u.id + 1, pin2->uv[1]);
2849 /* set and lock the pins */
2850 for (v=chart->verts; v; v=v->nextlink) {
2851 if (v->flag & PVERT_PIN) {
2852 nlLockVariable(2*v->u.id);
2853 nlLockVariable(2*v->u.id + 1);
2855 nlSetVariable(0, 2*v->u.id, v->uv[0]);
2856 nlSetVariable(0, 2*v->u.id + 1, v->uv[1]);
2861 /* construct matrix */
2866 for (f=chart->faces; f; f=f->nextlink) {
2867 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
2868 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
2869 float a1, a2, a3, ratio, cosine, sine;
2870 float sina1, sina2, sina3, sinmax;
2873 /* use abf angles if passed on */
2879 p_face_angles(f, &a1, &a2, &a3);
2885 sinmax = MAX3(sina1, sina2, sina3);
2887 /* shift vertices to find most stable order */
2888 if (sina3 != sinmax) {
2889 SHIFT3(PVert*, v1, v2, v3);
2890 SHIFT3(float, a1, a2, a3);
2891 SHIFT3(float, sina1, sina2, sina3);
2893 if (sina2 == sinmax) {
2894 SHIFT3(PVert*, v1, v2, v3);
2895 SHIFT3(float, a1, a2, a3);
2896 SHIFT3(float, sina1, sina2, sina3);
2900 /* angle based lscm formulation */
2901 ratio = (sina3 == 0.0f)? 1.0f: sina2/sina3;
2902 cosine = cos(a1)*ratio;
2907 nlCoefficient(2*v1->u.id, cosine - 1.0);
2908 nlCoefficient(2*v1->u.id+1, -sine);
2909 nlCoefficient(2*v2->u.id, -cosine);
2910 nlCoefficient(2*v2->u.id+1, sine);
2911 nlCoefficient(2*v3->u.id, 1.0);
2915 nlCoefficient(2*v1->u.id, sine);
2916 nlCoefficient(2*v1->u.id+1, cosine - 1.0);
2917 nlCoefficient(2*v2->u.id, -sine);
2918 nlCoefficient(2*v2->u.id+1, -cosine);
2919 nlCoefficient(2*v3->u.id+1, 1.0);
2922 nlMatrixAdd(row, 2*v1->u.id, cosine - 1.0);
2923 nlMatrixAdd(row, 2*v1->u.id+1, -sine);
2924 nlMatrixAdd(row, 2*v2->u.id, -cosine);
2925 nlMatrixAdd(row, 2*v2->u.id+1, sine);
2926 nlMatrixAdd(row, 2*v3->u.id, 1.0);
2929 nlMatrixAdd(row, 2*v1->u.id, sine);
2930 nlMatrixAdd(row, 2*v1->u.id+1, cosine - 1.0);
2931 nlMatrixAdd(row, 2*v2->u.id, -sine);
2932 nlMatrixAdd(row, 2*v2->u.id+1, -cosine);
2933 nlMatrixAdd(row, 2*v3->u.id+1, 1.0);
2942 if (nlSolveAdvanced(NULL, NL_TRUE)) {
2943 p_chart_lscm_load_solution(chart);
2947 for (v=chart->verts; v; v=v->nextlink) {
2956 static void p_chart_lscm_end(PChart *chart)
2958 if (chart->u.lscm.context)
2959 nlDeleteContext(chart->u.lscm.context);
2961 if (chart->u.lscm.abf_alpha) {
2962 MEM_freeN(chart->u.lscm.abf_alpha);
2963 chart->u.lscm.abf_alpha = NULL;
2966 chart->u.lscm.context = NULL;
2967 chart->u.lscm.pin1 = NULL;
2968 chart->u.lscm.pin2 = NULL;
2973 #define P_STRETCH_ITER 20
2975 static void p_stretch_pin_boundary(PChart *chart)
2979 for(v=chart->verts; v; v=v->nextlink)
2980 if (v->edge->pair == NULL)
2981 v->flag |= PVERT_PIN;
2983 v->flag &= ~PVERT_PIN;
2986 static float p_face_stretch(PFace *f)
2991 PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
2992 PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
2994 area = p_face_uv_area_signed(f);
2996 if (area <= 0.0f) /* flipped face -> infinite stretch */
2999 w= 1.0f/(2.0f*area);
3001 /* compute derivatives */
3002 VecCopyf(Ps, v1->co);
3003 VecMulf(Ps, (v2->uv[1] - v3->uv[1]));
3005 VecCopyf(tmp, v2->co);
3006 VecMulf(tmp, (v3->uv[1] - v1->uv[1]));
3007 VecAddf(Ps, Ps, tmp);
3009 VecCopyf(tmp, v3->co);
3010 VecMulf(tmp, (v1->uv[1] - v2->uv[1]));
3011 VecAddf(Ps, Ps, tmp);
3015 VecCopyf(Pt, v1->co);
3016 VecMulf(Pt, (v3->uv[0] - v2->uv[0]));
3018 VecCopyf(tmp, v2->co);
3019 VecMulf(tmp, (v1->uv[0] - v3->uv[0]));
3020 VecAddf(Pt, Pt, tmp);
3022 VecCopyf(tmp, v3->co);
3023 VecMulf(tmp, (v2->uv[0] - v1->uv[0]));
3024 VecAddf(Pt, Pt, tmp);
3032 T = sqrt(0.5f*(a + c));
3033 if (f->flag & PFACE_FILLED)
3039 static float p_stretch_compute_vertex(PVert *v)
3045 sum += p_face_stretch(e->face);
3046 e = p_wheel_edge_next(e);
3047 } while (e && e != (v->edge));
3052 static void p_chart_stretch_minimize(PChart *chart, RNG *rng)
3057 float orig_stretch, low, stretch_low, high, stretch_high, mid, stretch;
3058 float orig_uv[2], dir[2], random_angle, trusted_radius;
3060 for(v=chart->verts; v; v=v->nextlink) {
3061 if((v->flag & PVERT_PIN) || !(v->flag & PVERT_SELECT))
3064 orig_stretch = p_stretch_compute_vertex(v);
3065 orig_uv[0] = v->uv[0];
3066 orig_uv[1] = v->uv[1];
3068 /* move vertex in a random direction */
3069 trusted_radius = 0.0f;
3074 trusted_radius += p_edge_uv_length(e);
3077 e = p_wheel_edge_next(e);
3078 } while (e && e != (v->edge));
3080 trusted_radius /= 2 * nedges;
3082 random_angle = rng_getFloat(rng) * 2.0 * M_PI;
3083 dir[0] = trusted_radius * cos(random_angle);
3084 dir[1] = trusted_radius * sin(random_angle);
3086 /* calculate old and new stretch */
3088 stretch_low = orig_stretch;
3090 Vec2Addf(v->uv, orig_uv, dir);
3092 stretch = stretch_high = p_stretch_compute_vertex(v);
3094 /* binary search for lowest stretch position */
3095 for (j = 0; j < P_STRETCH_ITER; j++) {
3096 mid = 0.5 * (low + high);
3097 v->uv[0]= orig_uv[0] + mid*dir[0];
3098 v->uv[1]= orig_uv[1] + mid*dir[1];
3099 stretch = p_stretch_compute_vertex(v);
3101 if (stretch_low < stretch_high) {
3103 stretch_high = stretch;
3107 stretch_low = stretch;
3111 /* no luck, stretch has increased, reset to old values */
3112 if(stretch >= orig_stretch)
3113 Vec2Copyf(v->uv, orig_uv);
3117 /* Minimum area enclosing rectangle for packing */
3119 static int p_compare_geometric_uv(const void *a, const void *b)
3121 PVert *v1 = *(PVert**)a;
3122 PVert *v2 = *(PVert**)b;
3124 if (v1->uv[0] < v2->uv[0])
3126 else if (v1->uv[0] == v2->uv[0]) {
3127 if (v1->uv[1] < v2->uv[1])
3129 else if (v1->uv[1] == v2->uv[1])
3138 static PBool p_chart_convex_hull(PChart *chart, PVert ***verts, int *nverts, int *right)
3140 /* Graham algorithm, taken from:
3141 * http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/117225 */
3144 int npoints = 0, i, ulen, llen;
3145 PVert **U, **L, **points, **p;
3147 p_chart_boundaries(chart, NULL, &be);
3155 e = p_boundary_edge_next(e);
3158 p = points = (PVert**)MEM_mallocN(sizeof(PVert*)*npoints*2, "PCHullpoints");
3159 U = (PVert**)MEM_mallocN(sizeof(PVert*)*npoints, "PCHullU");
3160 L = (PVert**)MEM_mallocN(sizeof(PVert*)*npoints, "PCHullL");
3166 e = p_boundary_edge_next(e);
3169 qsort(points, npoints, sizeof(PVert*), p_compare_geometric_uv);
3172 for (p=points, i = 0; i < npoints; i++, p++) {
3173 while ((ulen > 1) && (p_area_signed(U[ulen-2]->uv, (*p)->uv, U[ulen-1]->uv) <= 0))
3175 while ((llen > 1) && (p_area_signed(L[llen-2]->uv, (*p)->uv, L[llen-1]->uv) >= 0))
3185 for (p=points, i = 0; i < ulen; i++, p++, npoints++)
3188 /* the first and last point in L are left out, since they are also in U */
3189 for (i = llen-2; i > 0; i--, p++, npoints++)
3202 static float p_rectangle_area(float *p1, float *dir, float *p2, float *p3, float *p4)
3204 /* given 4 points on the rectangle edges and the direction of on edge,
3205 compute the area of the rectangle */
3207 float orthodir[2], corner1[2], corner2[2], corner3[2];
3209 orthodir[0] = dir[1];
3210 orthodir[1] = -dir[0];
3212 if (!p_intersect_line_2d_dir(p1, dir, p2, orthodir, corner1))
3215 if (!p_intersect_line_2d_dir(p1, dir, p4, orthodir, corner2))
3218 if (!p_intersect_line_2d_dir(p3, dir, p4, orthodir, corner3))
3221 return Vec2Lenf(corner1, corner2)*Vec2Lenf(corner2, corner3);
3224 static float p_chart_minimum_area_angle(PChart *chart)
3226 /* minimum area enclosing rectangle with rotating calipers, info:
3227 * http://cgm.cs.mcgill.ca/~orm/maer.html */
3229 float rotated, minarea, minangle, area, len;
3230 float *angles, miny, maxy, v[2], a[4], mina;
3231 int npoints, right, mini, maxi, i, idx[4], nextidx;
3232 PVert **points, *p1, *p2, *p3, *p4, *p1n;
3234 /* compute convex hull */
3235 if (!p_chart_convex_hull(chart, &points, &npoints, &right))
3238 /* find left/top/right/bottom points, and compute angle for each point */
3239 angles = MEM_mallocN(sizeof(float)*npoints, "PMinAreaAngles");
3245 for (i = 0; i < npoints; i++) {
3246 p1 = (i == 0)? points[npoints-1]: points[i-1];
3248 p3 = (i == npoints-1)? points[0]: points[i+1];
3250 angles[i] = M_PI - p_vec2_angle(p1->uv, p2->uv, p3->uv);
3252 if (points[i]->uv[1] < miny) {
3253 miny = points[i]->uv[1];
3256 if (points[i]->uv[1] > maxy) {
3257 maxy = points[i]->uv[1];
3262 /* left, top, right, bottom */
3268 v[0] = points[idx[0]]->uv[0];
3269 v[1] = points[idx[0]]->uv[1] + 1.0f;
3270 a[0] = p_vec2_angle(points[(idx[0]+1)%npoints]->uv, points[idx[0]]->uv, v);
3272 v[0] = points[idx[1]]->uv[0] + 1.0f;
3273 v[1] = points[idx[1]]->uv[1];
3274 a[1] = p_vec2_angle(points[(idx[1]+1)%npoints]->uv, points[idx[1]]->uv, v);
3276 v[0] = points[idx[2]]->uv[0];
3277 v[1] = points[idx[2]]->uv[1] - 1.0f;
3278 a[2] = p_vec2_angle(points[(idx[2]+1)%npoints]->uv, points[idx[2]]->uv, v);
3280 v[0] = points[idx[3]]->uv[0] - 1.0f;
3281 v[1] = points[idx[3]]->uv[1];
3282 a[3] = p_vec2_angle(points[(idx[3]+1)%npoints]->uv, points[idx[3]]->uv, v);
3284 /* 4 rotating calipers */
3290 while (rotated <= M_PI/2) { /* INVESTIGATE: how far to rotate? */
3291 /* rotate with the smallest angle */
3295 for (i = 0; i < 4; i++)
3302 nextidx = (idx[mini]+1)%npoints;
3304 a[mini] = angles[nextidx];
3305 a[(mini+1)%4] = a[(mini+1)%4] - mina;
3306 a[(mini+2)%4] = a[(mini+2)%4] - mina;
3307 a[(mini+3)%4] = a[(mini+3)%4] - mina;
3310 p1 = points[idx[mini]];
3311 p1n = points[nextidx];
3312 p2 = points[idx[(mini+1)%4]];
3313 p3 = points[idx[(mini+2)%4]];
3314 p4 = points[idx[(mini+3)%4]];
3316 len = Vec2Lenf(p1->uv, p1n->uv);
3320 v[0] = (p1n->uv[0] - p1->uv[0])*len;
3321 v[1] = (p1n->uv[1] - p1->uv[1])*len;
3323 area = p_rectangle_area(p1->uv, v, p2->uv, p3->uv, p4->uv);
3325 /* remember smallest area */
3326 if (area < minarea) {
3332 idx[mini] = nextidx;
3335 /* try keeping rotation as small as possible */
3336 if (minangle > M_PI/4)
3345 static void p_chart_rotate_minimum_area(PChart *chart)
3347 float angle = p_chart_minimum_area_angle(chart);
3348 float sine = sin(angle);
3349 float cosine = cos(angle);
3352 for (v = chart->verts; v; v=v->nextlink) {
3353 float oldu = v->uv[0], oldv = v->uv[1];
3354 v->uv[0] = cosine*oldu - sine*oldv;
3355 v->uv[1] = sine*oldu + cosine*oldv;
3359 /* Area Smoothing */
3361 /* 2d bsp tree for inverse mapping - that's a bit silly */
3363 typedef struct SmoothTriangle {
3364 float co1[2], co2[2], co3[2];
3365 float oco1[2], oco2[2], oco3[2];
3368 typedef struct SmoothNode {
3369 struct SmoothNode *c1, *c2;
3370 SmoothTriangle **tri;
3375 static void p_barycentric_2d(float *v1, float *v2, float *v3, float *p, float *b)
3377 float a[2], c[2], h[2], div;
3379 a[0] = v2[0] - v1[0];
3380 a[1] = v2[1] - v1[1];
3381 c[0] = v3[0] - v1[0];
3382 c[1] = v3[1] - v1[1];
3384 div = a[0]*c[1] - a[1]*c[0];
3392 h[0] = p[0] - v1[0];
3393 h[1] = p[1] - v1[1];
3397 b[1] = (h[0]*c[1] - h[1]*c[0])*div;
3398 b[2] = (a[0]*h[1] - a[1]*h[0])*div;
3399 b[0] = 1.0 - b[1] - b[2];
3403 static PBool p_triangle_inside(SmoothTriangle *t, float *co)
3407 p_barycentric_2d(t->co1, t->co2, t->co3, co, b);
3409 if ((b[0] >= 0.0) && (b[1] >= 0.0) && (b[2] >= 0.0f)) {
3410 co[0] = t->oco1[0]*b[0] + t->oco2[0]*b[1] + t->oco3[0]*b[2];
3411 co[1] = t->oco1[1]*b[0] + t->oco2[1]*b[1] + t->oco3[1]*b[2];
3418 static SmoothNode *p_node_new(MemArena *arena, SmoothTriangle **tri, int ntri, float *bmin, float *bmax, int depth)
3420 SmoothNode *node = BLI_memarena_alloc(arena, sizeof *node);
3421 int axis, i, t1size = 0, t2size = 0;
3422 float split, mi, mx;
3423 SmoothTriangle **t1, **t2, *t;
3428 if (ntri <= 10 || depth >= 15)
3431 t1 = MEM_mallocN(sizeof(SmoothTriangle)*ntri, "PNodeTri1");
3432 t2 = MEM_mallocN(sizeof(SmoothTriangle)*ntri, "PNodeTri1");
3434 axis = (bmax[0] - bmin[0] > bmax[1] - bmin[1])? 0: 1;
3435 split = 0.5f*(bmin[axis] + bmax[axis]);
3437 for (i = 0; i < ntri; i++) {
3440 if ((t->co1[axis] <= split) || (t->co2[axis] <=&nbs