Procedurally drawing a tube.

Started by
6 comments, last by tksuoran 13 years, 9 months ago
This has been bothering me for years and I still can't figure it out. How does one draw a tube along a curve? I'm talking about how in all these demoscene demos they draw tentacles and tubes spawning out from somewhere and growing along a curve. How is that procedurally generated?

One idea I had was to create points around the tangent of the curve, but how would you keep the angle constant, would you just have one up vector and just rotate off of that? So maybe tessellate it with like 10 points all around to get a round object...

Another solution was to make it purely in shaders where you just make the color lighter as you go closer to the center of the curve so it just looks like it's round.

Am I over-thinking this? Does anyone have any ideas?
Advertisement
I can't comment directly on the shader-based method, but the best way to generate a 'tube' mesh (IMO) is to 'walk' along the medial spline using a 'parallel transport frame', generating successive 'rings' of vertices as you go.

I've discussed this in some detail in previous threads, so if you're interested in this method, I'd try searching the forums for 'parallel transform frame'. (You should be able to find some good references, I think.)
I did something like this a couple of years ago for a university project.
I went for the "rotate one vector approach", I had my curve defined as line segments, just a list of vectors, each giving the movement to the next point of the curve, so point_i = sum vector_i from 0 to i

For each pair of vectors, I calculated the tangent (just the average of both vectors), and the cross product, and created the "ring" by rotating the cross product using the tangent as rotation direction.
I recently made a tube for cubic Bezier curve in 3D. This may be useful:

http://neure.ath.cx/curve.html

specifically see CubicBezierCurveTube.cs. While this code is somewhat specific to cubic Bezier curves, it should be fairly easy to adapt it to any curve. Initially you may choose fixed parameter steps instead of adaptive subdivision, and you might just apply tube ring without any cusp detection. However, if there are any sharp turns (cusps), you will need some logic to detect problematic cases, and then how to deal with them.
Just found the article in GPU gems 2. So basically you use the previous tangent vector as a reference. Then you get the new tangent, calculate the cross product and get the third vector. Then based on the angle between the two tangents, you rotate around the third. That's perfect for a round object since I don't care about it banking.

And even if you want twisting and stuff, like in a ribbon, you can have another curve controlling the twist.

I'll post my code once I get home and write it.
Quote:Just found the article in GPU gems 2. So basically you use the previous tangent vector as a reference. Then you get the new tangent, calculate the cross product and get the third vector. Then based on the angle between the two tangents, you rotate around the third. That's perfect for a round object since I don't care about it banking.
Right, that's the 'parallel transport frame' I mentioned.
@jyk yup, thanks for pointing me in the right direction. For those with the same problem here are some links with more info.

@tksuoran yeah you're talking about a frenet frame approach where if the curve changes, i.e. 2nd derivative changes sign (I guess?) you don't know what side the tangent should be on. By reusing the previous tangent to find the cross product, you ensure that the frame stays consistent through sharp turns. If you're building geometry around the curve it's nice if the points stay consistently on the same side.

A paper that goes into a lot of mathematical detail and proofs:

"Parallel Transport Approach to Curve Framing" by Hanson and Ma

and the game programming gems 2 link(I know I said GPU gems above, disregard that):
http://books.google.com/books?id=M2QYbTVd0VgC&lpg=PA215&ots=K4t0eyqKVS&dq=parallel%20transport%20frame%20gems%202&pg=PA215#v=onepage&q&f=false
Quote:Original post by johnl87
@tksuoran yeah you're talking about a frenet frame approach where if the curve changes, i.e. 2nd derivative changes sign (I guess?) you don't know what side the tangent should be on. By reusing the previous tangent to find the cross product, you ensure that the frame stays consistent through sharp turns. If you're building geometry around the curve it's nice if the points stay consistently on the same side.

A paper that goes into a lot of mathematical detail and proofs:

"Parallel Transport Approach to Curve Framing" by Hanson and Ma


and the game programming gems 2 link(I know I said GPU gems above, disregard that):
http://books.google.com/books?id=M2QYbTVd0VgC&lpg=PA215&ots=K4t0eyqKVS&dq=parallel%20transport%20frame%20gems%202&pg=PA215#v=onepage&q&f=false

Thanks for the links! They are certainly good references, I shall have a more careful look at them soon. As a small clarification, I do not reuse tangent, I reuse normal. Perhaps we are talking about the same thing with different names?

My approach is to numerically compute approximation of the tangent (based on two nearby position values) and maintain 'current' normal of the curve. This indeed minimizes ring twists that happen, I think, at the inflection points, like you described it.

This topic is closed to new replies.

Advertisement