OpenGL Glut C - хочу сделать изогнутый цилиндр - PullRequest
0 голосов
/ 22 октября 2018

Следующий код показывает прямой цилиндр / трубу на языке 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;
}

В данный момент он рисует прямой цилиндр / трубу.И я хотел изогнуть его так, чтобы он выглядел как this .

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Сначала я рекомендую разделить цилиндр на ломтики.Следующий конус нарисует точно такой же цилиндр, но он разбивает цилиндр на части.Срезы имеют разные цвета для визуализации эффекта.

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_ang0 до bend_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();
}

0 голосов
/ 22 октября 2018

В настоящее время вы рисуете всю высоту цилиндра за один раз ... чтобы создать изогнутую поверхность, вместо этого вы должны взять существующий код и создать последовательность маленьких цилиндров, каждый из которых имеет небольшую высоту, а затем сложить их допотреблять исходную высоту.

Один из подходов состоит в том, чтобы ввести новую функцию, которая становится родителем вашей

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 устарел и его следует избегать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...