Cleanup: remove unused area smoothing logic for UV unwrap

This used to run when holding Shift while unwrapping until 2006 when it
was removed [0].

[0]: e66b5e5cd5

Reviewed By: brecht

Ref D15075
This commit is contained in:
Chris Blackbourn 2022-06-02 09:43:04 +10:00 committed by Campbell Barton
parent 68150b666c
commit b450a8c851
2 changed files with 0 additions and 565 deletions

View File

@ -87,14 +87,6 @@ void GEO_uv_parametrizer_stretch_end(ParamHandle *handle);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Area Smooth
* \{ */
void GEO_uv_parametrizer_smooth_area(ParamHandle *handle);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Packing
* \{ */

View File

@ -3819,545 +3819,6 @@ static void p_chart_rotate_fit_aabb(PChart *chart)
}
}
/* Area Smoothing */
/* 2d BSP tree for inverse mapping - that's a bit silly. */
typedef struct SmoothTriangle {
float co1[2], co2[2], co3[2];
float oco1[2], oco2[2], oco3[2];
} SmoothTriangle;
typedef struct SmoothNode {
struct SmoothNode *c1, *c2;
SmoothTriangle **tri;
float split;
int axis, ntri;
} SmoothNode;
static void p_barycentric_2d(
const float v1[2], const float v2[2], const float v3[2], const float p[2], float b[3])
{
float a[2], c[2], h[2], div;
a[0] = v2[0] - v1[0];
a[1] = v2[1] - v1[1];
c[0] = v3[0] - v1[0];
c[1] = v3[1] - v1[1];
div = a[0] * c[1] - a[1] * c[0];
if (div == 0.0f) {
b[0] = 1.0f / 3.0f;
b[1] = 1.0f / 3.0f;
b[2] = 1.0f / 3.0f;
}
else {
h[0] = p[0] - v1[0];
h[1] = p[1] - v1[1];
div = 1.0f / div;
b[1] = (h[0] * c[1] - h[1] * c[0]) * div;
b[2] = (a[0] * h[1] - a[1] * h[0]) * div;
b[0] = 1.0f - b[1] - b[2];
}
}
static PBool p_triangle_inside(SmoothTriangle *t, float co[2])
{
float b[3];
p_barycentric_2d(t->co1, t->co2, t->co3, co, b);
if ((b[0] >= 0.0f) && (b[1] >= 0.0f) && (b[2] >= 0.0f)) {
co[0] = t->oco1[0] * b[0] + t->oco2[0] * b[1] + t->oco3[0] * b[2];
co[1] = t->oco1[1] * b[0] + t->oco2[1] * b[1] + t->oco3[1] * b[2];
return P_TRUE;
}
return P_FALSE;
}
static SmoothNode *p_node_new(
MemArena *arena, SmoothTriangle **tri, int ntri, float *bmin, float *bmax, int depth)
{
SmoothNode *node = BLI_memarena_alloc(arena, sizeof(*node));
int axis, i, t1size = 0, t2size = 0;
float split, /* mi, */ /* UNUSED */ mx;
SmoothTriangle **t1, **t2, *t;
node->tri = tri;
node->ntri = ntri;
if (ntri <= 10 || depth >= 15) {
return node;
}
t1 = MEM_mallocN(sizeof(*t1) * ntri, "PNodeTri1");
t2 = MEM_mallocN(sizeof(*t2) * ntri, "PNodeTri1");
axis = (bmax[0] - bmin[0] > bmax[1] - bmin[1]) ? 0 : 1;
split = 0.5f * (bmin[axis] + bmax[axis]);
for (i = 0; i < ntri; i++) {
t = tri[i];
if ((t->co1[axis] <= split) || (t->co2[axis] <= split) || (t->co3[axis] <= split)) {
t1[t1size] = t;
t1size++;
}
if ((t->co1[axis] >= split) || (t->co2[axis] >= split) || (t->co3[axis] >= split)) {
t2[t2size] = t;
t2size++;
}
}
if ((t1size == t2size) && (t1size == ntri)) {
MEM_freeN(t1);
MEM_freeN(t2);
return node;
}
node->tri = NULL;
node->ntri = 0;
MEM_freeN(tri);
node->axis = axis;
node->split = split;
/* mi = bmin[axis]; */ /* UNUSED */
mx = bmax[axis];
bmax[axis] = split;
node->c1 = p_node_new(arena, t1, t1size, bmin, bmax, depth + 1);
bmin[axis] = bmax[axis];
bmax[axis] = mx;
node->c2 = p_node_new(arena, t2, t2size, bmin, bmax, depth + 1);
return node;
}
static void p_node_delete(SmoothNode *node)
{
if (node->c1) {
p_node_delete(node->c1);
}
if (node->c2) {
p_node_delete(node->c2);
}
if (node->tri) {
MEM_freeN(node->tri);
}
}
static PBool p_node_intersect(SmoothNode *node, float co[2])
{
int i;
if (node->tri) {
for (i = 0; i < node->ntri; i++) {
if (p_triangle_inside(node->tri[i], co)) {
return P_TRUE;
}
}
return P_FALSE;
}
if (co[node->axis] < node->split) {
return p_node_intersect(node->c1, co);
}
return p_node_intersect(node->c2, co);
}
/* smoothing */
static int p_compare_float(const void *a_, const void *b_)
{
const float a = *(const float *)a_;
const float b = *(const float *)b_;
if (a < b) {
return -1;
}
if (a == b) {
return 0;
}
return 1;
}
static float p_smooth_median_edge_length(PChart *chart)
{
PEdge *e;
float *lengths = MEM_mallocN(sizeof(chart->edges) * chart->nedges, "PMedianLength");
float median;
int i;
/* ok, so I'm lazy */
for (i = 0, e = chart->edges; e; e = e->nextlink, i++) {
lengths[i] = p_edge_length(e);
}
qsort(lengths, i, sizeof(float), p_compare_float);
median = lengths[i / 2];
MEM_freeN(lengths);
return median;
}
static float p_smooth_distortion(PEdge *e, float avg2d, float avg3d)
{
float len2d = p_edge_uv_length(e) * avg3d;
float len3d = p_edge_length(e) * avg2d;
return (len3d == 0.0f) ? 0.0f : len2d / len3d;
}
static void p_smooth(PChart *chart)
{
PEdge *e;
PVert *v;
PFace *f;
int j, it2, maxiter2, it;
int nedges = chart->nedges, nwheel, gridx, gridy;
int edgesx, edgesy, nsize, esize, i, x, y, maxiter;
float minv[2], maxv[2], median, invmedian, avglen2d, avglen3d;
float center[2], dx, dy, *nodes, dlimit, d, *oldnodesx, *oldnodesy;
float *nodesx, *nodesy, *hedges, *vedges, climit, moved, padding;
SmoothTriangle *triangles, *t, *t2, **tri, **trip;
SmoothNode *root;
MemArena *arena;
if (nedges == 0) {
return;
}
p_chart_uv_bbox(chart, minv, maxv);
median = p_smooth_median_edge_length(chart) * 0.10f;
if (median == 0.0f) {
return;
}
invmedian = 1.0f / median;
/* compute edge distortion */
avglen2d = avglen3d = 0.0;
for (e = chart->edges; e; e = e->nextlink) {
avglen2d += p_edge_uv_length(e);
avglen3d += p_edge_length(e);
}
avglen2d /= nedges;
avglen3d /= nedges;
for (v = chart->verts; v; v = v->nextlink) {
v->u.distortion = 0.0;
nwheel = 0;
e = v->edge;
do {
v->u.distortion += p_smooth_distortion(e, avglen2d, avglen3d);
nwheel++;
e = e->next->next->pair;
} while (e && (e != v->edge));
v->u.distortion /= nwheel;
}
/* need to do excessive grid size checking still */
center[0] = 0.5f * (minv[0] + maxv[0]);
center[1] = 0.5f * (minv[1] + maxv[1]);
dx = 0.5f * (maxv[0] - minv[0]);
dy = 0.5f * (maxv[1] - minv[1]);
padding = 0.15f;
dx += padding * dx + 2.0f * median;
dy += padding * dy + 2.0f * median;
gridx = (int)(dx * invmedian);
gridy = (int)(dy * invmedian);
minv[0] = center[0] - median * gridx;
minv[1] = center[1] - median * gridy;
maxv[0] = center[0] + median * gridx;
maxv[1] = center[1] + median * gridy;
/* create grid */
gridx = gridx * 2 + 1;
gridy = gridy * 2 + 1;
if ((gridx <= 2) || (gridy <= 2)) {
return;
}
edgesx = gridx - 1;
edgesy = gridy - 1;
nsize = gridx * gridy;
esize = edgesx * edgesy;
nodes = MEM_mallocN(sizeof(float) * nsize, "PSmoothNodes");
nodesx = MEM_mallocN(sizeof(float) * nsize, "PSmoothNodesX");
nodesy = MEM_mallocN(sizeof(float) * nsize, "PSmoothNodesY");
oldnodesx = MEM_mallocN(sizeof(float) * nsize, "PSmoothOldNodesX");
oldnodesy = MEM_mallocN(sizeof(float) * nsize, "PSmoothOldNodesY");
hedges = MEM_mallocN(sizeof(float) * esize, "PSmoothHEdges");
vedges = MEM_mallocN(sizeof(float) * esize, "PSmoothVEdges");
if (!nodes || !nodesx || !nodesy || !oldnodesx || !oldnodesy || !hedges || !vedges) {
if (nodes) {
MEM_freeN(nodes);
}
if (nodesx) {
MEM_freeN(nodesx);
}
if (nodesy) {
MEM_freeN(nodesy);
}
if (oldnodesx) {
MEM_freeN(oldnodesx);
}
if (oldnodesy) {
MEM_freeN(oldnodesy);
}
if (hedges) {
MEM_freeN(hedges);
}
if (vedges) {
MEM_freeN(vedges);
}
// printf("Not enough memory for area smoothing grid");
return;
}
for (x = 0; x < gridx; x++) {
for (y = 0; y < gridy; y++) {
i = x + y * gridx;
nodesx[i] = minv[0] + median * x;
nodesy[i] = minv[1] + median * y;
nodes[i] = 1.0f;
}
}
/* embed in grid */
for (f = chart->faces; f; f = f->nextlink) {
PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
float fmin[2], fmax[2];
int bx1, by1, bx2, by2;
INIT_MINMAX2(fmin, fmax);
minmax_v2v2_v2(fmin, fmax, e1->vert->uv);
minmax_v2v2_v2(fmin, fmax, e2->vert->uv);
minmax_v2v2_v2(fmin, fmax, e3->vert->uv);
bx1 = (int)((fmin[0] - minv[0]) * invmedian);
by1 = (int)((fmin[1] - minv[1]) * invmedian);
bx2 = (int)((fmax[0] - minv[0]) * invmedian + 2);
by2 = (int)((fmax[1] - minv[1]) * invmedian + 2);
for (x = bx1; x < bx2; x++) {
for (y = by1; y < by2; y++) {
float p[2], b[3];
i = x + y * gridx;
p[0] = nodesx[i];
p[1] = nodesy[i];
p_barycentric_2d(e1->vert->uv, e2->vert->uv, e3->vert->uv, p, b);
if ((b[0] > 0.0f) && (b[1] > 0.0f) && (b[2] > 0.0f)) {
nodes[i] = e1->vert->u.distortion * b[0];
nodes[i] += e2->vert->u.distortion * b[1];
nodes[i] += e3->vert->u.distortion * b[2];
}
}
}
}
/* smooth the grid */
maxiter = 10;
climit = 0.00001f * nsize;
for (it = 0; it < maxiter; it++) {
moved = 0.0f;
for (x = 0; x < edgesx; x++) {
for (y = 0; y < edgesy; y++) {
i = x + y * gridx;
j = x + y * edgesx;
hedges[j] = (nodes[i] + nodes[i + 1]) * 0.5f;
vedges[j] = (nodes[i] + nodes[i + gridx]) * 0.5f;
/* we do *inverse* mapping */
hedges[j] = 1.0f / hedges[j];
vedges[j] = 1.0f / vedges[j];
}
}
maxiter2 = 50;
dlimit = 0.0001f;
for (it2 = 0; it2 < maxiter2; it2++) {
d = 0.0f;
memcpy(oldnodesx, nodesx, sizeof(float) * nsize);
memcpy(oldnodesy, nodesy, sizeof(float) * nsize);
for (x = 1; x < gridx - 1; x++) {
for (y = 1; y < gridy - 1; y++) {
float p[2], oldp[2], sum1, sum2, diff[2], length;
i = x + gridx * y;
j = x + edgesx * y;
oldp[0] = oldnodesx[i];
oldp[1] = oldnodesy[i];
sum1 = hedges[j - 1] * oldnodesx[i - 1];
sum1 += hedges[j] * oldnodesx[i + 1];
sum1 += vedges[j - edgesx] * oldnodesx[i - gridx];
sum1 += vedges[j] * oldnodesx[i + gridx];
sum2 = hedges[j - 1];
sum2 += hedges[j];
sum2 += vedges[j - edgesx];
sum2 += vedges[j];
nodesx[i] = sum1 / sum2;
sum1 = hedges[j - 1] * oldnodesy[i - 1];
sum1 += hedges[j] * oldnodesy[i + 1];
sum1 += vedges[j - edgesx] * oldnodesy[i - gridx];
sum1 += vedges[j] * oldnodesy[i + gridx];
nodesy[i] = sum1 / sum2;
p[0] = nodesx[i];
p[1] = nodesy[i];
diff[0] = p[0] - oldp[0];
diff[1] = p[1] - oldp[1];
length = len_v2(diff);
d = max_ff(d, length);
moved += length;
}
}
if (d < dlimit) {
break;
}
}
if (moved < climit) {
break;
}
}
MEM_freeN(oldnodesx);
MEM_freeN(oldnodesy);
MEM_freeN(hedges);
MEM_freeN(vedges);
/* Create BSP. */
t = triangles = MEM_mallocN(sizeof(SmoothTriangle) * esize * 2, "PSmoothTris");
trip = tri = MEM_mallocN(sizeof(SmoothTriangle *) * esize * 2, "PSmoothTriP");
if (!triangles || !tri) {
MEM_freeN(nodes);
MEM_freeN(nodesx);
MEM_freeN(nodesy);
if (triangles) {
MEM_freeN(triangles);
}
if (tri) {
MEM_freeN(tri);
}
// printf("Not enough memory for area smoothing grid");
return;
}
for (x = 0; x < edgesx; x++) {
for (y = 0; y < edgesy; y++) {
i = x + y * gridx;
t->co1[0] = nodesx[i];
t->co1[1] = nodesy[i];
t->co2[0] = nodesx[i + 1];
t->co2[1] = nodesy[i + 1];
t->co3[0] = nodesx[i + gridx];
t->co3[1] = nodesy[i + gridx];
t->oco1[0] = minv[0] + x * median;
t->oco1[1] = minv[1] + y * median;
t->oco2[0] = minv[0] + (x + 1) * median;
t->oco2[1] = minv[1] + y * median;
t->oco3[0] = minv[0] + x * median;
t->oco3[1] = minv[1] + (y + 1) * median;
t2 = t + 1;
t2->co1[0] = nodesx[i + gridx + 1];
t2->co1[1] = nodesy[i + gridx + 1];
t2->oco1[0] = minv[0] + (x + 1) * median;
t2->oco1[1] = minv[1] + (y + 1) * median;
t2->co2[0] = t->co2[0];
t2->co2[1] = t->co2[1];
t2->oco2[0] = t->oco2[0];
t2->oco2[1] = t->oco2[1];
t2->co3[0] = t->co3[0];
t2->co3[1] = t->co3[1];
t2->oco3[0] = t->oco3[0];
t2->oco3[1] = t->oco3[1];
*trip = t;
trip++;
t++;
*trip = t;
trip++;
t++;
}
}
MEM_freeN(nodes);
MEM_freeN(nodesx);
MEM_freeN(nodesy);
arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "param smooth arena");
root = p_node_new(arena, tri, esize * 2, minv, maxv, 0);
for (v = chart->verts; v; v = v->nextlink) {
if (!p_node_intersect(root, v->uv)) {
param_warning("area smoothing error: couldn't find mapping triangle\n");
}
}
p_node_delete(root);
BLI_memarena_free(arena);
MEM_freeN(triangles);
}
/* Exported */
ParamHandle *GEO_uv_parametrizer_construct_begin(void)
@ -4702,24 +4163,6 @@ void GEO_uv_parametrizer_stretch_end(ParamHandle *phandle)
phandle->rng = NULL;
}
void GEO_uv_parametrizer_smooth_area(ParamHandle *phandle)
{
int i;
param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED);
for (i = 0; i < phandle->ncharts; i++) {
PChart *chart = phandle->charts[i];
PVert *v;
for (v = chart->verts; v; v = v->nextlink) {
v->flag &= ~PVERT_PIN;
}
p_smooth(chart);
}
}
/* don't pack, just rotate (used for better packing) */
static void GEO_uv_parametrizer_pack_rotate(ParamHandle *phandle, bool ignore_pinned)
{