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;
240 if (ph->
size > (size * 3)) {
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 =
DEG2RADF(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])));
425 return len_v2v2(
e->vert->uv,
e->next->vert->uv);
434 for (
v = chart->
verts;
v;
v =
v->nextlink) {
443 for (
PFace *f = chart->
faces; f; f = f->nextlink) {
464 if (scale_x == 1.0f) {
469 for (
int i = 0; i < phandle->
ncharts; i++) {
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];
628 v->uv[0] +=
e->orig_uv[0] * handle->aspect_y;
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) {
653 const float blend = handle->blend;
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;
930 PChart *chart = handle->construction_chart;
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) {
1214 be = be->next->vert->edge;
1217 if (r_outer && (
len > maxlen)) {
1223 for (
e = chart->
edges;
e;
e =
e->nextlink) {
1224 e->flag &= ~PEDGE_DONE;
1246 }
while (we && (we !=
v->edge));
1269 e = be->next->vert->edge;
1277 while (nedges > 2) {
1278 PEdge *ne, *ne1, *ne2;
1307 ne1->
vert =
e->vert;
1333 for (
e = chart->
edges;
e;
e =
e->nextlink) {
1344 be = be->next->vert->edge;
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;
1423 oldpoints =
MEM_mallocN(
sizeof(
float[2]) * size,
"PPolygonOldPoints");
1424 newpoints =
MEM_mallocN(
sizeof(
float[2]) * size,
"PPolygonNewPoints");
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) {
1453 oldpoints =
MEM_mallocN(
sizeof(
float[2]) * size,
"oldpoints");
1454 memcpy(oldpoints, newpoints,
sizeof(
float[2]) * nnewpoints);
1456 newpoints =
MEM_mallocN(
sizeof(
float[2]) * size,
"newpoints");
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));
1614 points =
MEM_mallocN(
sizeof(
float[2]) * npoints,
"PHarmonicPoints");
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;
1671 *r_keepv = edge->next->vert;
1674 *r_newv = pair->next->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)) {
1698 if (edge && edge->next->pair) {
1701 else if (pair && pair->next->next->pair) {
1704 else if (edge && edge->next->next->pair) {
1755 PFace *f = edge->face;
1765 PFace *f = pair->face;
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;
1800 PEdge *e1 = pair->next, *e2 = e1->next;
1803 e1->pair->pair = e1;
1806 e2->pair->pair = e2;
1809 e2->vert->edge = e2;
1821 }
while (
e && (
e != newv->edge));
1827 PVert *oldv, *keepv;
1832 if (!edge || !pair) {
1834 if (edge && !edge->next->pair && !edge->next->next->pair) {
1837 else if (pair && !pair->next->pair && !pair->next->next->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;
2094 PFace *f, *nextf =
nullptr, *faces = chart->
faces;
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;
2210 if (edge->vert->u.heaplink != link) {
2212 edge->next->vert->u.heaplink =
nullptr;
2213 std::swap(edge, pair);
2217 edge->vert->u.heaplink =
nullptr;
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;
2304 PEdge *
e, *pair, *edge;
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;
2405 for (
int i = 0; i < sys->
nangles; i++) {
2406 const double angle = alpha[i];
2407 sine[i] = sin(angle);
2408 cosine[i] =
cos(angle);
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++) {
2543 for (
PFace *f = chart->
faces; f; f = f->nextlink) {
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++) {
2689 for (
PFace *f = chart->
faces; f; f = f->nextlink) {
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) {
2759 v->flag &= ~PVERT_INTERIOR;
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;
3172 for (
PFace *f = chart->
faces; f; f = f->nextlink) {
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);
3193 for (
PFace *f = chart->
faces; f; f = f->nextlink) {
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) {
3313 v->flag &= ~PVERT_PIN;
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;
3587 angles = (
float *)
MEM_mallocN(
sizeof(
float) * npoints,
"PMinAreaAngles");
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)) {
3698 float sine =
sinf(angle);
3699 float cosine =
cosf(angle);
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;
3711 float(*points)[2] =
static_cast<float(*)[2]
>(
3720 if (angle != 0.0f) {
3760 for (
int i = 0; i <
ncharts; i++) {
3785 if (!handle->pin_hash) {
3798 pinuvlist = pinuvlist->
next;
3801 if (bestdistsquared > distsquared) {
3802 bestdistsquared = distsquared;
3805 pinuvlist = pinuvlist->
next;
3813 pinuv->
next =
nullptr;
3821 if (!handle->pin_hash) {
3837 if (!pinuvlist->
next) {
3841 pinuvlist = pinuvlist->
next;
3851 const float *weight,
3856 MemArena *arena = handle->polyfill_arena;
3857 Heap *heap = handle->polyfill_heap;
3858 uint nfilltri = nverts - 2;
3859 uint(*tris)[3] =
static_cast<uint(*)[3]
>(
3861 float(*projverts)[2] =
static_cast<float(*)[2]
>(
3868 const float *co_curr, *co_prev = co[nverts - 1];
3869 for (
int j = 0; j < nverts; j++) {
3879 float axis_mat[3][3];
3881 for (
int j = 0; j < nverts; j++) {
3891 for (
uint j = 0; j < nfilltri; j++) {
3892 uint *tri = tris[j];
3897 const ParamKey tri_vkeys[3] = {vkeys[v0], vkeys[v1], vkeys[
v2]};
3898 const float *tri_co[3] = {co[v0], co[v1], co[
v2]};
3899 float *tri_uv[3] = {uv[v0], uv[v1], uv[
v2]};
3901 const float *tri_weight =
nullptr;
3902 float tri_weight_tmp[3];
3905 tri_weight_tmp[0] = weight[v0];
3906 tri_weight_tmp[1] = weight[v1];
3907 tri_weight_tmp[2] = weight[
v2];
3908 tri_weight = tri_weight_tmp;
3911 const bool tri_pin[3] = {pin[v0], pin[v1], pin[
v2]};
3915 handle, key, 3, tri_vkeys, tri_co, tri_uv, tri_weight, tri_pin, tri_select);
3927 const float *weight,
3940 for (
int i = 0; i < nverts; i++) {
3944 for (
int i = nverts - 1; i >= 0;) {
3949 const int pm =
int(permute.
size());
3951 int i0 = permute[i];
3952 int i1 = permute[(i + 1) % pm];
3953 int i2 = permute[(i + 2) % pm];
3963 int iprev = permute[(i + pm - 1) % pm];
3964 p_face_add_construct(phandle, key, vkeys, co, uv, weight, iprev, i0, i1, pin,
select);
3967 if (permute.
size() == 3) {
3971 if (permute.
size() != nverts) {
3972 const int pm =
int(permute.
size());
3980 for (
int i = 0; i < pm; i++) {
3982 vkeys_sub[i] = vkeys[j];
3986 weight_sub[i] = weight[j];
3988 pin_sub[i] = pin && pin[j];
3997 weight ? &weight_sub.
first() :
nullptr,
3999 &select_sub.
first());
4010 p_face_add_construct(phandle, key, vkeys, co, uv, weight, 0, 1, 2, pin,
select);
4026 bool topology_from_uvs,
4027 int *r_count_failed)
4043 for (i = j = 0; i < phandle->
ncharts; i++) {
4049 if (!topology_from_uvs && chart->
nboundaries == 0) {
4051 if (r_count_failed) {
4052 *r_count_failed += 1;
4057 phandle->
charts[j++] = chart;
4078 for (
int i = 0; i < phandle->
ncharts; i++) {
4090 for (
int i = 0; i < phandle->
ncharts; i++) {
4112 if (count_changed !=
nullptr) {
4113 *count_changed += 1;
4117 if (count_failed !=
nullptr) {
4128 for (
int i = 0; i < phandle->
ncharts; i++) {
4131 p_chart_complexify(phandle->
charts[i]);
4144 phandle->
blend = 0.0f;
4146 for (
int i = 0; i < phandle->
ncharts; i++) {
4150 v->flag &= ~PVERT_PIN;
4155 for (
PFace *f = chart->
faces; f; f = f->nextlink) {
4171 for (
int i = 0; i < phandle->
ncharts; i++) {
4184 if (handle->ncharts == 0) {
4197 for (
int i = 0; i < handle->ncharts; i++) {
4198 PChart *chart = handle->charts[i];
4199 if (ignore_pinned && chart->
has_pins) {
4205 pack_island->
aspect_y = handle->aspect_y;
4208 for (
PFace *f = chart->
faces; f; f = f->nextlink) {
4211 PVert *
v2 = f->edge->next->next->vert;
4215 pack_island_vector.
append(pack_island);
4221 PackIsland *pack_island = pack_island_vector[i];
4231 pack_island_vector[i] =
nullptr;
4241 float tot_area_3d = 0.0f;
4242 float tot_area_uv = 0.0f;
4243 float minv[2], maxv[2], trans[2];
4249 for (i = 0; i < phandle->
ncharts; i++) {
4252 if (ignore_pinned && chart->
has_pins) {
4260 if (scale_uv || shear) {
4265 for (
int j = 0; j < max_iter; j++) {
4269 double scale_cou = 0;
4270 double scale_cov = 0;
4271 double scale_cross = 0;
4272 double weight_sum = 0;
4273 for (
PFace *f = chart->
faces; f; f = f->nextlink) {
4274 float m[2][2], s[2][2];
4278 s[0][0] = va->
uv[0] - vc->
uv[0];
4279 s[0][1] = va->
uv[1] - vc->
uv[1];
4280 s[1][0] = vb->
uv[0] - vc->
uv[0];
4281 s[1][1] = vb->
uv[1] - vc->
uv[1];
4287 float cou[3], cov[3];
4288 for (
int k = 0; k < 3; k++) {
4289 cou[k] = m[0][0] * (va->
co[k] - vc->
co[k]) + m[0][1] * (vb->
co[k] - vc->
co[k]);
4290 cov[k] = m[1][0] * (va->
co[k] - vc->
co[k]) + m[1][1] * (vb->
co[k] - vc->
co[k]);
4293 scale_cou +=
len_v3(cou) * weight;
4294 scale_cov +=
len_v3(cov) * weight;
4303 scale_cross +=
dot_v3v3(cou, cov) * weight;
4305 weight_sum += weight;
4307 if (scale_cou * scale_cov < 1e-10f) {
4310 const float scale_factor_u = scale_uv ?
sqrtf(scale_cou / scale_cov) : 1.0f;
4314 t[0][0] = scale_factor_u;
4315 t[1][0] =
clamp_f(
float(scale_cross / weight_sum), -0.5f, 0.5f);
4317 t[1][1] = 1.0f / scale_factor_u;
4323 const float err =
fabsf(t[0][0] - 1.0f) +
fabsf(t[1][0]) +
fabsf(t[0][1]) +
4324 fabsf(t[1][1] - 1.0f);
4326 const float tolerance = 1e-6f;
4327 if (err < tolerance) {
4337 for (
PFace *f = chart->
faces; f; f = f->nextlink) {
4342 tot_area_3d += chart->
area_3d;
4343 tot_area_uv += chart->
area_uv;
4346 if (tot_area_3d == 0.0f || tot_area_uv == 0.0f) {
4351 const float tot_fac = tot_area_3d / tot_area_uv;
4353 for (i = 0; i < phandle->
ncharts; i++) {
4356 if (ignore_pinned && chart->
has_pins) {
4380 for (
int i = 0; i < phandle->
ncharts; i++) {
4392 for (
int i = 0; i < phandle->
ncharts; i++) {
4394 for (
PFace *f = chart->
faces; f; f = f->nextlink) {
4406 PVert *oldv, *keepv;
4420 PEdge *collapse_e = edge ? edge : pair;
4426 PEdge *collapse_e = edge ? edge : pair;
4432 const float threshold_squared = threshold * threshold;
4442 PVert *newv, *keepv;
4451 std::swap(edge, pair);
4456 newv->
uv[0] = keepv->
uv[0];
4457 newv->
uv[1] = keepv->
uv[1];
4463 const float corr_co1[3],
4464 const float corr_co2[3],
4465 const float min_area,
4466 const float min_angle_cos)
4485 if (
e->next->next == corr_e->
pair) {
4486 PVert *other_v =
e->next->next->vert;
4490 const PVert *other_v1 =
e->next->vert;
4491 const PVert *other_v2 =
e->next->next->vert;
4495 if (area < min_area) {
4501 if (
e->next->next == corr_e->
pair) {
4502 PVert *other_v =
e->next->next->vert;
4503 p_triangle_cos(corr_co1, corr_co2, other_v->
co, f_cos, f_cos + 1, f_cos + 2);
4506 const PVert *other_v1 =
e->next->vert;
4507 const PVert *other_v2 =
e->next->next->vert;
4511 for (
int i = 0; i < 3; i++) {
4512 if (f_cos[i] > min_angle_cos) {
4523 const float corr_co[3],
4525 float min_angle_cos)
4538 const PVert *other_v1 =
e->next->vert;
4539 const PVert *other_v2 =
e->next->next->vert;
4543 if (area < min_area) {
4550 for (
int i = 0; i < 3; i++) {
4551 if (f_cos[i] > min_angle_cos) {
4563 static const constexpr float eps = 1.0e-5;
4564 static const constexpr float n1[3] = {0.0f, 0.0f, 1.0f};
4565 static const constexpr float n2[3] = {0.0f, 1.0f, 0.0f};
4567 float edge_len =
len_v3(edge_dir);
4568 if (edge_len <
eps) {
4572 float edge_dir_norm[3];
4574 mul_v3_fl(edge_dir_norm, 1.0f / edge_len);
4576 float normal_dir[3];
4578 float normal_len =
len_v3(normal_dir);
4580 if (normal_len <
eps) {
4582 normal_len =
len_v3(normal_dir);
4584 if (normal_len <
eps) {
4589 mul_v3_fl(normal_dir, 1.0f / normal_len);
4591 float tangent_dir[3];
4594 R[0][0] = edge_dir_norm[0];
4595 R[1][0] = edge_dir_norm[1];
4596 R[2][0] = edge_dir_norm[2];
4598 R[0][1] = normal_dir[0];
4599 R[1][1] = normal_dir[1];
4600 R[2][1] = normal_dir[2];
4602 R[0][2] = tangent_dir[0];
4603 R[1][2] = tangent_dir[1];
4604 R[2][2] = tangent_dir[2];
4622 float min_angle_cos)
4624 static const float3 ref_edges[] = {
4640 static const int ref_edge_count =
ARRAY_SIZE(ref_edges);
4641 static const int LEN_MULTIPLIER_COUNT = 3;
4642 bool corr_co_found =
false;
4644 float corr_len = 2.0f * std::sqrt((min_area +
CORR_ZERO_AREA_EPS) / 3.0f / std::sqrt(3.0f));
4646 for (
int m = 0; m < LEN_MULTIPLIER_COUNT; m++) {
4647 for (
int re = 0; re < ref_edge_count; re++) {
4654 float corr_co[3][3];
4657 for (
int i = 0; i < 3; i++) {
4658 const float angle = (
float(i) / 3.0f) *
float(2.0 *
M_PI);
4659 float corr_dir[3] = {0.0f,
cos(angle), sin(angle)};
4661 float corr_len_multiplied = corr_len * (m + 1);
4664 mul_v3_fl(corr_dir, corr_len_multiplied);
4672 for (
int i = 0; i < 3; i++) {
4674 e, corr_co[i], corr_co[(i + 1) % 3], min_area, min_angle_cos))
4683 for (
int i = 0; i < 3; i++) {
4688 corr_co_found =
true;
4692 if (corr_co_found) {
4697 if (!corr_co_found) {
4707 static const float eps = 1.0e-6;
4709 float min_angle_cos = std::cos(min_angle);
4712 for (
PFace *f = chart->
faces; f; f = f->nextlink) {
4719 PEdge *max_edge =
nullptr;
4720 float max_edge_len = -std::numeric_limits<float>::infinity();
4722 PEdge *min_edge =
nullptr;
4723 float min_edge_len = std::numeric_limits<float>::infinity();
4725 PEdge *middle_edge =
nullptr;
4731 if (
len > max_edge_len) {
4735 middle_edge = max_edge->
next == min_edge ? min_edge->
next : max_edge->
next;
4738 if (
len < min_edge_len) {
4742 middle_edge = min_edge->
next == max_edge ? max_edge->
next : min_edge->
next;
4746 }
while (
e != f->edge);
4752 bool small_uniside_tri = (face_area <= min_area) && (min_edge == max_edge);
4754 if ((max_edge_len <
eps) || small_uniside_tri) {
4759 if (min_edge == max_edge) {
4773 float max_face_cos =
4774 middle_edge->
next == max_edge ?
4778 float angle_corr_len = max_face_cos > min_angle_cos ?
4782 if ((face_area > min_area) && (angle_corr_len == 0.0f)) {
4788 corr_len = std::max(corr_len, angle_corr_len);
4794 static const constexpr int DIR_COUNT = 16;
4795 static const constexpr int LEN_MULTIPLIER_COUNT = 2;
4797 bool corr_co_found =
false;
4799 for (
int m = 0; m < LEN_MULTIPLIER_COUNT; m++) {
4800 for (
int d = 0; d < DIR_COUNT; d++) {
4801 const float angle = (
float(d) / DIR_COUNT) *
float(2.0 *
M_PI);
4802 float corr_dir[3] = {0.0f,
cos(angle), sin(angle)};
4804 const float corr_len_multiplied = corr_len * (m + 1);
4807 mul_v3_fl(corr_dir, corr_len_multiplied);
4813 corr_co_found =
true;
4818 if (corr_co_found) {
4823 if (!corr_co_found) {
4839 const float min_angle_cos)
4844 for (
int i = 0; i < 3; i++) {
4845 if (t_cos[i] > min_angle_cos) {
4856 const float min_area,
4857 const float min_angle)
4872 for (
PFace *f = chart->faces; f; f = f->nextlink) {
4889 f->flag &= ~PFACE_DONE;
4910 mt->
use_weights = slim_options->weight_influence > 0.0f;
4949 std::vector<double> &EL = mt_chart->
el_vectors;
4957 static const float DOUBLED_VERT_THRESHOLD = 1.0e-5;
4960 E[eid] = be->vert->slim_id;
4965 if (edge_len < DOUBLED_VERT_THRESHOLD) {
4973 }
while (be != outer);
4975 for (PEdge *
e = chart->edges;
e;
e =
e->nextlink) {
4976 PEdge *e1 =
e->next;
4978 E[eid] =
e->vert->slim_id;
4983 if (edge_len < DOUBLED_VERT_THRESHOLD) {
4995static void slim_transfer_vertices(
const PChart *chart,
5000 std::vector<double> &v_mat = mt_chart->
v_matrices;
5001 std::vector<double> &uv_mat = mt_chart->
uv_matrices;
5002 std::vector<int> &p_mat = mt_chart->
p_matrices;
5003 std::vector<double> &pp_mat = mt_chart->
pp_matrices;
5004 std::vector<float> &w_vec = mt_chart->
w_vectors;
5010 for (PVert *
v = chart->verts;
v;
v =
v->nextlink) {
5011 if (!
v->on_boundary_flag) {
5013 w_vec[vid] =
v->weight;
5020 v_mat[
v->slim_id] =
v->
co[0];
5021 v_mat[r +
v->slim_id] =
v->
co[1];
5022 v_mat[2 * r +
v->slim_id] =
v->
co[2];
5024 uv_mat[
v->slim_id] =
v->uv[0];
5025 uv_mat[r +
v->slim_id] =
v->uv[1];
5030 p_mat[p_vid] =
v->slim_id;
5031 pp_mat[2 * p_vid] =
double(
v->uv[0]);
5032 pp_mat[2 * p_vid + 1] =
double(
v->uv[1]);
5041static void slim_transfer_boundary_vertices(PChart *chart,
5045 std::vector<int> &b_vec = mt_chart->
b_vectors;
5046 std::vector<float> &w_vec = mt_chart->
w_vectors;
5049 for (PVert *
v = chart->verts;
v;
v =
v->nextlink) {
5050 v->on_boundary_flag =
false;
5062 w_vec[vid] = be->vert->weight;
5066 be->vert->slim_id = vid;
5067 be->vert->on_boundary_flag =
true;
5073 }
while (be != outer);
5083 for (PFace *f = chart->faces; f; f = f->nextlink) {
5085 PEdge *e1 =
e->next;
5086 PEdge *e2 = e1->next;
5091 F[fid] =
e->vert->slim_id;
5092 F[r + fid] = e1->vert->slim_id;
5093 F[2 * r + fid] = e2->vert->slim_id;
5103 static const float SLIM_CORR_MIN_AREA = 1.0e-8;
5104 static const float SLIM_CORR_MIN_ANGLE =
DEG2RADF(1.0);
5106 mt->
charts.resize(phandle->ncharts);
5108 for (
int i = 0; i < phandle->ncharts; i++) {
5109 PChart *chart = phandle->charts[i];
5119 slim_allocate_matrices(chart, mt_chart);
5122 slim_transfer_boundary_vertices(chart, mt_chart, mt);
5123 slim_transfer_vertices(chart, mt_chart, mt);
5124 slim_transfer_edges(chart, mt_chart);
5125 slim_transfer_faces(chart, mt_chart);
5141static void slim_transfer_data_to_slim(ParamHandle *phandle,
const ParamSlimOptions *slim_options)
5145 slim_convert_blender(phandle, mt);
5146 phandle->slim_mt = mt;
5152static void slim_flush_uvs(ParamHandle *phandle,
5161 for (
int i = 0; i < phandle->ncharts; i++) {
5162 PChart *chart = phandle->charts[i];
5166 if (count_changed) {
5170 const std::vector<double> &UV = mt_chart->
uv_matrices;
5171 for (
v = chart->verts;
v;
v =
v->nextlink) {
5187 for (
v = chart->verts;
v;
v =
v->nextlink) {
5199static void slim_free_matrix_transfer(ParamHandle *phandle)
5201 delete phandle->slim_mt;
5202 phandle->slim_mt =
nullptr;
5205static void slim_get_pinned_vertex_data(ParamHandle *phandle,
5212 std::vector<int> &selected_pins = pinned_vertex_data.
selected_pins;
5214 pinned_vertex_indices.clear();
5215 pinned_vertex_positions_2D.clear();
5216 selected_pins.clear();
5228 selected_pins.push_back(be->vert->slim_id);
5231 pinned_vertex_indices.push_back(be->vert->slim_id);
5232 pinned_vertex_positions_2D.push_back(be->vert->uv[0]);
5233 pinned_vertex_positions_2D.push_back(be->vert->uv[1]);
5236 }
while (be != outer);
5239 for (
v = chart->verts;
v;
v =
v->nextlink) {
5240 if (!
v->on_boundary_flag && (
v->flag &
PVERT_PIN)) {
5245 selected_pins.push_back(
v->slim_id);
5247 pinned_vertex_indices.push_back(
v->slim_id);
5248 pinned_vertex_positions_2D.push_back(
v->uv[0]);
5249 pinned_vertex_positions_2D.push_back(
v->uv[1]);
5270 slim_transfer_data_to_slim(phandle, slim_options);
5275 slim_flush_uvs(phandle, mt, count_changed, count_failed);
5276 slim_free_matrix_transfer(phandle);
5280 UNUSED_VARS(phandle, slim_options, count_changed, count_failed);
5287 slim_transfer_data_to_slim(phandle, slim_options);
5290 for (
int i = 0; i < phandle->
ncharts; i++) {
5296 for (
int i = 0; i < phandle->
ncharts; i++) {
5300 bool select =
false, deselect =
false;
5315 if (!
select || !deselect) {
5334 for (
int i = 0; i < phandle->
ncharts; i++) {
5335 mt->
charts[i].parametrize_single_iteration();
5340 slim_flush_uvs(phandle, mt,
nullptr,
nullptr);
5352 for (
int i = 0; i < phandle->
ncharts; i++) {
5356 if (!mt_chart.
data) {
5366 const bool live =
true;
5367 slim_flush_uvs(phandle, mt,
nullptr,
nullptr, live);
5378 for (
int i = 0; i < phandle->
ncharts; i++) {
5383 slim_free_matrix_transfer(phandle);
5392 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
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void * BLI_memarena_calloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
#define BLI_MEMARENA_STD_BUFSIZE
void 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)
typedef double(DMatrix)[4][4]
@ ED_UVPACK_MARGIN_SCALED
@ ED_UVPACK_ROTATION_NONE
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.
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 rotation, 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
local_group_size(16, 16) .push_constant(Type b
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
LinearSolver * EIG_linear_solver_new(int num_rows, int num_columns, int num_rhs)
LinearSolver * EIG_linear_least_squares_solver_new(int num_rows, int num_columns, int num_rhs)
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)
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_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
void *(* MEM_dupallocN)(const void *vmemh)
ccl_device_inline float3 cos(float3 v)
ccl_device_inline float4 select(const int4 mask, const float4 a, const float4 b)
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)
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
_W64 unsigned int uintptr_t
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
ccl_device_inline float beta(float x, float y)
#define UNUSED_FUNCTION_NO_SLIM
#define PHASH_hash(ph, item)
#define PHASH_edge(v1, v2)
#define PEDGE_VERTEX_FLAGS
#define param_warning(message)