So I'm playing around with OpenGL and trying to figure out how to draw some fun shapes.
Right now, I'm working on a tube. I can draw a straight tube just fine with:
void tube(GLfloat radius, GLfloat segment_length) {
glPolygonMode(GL_BACK, GL_NONE);
glPolygonMode(GL_FRONT, GL_FILL);
glPushMatrix(); {
GLfloat z1 = 0.0;
GLfloat z2 = segment_length;
GLfloat y_offset = 0.0;
GLfloat y_change = 0.00;
int i = 0;
int j = 0;
for (j = 0; j < 20; j++) {
glPushMatrix(); {
glBegin(GL_TRIANGLE_STRIP); {
for (i = 360; i >= 0; i--) {
GLfloat theta = i * pi/180;
GLfloat x = radius * cos(theta);
GLfloat y = radius * sin(theta) + y_offset;
glVertex3f(x, y, z1);
glVertex3f(x, y, z2);
}
} glEnd();
} glPopMatrix();
// attach the front of the next segment to the back of the previous
z1 = z2;
z2 += segment_length;
// make some other adjustments
y_offset += y_change;
}
} glPopMatrix();
}
However, I haven't figured out how to make the tube follow any predefined path like a spiral, or even a simple line. If you change y_change to something like 0.01, it will draw each tube segment offset an additional 0.01 in the y direction. That great, but how can I make each segment point in that direction? In other words, right now, each segment is drawn so that they all face the same direction, and the direction is not the direction of the tube (since with y_change = 0.01, the direction is slightly "up").
I'm not sure how to proceed. I've played with vectors by getting the vector between the previous segment and the current one, but I'm not really sure what to do with it past that.
The idea is called path controlled extrusion, i.e. you have a basic n dimensional shape and extrude it along a n+1 dimensional curve. I can read your face: "Huh, what is he saying?"
So here's a coarse outline. First you need a function that maps a value, usually called t, to a continous, smooth curve in space. For example a screw:
path(t): R → R³, t ↦ ( a·sin(k·t), b·cos(k·t), c·t )
The idea is, to find a localized coordinate base to define your vertices positions in relation to that path - it makes sense, that one of the coordinate is aligned in parallel to the path, so you want to find it's tangent. This is done by finding its gradient:
tangent(t): R → R³, t ↦ ( k·a·cos(k·t), -k·b·sin(k·t), c ) = d/dt path(t)
So this is the local base vector that's pointing along the curve, with the origin of the local coordinate system at the point t
of the curve.
But we need two other vectors, to form a full 3d base. It is usually a good choice to have the second base point perpendicular to the curvature, which you get by finding the curl of the tangent:
normal(t): R → R³, t ↦ ( -k²·a·sin(k·t), -k²·b·cos(k·t), 0 ) = d/dt tangent(t) = d²/dt² path(t)
This is called the normal.
The thrid base vector can be obtained, taking the cross product of normal and tangent, yielding the binormal. I'll let you figure that one out as an exercise.
Now to extrude a shape along the curve, you've to split the path into segments, simply by iterating t
over a choosen range, giving you the local origin. The points of your extruded shape are relative to this origin path(t). Let's say your shape consists of the points P_n in the x-y plane then:
for t in [k..l]:
for p in P_n:
yield_vertex( path(t).x + binormal(t).x * p.x,
path(t).y + normal(t).y * p.y,
path(t).z )
I'll leave it to you, figuring out how to adapt this to OpenGL, after all you should learn something by thinking about it. If you can't solve it until tomorrow, I'll gladly give you the solution, but it's usually more fun figuring things out by your own.
Reduce it to a previously-solved problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With