沿路径的OpenGL管

gre*_*ghz 5 c opengl

所以我正在玩OpenGL并试图弄清楚如何绘制一些有趣的形状.

现在,我正在做一个管子.我可以画直管很好用:

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();
}
Run Code Online (Sandbox Code Playgroud)

但是,我还没弄清楚如何使管子遵循任何预定义的路径,如螺旋线,甚至是简单的线.如果将y_change更改为0.01,则会在y方向上将每个管段偏移另外0.01.那太棒了,但我怎样才能让每个细分都指向那个方向呢?换句话说,现在,绘制每个线段使它们都面向相同的方向,并且方向不是管的方向(因为y_change = 0.01,方向略微"向上").

我不知道该怎么办.我通过获取前一个段和当前段之间的向量来玩向量,但我不确定如何处理过去.

dat*_*olf 19

这个想法被称为路径控制挤压,即你有一个基本的n维形状,并沿着n + 1维曲线挤出它.我能看清你的脸:"呃,他说的是什么?"

所以这是一个粗略的轮廓.首先,您需要一个将值(通常称为t)映射到空间中连续,平滑曲线的函数.例如螺丝:

path(t): R ? R³, t ? ( a·sin(k·t), b·cos(k·t), c·t )
Run Code Online (Sandbox Code Playgroud)

我们的想法是找到一个局部坐标基础来定义与该路径相关的顶点位置 - 有意义的是,其中一个坐标与路径平行对齐,因此您希望找到它的切线.这是通过找到它的梯度来完成的:

tangent(t): R ? R³, t ? ( k·a·cos(k·t), -k·b·sin(k·t), c ) = d/dt path(t)
Run Code Online (Sandbox Code Playgroud)

因此,这是指向曲线的局部基矢量,局部坐标系的原点t位于曲线点.

但我们需要另外两个向量,以形成一个完整的3d基础.将第二个基点垂直于曲率通常是一个不错的选择,通过找到切线的卷曲可以得到:

normal(t): R ? R³, t ? ( -k²·a·sin(k·t), -k²·b·cos(k·t), 0 ) = d/dt tangent(t) = d²/dt² path(t)
Run Code Online (Sandbox Code Playgroud)

这被称为正常.

可以获得第三个基本向量,取正态和正切的交叉乘积,得到二次正规.我会让你把这一个想象成一个练习.

现在要沿着曲线挤出一个形状,你只需要t在一个选择的范围内迭代,就可以将路径分割成段,从而为你提供本地原点.挤压形状的点相对于此原点路径(t).假设你的形状由xy平面中的点P_n组成:

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 )
Run Code Online (Sandbox Code Playgroud)

我会把它留给你,弄清楚如何使它适应OpenGL,毕竟你应该通过思考来学习一些东西.如果直到明天你才能解决它,我很乐意为你提供解决方案,但通常你自己解决问题会更有趣.

  • +1:很好的答案。如果你对分段线性函数感兴趣,你可以找到作为 v(n)(从最后一个点到这个点的向量)和 v(n+1)(从这个点开始的向量)的平均值的切线到下一个)。 (2认同)