37#define param_warning(message) \
42# define UNUSED_FUNCTION_NO_SLIM(x) x
44# define UNUSED_FUNCTION_NO_SLIM UNUSED_FUNCTION
136#define PEDGE_VERTEX_FLAGS (PEDGE_PIN)
180 1, 3, 5, 11, 17, 37, 67, 131, 257, 521,
181 1031, 2053, 4099, 8209, 16411, 32771, 65537, 131101, 262147, 524309,
182 1048583, 2097169, 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459,
185#define PHASH_hash(ph, item) (uintptr_t(item) % uint((ph)->cursize))
186#define PHASH_edge(v1, v2) (((v1) < (v2)) ? ((v1) * 39) ^ ((v2) * 31) : ((v1) * 31) ^ ((v2) * 39))
226 if (lookup ==
nullptr) {
234 link->
next = lookup->next;
247 *(ph->
list) =
nullptr;
249 for (link = first; link; link =
next) {
262 if (link->
key == key) {
277 for (link = link->
next; link; link = link->
next) {
278 if (link->
key == key) {
300 const double max_angle =
DEG2RAD(179.0);
301 const double fix_amount = *r_fix - max_angle;
302 if (fix_amount < 0.0f) {
325 const double dist_v1 =
len_v3v3(v_fix, v1);
327 const double sum = dist_v1 + dist_v2;
328 const double weight = (
sum > 1e-20f) ? dist_v2 /
sum : 0.5f;
331 *r_fix -= fix_amount;
332 *r_a1 += fix_amount * weight;
333 *r_a2 += fix_amount * (1.0f - weight);
353 *r_a1 =
max_dd(*r_a1, 0.001f);
354 *r_a2 =
max_dd(*r_a2, 0.001f);
355 *r_a3 =
max_dd(*r_a3, 0.001f);
361 PVert *v1 = e1->
vert, *
v2 = e2->vert, *v3 = e3->vert;
366static float p_vec_cos(
const float v1[3],
const float v2[3],
const float v3[3])
386 PVert *v1 = e1->
vert, *
v2 = e2->vert, *v3 = e3->vert;
394 PVert *v1 = e1->
vert, *
v2 = e2->vert, *v3 = e3->vert;
401 return 0.5f * (((
v2[0] - v1[0]) * (v3[1] - v1[1])) - ((v3[0] - v1[0]) * (
v2[1] - v1[1])));
407 PVert *v1 = e1->
vert, *
v2 = e2->vert, *v3 = e3->vert;
409 return 0.5f * (((
v2->uv[0] - v1->
uv[0]) * (v3->uv[1] - v1->
uv[1])) -
410 ((v3->uv[0] - v1->
uv[0]) * (
v2->uv[1] - v1->
uv[1])));
415 return len_v3v3(
e->vert->co,
e->next->vert->co);
425 return len_v2v2(
e->vert->uv,
e->next->vert->uv);
434 for (
v = chart->
verts;
v;
v =
v->nextlink) {
464 if (scale_x == 1.0f) {
480 v->uv[0] += trans[0];
481 v->uv[1] += trans[1];
497 for (
v = chart->
verts;
v;
v =
v->nextlink) {
510 div = dir2[0] * dir1[1] - dir2[1] * dir1[0];
516 lmbda = ((v1[1] -
v2[1]) * dir1[0] - (v1[0] -
v2[0]) * dir1[1]) / div;
517 r_isect[0] = v1[0] + lmbda * dir2[0];
518 r_isect[1] = v1[1] + lmbda * dir2[1];
527 return e->next->next->pair;
532 return e->next->next->pair;
537 return (
e->pair) ?
e->pair->next :
nullptr;
542 return e->next->vert->edge;
552 }
while (we && (we !=
e));
554 return last->next->next;
559 return v->edge->pair;
565 PVert *v1 = e1->
vert, *
v2 = e2->vert, *v3 = e3->vert;
566 int f1 = e1->
flag, f2 = e2->flag, f3 = e3->flag;
567 float *orig_uv1 = e1->
orig_uv, *orig_uv2 = e2->orig_uv, *orig_uv3 = e3->orig_uv;
581 e3->orig_uv = orig_uv1;
586static void p_chart_topological_sanity_check(PChart *chart)
591 for (
v = chart->verts;
v;
v =
v->nextlink) {
592 GEO_uv_parametrizer_test_equals_ptr(
"v->edge->vert",
v,
v->edge->vert);
595 for (
e = chart->edges;
e;
e =
e->nextlink) {
597 GEO_uv_parametrizer_test_equals_ptr(
"e->pair->pair",
e,
e->pair->pair);
598 GEO_uv_parametrizer_test_equals_ptr(
"pair->vert",
e->vert,
e->pair->next->vert);
599 GEO_uv_parametrizer_test_equals_ptr(
"pair->next->vert",
e->next->vert,
e->pair->vert);
610 int nedges = 0, npins = 0;
613 v->uv[0] =
v->uv[1] = 0.0f;
614 pinuv[0] = pinuv[1] = 0.0f;
623 pinuv[0] +=
e->orig_uv[0] * handle->
aspect_y;
624 pinuv[1] +=
e->orig_uv[1];
629 v->uv[1] +=
e->orig_uv[1];
636 }
while (
e &&
e != (
v->edge));
639 v->uv[0] = pinuv[0] / npins;
640 v->uv[1] = pinuv[1] / npins;
643 else if (nedges > 0) {
654 const float invblend = 1.0f -
blend;
655 const float invblend_x = invblend / handle->
aspect_y;
658 e->orig_uv[0] =
blend *
e->old_uv[0] + invblend_x *
e->vert->uv[0];
659 e->orig_uv[1] =
blend *
e->old_uv[1] + invblend *
e->vert->uv[1];
668 e->orig_uv[0] =
blend *
e->old_uv[0] + invblend_x *
e->vert->uv[0];
669 e->orig_uv[1] =
blend *
e->old_uv[1] + invblend *
e->vert->uv[1];
684 e2->old_uv[0] = e2->orig_uv[0];
685 e2->old_uv[1] = e2->orig_uv[1];
688 e3->old_uv[0] = e3->orig_uv[0];
689 e3->old_uv[1] = e3->orig_uv[1];
702 e2->orig_uv[0] = e2->old_uv[0];
703 e2->orig_uv[1] = e2->old_uv[1];
706 e3->orig_uv[0] = e3->old_uv[0];
707 e3->orig_uv[1] = e3->old_uv[1];
723 for (
int i = 0;
i < 3;
i++) {
734 v->on_boundary_flag =
false;
758 nv->
uv[0] =
v->uv[0];
759 nv->
uv[1] =
v->uv[1];
760 nv->
u.
key =
v->u.key;
777 if ((
e->vert->u.key == vkeys[0]) && (
e->next->vert->u.key == vkeys[1])) {
780 if ((
e->vert->u.key == vkeys[1]) && (
e->next->vert->u.key == vkeys[0])) {
797 if ((
e->vert->u.key == vkeys[i1]) && (
e->next->vert->u.key == vkeys[i2])) {
798 if (
e->next->next->vert->u.key == vkeys[i3]) {
802 else if ((
e->vert->u.key == vkeys[i2]) && (
e->next->vert->u.key == vkeys[i1])) {
803 if (
e->next->next->vert->u.key == vkeys[i3]) {
816 const float *uv1, *uv2, *uvp1, *uvp2;
823 uv2 =
e->next->orig_uv;
834 if ((
fabsf(uv1[0] - uvp1[0]) > limit[0]) || (
fabsf(uv1[1] - uvp1[1]) > limit[1])) {
839 if ((
fabsf(uv2[0] - uvp2[0]) > limit[0]) || (
fabsf(uv2[1] - uvp2[1]) > limit[1])) {
869 if (((v1->
u.
key == key1) && (
v2->u.key == key2)) ||
870 ((v1->
u.
key == key2) && (
v2->u.key == key1)))
888 if (*r_pair && (
e->vert == (*r_pair)->vert)) {
889 if ((*r_pair)->next->pair || (*r_pair)->next->next->pair) {
896 return (*r_pair !=
nullptr);
901 bool topology_from_uvs,
904 PEdge *pair =
nullptr;
907 if (
e->vert == pair->
vert) {
920 return (
e->pair !=
nullptr);
927 PEdge **stack = stackbase;
939 *stack = first->
edge;
942 while (stack != stackbase) {
975 PEdge *we, *lastwe =
nullptr;
1001 if (we ==
v->edge) {
1004 v->nextlink = chart->
verts;
1016 v->nextlink = chart->
verts;
1026 }
while (we && (we != lastwe));
1034 for (
int i = 0;
i < ncharts;
i++) {
1095 const float *weight,
1105 float weight1, weight2, weight3;
1107 weight1 = weight[i1];
1108 weight2 = weight[i2];
1109 weight3 = weight[i3];
1118 e2->vert =
p_vert_lookup(handle, vkeys[i2], co[i2], weight2, e2);
1119 e3->vert =
p_vert_lookup(handle, vkeys[i3], co[i3], weight3, e3);
1122 e2->orig_uv = uv[i2];
1123 e3->orig_uv = uv[i3];
1153 e2->u.key =
PHASH_edge(vkeys[i2], vkeys[i3]);
1154 e3->u.key =
PHASH_edge(vkeys[i3], vkeys[i1]);
1172 e1->
orig_uv = e2->orig_uv = e3->orig_uv =
nullptr;
1194 float len, maxlen = -1.0;
1201 for (
e = chart->
edges;
e;
e =
e->nextlink) {
1217 if (r_outer && (
len > maxlen)) {
1223 for (
e = chart->
edges;
e;
e =
e->nextlink) {
1246 }
while (we && (we !=
v->edge));
1277 while (nedges > 2) {
1278 PEdge *ne, *ne1, *ne2;
1307 ne1->
vert =
e->vert;
1333 for (
e = chart->
edges;
e;
e =
e->nextlink) {
1357static int p_polygon_point_in(
const float cp1[2],
const float cp2[2],
const float p[2])
1359 if ((cp1[0] == p[0]) && (cp1[1] == p[1])) {
1362 else if ((cp2[0] == p[0]) && (cp2[1] == p[1])) {
1370static void p_polygon_kernel_clip(
float (*oldpoints)[2],
1372 float (*newpoints)[2],
1377 float *p2, *p1, isect[2];
1380 p1 = oldpoints[noldpoints - 1];
1381 p1in = p_polygon_point_in(cp1, cp2, p1);
1384 for (
i = 0;
i < noldpoints;
i++) {
1386 p2in = p_polygon_point_in(cp1, cp2, p2);
1388 if ((p2in >= 2) || (p1in && p2in)) {
1389 newpoints[*r_nnewpoints][0] = p2[0];
1390 newpoints[*r_nnewpoints][1] = p2[1];
1393 else if (p1in && !p2in) {
1395 p_intersect_line_2d(p1, p2, cp1, cp2, isect);
1396 newpoints[*r_nnewpoints][0] = isect[0];
1397 newpoints[*r_nnewpoints][1] = isect[1];
1401 else if (!p1in && p2in) {
1402 p_intersect_line_2d(p1, p2, cp1, cp2, isect);
1403 newpoints[*r_nnewpoints][0] = isect[0];
1404 newpoints[*r_nnewpoints][1] = isect[1];
1407 newpoints[*r_nnewpoints][0] = p2[0];
1408 newpoints[*r_nnewpoints][1] = p2[1];
1417static void p_polygon_kernel_center(
float (*points)[2],
int npoints,
float *center)
1419 int i,
size, nnewpoints = npoints;
1420 float(*oldpoints)[2], (*newpoints)[2], *p1, *p2;
1426 memcpy(oldpoints, points,
sizeof(
float[2]) * npoints);
1428 for (
i = 0;
i < npoints;
i++) {
1430 p2 = points[(
i + 1) % npoints];
1431 p_polygon_kernel_clip(oldpoints, nnewpoints, newpoints, &nnewpoints, p1, p2);
1433 if (nnewpoints == 0) {
1435 memcpy(oldpoints, points,
sizeof(
float[2]) * npoints);
1436 nnewpoints = npoints;
1439 else if (nnewpoints == 1) {
1441 center[0] = newpoints[0][0];
1442 center[1] = newpoints[0][1];
1450 if (nnewpoints * 2 >
size) {
1454 memcpy(oldpoints, newpoints,
sizeof(
float[2]) * nnewpoints);
1459 float(*sw_points)[2] = oldpoints;
1460 oldpoints = newpoints;
1461 newpoints = sw_points;
1465 center[0] = center[1] = 0.0f;
1467 for (
i = 0;
i < nnewpoints;
i++) {
1468 center[0] += oldpoints[
i][0];
1469 center[1] += oldpoints[
i][1];
1472 center[0] /= nnewpoints;
1473 center[1] /= nnewpoints;
1488static float p_vert_cotan(
const float v1[3],
const float v2[3],
const float v3[3])
1490 float a[3],
b[3], c[3], clen;
1505static bool p_vert_flipped_wheel_triangle(
PVert *
v)
1515 }
while (
e && (
e !=
v->edge));
1520static bool p_vert_map_harmonic_weights(
PVert *
v)
1522 float weightsum, positionsum[2], olduv[2];
1525 positionsum[0] = positionsum[1] = 0.0f;
1531 float t1, t2, weight;
1535 v2 =
e->next->next->vert;
1536 t1 = p_vert_cotan(
v2->
co,
e->vert->
co, v1->co);
1538 v1 =
e->pair->next->vert;
1539 v2 =
e->pair->next->next->vert;
1540 t2 = p_vert_cotan(
v2->
co,
e->pair->vert->
co, v1->co);
1542 weight = 0.5f * (t1 + t2);
1543 weightsum += weight;
1544 positionsum[0] += weight *
e->pair->vert->uv[0];
1545 positionsum[1] += weight *
e->pair->vert->uv[1];
1548 }
while (
e && (
e !=
v->edge));
1558 v1 =
e->next->next->vert;
1560 t1 = p_vert_cotan(v1->co,
v->
co,
v2->
co);
1561 t2 = p_vert_cotan(
v2->
co,
v->
co, v1->co);
1563 weightsum += t1 + t2;
1564 positionsum[0] += (
v2->uv[1] - v1->uv[1]) + (t1 *
v2->uv[0] + t2 * v1->uv[0]);
1565 positionsum[1] += (v1->uv[0] -
v2->uv[0]) + (t1 *
v2->uv[1] + t2 * v1->uv[1]);
1568 }
while (
e && (
e !=
v->edge));
1571 if (weightsum != 0.0f) {
1572 weightsum = 1.0f / weightsum;
1573 positionsum[0] *= weightsum;
1574 positionsum[1] *= weightsum;
1577 olduv[0] =
v->uv[0];
1578 olduv[1] =
v->uv[1];
1579 v->uv[0] = positionsum[0];
1580 v->uv[1] = positionsum[1];
1582 if (p_vert_flipped_wheel_triangle(
v)) {
1583 v->uv[0] = olduv[0];
1584 v->uv[1] = olduv[1];
1592static void p_vert_harmonic_insert(
PVert *
v)
1596 if (!p_vert_map_harmonic_weights(
v)) {
1608 }
while (
e && (
e !=
v->edge));
1621 points[
i][0] =
e->next->vert->uv[0];
1622 points[
i][1] =
e->next->vert->uv[1];
1624 if (nexte ==
nullptr) {
1626 points[
i][0] =
e->next->next->vert->uv[0];
1627 points[
i][1] =
e->next->next->vert->uv[1];
1633 }
while (
e !=
v->edge);
1635 p_polygon_kernel_center(points, npoints,
v->uv);
1643 p_vert_map_harmonic_weights(
e->next->vert);
1646 }
while (
e && (
e !=
v->edge));
1648 p_vert_map_harmonic_weights(
v);
1657 while (
v->edge->pair) {
1660 if (
v->edge == start) {
1670 *r_newv = edge->
vert;
1675 *r_keepv = pair->
vert;
1681 PVert *oldv, *keepv;
1689 if ((
e != edge) && !(pair && pair->
next ==
e)) {
1694 }
while (
e && (
e != oldv->
edge));
1697 if ((edge && (keepv->
edge == edge->
next)) || (keepv->
edge == pair)) {
1721 e2->pair->pair = e1->
pair;
1739 e2->pair->pair = e1->
pair;
1776static void p_split_vertex(PEdge *edge, PEdge *pair)
1778 PVert *newv, *keepv;
1785 PEdge *e1 = edge->next, *e2 = e1->next;
1788 e1->pair->pair = e1;
1791 e2->pair->pair = e2;
1794 e2->vert->edge = e2;
1803 e1->pair->pair = e1;
1806 e2->pair->pair = e2;
1821 }
while (
e && (
e != newv->edge));
1827 PVert *oldv, *keepv;
1832 if (!edge || !pair) {
1851static bool p_collapse_normal_flipped(
float *v1,
float *
v2,
float *vold,
float *vnew)
1853 float nold[3], nnew[3], sub1[3], sub2[3];
1863 return (
dot_v3v3(nold, nnew) <= 0.0f);
1866static bool p_collapse_allowed_geometric(PEdge *edge, PEdge *pair)
1868 PVert *oldv, *keepv;
1870 float angulardefect,
angle;
1874 angulardefect = 2 *
M_PI;
1878 float a[3],
b[3], minangle, maxangle;
1879 PEdge *e1 =
e->next, *e2 = e1->next;
1880 PVert *v1 = e1->vert, *
v2 = e2->vert;
1883 angle = p_vec_angle(v1->co, oldv->co,
v2->co);
1884 angulardefect -=
angle;
1887 if (v1 == keepv ||
v2 == keepv) {
1892 if (p_collapse_normal_flipped(v1->co,
v2->
co, oldv->co, keepv->co)) {
1897 a[1] = p_vec_angle(
v2->
co, v1->co, oldv->co);
1898 a[2] =
M_PI - a[0] - a[1];
1900 b[0] = p_vec_angle(v1->co, keepv->co,
v2->
co);
1901 b[1] = p_vec_angle(
v2->
co, v1->co, keepv->co);
1906 maxangle =
M_PI - minangle;
1908 for (
i = 0;
i < 3;
i++) {
1909 if ((
b[
i] < a[
i]) && (
b[
i] < minangle)) {
1912 else if ((
b[
i] > a[
i]) && (
b[
i] > maxangle)) {
1918 }
while (
e && (
e != oldv->edge));
1936 angle = p_vec_angle(v1->co, oldv->co,
v2->
co);
1945static bool p_collapse_allowed(
PEdge *edge,
PEdge *pair)
1947 PVert *oldv, *keepv;
1958static float p_collapse_cost(
PEdge *edge,
PEdge *pair)
1963 PVert *oldv, *keepv;
1965 PFace *oldf1, *oldf2;
1966 float volumecost = 0.0f, areacost = 0.0f, edgevec[3], cost, weight, elen;
1967 float shapecost = 0.0f;
1968 float shapeold = 0.0f, shapenew = 0.0f;
1969 int nshapeold = 0, nshapenew = 0;
1972 oldf1 = (edge) ? edge->face :
nullptr;
1973 oldf2 = (pair) ? pair->face :
nullptr;
1980 float *co1 =
e->next->vert->
co;
1981 float *co2 =
e->next->next->vert->
co;
1983 if (!
ELEM(
e->face, oldf1, oldf2)) {
1984 float tetrav2[3], tetrav3[3];
1992 shapecost +=
dot_v3v3(co1, keepv->co);
1995 shapecost +=
dot_v3v3(co2, keepv->co);
2000 a1 = a1 -
M_PI / 3.0;
2001 a2 = a2 -
M_PI / 3.0;
2002 a3 = a3 -
M_PI / 3.0;
2003 shapeold = (a1 * a1 + a2 * a2 + a3 * a3) / (
M_PI_2 *
M_PI_2);
2009 a1 = a1 -
M_PI / 3.0;
2010 a2 = a2 -
M_PI / 3.0;
2011 a3 = a3 -
M_PI / 3.0;
2012 shapenew = (a1 * a1 + a2 * a2 + a3 * a3) / (
M_PI_2 *
M_PI_2);
2018 }
while (
e && (
e != oldv->edge));
2029 cost = weight * volumecost * volumecost + elen * elen * areacost * areacost;
2033 shapeold /= nshapeold;
2034 shapenew /= nshapenew;
2035 shapecost = (shapeold + 0.00001) / (shapenew + 0.00001);
2048 const std::function<
float(
PEdge *,
PEdge *)> &collapse_cost_fn,
2049 const std::function<
float(
PEdge *,
PEdge *)> &collapse_allowed_fn)
2057 if (collapse_allowed_fn(
e,
e->pair)) {
2058 float cost = collapse_cost_fn(
e,
e->pair);
2060 if ((*r_mine ==
nullptr) || (cost < *r_mincost)) {
2068 if (enext ==
nullptr) {
2070 pair =
e->next->next;
2072 if (collapse_allowed_fn(
nullptr, pair)) {
2073 float cost = collapse_cost_fn(
nullptr, pair);
2075 if ((*r_mine ==
nullptr) || (cost < *r_mincost)) {
2085 }
while (
e != vert->
edge);
2093 PEdge *
e, *nexte =
nullptr, *edges = chart->
edges, *laste =
nullptr;
2103 nextv =
v->nextlink;
2110 v->nextlink = chart->
verts;
2116 for (
e = edges;
e;
e = nexte) {
2117 nexte =
e->nextlink;
2125 e->nextlink = chart->
edges;
2134 for (
e = collapsed;
e;
e =
e->nextlink) {
2135 e->nextlink =
e->u.nextcollapse;
2143 for (f =
faces; f; f = nextf) {
2159 std::function<
float(
PEdge *,
PEdge *)> collapse_cost_fn,
2160 std::function<
float(
PEdge *,
PEdge *)> collapse_allowed_fn)
2163 static const int MAX_SIMPLIFY = INT_MAX;
2171 PEdge *collapsededges =
nullptr;
2187 v->u.heaplink =
nullptr;
2192 e->u.nextcollapse =
nullptr;
2197 if (ncollapsed == MAX_SIMPLIFY) {
2203 PVert *oldv, *keepv;
2204 PEdge *wheele, *nexte;
2208 collapsededges = edge;
2213 std::swap(edge, pair);
2224 wheele = oldv->
edge;
2230 if (nexte ==
nullptr) {
2235 }
while (wheele && (wheele != oldv->
edge));
2240 for (
PVert *
v : wheelverts) {
2242 PEdge *collapse =
nullptr;
2244 if (
v->u.heaplink) {
2246 v->u.heaplink =
nullptr;
2265static void p_chart_post_split_flush(PChart *chart)
2269 PVert *
v, *nextv =
nullptr;
2270 PEdge *
e, *nexte =
nullptr;
2271 PFace *f, *nextf =
nullptr;
2273 for (
v = chart->collapsed_verts;
v;
v = nextv) {
2274 nextv =
v->nextlink;
2275 v->nextlink = chart->verts;
2280 for (
e = chart->collapsed_edges;
e;
e = nexte) {
2281 nexte =
e->nextlink;
2282 e->nextlink = chart->edges;
2287 for (f = chart->collapsed_faces; f; f = nextf) {
2288 nextf = f->nextlink;
2289 f->nextlink = chart->faces;
2294 chart->collapsed_verts =
nullptr;
2295 chart->collapsed_edges =
nullptr;
2296 chart->collapsed_faces =
nullptr;
2299static void p_chart_complexify(
PChart *chart)
2302 static const int MAX_COMPLEXIFY = INT_MAX;
2305 PVert *newv, *keepv;
2308 for (
e = chart->collapsed_edges;
e;
e =
e->nextlink) {
2317 std::swap(edge, pair);
2320 p_split_vertex(edge, pair);
2323 if (
x >= MAX_COMPLEXIFY) {
2324 newv->uv[0] = keepv->uv[0];
2325 newv->uv[1] = keepv->uv[1];
2328 p_vert_harmonic_insert(newv);
2333 p_chart_post_split_flush(chart);
2336static void p_chart_simplify(
PChart *chart)
2344#define ABF_MAX_ITER 20
2401 float *sine = sys->
sine;
2402 float *cosine = sys->
cosine;
2403 const float *alpha = sys->
alpha;
2406 const double angle = alpha[
i];
2424 if (aid == e1->
u.
id) {
2434 if (aid == e2->
u.
id) {
2443 e =
e->next->next->pair;
2444 }
while (
e && (
e !=
v->edge));
2446 return (sin1 - sin2);
2451 PVert *
v =
e->vert, *v1 =
e->next->vert, *
v2 =
e->next->next->vert;
2483 float gtriangle, galpha1, galpha2, galpha3;
2490 sys->
bAlpha[e2->u.id] = -galpha2;
2491 sys->
bAlpha[e3->u.id] = -galpha3;
2493 norm += galpha1 * galpha1 + galpha2 * galpha2 + galpha3 * galpha3;
2497 norm += gtriangle * gtriangle;
2500 for (
v = chart->
verts;
v;
v =
v->nextlink) {
2502 float gplanar = -2 *
M_PI, glength;
2506 gplanar += sys->
alpha[
e->u.id];
2507 e =
e->next->next->pair;
2508 }
while (
e && (
e !=
v->edge));
2511 norm += gplanar * gplanar;
2515 norm += glength * glength;
2524 const float dlambda1,
2527 float alpha = sys->
alpha[id];
2528 const float dalpha = (sys->
bAlpha[id] - dlambda1);
2529 alpha += dalpha / sys->
weight[id] - pre;
2536 int nvar = 2 * ninterior;
2539 for (
int i = 0;
i < nvar;
i++) {
2544 float wi1, wi2, wi3,
b, si,
beta[3], j2[3][3],
W[3][3];
2545 float row1[6], row2[6], row3[6];
2548 PVert *v1 = e1->
vert, *
v2 = e2->vert, *v3 = e3->vert;
2551 wi2 = 1.0f / sys->
weight[e2->u.id];
2552 wi3 = 1.0f / sys->
weight[e3->u.id];
2556 b += sys->
bAlpha[e2->u.id] * wi2;
2557 b += sys->
bAlpha[e3->u.id] * wi3;
2561 si = 1.0f / (wi1 + wi2 + wi3);
2570 sys->
dstar[f->u.id] = si;
2577 W[1][1] = si - sys->
weight[e2->u.id];
2581 W[2][2] = si - sys->
weight[e3->u.id];
2583 vid[0] = vid[1] = vid[2] = vid[3] = vid[4] = vid[5] = -1;
2587 vid[3] = ninterior + v1->
u.
id;
2589 sys->
J2dt[e1->
u.
id][0] = j2[0][0] = 1.0f * wi1;
2595 context, 0, ninterior + v1->
u.
id, j2[1][0] *
beta[1] + j2[2][0] *
beta[2]);
2597 row1[0] = j2[0][0] *
W[0][0];
2598 row2[0] = j2[0][0] *
W[1][0];
2599 row3[0] = j2[0][0] *
W[2][0];
2601 row1[3] = j2[1][0] *
W[0][1] + j2[2][0] *
W[0][2];
2602 row2[3] = j2[1][0] *
W[1][1] + j2[2][0] *
W[1][2];
2603 row3[3] = j2[1][0] *
W[2][1] + j2[2][0] *
W[2][2];
2608 vid[4] = ninterior +
v2->u.id;
2611 sys->
J2dt[e2->u.id][1] = j2[1][1] = 1.0f * wi2;
2616 context, 0, ninterior +
v2->u.id, j2[0][1] *
beta[0] + j2[2][1] *
beta[2]);
2618 row1[1] = j2[1][1] *
W[0][1];
2619 row2[1] = j2[1][1] *
W[1][1];
2620 row3[1] = j2[1][1] *
W[2][1];
2622 row1[4] = j2[0][1] *
W[0][0] + j2[2][1] *
W[0][2];
2623 row2[4] = j2[0][1] *
W[1][0] + j2[2][1] *
W[1][2];
2624 row3[4] = j2[0][1] *
W[2][0] + j2[2][1] *
W[2][2];
2629 vid[5] = ninterior + v3->u.id;
2633 sys->
J2dt[e3->u.id][2] = j2[2][2] = 1.0f * wi3;
2637 context, 0, ninterior + v3->u.id, j2[0][2] *
beta[0] + j2[1][2] *
beta[1]);
2639 row1[2] = j2[2][2] *
W[0][2];
2640 row2[2] = j2[2][2] *
W[1][2];
2641 row3[2] = j2[2][2] *
W[2][2];
2643 row1[5] = j2[0][2] *
W[0][0] + j2[1][2] *
W[0][1];
2644 row2[5] = j2[0][2] *
W[1][0] + j2[1][2] *
W[1][1];
2645 row3[5] = j2[0][2] *
W[2][0] + j2[1][2] *
W[2][1];
2648 for (
int i = 0;
i < 3;
i++) {
2655 for (
int j = 0; j < 6; j++) {
2692 PVert *v1 = e1->
vert, *
v2 = e2->vert, *v3 = e3->vert;
2694 pre[0] = pre[1] = pre[2] = 0.0f;
2699 pre[0] += sys->
J2dt[e1->
u.
id][0] *
x;
2700 pre[1] += sys->
J2dt[e2->u.id][0] * x2;
2701 pre[2] += sys->
J2dt[e3->u.id][0] * x2;
2707 pre[0] += sys->
J2dt[e1->
u.
id][1] * x2;
2708 pre[1] += sys->
J2dt[e2->u.id][1] *
x;
2709 pre[2] += sys->
J2dt[e3->u.id][1] * x2;
2715 pre[0] += sys->
J2dt[e1->
u.
id][2] * x2;
2716 pre[1] += sys->
J2dt[e2->u.id][2] * x2;
2717 pre[2] += sys->
J2dt[e3->u.id][2] *
x;
2720 float dlambda1 = pre[0] + pre[1] + pre[2];
2721 dlambda1 = sys->
dstar[f->u.id] * (sys->
bstar[f->u.id] - dlambda1);
2730 for (
int i = 0;
i < ninterior;
i++) {
2748 float limit = (chart->
nfaces > 100) ? 1.0f : 0.001f;
2753 for (
v = chart->
verts;
v;
v =
v->nextlink) {
2790 sys.
weight[e1->
u.
id] = 2.0f / (a1 * a1);
2791 sys.
weight[e2->
u.
id] = 2.0f / (a2 * a2);
2792 sys.
weight[e3->
u.
id] = 2.0f / (a3 * a3);
2795 for (
v = chart->
verts;
v;
v =
v->nextlink) {
2797 float anglesum = 0.0, scale;
2801 anglesum += sys.
beta[
e->u.id];
2802 e =
e->next->next->pair;
2803 }
while (
e && (
e !=
v->edge));
2805 scale = (anglesum == 0.0f) ? 0.0f : 2.0f * float(
M_PI) / anglesum;
2810 e =
e->next->next->pair;
2811 }
while (
e && (
e !=
v->edge));
2856 if (!*pin1 || !*pin2 || *pin1 == *pin2) {
2862 (*pin1)->
uv[0] = 0.0f;
2863 (*pin1)->uv[1] = 0.5f;
2864 (*pin2)->uv[0] = 1.0f;
2865 (*pin2)->uv[1] = 0.5f;
2868 int diru, dirv, dirx, diry;
2872 sub[0] =
fabsf(sub[0]);
2873 sub[1] =
fabsf(sub[1]);
2874 sub[2] =
fabsf(sub[2]);
2876 if ((sub[0] > sub[1]) && (sub[0] > sub[2])) {
2878 diry = (sub[1] > sub[2]) ? 1 : 2;
2880 else if ((sub[1] > sub[0]) && (sub[1] > sub[2])) {
2882 diry = (sub[0] > sub[2]) ? 0 : 2;
2886 diry = (sub[0] > sub[1]) ? 0 : 1;
2898 (*pin1)->uv[diru] = (*pin1)->co[dirx];
2899 (*pin1)->uv[dirv] = (*pin1)->co[diry];
2900 (*pin2)->uv[diru] = (*pin2)->co[dirx];
2901 (*pin2)->uv[dirv] = (*pin2)->co[diry];
2907 PEdge *be, *lastbe =
nullptr, *maxe1 =
nullptr, *maxe2 =
nullptr, *be1, *be2;
2908 PEdge *cure =
nullptr, *firste1 =
nullptr, *firste2 =
nullptr, *nextbe;
2909 float maxlen = 0.0f, curlen = 0.0f, totlen = 0.0f, firstlen = 0.0f;
2935 if (curlen > maxlen) {
2941 if (firste1 == cure) {
2952 }
while (be != outer);
2955 if (cure && (cure != outer)) {
2958 if (firstlen > maxlen) {
2965 if (!maxe1 || !maxe2 || (maxlen < 0.5f * totlen)) {
2984 }
while (be1 != be2);
3003 }
while (be1 != be2);
3014 float minv[3], maxv[3], dirlen;
3015 PVert *
v, *minvert[3], *maxvert[3];
3019 minv[0] = minv[1] = minv[2] = 1e20;
3020 maxv[0] = maxv[1] = maxv[2] = -1e20;
3022 minvert[0] = minvert[1] = minvert[2] =
nullptr;
3023 maxvert[0] = maxvert[1] = maxvert[2] =
nullptr;
3025 for (
v = chart->
verts;
v;
v =
v->nextlink) {
3026 for (
i = 0;
i < 3;
i++) {
3027 if (
v->co[
i] < minv[
i]) {
3031 if (
v->co[
i] > maxv[
i]) {
3042 for (
i = 0;
i < 3;
i++) {
3043 if (maxv[
i] - minv[
i] > dirlen) {
3045 dirlen = maxv[
i] - minv[
i];
3049 *pin1 = minvert[dir];
3050 *pin2 = maxvert[dir];
3060 bool deselect =
false;
3077 if (live && (!
select || !deselect)) {
3083 p_chart_topological_sanity_check(chart);
3098 param_warning(
"ABF solving failed: falling back to LSCM.\n");
3169 float area_pinned_up = 0.0f;
3170 float area_pinned_down = 0.0f;
3174 PVert *v1 = e1->
vert, *
v2 = e2->vert, *v3 = e3->vert;
3180 area_pinned_up += area;
3183 area_pinned_down -= area;
3188 const bool flip_faces = (area_pinned_down > area_pinned_up);
3195 PVert *v1 = e1->
vert, *
v2 = e2->vert, *v3 = e3->vert;
3214 double sina1 =
sin(a1);
3215 double sina2 =
sin(a2);
3216 double sina3 =
sin(a3);
3218 const double sinmax =
max_ddd(sina1, sina2, sina3);
3221 if (sina3 != sinmax) {
3223 SHIFT3(
double, a1, a2, a3);
3224 SHIFT3(
double, sina1, sina2, sina3);
3226 if (sina2 == sinmax) {
3228 SHIFT3(
double, a1, a2, a3);
3229 SHIFT3(
double, sina1, sina2, sina3);
3234 const double ratio = (sina3 == 0.0f) ? 1.0f : sina2 / sina3;
3235 const double cosine =
cos(a1) * ratio;
3236 const double sine = sina1 * ratio;
3275 if (new_area > 0.0f) {
3276 const float scale = chart->
area_uv / new_area;
3295 chart->
pin1 =
nullptr;
3296 chart->
pin2 =
nullptr;
3302#define P_STRETCH_ITER 20
3308 for (
v = chart->
verts;
v;
v =
v->nextlink) {
3309 if (
v->edge->pair ==
nullptr) {
3324 PVert *v1 = e1->
vert, *
v2 = e2->vert, *v3 = e3->vert;
3334 w = 1.0f / (2.0f * area);
3367 T =
sqrtf(0.5f * (a + c));
3383 }
while (
e &&
e != (
v->edge));
3393 float orig_stretch, low, stretch_low, high, stretch_high, mid, stretch;
3394 float orig_uv[2], dir[2], random_angle, trusted_radius;
3396 for (
v = chart->
verts;
v;
v =
v->nextlink) {
3402 orig_uv[0] =
v->uv[0];
3403 orig_uv[1] =
v->uv[1];
3406 trusted_radius = 0.0f;
3415 }
while (
e &&
e != (
v->edge));
3417 trusted_radius /= 2 * nedges;
3420 dir[0] = trusted_radius *
cosf(random_angle);
3421 dir[1] = trusted_radius *
sinf(random_angle);
3425 stretch_low = orig_stretch;
3433 mid = 0.5f * (low + high);
3434 v->uv[0] = orig_uv[0] + mid * dir[0];
3435 v->uv[1] = orig_uv[1] + mid * dir[1];
3438 if (stretch_low < stretch_high) {
3440 stretch_high = stretch;
3444 stretch_low = stretch;
3449 if (stretch >= orig_stretch) {
3462 if (v1->
uv[0] <
v2->uv[0]) {
3465 if (v1->
uv[0] ==
v2->uv[0]) {
3466 if (v1->
uv[1] <
v2->uv[1]) {
3469 if (v1->
uv[1] ==
v2->uv[1]) {
3483 int npoints = 0,
i, ulen, llen;
3484 PVert **
U, **
L, **points, **p;
3512 for (p = points,
i = 0;
i < npoints;
i++, p++) {
3513 while ((ulen > 1) && (
p_area_signed(
U[ulen - 2]->uv, (*p)->uv,
U[ulen - 1]->uv) <= 0)) {
3516 while ((llen > 1) && (
p_area_signed(
L[llen - 2]->uv, (*p)->uv,
L[llen - 1]->uv) >= 0)) {
3527 for (p = points,
i = 0;
i < ulen;
i++, p++, npoints++) {
3532 for (
i = llen - 2;
i > 0;
i--, p++, npoints++) {
3537 *r_nverts = npoints;
3538 *r_right = ulen - 1;
3553 orthodir[0] = dir[1];
3554 orthodir[1] = -dir[0];
3576 float rotated, minarea, minangle, area,
len;
3577 float *angles, miny, maxy,
v[2], a[4], mina;
3578 int npoints, right, i_min, i_max,
i, idx[4], nextidx;
3579 PVert **points, *p1, *p2, *p3, *p4, *p1n;
3593 for (
i = 0;
i < npoints;
i++) {
3594 p1 = (
i == 0) ? points[npoints - 1] : points[
i - 1];
3596 p3 = (
i == npoints - 1) ? points[0] : points[
i + 1];
3600 if (points[
i]->uv[1] < miny) {
3601 miny = points[
i]->
uv[1];
3604 if (points[
i]->uv[1] > maxy) {
3605 maxy = points[
i]->
uv[1];
3616 v[0] = points[idx[0]]->
uv[0];
3617 v[1] = points[idx[0]]->
uv[1] + 1.0f;
3618 a[0] =
angle_v2v2v2(points[(idx[0] + 1) % npoints]->uv, points[idx[0]]->uv,
v);
3620 v[0] = points[idx[1]]->
uv[0] + 1.0f;
3621 v[1] = points[idx[1]]->
uv[1];
3622 a[1] =
angle_v2v2v2(points[(idx[1] + 1) % npoints]->uv, points[idx[1]]->uv,
v);
3624 v[0] = points[idx[2]]->
uv[0];
3625 v[1] = points[idx[2]]->
uv[1] - 1.0f;
3626 a[2] =
angle_v2v2v2(points[(idx[2] + 1) % npoints]->uv, points[idx[2]]->uv,
v);
3628 v[0] = points[idx[3]]->
uv[0] - 1.0f;
3629 v[1] = points[idx[3]]->
uv[1];
3630 a[3] =
angle_v2v2v2(points[(idx[3] + 1) % npoints]->uv, points[idx[3]]->uv,
v);
3638 while (rotated <=
float(
M_PI_2)) {
3643 for (
i = 0;
i < 4;
i++) {
3651 nextidx = (idx[i_min] + 1) % npoints;
3653 a[i_min] = angles[nextidx];
3654 a[(i_min + 1) % 4] = a[(i_min + 1) % 4] - mina;
3655 a[(i_min + 2) % 4] = a[(i_min + 2) % 4] - mina;
3656 a[(i_min + 3) % 4] = a[(i_min + 3) % 4] - mina;
3659 p1 = points[idx[i_min]];
3660 p1n = points[nextidx];
3661 p2 = points[idx[(i_min + 1) % 4]];
3662 p3 = points[idx[(i_min + 2) % 4]];
3663 p4 = points[idx[(i_min + 3) % 4]];
3669 v[0] = (p1n->
uv[0] - p1->
uv[0]) *
len;
3670 v[1] = (p1n->
uv[1] - p1->
uv[1]) *
len;
3675 if (area < minarea) {
3681 idx[i_min] = nextidx;
3685 if (minangle >
float(
M_PI_4)) {
3686 minangle -= float(
M_PI_2);
3702 for (
v = chart->
verts;
v;
v =
v->nextlink) {
3703 float oldu =
v->uv[0], oldv =
v->uv[1];
3704 v->uv[0] = cosine * oldu - sine * oldv;
3705 v->uv[1] = sine * oldu + cosine * oldv;
3719 if (
angle != 0.0f) {
3797 pinuvlist = pinuvlist->
next;
3800 if (bestdistsquared > distsquared) {
3801 bestdistsquared = distsquared;
3804 pinuvlist = pinuvlist->
next;
3812 pinuv->
next =
nullptr;
3836 if (!pinuvlist->
next) {
3840 pinuvlist = pinuvlist->
next;
3850 const float *weight,
3857 uint nfilltri = nverts - 2;
3858 uint(*tris)[3] =
static_cast<uint(*)[3]
>(
3860 float(*projverts)[2] =
static_cast<float(*)[2]
>(
3867 const float *co_curr, *co_prev = co[nverts - 1];
3868 for (
int j = 0; j < nverts; j++) {
3878 float axis_mat[3][3];
3880 for (
int j = 0; j < nverts; j++) {
3890 for (
uint j = 0; j < nfilltri; j++) {
3891 uint *tri = tris[j];
3896 const ParamKey tri_vkeys[3] = {vkeys[v0], vkeys[v1], vkeys[
v2]};
3897 const float *tri_co[3] = {co[v0], co[v1], co[
v2]};
3898 float *tri_uv[3] = {uv[v0], uv[v1], uv[
v2]};
3900 const float *tri_weight =
nullptr;
3901 float tri_weight_tmp[3];
3904 tri_weight_tmp[0] = weight[v0];
3905 tri_weight_tmp[1] = weight[v1];
3906 tri_weight_tmp[2] = weight[
v2];
3907 tri_weight = tri_weight_tmp;
3910 const bool tri_pin[3] = {pin[v0], pin[v1], pin[
v2]};
3914 handle, key, 3, tri_vkeys, tri_co, tri_uv, tri_weight, tri_pin, tri_select);
3926 const float *weight,
3939 for (
int i = 0;
i < nverts;
i++) {
3943 for (
int i = nverts - 1;
i >= 0;) {
3948 const int pm = int(permute.
size());
3950 int i0 = permute[
i];
3951 int i1 = permute[(
i + 1) % pm];
3952 int i2 = permute[(
i + 2) % pm];
3962 int iprev = permute[(
i + pm - 1) % pm];
3963 p_face_add_construct(phandle, key, vkeys, co, uv, weight, iprev, i0, i1, pin,
select);
3966 if (permute.
size() == 3) {
3970 if (permute.
size() != nverts) {
3971 const int pm = int(permute.
size());
3979 for (
int i = 0;
i < pm;
i++) {
3981 vkeys_sub[
i] = vkeys[j];
3985 weight_sub[
i] = weight[j];
3987 pin_sub[
i] = pin && pin[j];
3996 weight ? &weight_sub.
first() :
nullptr,
3998 &select_sub.
first());
4009 p_face_add_construct(phandle, key, vkeys, co, uv, weight, 0, 1, 2, pin,
select);
4025 bool topology_from_uvs,
4026 int *r_count_failed)
4048 if (!topology_from_uvs && chart->
nboundaries == 0) {
4050 if (r_count_failed) {
4051 *r_count_failed += 1;
4056 phandle->
charts[j++] = chart;
4111 if (count_changed !=
nullptr) {
4112 *count_changed += 1;
4116 if (count_failed !=
nullptr) {
4130 p_chart_complexify(phandle->
charts[
i]);
4143 phandle->
blend = 0.0f;
4198 if (ignore_pinned && chart->
has_pins) {
4210 PVert *
v2 = f->edge->next->next->vert;
4214 pack_island_vector.
append(pack_island);
4230 pack_island_vector[
i] =
nullptr;
4240 float tot_area_3d = 0.0f;
4241 float tot_area_uv = 0.0f;
4242 float minv[2], maxv[2], trans[2];
4251 if (ignore_pinned && chart->
has_pins) {
4259 if (scale_uv || shear) {
4264 for (
int j = 0; j < max_iter; j++) {
4268 double scale_cou = 0;
4269 double scale_cov = 0;
4270 double scale_cross = 0;
4271 double weight_sum = 0;
4273 float m[2][2], s[2][2];
4277 s[0][0] = va->
uv[0] - vc->
uv[0];
4278 s[0][1] = va->
uv[1] - vc->
uv[1];
4279 s[1][0] = vb->
uv[0] - vc->
uv[0];
4280 s[1][1] = vb->
uv[1] - vc->
uv[1];
4286 float cou[3], cov[3];
4287 for (
int k = 0; k < 3; k++) {
4288 cou[k] = m[0][0] * (va->
co[k] - vc->
co[k]) + m[0][1] * (vb->
co[k] - vc->
co[k]);
4289 cov[k] = m[1][0] * (va->
co[k] - vc->
co[k]) + m[1][1] * (vb->
co[k] - vc->
co[k]);
4292 scale_cou +=
len_v3(cou) * weight;
4293 scale_cov +=
len_v3(cov) * weight;
4302 scale_cross +=
dot_v3v3(cou, cov) * weight;
4304 weight_sum += weight;
4306 if (scale_cou * scale_cov < 1e-10f) {
4309 const float scale_factor_u = scale_uv ?
sqrtf(scale_cou / scale_cov) : 1.0f;
4313 t[0][0] = scale_factor_u;
4314 t[1][0] =
clamp_f(
float(scale_cross / weight_sum), -0.5f, 0.5f);
4316 t[1][1] = 1.0f / scale_factor_u;
4322 const float err =
fabsf(t[0][0] - 1.0f) +
fabsf(t[1][0]) +
fabsf(t[0][1]) +
4323 fabsf(t[1][1] - 1.0f);
4325 const float tolerance = 1e-6f;
4326 if (err < tolerance) {
4341 tot_area_3d += chart->
area_3d;
4342 tot_area_uv += chart->
area_uv;
4345 if (tot_area_3d == 0.0f || tot_area_uv == 0.0f) {
4350 const float tot_fac = tot_area_3d / tot_area_uv;
4355 if (ignore_pinned && chart->
has_pins) {
4405 PVert *oldv, *keepv;
4419 PEdge *collapse_e = edge ? edge : pair;
4425 PEdge *collapse_e = edge ? edge : pair;
4431 const float threshold_squared = threshold * threshold;
4441 PVert *newv, *keepv;
4450 std::swap(edge, pair);
4455 newv->
uv[0] = keepv->
uv[0];
4456 newv->
uv[1] = keepv->
uv[1];
4462 const float corr_co1[3],
4463 const float corr_co2[3],
4464 const float min_area,
4465 const float min_angle_cos)
4484 if (
e->next->next == corr_e->
pair) {
4485 PVert *other_v =
e->next->next->vert;
4489 const PVert *other_v1 =
e->next->vert;
4490 const PVert *other_v2 =
e->next->next->vert;
4494 if (area < min_area) {
4500 if (
e->next->next == corr_e->
pair) {
4501 PVert *other_v =
e->next->next->vert;
4502 p_triangle_cos(corr_co1, corr_co2, other_v->
co, f_cos, f_cos + 1, f_cos + 2);
4505 const PVert *other_v1 =
e->next->vert;
4506 const PVert *other_v2 =
e->next->next->vert;
4510 for (
int i = 0;
i < 3;
i++) {
4511 if (f_cos[
i] > min_angle_cos) {
4522 const float corr_co[3],
4524 float min_angle_cos)
4537 const PVert *other_v1 =
e->next->vert;
4538 const PVert *other_v2 =
e->next->next->vert;
4542 if (area < min_area) {
4549 for (
int i = 0;
i < 3;
i++) {
4550 if (f_cos[
i] > min_angle_cos) {
4562 static const constexpr float eps = 1.0e-5;
4563 static const constexpr float n1[3] = {0.0f, 0.0f, 1.0f};
4564 static const constexpr float n2[3] = {0.0f, 1.0f, 0.0f};
4566 float edge_len =
len_v3(edge_dir);
4567 if (edge_len <
eps) {
4571 float edge_dir_norm[3];
4573 mul_v3_fl(edge_dir_norm, 1.0f / edge_len);
4575 float normal_dir[3];
4577 float normal_len =
len_v3(normal_dir);
4579 if (normal_len <
eps) {
4581 normal_len =
len_v3(normal_dir);
4583 if (normal_len <
eps) {
4588 mul_v3_fl(normal_dir, 1.0f / normal_len);
4590 float tangent_dir[3];
4593 R[0][0] = edge_dir_norm[0];
4594 R[1][0] = edge_dir_norm[1];
4595 R[2][0] = edge_dir_norm[2];
4597 R[0][1] = normal_dir[0];
4598 R[1][1] = normal_dir[1];
4599 R[2][1] = normal_dir[2];
4601 R[0][2] = tangent_dir[0];
4602 R[1][2] = tangent_dir[1];
4603 R[2][2] = tangent_dir[2];
4621 float min_angle_cos)
4623 static const float3 ref_edges[] = {
4639 static const int ref_edge_count =
ARRAY_SIZE(ref_edges);
4640 static const int LEN_MULTIPLIER_COUNT = 3;
4641 bool corr_co_found =
false;
4643 float corr_len = 2.0f * std::sqrt((min_area +
CORR_ZERO_AREA_EPS) / 3.0f / std::sqrt(3.0f));
4645 for (
int m = 0; m < LEN_MULTIPLIER_COUNT; m++) {
4646 for (
int re = 0; re < ref_edge_count; re++) {
4653 float corr_co[3][3];
4656 for (
int i = 0;
i < 3;
i++) {
4657 const float angle = (float(
i) / 3.0f) *
float(2.0 *
M_PI);
4660 float corr_len_multiplied = corr_len * (m + 1);
4663 mul_v3_fl(corr_dir, corr_len_multiplied);
4671 for (
int i = 0;
i < 3;
i++) {
4673 e, corr_co[
i], corr_co[(
i + 1) % 3], min_area, min_angle_cos))
4682 for (
int i = 0;
i < 3;
i++) {
4687 corr_co_found =
true;
4691 if (corr_co_found) {
4696 if (!corr_co_found) {
4706 static const float eps = 1.0e-6;
4708 float min_angle_cos = std::cos(min_angle);
4718 PEdge *max_edge =
nullptr;
4719 float max_edge_len = -std::numeric_limits<float>::infinity();
4721 PEdge *min_edge =
nullptr;
4722 float min_edge_len = std::numeric_limits<float>::infinity();
4724 PEdge *middle_edge =
nullptr;
4730 if (
len > max_edge_len) {
4734 middle_edge = max_edge->
next == min_edge ? min_edge->
next : max_edge->
next;
4737 if (
len < min_edge_len) {
4741 middle_edge = min_edge->
next == max_edge ? max_edge->
next : min_edge->
next;
4745 }
while (
e != f->edge);
4751 bool small_uniside_tri = (face_area <= min_area) && (min_edge == max_edge);
4753 if ((max_edge_len <
eps) || small_uniside_tri) {
4758 if (min_edge == max_edge) {
4772 float max_face_cos =
4773 middle_edge->
next == max_edge ?
4777 float angle_corr_len = max_face_cos > min_angle_cos ?
4781 if ((face_area > min_area) && (angle_corr_len == 0.0f)) {
4787 corr_len = std::max(corr_len, angle_corr_len);
4793 static const constexpr int DIR_COUNT = 16;
4794 static const constexpr int LEN_MULTIPLIER_COUNT = 2;
4796 bool corr_co_found =
false;
4798 for (
int m = 0; m < LEN_MULTIPLIER_COUNT; m++) {
4799 for (
int d = 0; d < DIR_COUNT; d++) {
4800 const float angle = (float(d) / DIR_COUNT) *
float(2.0 *
M_PI);
4803 const float corr_len_multiplied = corr_len * (m + 1);
4806 mul_v3_fl(corr_dir, corr_len_multiplied);
4812 corr_co_found =
true;
4817 if (corr_co_found) {
4822 if (!corr_co_found) {
4838 const float min_angle_cos)
4843 for (
int i = 0;
i < 3;
i++) {
4844 if (t_cos[
i] > min_angle_cos) {
4855 const float min_area,
4856 const float min_angle)
4945static void slim_transfer_edges(
PChart *chart, slim::MatrixTransferChart *mt_chart)
4948 std::vector<double> &EL = mt_chart->
el_vectors;
4956 static const float DOUBLED_VERT_THRESHOLD = 1.0e-5;
4959 E[eid] = be->vert->slim_id;
4964 if (edge_len < DOUBLED_VERT_THRESHOLD) {
4972 }
while (be != outer);
4974 for (
PEdge *
e = chart->edges;
e;
e =
e->nextlink) {
4977 E[eid] =
e->vert->slim_id;
4982 if (edge_len < DOUBLED_VERT_THRESHOLD) {
4994static void slim_transfer_vertices(
const PChart *chart,
4995 slim::MatrixTransferChart *mt_chart,
4996 slim::MatrixTransfer *mt)
4999 std::vector<double> &v_mat = mt_chart->
v_matrices;
5000 std::vector<double> &uv_mat = mt_chart->
uv_matrices;
5001 std::vector<int> &p_mat = mt_chart->
p_matrices;
5002 std::vector<double> &pp_mat = mt_chart->
pp_matrices;
5003 std::vector<float> &w_vec = mt_chart->
w_vectors;
5009 for (
PVert *
v = chart->verts;
v;
v =
v->nextlink) {
5010 if (!
v->on_boundary_flag) {
5012 w_vec[vid] =
v->weight;
5019 v_mat[
v->slim_id] =
v->
co[0];
5020 v_mat[r +
v->slim_id] =
v->
co[1];
5021 v_mat[2 * r +
v->slim_id] =
v->
co[2];
5023 uv_mat[
v->slim_id] =
v->uv[0];
5024 uv_mat[r +
v->slim_id] =
v->uv[1];
5029 p_mat[p_vid] =
v->slim_id;
5030 pp_mat[2 * p_vid] = double(
v->uv[0]);
5031 pp_mat[2 * p_vid + 1] = double(
v->uv[1]);
5040static void slim_transfer_boundary_vertices(
PChart *chart,
5041 slim::MatrixTransferChart *mt_chart,
5042 const slim::MatrixTransfer *mt)
5044 std::vector<int> &b_vec = mt_chart->
b_vectors;
5045 std::vector<float> &w_vec = mt_chart->
w_vectors;
5048 for (
PVert *
v = chart->verts;
v;
v =
v->nextlink) {
5049 v->on_boundary_flag =
false;
5061 w_vec[vid] = be->vert->weight;
5065 be->vert->slim_id = vid;
5066 be->vert->on_boundary_flag =
true;
5072 }
while (be != outer);
5078static void slim_transfer_faces(
const PChart *chart, slim::MatrixTransferChart *mt_chart)
5090 F[fid] =
e->vert->slim_id;
5091 F[r + fid] = e1->vert->slim_id;
5092 F[2 * r + fid] = e2->vert->slim_id;
5100static void slim_convert_blender(
ParamHandle *phandle, slim::MatrixTransfer *mt)
5102 static const float SLIM_CORR_MIN_AREA = 1.0e-8;
5103 static const float SLIM_CORR_MIN_ANGLE =
DEG2RADF(1.0f);
5109 slim::MatrixTransferChart *mt_chart = &mt->
charts[
i];
5118 slim_allocate_matrices(chart, mt_chart);
5121 slim_transfer_boundary_vertices(chart, mt_chart, mt);
5122 slim_transfer_vertices(chart, mt_chart, mt);
5123 slim_transfer_edges(chart, mt_chart);
5124 slim_transfer_faces(chart, mt_chart);
5142 slim::MatrixTransfer *mt = slim_matrix_transfer(slim_options);
5144 slim_convert_blender(phandle, mt);
5152 slim::MatrixTransfer *mt,
5162 slim::MatrixTransferChart *mt_chart = &mt->
charts[
i];
5165 if (count_changed) {
5170 for (
v = chart->verts;
v;
v =
v->nextlink) {
5186 for (
v = chart->verts;
v;
v =
v->nextlink) {
5198static void slim_free_matrix_transfer(
ParamHandle *phandle)
5204static void slim_get_pinned_vertex_data(
ParamHandle *phandle,
5206 slim::MatrixTransferChart &mt_chart,
5207 slim::PinnedVertexData &pinned_vertex_data)
5211 std::vector<int> &selected_pins = pinned_vertex_data.
selected_pins;
5213 pinned_vertex_indices.clear();
5214 pinned_vertex_positions_2D.clear();
5215 selected_pins.clear();
5227 selected_pins.push_back(be->vert->slim_id);
5230 pinned_vertex_indices.push_back(be->vert->slim_id);
5231 pinned_vertex_positions_2D.push_back(be->vert->uv[0]);
5232 pinned_vertex_positions_2D.push_back(be->vert->uv[1]);
5235 }
while (be != outer);
5238 for (
v = chart->verts;
v;
v =
v->nextlink) {
5239 if (!
v->on_boundary_flag && (
v->flag &
PVERT_PIN)) {
5244 selected_pins.push_back(
v->slim_id);
5246 pinned_vertex_indices.push_back(
v->slim_id);
5247 pinned_vertex_positions_2D.push_back(
v->uv[0]);
5248 pinned_vertex_positions_2D.push_back(
v->uv[1]);
5269 slim_transfer_data_to_slim(phandle, slim_options);
5274 slim_flush_uvs(phandle, mt, count_changed, count_failed);
5275 slim_free_matrix_transfer(phandle);
5279 UNUSED_VARS(phandle, slim_options, count_changed, count_failed);
5286 slim_transfer_data_to_slim(phandle, slim_options);
5299 bool select =
false, deselect =
false;
5314 if (!
select || !deselect) {
5334 mt->
charts[
i].parametrize_single_iteration();
5339 slim_flush_uvs(phandle, mt,
nullptr,
nullptr);
5355 if (!mt_chart.
data) {
5365 const bool live =
true;
5366 slim_flush_uvs(phandle, mt,
nullptr,
nullptr, live);
5382 slim_free_matrix_transfer(phandle);
5391 return phandle->
slim_mt !=
nullptr;
float BLI_convexhull_aabb_fit_points_2d(const float(*points)[2], int points_num)
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
void BLI_ghash_insert(GHash *gh, void *key, void *val)
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
GHash * BLI_ghash_int_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
HeapNode * BLI_heap_top(const Heap *heap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1)
Heap * BLI_heap_new_ex(unsigned int reserve_num) ATTR_WARN_UNUSED_RESULT
void void bool BLI_heap_is_empty(const Heap *heap) ATTR_NONNULL(1)
void * BLI_heap_pop_min(Heap *heap) ATTR_NONNULL(1)
HeapNode * BLI_heap_insert(Heap *heap, float value, void *ptr) ATTR_NONNULL(1)
void void BLI_heap_remove(Heap *heap, HeapNode *node) ATTR_NONNULL(1
Heap * BLI_heap_new(void) ATTR_WARN_UNUSED_RESULT
MINLINE double max_ddd(double a, double b, double c)
MINLINE float clamp_f(float value, float min, float max)
MINLINE double max_dd(double a, double b)
float volume_tri_tetrahedron_signed_v3(const float v1[3], const float v2[3], const float v3[3])
void axis_dominant_v3_to_m3_negate(float r_mat[3][3], const float normal[3])
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
bool invert_m2_m2(float inverse[2][2], const float mat[2][2])
void mul_m3_v3(const float M[3][3], float r[3])
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
void mul_m2_v2(const float mat[2][2], float vec[2])
void angle_to_mat2(float R[2][2], float angle)
float angle_v2v2v2(const float a[2], const float b[2], const float c[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
float cos_v3v3v3(const float p1[3], const float p2[3], const float p3[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE bool equals_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float len_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
void mid_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void zero_v3(float r[3])
float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
#define BLI_MEMARENA_STD_BUFSIZE
MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
void * BLI_memarena_calloc(MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_free(MemArena *ma) ATTR_NONNULL(1)
void * BLI_memarena_alloc(MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1)
void BLI_polyfill_calc_arena(const float(*coords)[2], unsigned int coords_num, int coords_sign, unsigned int(*r_tris)[3], struct MemArena *arena)
#define BLI_POLYFILL_ALLOC_NGON_RESERVE
void BLI_polyfill_beautify(const float(*coords)[2], unsigned int coords_num, unsigned int(*tris)[3], struct MemArena *arena, struct Heap *eheap)
struct RNG * BLI_rng_new(unsigned int seed)
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define INIT_MINMAX2(min, max)
#define UNUSED_FUNCTION(x)
#define POINTER_FROM_INT(i)
#define SHIFT3(type, a, b, c)
@ ED_UVPACK_MARGIN_SCALED
@ ED_UVPACK_ROTATION_NONE
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
static T sum(const btAlignedObjectArray< T > &items)
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
slim::MatrixTransfer * slim_mt
void append(const T &value)
void remove(const int64_t index)
IndexRange index_range() const
void append_unchecked(const T &value)
void reserve(const int64_t min_capacity)
bool can_scale_(const UVPackIsland_Params ¶ms) const
void build_transformation(float scale, double angle, float r_matrix[2][2]) const
void add_triangle(float2 uv0, float2 uv1, float2 uv2)
PChart * construction_chart
MemArena * polyfill_arena
slim::MatrixTransfer * slim_mt
#define MEM_SIZE_OPTIMAL(size)
LinearSolver * EIG_linear_solver_new(int num_rows, int num_columns, int num_right_hand_sides)
void EIG_linear_solver_variable_set(LinearSolver *solver, int rhs, int index, double value)
void EIG_linear_solver_right_hand_side_add(LinearSolver *solver, int rhs, int index, double value)
LinearSolver * EIG_linear_least_squares_solver_new(int num_rows, int num_columns, int num_right_hand_sides)
void EIG_linear_solver_delete(LinearSolver *solver)
double EIG_linear_solver_variable_get(LinearSolver *solver, int rhs, int index)
void EIG_linear_solver_matrix_add(LinearSolver *solver, int row, int col, double value)
bool EIG_linear_solver_solve(LinearSolver *solver)
void EIG_linear_solver_variable_lock(LinearSolver *solver, int index)
void * MEM_mallocN(size_t len, const char *str)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(void *vmemh)
ccl_device_inline float beta(const float x, const float y)
static void p_chart_rotate_minimum_area(PChart *chart)
bool uv_parametrizer_is_slim(const ParamHandle *phandle)
static PVert * p_vert_add(ParamHandle *handle, PHashKey key, const float co[3], const float weight, PEdge *e)
static PFace * p_face_add_construct(ParamHandle *handle, ParamKey key, const ParamKey *vkeys, const float **co, float **uv, const float *weight, int i1, int i2, int i3, const bool *pin, const bool *select)
void uv_parametrizer_construct_end(ParamHandle *phandle, bool fill_holes, bool topology_from_uvs, int *r_count_failed=nullptr)
static bool p_validate_corrected_coords(const PEdge *corr_e, const float corr_co[3], float min_area, float min_angle_cos)
static void p_chart_fill_boundaries(ParamHandle *handle, PChart *chart, const PEdge *outer)
static PFace * p_face_add_fill(ParamHandle *handle, PChart *chart, PVert *v1, PVert *v2, PVert *v3)
void uv_parametrizer_edge_set_seam(ParamHandle *phandle, const ParamKey *vkeys)
static void p_vert_load_pin_select_uvs(ParamHandle *handle, PVert *v)
static bool p_chart_lscm_solve(ParamHandle *handle, PChart *chart)
static void p_face_angles(PFace *f, double *r_a1, double *r_a2, double *r_a3)
static bool p_intersect_line_2d_dir(const float v1[2], const float dir1[2], const float v2[2], const float dir2[2], float r_isect[2])
void uv_parametrizer_average(ParamHandle *handle, bool ignore_pinned, bool scale_uv, bool shear)
static float p_chart_uv_area(PChart *chart)
void uv_parametrizer_flush(ParamHandle *handle)
static PHash * phash_new(PHashLink **list, int sizehint)
static bool UNUSED_FUNCTION_NO_SLIM p_chart_correct_degenerate_triangles(PChart *chart, const float min_area, const float min_angle)
static void p_face_backup_uvs(PFace *f)
static void p_abf_adjust_alpha(PAbfSystem *sys, const int id, const float dlambda1, const float pre)
static void p_chart_rotate_fit_aabb(PChart *chart)
static void p_flush_uvs(ParamHandle *handle, PChart *chart)
void uv_parametrizer_slim_live_begin(ParamHandle *phandle, const ParamSlimOptions *slim_options)
static void p_collapse_cost_vertex(PVert *vert, float *r_mincost, PEdge **r_mine, const std::function< float(PEdge *, PEdge *)> &collapse_cost_fn, const std::function< float(PEdge *, PEdge *)> &collapse_allowed_fn)
static float p_rectangle_area(float *p1, float *dir, float *p2, float *p3, float *p4)
void uv_parametrizer_slim_stretch_iteration(ParamHandle *phandle, float blend)
static float p_collapse_doubles_cost(PEdge *edge, PEdge *pair)
static bool p_collapse_allowed_topologic(PEdge *edge, PEdge *pair)
static void phash_safe_delete(PHash **pph)
static bool p_chart_symmetry_pins(PChart *chart, PEdge *outer, PVert **pin1, PVert **pin2)
static bool p_chart_convex_hull(PChart *chart, PVert ***r_verts, int *r_nverts, int *r_right)
static float p_vec_cos(const float v1[3], const float v2[3], const float v3[3])
void uv_parametrizer_slim_live_solve_iteration(ParamHandle *phandle)
static void p_chart_stretch_minimize(PChart *chart, RNG *rng)
static PEdge * p_edge_lookup(ParamHandle *handle, const PHashKey *vkeys)
static float p_face_stretch(PFace *f)
ParamKey uv_find_pin_index(ParamHandle *handle, const int bmvertindex, const float uv[2])
static void p_split_vert(ParamHandle *handle, PChart *chart, PEdge *e)
static PEdge * p_wheel_edge_prev(PEdge *e)
static void p_collapsing_verts(PEdge *edge, PEdge *pair, PVert **r_newv, PVert **r_keepv)
static void p_stretch_pin_boundary(PChart *chart)
static float p_chart_minimum_area_angle(PChart *chart)
static bool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
static int phash_size(PHash *ph)
static bool p_chart_correct_degenerate_triangle_point(PFace *f, float min_area, float min_angle_cos)
static float p_edge_length(PEdge *e)
void uv_prepare_pin_index(ParamHandle *handle, const int bmvertindex, const float uv[2])
static void p_face_restore_uvs(PFace *f)
static PEdge * p_wheel_edge_next(PEdge *e)
void uv_parametrizer_slim_live_end(ParamHandle *phandle)
static void p_chart_lscm_end(PChart *chart)
static void UNUSED_FUNCTION p_chart_collapse_doubles(PChart *chart, const float threshold)
static void p_abf_setup_system(PAbfSystem *sys)
static const float CORR_ZERO_AREA_EPS
static void p_abf_compute_sines(PAbfSystem *sys)
static int p_compare_geometric_uv(const void *a, const void *b)
static void p_chart_pin_positions(PChart *chart, PVert **pin1, PVert **pin2)
static float p_edge_length_squared(PEdge *e)
void uv_parametrizer_stretch_blend(ParamHandle *handle, float blend)
static void p_chart_uv_bbox(PChart *chart, float minv[2], float maxv[2])
static bool p_edge_matrix(float R[3][3], const float edge_dir[3])
void uv_parametrizer_slim_solve(ParamHandle *phandle, const ParamSlimOptions *slim_options, int *count_changed, int *count_failed)
static bool p_edge_connect_pair(ParamHandle *handle, PEdge *e, bool topology_from_uvs, PEdge ***stack)
void mul_v2_m2_add_v2v2(float r[2], const float mat[2][2], const float a[2], const float b[2])
static void p_chart_post_collapse_flush(PChart *chart, PEdge *collapsed)
static void p_collapse_edge(PEdge *edge, PEdge *pair)
static bool p_vert_interior(PVert *v)
static GeoUVPinIndex * new_geo_uv_pinindex(ParamHandle *handle, const float uv[2])
static float p_abf_compute_grad_alpha(PAbfSystem *sys, PFace *f, PEdge *e)
static float p_face_uv_area_signed(PFace *f)
static bool p_collapse_doubles_allowed(PEdge *edge, PEdge *pair, float threshold_squared)
static void UNUSED_FUNCTION p_face_cos(PFace *f, float *r_cos1, float *r_cos2, float *r_cos3)
static void p_vert_fix_edge_pointer(PVert *v)
static void p_chart_uv_translate(PChart *chart, const float trans[2])
static bool p_edge_implicit_seam(PEdge *e, PEdge *ep)
static void p_chart_uv_scale(PChart *chart, const float scale)
void uv_parametrizer_lscm_end(ParamHandle *handle)
static void p_chart_fill_boundary(ParamHandle *handle, PChart *chart, PEdge *be, int nedges)
static bool p_edge_has_pair(ParamHandle *handle, PEdge *e, bool topology_from_uvs, PEdge **r_pair)
static void p_chart_uv_to_array(PChart *chart, float(*points)[2])
static float p_area_signed(const float v1[2], const float v2[2], const float v3[2])
void uv_parametrizer_aspect_ratio(ParamHandle *handle, float aspect_y)
static void p_chart_uv_transform(PChart *chart, const float mat[2][2])
static float p_abf_compute_gradient(PAbfSystem *sys, PChart *chart)
void uv_parametrizer_stretch_begin(ParamHandle *handle)
static PEdge * p_boundary_edge_next(PEdge *e)
static void p_chart_lscm_begin(PChart *chart, bool live, bool abf)
static PHashLink * phash_lookup(PHash *ph, PHashKey key)
static void p_abf_free_system(PAbfSystem *sys)
static void p_triangle_angles(const float v1[3], const float v2[3], const float v3[3], double *r_a1, double *r_a2, double *r_a3)
void uv_parametrizer_flush_restore(ParamHandle *handle)
static bool p_chart_abf_solve(PChart *chart)
static bool p_chart_correct_degenerate_triangles2(PChart *chart, float min_area, float min_angle)
static PVert * p_vert_copy(ParamHandle *handle, PVert *v)
static bool p_validate_corrected_coords_point(const PEdge *corr_e, const float corr_co1[3], const float corr_co2[3], const float min_area, const float min_angle_cos)
static PFace * p_face_add(ParamHandle *handle)
static void p_triangle_cos(const float v1[3], const float v2[3], const float v3[3], float *r_cos1, float *r_cos2, float *r_cos3)
static float p_stretch_compute_vertex(PVert *v)
static PChart ** p_split_charts(ParamHandle *handle, PChart *chart, int ncharts)
static void p_add_ngon(ParamHandle *handle, const ParamKey key, const int nverts, const ParamKey *vkeys, const float **co, float **uv, const float *weight, const bool *pin, const bool *select)
static float p_abf_compute_sin_product(PAbfSystem *sys, PVert *v, int aid)
void uv_parametrizer_lscm_begin(ParamHandle *handle, bool live, bool abf)
static void p_chart_extrema_verts(PChart *chart, PVert **pin1, PVert **pin2)
float pack_islands(Span< PackIsland * > islands, const UVPackIsland_Params ¶ms)
static float p_edge_boundary_angle(PEdge *e)
void uv_parametrizer_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed)
static void fix_large_angle(const float v_fix[3], const float v1[3], const float v2[3], double *r_fix, double *r_a1, double *r_a2)
@ PHANDLE_STATE_ALLOCATED
@ PHANDLE_STATE_CONSTRUCTED
static void p_chart_simplify_compute(PChart *chart, std::function< float(PEdge *, PEdge *)> collapse_cost_fn, std::function< float(PEdge *, PEdge *)> collapse_allowed_fn)
void uv_parametrizer_stretch_iter(ParamHandle *handle)
static void uv_parametrizer_scale_x(ParamHandle *phandle, const float scale_x)
static int p_face_exists(ParamHandle *handle, const ParamKey *pvkeys, int i1, int i2, int i3)
static void p_face_flip(PFace *f)
static void phash_insert(PHash *ph, PHashLink *link)
static float p_face_area(PFace *f)
static PVert * p_vert_lookup(ParamHandle *handle, PHashKey key, const float co[3], const float weight, PEdge *e)
void uv_parametrizer_pack(ParamHandle *handle, float margin, bool do_rotate, bool ignore_pinned)
static void p_chart_flush_collapsed_uvs(PChart *chart)
void uv_parametrizer_stretch_end(ParamHandle *handle)
static PEdge * p_boundary_edge_prev(PEdge *e)
static PHashLink * phash_next(PHash *ph, PHashKey key, PHashLink *link)
static float p_edge_uv_length(PEdge *e)
static void p_chart_boundaries(PChart *chart, PEdge **r_outer)
static int p_connect_pairs(ParamHandle *handle, bool topology_from_uvs)
static void p_chart_lscm_transform_single_pin(PChart *chart)
static bool p_validate_triangle_angles(const PVert *vert1, const PVert *vert2, const PVert *vert3, const float min_angle_cos)
void uv_parametrizer_face_add(ParamHandle *handle, const ParamKey key, const int nverts, const ParamKey *vkeys, const float **co, float **uv, const float *weight, const bool *pin, const bool *select)
VecBase< float, 3 > float3
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
union blender::geometry::PEdge::PEdgeUnion u
union blender::geometry::PFace::PFaceUnion u
union blender::geometry::PVert::PVertUnion u
std::vector< float > w_vectors
std::vector< double > el_vectors
std::vector< int > p_matrices
std::vector< double > v_matrices
int boundary_vertices_num
std::vector< double > uv_matrices
std::vector< int > e_matrices
std::vector< double > pp_matrices
std::vector< int > b_vectors
std::vector< int > f_matrices
void setup_slim_data(MatrixTransferChart &chart) const
std::vector< MatrixTransferChart > charts
PinnedVertexData pinned_vertex_data
void parametrize_live(MatrixTransferChart &chart, const PinnedVertexData &pinned_vertex_data)
std::vector< int > selected_pins
std::vector< int > pinned_vertex_indices
std::vector< double > pinned_vertex_positions_2D
static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
#define UNUSED_FUNCTION_NO_SLIM
#define PHASH_hash(ph, item)
#define PHASH_edge(v1, v2)
#define PEDGE_VERTEX_FLAGS
#define param_warning(message)