OpenGL Glut C - 想要渲染曲面圆柱

6
下面的代码展示了OpenGL C语言中的一个直立的圆柱/管道。
 #include <stdio.h>
 #include <stdlib.h>
 #include <GL/glut.h>
 #include <math.h>
 #define PI 3.1415927

void draw_cylinder(GLfloat radius, GLfloat height, GLubyte R, GLubyte G, GLubyte B)
{
    GLfloat x = 0.0;
    GLfloat y = 0.0;
    GLfloat angle = 0.0;
    GLfloat angle_stepsize = 0.1;

    // Draw the tube
    glColor3ub(R-40,G-40,B-40);
    glBegin(GL_QUAD_STRIP);
        angle = 0.0;
        while( angle < 2*PI ) {
            x = radius * cos(angle);
            y = radius * sin(angle);
            glVertex3f(x, y , height);
            glVertex3f(x, y , 0.0);
            angle = angle + angle_stepsize;
        }
        glVertex3f(radius, 0.0, height);
        glVertex3f(radius, 0.0, 0.0);
    glEnd();

    // Draw the circle on top of cylinder
    glColor3ub(R,G,B);
    glBegin(GL_POLYGON);
        angle = 0.0;
        while( angle < 2*PI ) {
            x = radius * cos(angle);
            y = radius * sin(angle);
            glVertex3f(x, y , height);
            angle = angle + angle_stepsize;
        }
        glVertex3f(radius, 0.0, height);
    glEnd();
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();

    glTranslatef(-0.5,0.0,-2.5);
    glRotatef(100.0, 0.725, 1.0, 1.0);

    draw_cylinder(0.15, 1.0, 255, 160, 100);

    glFlush();
}

void reshape(int width, int height)
{    
    if (width == 0 || height == 0) return;

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(35.0, (GLdouble)width/(GLdouble)height,0.5, 20.0);

    glMatrixMode(GL_MODELVIEW);
    glViewport(0, 0, width, height);
}    

int main(int argc, char **argv)
{    
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(640,580);
    glutCreateWindow("Create Cylinder");
    glClearColor(0.0,0.0,0.0,0.0);
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);

    glutMainLoop();

    return 0;
}

目前它绘制的是一个直筒/管道。我想将其弯曲,使它看起来像这样


请参考 https://dev59.com/-pPfa4cB1Zd3GeqPDXJE#35055911 获取一些灵感。 - Spektre
2个回答

2

首先,我建议将圆柱体分成若干片。下面的圆锥体会画出完全相同的圆柱体,但它将圆柱体分成了若干片。为了更好地可视化效果,每个片段都有不同的颜色。

GLfloat h0, h1, angle, x, y;
int i, j;

int     slices      = 8;

for ( i = 0; i < slices; i++ )
{
    h0 = (float)i / (float)slices;
    h1 = (float)(i+1) / (float)slices;

    glColor3f( 1.0f-h0, 0.0, h1 );
    glBegin(GL_QUAD_STRIP);
        for ( j = 0; j <= 360; ++ j )
        {
            angle = PI * (float)j * PI / 180.0f;
            x = radius * cos(angle);
            y = radius * sin(angle);
            glVertex3f( x, y, h0 );
            glVertex3f( x, y, h1 );
        }
    glEnd();
}

接下来,您需要定义弯曲半径和弯曲起始和结束角度。以下代码绘制了一个从bend_ang0bend_ang1的弯曲管道,半径为bend_radius。弯曲角度可以根据弯曲半径和管道长度计算得出:

GLfloat w0, w1, ang0, ang1, angle, x, y, xb, yb, zb;
int i, j;

int     slices      = 8;
GLfloat bend_radius = 1.0f;

GLfloat bend_angle, bend_ang0, bend_ang1; 

bend_angle = bend_radius * height;
bend_ang0  = -bend_angle/2.0f;
bend_ang1  = bend_angle/2.0f;

for ( i = 0; i < slices; i++ )
{
    w0 = (float)i / (float)slices;
    w1 = (float)(i+1) / (float)slices;

    ang0 = bend_ang0 + (bend_ang1-bend_ang0) * w0;
    ang1 = bend_ang0 + (bend_ang1-bend_ang0) * w1;

    glColor3f( 1.0f-w0, 0.0, w1 );
    glBegin(GL_QUAD_STRIP);

        for ( j = 0; j <= 360; ++ j )
        {
            angle = PI * (float)j * PI / 180.0f;
            x = radius * cos(angle) + bend_radius;
            y = radius * sin(angle);

            xb = sin( ang0 ) * x;
            yb = y;
            zb = cos( ang0 ) * x;
            glVertex3f( xb, yb, zb );

            xb = sin( ang1 ) * x;
            yb = y;
            zb = cos( ang1 ) * x;
            glVertex3f( xb, yb, zb );
        }
    glEnd();
}

对于以下图像,我激活了深度测试并更改了模型视图矩阵:

void display(void)
{
    glEnable( GL_DEPTH_TEST );
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();
    glTranslatef(0.0f, -0.5f, -4.0f);
    glRotatef(-90.0f, 1.0f, 0.0, 0.0f);

    draw_cylinder(0.15, 2.0, 255, 160, 100);

    glFlush();
}


1

目前您是一次性绘制整个圆柱的高度...要创建曲面,您必须改用现有代码,并使其创建一系列微小圆柱,每个圆柱都具有微小高度,然后将它们堆叠起来以使用原始高度。

一种方法是引入一个新函数,它成为现有函数的父级

void draw_cylinder(GLfloat radius, GLfloat height, GLubyte R, GLubyte G, GLubyte B)

也许称其为


draw_curved_cylinder

在这个新函数中,你有一个循环,在其中调用draw_cylinder并给出每个小圆柱体的参数...目前你的绘制函数盲目地将高度从0拉伸到给定的height...将其替换为给定小圆柱体的设置...另外,为了使最终的圆柱体弯曲,每个小圆柱体的X和Y坐标必须沿着弯曲的轨迹变化,所以在那个新函数draw_curved_cylinder中递增它们,使它们随着合成每个新的小圆柱体而变化。
PS-请注意,您没有使用现代OpenGL-glBegin已过时,应避免使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接