I need to devise a function bends a mesh of points into a curve, depending on the angle entered. So an angle of 90 will turn a cylinder along the y-axis into a ring bending towards the x-axis. The function should not add new vertices, polygons or in anyway change the mesh structure to which it is applied. It should simply loop through the vertices and adjust their positions.
p1 = rot( p0, a * len( 0, p0 ))
where:
p0 input vertex
p1 output vertex
rot rotation around some axis
a amount of bending (0=none)
len distance of two points (0=origin)
in practice, this approach says:
please rotate this point around an axis, but as it gets farther from the origin (in the original mesh), rotate it more.
this means that an origin has to be specified, and that points at the origin won’t be affected.
in you exaple, you need a specific rotation function, one wich rotates around the z axis:
s = sin( a )
c = cos( a )
|X| |c -s| |x|
| | = | | * | |
|Y| |s c| |y|
if you’re in need of a bender like the tool in 3DSmax, then you do not want the sort of tapering you talk about…
because if you have your cylinder for example, when you bend it, it won’t resemble a torus as it should.
btw, mine is intended as just a quick specialized hack to give something to work on, and this can be the code:
Thanks, that’s pretty much the code I had (except I used the dot product between origin and p0, which was wrong).
I have a cylinder mesh centered at 0,0,0 extending from -1 to +1 on each axis. What values should I use to bend it into a torus, as you suggest? I can produce all manor of strange shapes, but the cylinder will NOT bend-in-on-itself as you would expect.
What values should I use for origin and amount? You say the origin is the center of the mesh (0,0,0), but that value results in no bend, and it seems that only y-axis values for origin result in a bend around x.
(I can also scale the mesh first to make it thinner, if that makes any difference).
the equation i suggested cannot in fact bend a cylinder to a torus: i’ve discovered it just yesterday.
to do it, a different equation and method is needed.
since it is an interesting topic, i’m going to find a good equation soon: once i have it, i’ll let you know.
I would imagine it would work something like this (for bending a Y-Axis-alingned cylinder around Z):
Translate point by R along X, where r is the circle radius.
Rotate point by angle A, computed from R and point’s Y position. The further the point is along Y, the greater the bend.
The trouble is, you need to careful with the sign of these components. The computed Angle, A, must always be positive, although this can be accomplished with a sqrt.
But the origin in this case is the center of the imaginary circle around which the shape is being bent. In my example it’s 0,0,0. The radius r, would determine the severity of the bend. The length of the cylinder must determine by how much it is bent. A long cylinder could be turned into a torus (with the right setting for r), but a short cylinder would look more like a wedge.
here’s my algorithm, it works as the one in 3DSmax:
V3 rot( V3 in, float angle ) {
float s = sin( angle );
float c = cos( angle );
return V3(
c*in.x - s*in.y,
s*in.x + c*in.y,
in.z
);
}
void bend( V3* out, V3* in, int count, float angle ) {
if( angle == 0 ) { // because it would mead a circle with infinite radius
memcpy( out, in, count*sizeof(out[0]));
return;
}
int i;
// find the mesh extension
float max = in[0].y;
for( i=0; i<count; i++ ) if( max < in[i].y ) max = in[i].y;
float cx = max / angle; // find center of rotation
for( i=0; i<count; i++ ) {
float a = in[i].y * angle / max; // amount of rotation depends on vertex position
V3 v = in[i];
v.y = 0;
v.x += cx;
v = rot( v, a );
v.x -= cx;
out[i] = v;
}
}
it works by first thinking of a vertical cylinder, starting from level 0 up to level max:
it takes one ring of vertices (same level), lower them to level 0, and rotates around the circle center by an amount linearly dependent on the level of the ring in the base mesh.
the code instead thinks in term of a y axis, instead of z.
this method extends to any shape, but the code it’s a prototype, it lacks some robustness…
the mesh axis (y in this case) is bent around a circle wich center has y and z coordinate fixed and set to 0.
the mesh extension calculation is not very much satisfying to me.
also, some benefit can be obtained from a more rigorous formulation, such as matrices… code tidyness at least.
to make a torus out of a cylinder, you can set the angle to M_2PI