Vex: How to proportionally conform a shape to rectangle?

   616   4   2
User Avatar
Member
90 posts
Joined: 8月 2017
Offline
Say we start with an irregular 4-sided UV island, and our goal would be to pull its 4 points to desired new positions and straighten out the boundary edge.

What technique/concept could be used that would distribute their internal points proportionally to the deformations performed on the boundary edge? (assuming it's even a multi-step process)

Attachments:
2D_reshape.png (1023.3 KB)

User Avatar
Member
705 posts
Joined: 9月 2013
Offline
The uv flatten-node features straightening edge groups:
https://www.sidefx.com/docs/houdini/nodes/sop/uvflatten.html [www.sidefx.com]
https://procegen.konstantinmagnus.de/ [procegen.konstantinmagnus.de]
User Avatar
Member
705 posts
Joined: 9月 2013
Offline
A custom setup to straighten UVs into a rectangle could be:

  1. Identify corners by points neighbour count with
    neighbourcount(0,@ptnum)==3
  2. Position corner points into UV corners with
    v@uv = rint(v@uv);
  3. Convert boundary edges to curve and smooth it while pinning the corners
  4. Copy boundary UV positions using corresponding point IDs
  5. Smooth non-boundary UVs until they are regularized
Edited by Konstantin Magnus - 2025年5月16日 10:53:12

Attachments:
UV_rectangular.hip (274.3 KB)

https://procegen.konstantinmagnus.de/ [procegen.konstantinmagnus.de]
User Avatar
Member
64 posts
Joined: 4月 2008
Offline
alexmajewski
Say we start with an irregular 4-sided UV island, and our goal would be to pull its 4 points to desired new positions and straighten out the boundary edge.

What technique/concept could be used that would distribute their internal points proportionally to the deformations performed on the boundary edge? (assuming it's even a multi-step process)
Image Not Found
Or you can try this.

Attachments:
uv_normalize.hip (844.7 KB)

User Avatar
Member
90 posts
Joined: 8月 2017
Offline
Thank you both very creative solutions that will fit 99% of use cases. The spark that ignited my question was trying to get a triangulated cone-shaped flower petal to have a rectangular UV.

I was fishing for a vex solution in the title, because the described situation is only the first step and I was going to expand this problem. What if we wanted to straighten only the sides and not the top and bottom parts of the island? What if we wanted the corner points to be arbitrary and exist only as a Python state in the viewport?

I'm basically trying to create a UV space lattice.

Yesterday I learned about quadrilateral interpolation [www.reedbeta.com]. I'm not a math person, so I only understand the core concept.

Here's what I got so far. I work on a point attribute UV to make it easier for myself for now.
The first point wrangle calculates the local uv of each point that will be used to recreate its position with interpolation
// corner points clockwise
i@pt0 = 90;
i@pt1 = 99;
i@pt2 = 9;
i@pt3 = 0;

float wedge2d(vector a; vector b) {
    return a.x * b.y - a.y * b.x;
}

vector2 invert_bilinear(vector p0, p1, p2, p3; vector q)
{
    vector b1 = p1 - p0;
    vector b2 = p3 - p0;
    vector b3 = p0 - p1 - p3 + p2;

    float A = wedge2d(b2, b3);
    float B = wedge2d(b3, q) - wedge2d(b1, b2);
    float C = wedge2d(b1, q);

    float v;
    if (abs(A) < 1e-5) {
        v = -C / B;
    } else {
        float discrim = B*B - 4*A*C;
        v = 0.5 * (-B + sqrt(discrim)) / A;
    }

    vector denom = b1 + v * b3;
    float u;
    if (abs(denom.x) > abs(denom.y))
        u = (q.x - b2.x * v) / denom.x;
    else
        u = (q.y - b2.y * v) / denom.y;

    return set(u, v);
}


vector uv0 = point(0, "uv", i@pt0);
vector uv1 = point(0, "uv", i@pt1);
vector uv2 = point(0, "uv", i@pt2);
vector uv3 = point(0, "uv", i@pt3);

vector q = v@uv - uv0;

u@local_uv = invert_bilinear(uv0, uv1, uv2, uv3, q);

Then I displace my corners.

Then in another point wrangle I apply the interpolation against my new corner positions:
vector uv0 = point(0, "uv", i@pt0);
vector uv1 = point(0, "uv", i@pt1);
vector uv2 = point(0, "uv", i@pt2);
vector uv3 = point(0, "uv", i@pt3);

vector pu0 = lerp(uv0, uv1, u@local_uv.x);
vector pu1 = lerp(uv3, uv2, u@local_uv.x);
vector new_uv = lerp(pu0, pu1, u@local_uv.y);

v@uv = new_uv;

So far it seems to work perfectly as long as the affected UV points are between the 4 points.

So my current workflow would involve straightening desired edges with UV Flatten and then stretching them with vex. At least, as long as I don't figure out how to straighten them with vex. I'm attaching a hip.
Edited by alexmajewski - 2025年5月17日 04:27:49

Attachments:
demo.gif (2.6 MB)
UV_quadrilateral_interpolation_vex.hiplc (228.1 KB)

  • Quick Links