Function to 'pinch' a mesh

I wonder if someone here can help me again.

I need to devise a general-purpase function to ‘pinch’ a 3D mesh of points - turning a Cylinder (which I can generate np) into an hour-glass shape.

Any suggestions?

Look into free-form deformations (FFD).

Thanks, but I’m sure there must be a simpler way.

First convert the vertices into cylindrical coordinates (r, phi, z). That is, (r, phi) are the polar coordinates in the (x,y)-plane and z is unchanged.

Then just modify r as a function of z, for example:
r’ := r * |z|

That one would give exactly an hourglass shape with radius 0 at z = 0, unchanged radius at |z| = 1, increased radius farther away. Of course, that might not be exactly what you want, play around with the exact formula you want.

Finally, convert the coordinates back to cartesian form…

EDIT: Just noticed, if your function is as simple as mine, and doesn’t involve the radius in a non-linear way, you don’t need to convert to cylinder coordinates, it’s sufficient to scale x and y. The conversion to cylindrical coordinates is only needed for more complicated deformations.

Won’t that simply produce a linear decrease in scaling towards Z = 0 ?

r’ = r * (z * z) seems closer, but the results aren’t right either.

I’m not sure what you mean by “hour-glass shape”, but a linear decrease in scaling sounds about right to me :wink:

Nope, I need a curved decrease to z = 0. Like…erm…an hourglass.


In theory, you can get any curve you want with the same method (if you’re satisfied with linear scale):

x’ := x * f(z)
y’ := y * f(z)

You can set any function for f. Most likely a polynomial will suffice. Draw the shape you want on a piece of paper and try to interpolate…

Also you might have a look at bezier curves or splines. Basically they are polynomials, too, but it’s a bit easier to get exactly the curve you want.

Or try the height–dependent radius r(z)=1.1 + cos(z - 0.5sin(z)) with z going from0 to 2PI. That’s how I imagine an hourglass.

Thanks dolf! That’s what I needed. A pinched tube:

Here’s my code for a y-axis pinch:

float y = pV.mY;
float radius = 1.0f - (mScale * cos(y + 0.5f * sin(y)));
pV.mX *= radius;
pV.mZ *= radius;

Where pV is a point on the surface and mScale is a value between 0 (no pinch) and 1.0f. Example image shows mScale at 0.75.