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)) {
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;
3717 if (
angle != 0.0f) {
3795 pinuvlist = pinuvlist->
next;
3798 if (bestdistsquared > distsquared) {
3799 bestdistsquared = distsquared;
3802 pinuvlist = pinuvlist->
next;
3810 pinuv->
next =
nullptr;
3834 if (!pinuvlist->
next) {
3838 pinuvlist = pinuvlist->
next;
3848 const float *weight,
3855 uint nfilltri = nverts - 2;
3856 uint(*tris)[3] =
static_cast<uint(*)[3]
>(
3858 float (*projverts)[2] =
static_cast<float (*)[2]
>(
3865 const float *co_curr, *co_prev = co[nverts - 1];
3866 for (
int j = 0; j < nverts; j++) {
3876 float axis_mat[3][3];
3878 for (
int j = 0; j < nverts; j++) {
3888 for (
uint j = 0; j < nfilltri; j++) {
3889 uint *tri = tris[j];
3894 const ParamKey tri_vkeys[3] = {vkeys[v0], vkeys[v1], vkeys[
v2]};
3895 const float *tri_co[3] = {co[v0], co[v1], co[
v2]};
3896 float *tri_uv[3] = {uv[v0], uv[v1], uv[
v2]};
3898 const float *tri_weight =
nullptr;
3899 float tri_weight_tmp[3];
3902 tri_weight_tmp[0] = weight[v0];
3903 tri_weight_tmp[1] = weight[v1];
3904 tri_weight_tmp[2] = weight[
v2];
3905 tri_weight = tri_weight_tmp;
3908 const bool tri_pin[3] = {pin[v0], pin[v1], pin[
v2]};
3912 handle, key, 3, tri_vkeys, tri_co, tri_uv, tri_weight, tri_pin, tri_select);
3924 const float *weight,
3937 for (
int i = 0;
i < nverts;
i++) {
3941 for (
int i = nverts - 1;
i >= 0;) {
3946 const int pm = int(permute.
size());
3948 int i0 = permute[
i];
3949 int i1 = permute[(
i + 1) % pm];
3950 int i2 = permute[(
i + 2) % pm];
3960 int iprev = permute[(
i + pm - 1) % pm];
3961 p_face_add_construct(phandle, key, vkeys, co, uv, weight, iprev, i0, i1, pin,
select);
3964 if (permute.
size() == 3) {
3968 if (permute.
size() != nverts) {
3969 const int pm = int(permute.
size());
3977 for (
int i = 0;
i < pm;
i++) {
3979 vkeys_sub[
i] = vkeys[j];
3983 weight_sub[
i] = weight[j];
3985 pin_sub[
i] = pin && pin[j];
3994 weight ? &weight_sub.
first() :
nullptr,
3996 &select_sub.
first());
4007 p_face_add_construct(phandle, key, vkeys, co, uv, weight, 0, 1, 2, pin,
select);
4023 bool topology_from_uvs,
4024 int *r_count_failed)
4046 if (!topology_from_uvs && chart->
nboundaries == 0) {
4048 if (r_count_failed) {
4049 *r_count_failed += 1;
4054 phandle->
charts[j++] = chart;
4109 if (count_changed !=
nullptr) {
4110 *count_changed += 1;
4114 if (count_failed !=
nullptr) {
4128 p_chart_complexify(phandle->
charts[
i]);
4141 phandle->
blend = 0.0f;
4203 PVert *
v2 = f->edge->next->next->vert;
4207 pack_island_vector.
append(pack_island);
4223 pack_island_vector[
i] =
nullptr;
4233 float tot_area_3d = 0.0f;
4234 float tot_area_uv = 0.0f;
4235 float minv[2], maxv[2], trans[2];
4244 if (ignore_pinned && chart->
has_pins) {
4252 if (scale_uv || shear) {
4257 for (
int j = 0; j < max_iter; j++) {
4261 double scale_cou = 0;
4262 double scale_cov = 0;
4263 double scale_cross = 0;
4264 double weight_sum = 0;
4266 float m[2][2], s[2][2];
4270 s[0][0] = va->
uv[0] - vc->
uv[0];
4271 s[0][1] = va->
uv[1] - vc->
uv[1];
4272 s[1][0] = vb->
uv[0] - vc->
uv[0];
4273 s[1][1] = vb->
uv[1] - vc->
uv[1];
4279 float cou[3], cov[3];
4280 for (
int k = 0; k < 3; k++) {
4281 cou[k] = m[0][0] * (va->
co[k] - vc->
co[k]) + m[0][1] * (vb->
co[k] - vc->
co[k]);
4282 cov[k] = m[1][0] * (va->
co[k] - vc->
co[k]) + m[1][1] * (vb->
co[k] - vc->
co[k]);
4285 scale_cou +=
len_v3(cou) * weight;
4286 scale_cov +=
len_v3(cov) * weight;
4295 scale_cross +=
dot_v3v3(cou, cov) * weight;
4297 weight_sum += weight;
4299 if (scale_cou * scale_cov < 1e-10f) {
4302 const float scale_factor_u = scale_uv ?
sqrtf(scale_cou / scale_cov) : 1.0f;
4306 t[0][0] = scale_factor_u;
4307 t[1][0] =
clamp_f(
float(scale_cross / weight_sum), -0.5f, 0.5f);
4309 t[1][1] = 1.0f / scale_factor_u;
4315 const float err =
fabsf(t[0][0] - 1.0f) +
fabsf(t[1][0]) +
fabsf(t[0][1]) +
4316 fabsf(t[1][1] - 1.0f);
4318 const float tolerance = 1e-6f;
4319 if (err < tolerance) {
4334 tot_area_3d += chart->
area_3d;
4335 tot_area_uv += chart->
area_uv;
4338 if (tot_area_3d == 0.0f || tot_area_uv == 0.0f) {
4343 const float tot_fac = tot_area_3d / tot_area_uv;
4348 if (ignore_pinned && chart->
has_pins) {
4398 PVert *oldv, *keepv;
4412 PEdge *collapse_e = edge ? edge : pair;
4418 PEdge *collapse_e = edge ? edge : pair;
4424 const float threshold_squared = threshold * threshold;
4434 PVert *newv, *keepv;
4443 std::swap(edge, pair);
4448 newv->
uv[0] = keepv->
uv[0];
4449 newv->
uv[1] = keepv->
uv[1];
4455 const float corr_co1[3],
4456 const float corr_co2[3],
4457 const float min_area,
4458 const float min_angle_cos)
4477 if (
e->next->next == corr_e->
pair) {
4478 PVert *other_v =
e->next->next->vert;
4482 const PVert *other_v1 =
e->next->vert;
4483 const PVert *other_v2 =
e->next->next->vert;
4487 if (area < min_area) {
4493 if (
e->next->next == corr_e->
pair) {
4494 PVert *other_v =
e->next->next->vert;
4495 p_triangle_cos(corr_co1, corr_co2, other_v->
co, f_cos, f_cos + 1, f_cos + 2);
4498 const PVert *other_v1 =
e->next->vert;
4499 const PVert *other_v2 =
e->next->next->vert;
4503 for (
int i = 0;
i < 3;
i++) {
4504 if (f_cos[
i] > min_angle_cos) {
4515 const float corr_co[3],
4517 float min_angle_cos)
4530 const PVert *other_v1 =
e->next->vert;
4531 const PVert *other_v2 =
e->next->next->vert;
4535 if (area < min_area) {
4542 for (
int i = 0;
i < 3;
i++) {
4543 if (f_cos[
i] > min_angle_cos) {
4555 static const constexpr float eps = 1.0e-5;
4556 static const constexpr float n1[3] = {0.0f, 0.0f, 1.0f};
4557 static const constexpr float n2[3] = {0.0f, 1.0f, 0.0f};
4559 float edge_len =
len_v3(edge_dir);
4560 if (edge_len <
eps) {
4564 float edge_dir_norm[3];
4566 mul_v3_fl(edge_dir_norm, 1.0f / edge_len);
4568 float normal_dir[3];
4570 float normal_len =
len_v3(normal_dir);
4572 if (normal_len <
eps) {
4574 normal_len =
len_v3(normal_dir);
4576 if (normal_len <
eps) {
4581 mul_v3_fl(normal_dir, 1.0f / normal_len);
4583 float tangent_dir[3];
4586 R[0][0] = edge_dir_norm[0];
4587 R[1][0] = edge_dir_norm[1];
4588 R[2][0] = edge_dir_norm[2];
4590 R[0][1] = normal_dir[0];
4591 R[1][1] = normal_dir[1];
4592 R[2][1] = normal_dir[2];
4594 R[0][2] = tangent_dir[0];
4595 R[1][2] = tangent_dir[1];
4596 R[2][2] = tangent_dir[2];
4614 float min_angle_cos)
4616 static const float3 ref_edges[] = {
4632 static const int ref_edge_count =
ARRAY_SIZE(ref_edges);
4633 static const int LEN_MULTIPLIER_COUNT = 3;
4634 bool corr_co_found =
false;
4636 float corr_len = 2.0f * std::sqrt((min_area +
CORR_ZERO_AREA_EPS) / 3.0f / std::sqrt(3.0f));
4638 for (
int m = 0; m < LEN_MULTIPLIER_COUNT; m++) {
4639 for (
int re = 0; re < ref_edge_count; re++) {
4646 float corr_co[3][3];
4649 for (
int i = 0;
i < 3;
i++) {
4653 float corr_len_multiplied = corr_len * (m + 1);
4656 mul_v3_fl(corr_dir, corr_len_multiplied);
4664 for (
int i = 0;
i < 3;
i++) {
4666 e, corr_co[
i], corr_co[(
i + 1) % 3], min_area, min_angle_cos))
4675 for (
int i = 0;
i < 3;
i++) {
4680 corr_co_found =
true;
4684 if (corr_co_found) {
4689 if (!corr_co_found) {
4699 static const float eps = 1.0e-6;
4701 float min_angle_cos = std::cos(min_angle);
4711 PEdge *max_edge =
nullptr;
4712 float max_edge_len = -std::numeric_limits<float>::infinity();
4714 PEdge *min_edge =
nullptr;
4715 float min_edge_len = std::numeric_limits<float>::infinity();
4717 PEdge *middle_edge =
nullptr;
4723 if (
len > max_edge_len) {
4727 middle_edge = max_edge->
next == min_edge ? min_edge->
next : max_edge->
next;
4730 if (
len < min_edge_len) {
4734 middle_edge = min_edge->
next == max_edge ? max_edge->
next : min_edge->
next;
4738 }
while (
e != f->edge);
4744 bool small_uniside_tri = (face_area <= min_area) && (min_edge == max_edge);
4746 if ((max_edge_len <
eps) || small_uniside_tri) {
4751 if (min_edge == max_edge) {
4765 float max_face_cos =
4766 middle_edge->
next == max_edge ?
4770 float angle_corr_len = max_face_cos > min_angle_cos ?
4774 if ((face_area > min_area) && (angle_corr_len == 0.0f)) {
4780 corr_len = std::max(corr_len, angle_corr_len);
4786 static const constexpr int DIR_COUNT = 16;
4787 static const constexpr int LEN_MULTIPLIER_COUNT = 2;
4789 bool corr_co_found =
false;
4791 for (
int m = 0; m < LEN_MULTIPLIER_COUNT; m++) {
4792 for (
int d = 0; d < DIR_COUNT; d++) {
4796 const float corr_len_multiplied = corr_len * (m + 1);
4799 mul_v3_fl(corr_dir, corr_len_multiplied);
4805 corr_co_found =
true;
4810 if (corr_co_found) {
4815 if (!corr_co_found) {
4831 const float min_angle_cos)
4836 for (
int i = 0;
i < 3;
i++) {
4837 if (t_cos[
i] > min_angle_cos) {
4848 const float min_area,
4849 const float min_angle)
4938static void slim_transfer_edges(
PChart *chart, slim::MatrixTransferChart *mt_chart)
4941 std::vector<double> &EL = mt_chart->
el_vectors;
4949 static const float DOUBLED_VERT_THRESHOLD = 1.0e-5;
4952 E[eid] = be->vert->slim_id;
4957 if (edge_len < DOUBLED_VERT_THRESHOLD) {
4965 }
while (be != outer);
4967 for (
PEdge *
e = chart->edges;
e;
e =
e->nextlink) {
4970 E[eid] =
e->vert->slim_id;
4975 if (edge_len < DOUBLED_VERT_THRESHOLD) {
4987static void slim_transfer_vertices(
const PChart *chart,
4988 slim::MatrixTransferChart *mt_chart,
4989 slim::MatrixTransfer *mt)
4992 std::vector<double> &v_mat = mt_chart->
v_matrices;
4993 std::vector<double> &uv_mat = mt_chart->
uv_matrices;
4994 std::vector<int> &p_mat = mt_chart->
p_matrices;
4995 std::vector<double> &pp_mat = mt_chart->
pp_matrices;
4996 std::vector<float> &w_vec = mt_chart->
w_vectors;
5002 for (
PVert *
v = chart->verts;
v;
v =
v->nextlink) {
5003 if (!
v->on_boundary_flag) {
5005 w_vec[vid] =
v->weight;
5012 v_mat[
v->slim_id] =
v->
co[0];
5013 v_mat[r +
v->slim_id] =
v->
co[1];
5014 v_mat[2 * r +
v->slim_id] =
v->
co[2];
5016 uv_mat[
v->slim_id] =
v->uv[0];
5017 uv_mat[r +
v->slim_id] =
v->uv[1];
5022 p_mat[p_vid] =
v->slim_id;
5023 pp_mat[2 * p_vid] = double(
v->uv[0]);
5024 pp_mat[2 * p_vid + 1] = double(
v->uv[1]);
5033static void slim_transfer_boundary_vertices(
PChart *chart,
5034 slim::MatrixTransferChart *mt_chart,
5035 const slim::MatrixTransfer *mt)
5037 std::vector<int> &b_vec = mt_chart->
b_vectors;
5038 std::vector<float> &w_vec = mt_chart->
w_vectors;
5041 for (
PVert *
v = chart->verts;
v;
v =
v->nextlink) {
5042 v->on_boundary_flag =
false;
5054 w_vec[vid] = be->vert->weight;
5058 be->vert->slim_id = vid;
5059 be->vert->on_boundary_flag =
true;
5065 }
while (be != outer);
5071static void slim_transfer_faces(
const PChart *chart, slim::MatrixTransferChart *mt_chart)
5083 F[fid] =
e->vert->slim_id;
5084 F[r + fid] = e1->vert->slim_id;
5085 F[2 * r + fid] = e2->vert->slim_id;
5093static void slim_convert_blender(
ParamHandle *phandle, slim::MatrixTransfer *mt)
5095 static const float SLIM_CORR_MIN_AREA = 1.0e-8;
5096 static const float SLIM_CORR_MIN_ANGLE =
DEG2RADF(1.0f);
5102 slim::MatrixTransferChart *mt_chart = &mt->
charts[
i];
5111 slim_allocate_matrices(chart, mt_chart);
5114 slim_transfer_boundary_vertices(chart, mt_chart, mt);
5115 slim_transfer_vertices(chart, mt_chart, mt);
5116 slim_transfer_edges(chart, mt_chart);
5117 slim_transfer_faces(chart, mt_chart);
5135 slim::MatrixTransfer *mt = slim_matrix_transfer(slim_options);
5137 slim_convert_blender(phandle, mt);
5145 slim::MatrixTransfer *mt,
5155 slim::MatrixTransferChart *mt_chart = &mt->
charts[
i];
5158 if (count_changed) {
5163 for (
v = chart->verts;
v;
v =
v->nextlink) {
5179 for (
v = chart->verts;
v;
v =
v->nextlink) {
5191static void slim_free_matrix_transfer(
ParamHandle *phandle)
5197static void slim_get_pinned_vertex_data(
ParamHandle *phandle,
5199 slim::MatrixTransferChart &mt_chart,
5200 slim::PinnedVertexData &pinned_vertex_data)
5204 std::vector<int> &selected_pins = pinned_vertex_data.
selected_pins;
5206 pinned_vertex_indices.clear();
5207 pinned_vertex_positions_2D.clear();
5208 selected_pins.clear();
5220 selected_pins.push_back(be->vert->slim_id);
5223 pinned_vertex_indices.push_back(be->vert->slim_id);
5224 pinned_vertex_positions_2D.push_back(be->vert->uv[0]);
5225 pinned_vertex_positions_2D.push_back(be->vert->uv[1]);
5228 }
while (be != outer);
5231 for (
v = chart->verts;
v;
v =
v->nextlink) {
5232 if (!
v->on_boundary_flag && (
v->flag &
PVERT_PIN)) {
5237 selected_pins.push_back(
v->slim_id);
5239 pinned_vertex_indices.push_back(
v->slim_id);
5240 pinned_vertex_positions_2D.push_back(
v->uv[0]);
5241 pinned_vertex_positions_2D.push_back(
v->uv[1]);
5262 slim_transfer_data_to_slim(phandle, slim_options);
5267 slim_flush_uvs(phandle, mt, count_changed, count_failed);
5268 slim_free_matrix_transfer(phandle);
5272 UNUSED_VARS(phandle, slim_options, count_changed, count_failed);
5279 slim_transfer_data_to_slim(phandle, slim_options);
5292 bool select =
false, deselect =
false;
5307 if (!
select || !deselect) {
5327 mt->
charts[
i].parametrize_single_iteration();
5332 slim_flush_uvs(phandle, mt,
nullptr,
nullptr);
5348 if (!mt_chart.
data) {
5358 const bool live =
true;
5359 slim_flush_uvs(phandle, mt,
nullptr,
nullptr, live);
5375 slim_free_matrix_transfer(phandle);
5384 return phandle->
slim_mt !=
nullptr;
float BLI_convexhull_aabb_fit_points_2d(blender::Span< blender::float2 > points)
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)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
#define MEM_SIZE_OPTIMAL(size)
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
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 p_chart_uv_to_array(PChart *chart, MutableSpan< float2 > points)
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 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)
void uv_parametrizer_pack(ParamHandle *handle, const UVPackIsland_Params ¶ms)
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)
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)