使用 OpenGl 库在 C++ 中生成 2D 形状

2D shape in C++ by using the OpenGl library

我正在尝试使用 OpenGl 库在 C++ 中绘制形状 我写了下面的代码,但我得到的只是下面的形状):

但是我需要使用 glRotatef 来获得这个形状吗:?我该如何使用它?

这是我的代码:)

#include <Windows.h>
#include <GL\glew.h>
#include <GL\freeglut.h>
#include <iostream>
#include <math.h>
using namespace std;

float angle, radius, xx1, yy1;

int main(int argc, char** argv) {
    void Transform(void);
    void circle(void);
    void shape(void);
    void init(void);
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(400, 300);
    glutInitWindowPosition(50, 100);
    glutCreateWindow("MyShape");
    init();
    glutDisplayFunc(Transform); 
    glutMainLoop();
    return 0;
}

void init(void) {
    glClearColor(1.0, 1.0, 1.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0.0, 200.0, 0.0, 150.0);
}

void Transform(void){
    void shape();
    void circle(); 
        shape();
    glClear(GL_COLOR_BUFFER_BIT);
    glPushMatrix();
    glColor3f(1, 0, 0);
    glScalef(1.5, 1.5, 0);
    circle();   
    shape();
    glPopMatrix();
    glutSwapBuffers();
    glFlush();
}

void circle(void) {
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1, 0, 0); /* draw filled red circle*/
    xx1 = 60; yy1 = 40; radius = 20;
    glBegin(GL_TRIANGLE_FAN);  
    for (angle = 0; angle <= 360; angle++)
        glVertex2f(xx1 + sin(angle)*radius, yy1 + cos(angle)*radius);
    glEnd();
    glFlush();

}

void shape(void) {
    // Main rectangle
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glColor3f(0, 0, 1);
    glBegin(GL_POLYGON);  
    glVertex2i(55, 75);// left
    glVertex2i(60, 85); // top center
    glVertex2i(65, 75); // right
    glVertex2i(61, 50);// buttom right
    glVertex2i(59, 50);// buttom left
    glEnd();

    //rectangle right
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glColor3f(0, 0, 1);
    glBegin(GL_POLYGON);  
    glVertex2i(65, 72);// top left 
    glVertex2i(66, 69); //top right 
    glVertex2i(62, 50); // buttom right
    glVertex2i(61, 50); // buttom left
    glEnd();

    //rectangle left
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glColor3f(0, 0, 1);
    glBegin(GL_POLYGON); 
    glVertex2i(54, 70);// top left 
    glVertex2i(55, 72); //top right 
    glVertex2i(59, 50); // buttom right
    glVertex2i(58, 50); // buttom left
    glEnd();

    glFlush();
}

我稍微调整了你的代码:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

float aspect=float(xs)/float(ys);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0/aspect,aspect,0.1,100.0);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();

glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
int e;
float x0=60.0,y0=40.0,r=20.0,a,da=M_PI/36.0;
// move modelview to center of shape
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-x0,-y0,-4.0*r);
// render disc
glColor3f(1.0,0.0,0.0);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(x0,y0);
for (e=1,a=0.0;e;a+=da)
    {
    if (a>=2.0*M_PI) { e=0; a=0.0; }
    glVertex2f(x0+(r*sin(a)),y0+(r*cos(a)));
    }
glEnd();
// rotation symetry construct
glMatrixMode(GL_MODELVIEW); // store matrix in case you need it later or
glPushMatrix();
for (e=8,a=360.0/float(e);e>0;e--)
    {
    // render shape
    glColor3f(0.0,0.0,1.0);
    glBegin(GL_POLYGON);
    glVertex2i(55, 75);
    glVertex2i(60, 85);
    glVertex2i(65, 75);
    glVertex2i(61, 50);
    glVertex2i(59, 50);
    glEnd();
    glBegin(GL_POLYGON);
    glVertex2i(65, 72);
    glVertex2i(66, 69);
    glVertex2i(62, 50);
    glVertex2i(61, 50);
    glEnd();
    glBegin(GL_POLYGON);
    glVertex2i(54, 70);
    glVertex2i(55, 72);
    glVertex2i(59, 50);
    glVertex2i(58, 50);
    glEnd();
    glMatrixMode(GL_MODELVIEW);
    // rotate around(x0,y0)
    glTranslatef(+x0,+y0,0.0);
    glRotatef(a,0.0,0.0,1.0);
    glTranslatef(-x0,-y0,0.0);
    }
glMatrixMode(GL_MODELVIEW); // restore matrix in case you need it later or
glPopMatrix();

glFlush();
SwapBuffers(hdc);

所以我添加了 for 循环和围绕形状中心的旋转。此处结果:

xs,ys 是我的 window 透视相机设置的分辨率,hdc 是我的上下文。我还发现你在交换缓冲区后调用 flush 我之前会调用它。

[Edit1] 完整代码

我正在使用 BDS2006 C++ 因此代码使用 VCL(仅用于创建 window 和事件)没有 GLUT 或任何你必须更改的部分以匹配你的平台...该应用程序只是一个干净的表单,上面有一个计时器。

//---------------------------------------------------------------------------
#include <vcl.h> // you can ignore this
#include <math.h>
#pragma hdrstop // you can ignore this
#include "Unit1.h" // you can ignore this
#include "gl_simple.h" // this file is in next code chunk
//---------------------------------------------------------------------------
#pragma package(smart_init) // you can ignore this
#pragma resource "*.dfm" // you can ignore this
TForm1 *Form1; // you can ignore this its is just my window class
//---------------------------------------------------------------------------
void gl_draw() // this renders the scene
    {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    float aspect=float(xs)/float(ys);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0/aspect,aspect,0.1,100.0);
    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();

    glDisable(GL_DEPTH_TEST);
    glDisable(GL_TEXTURE_2D);
//  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    int e;
    float x0=60.0,y0=40.0,r=20.0,a,da=M_PI/36.0;
    // move modelview to center of shape
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(-x0,-y0,-4.0*r);
    // render disc
    glColor3f(1.0,0.0,0.0);
    glBegin(GL_TRIANGLE_FAN);
    glVertex2f(x0,y0);
    for (e=1,a=0.0;e;a+=da)
        {
        if (a>=2.0*M_PI) { e=0; a=0.0; }
        glVertex2f(x0+(r*sin(a)),y0+(r*cos(a)));
        }
    glEnd();
    // rotation symetry construct
    glMatrixMode(GL_MODELVIEW); // store matrix in case you need it later or
    glPushMatrix();
    for (e=8,a=360.0/float(e);e>0;e--)
        {
        // render shape
        glColor3f(0.0,0.0,1.0);
        glBegin(GL_POLYGON);
        glVertex2i(55, 75);
        glVertex2i(60, 85);
        glVertex2i(65, 75);
        glVertex2i(61, 50);
        glVertex2i(59, 50);
        glEnd();
        glBegin(GL_POLYGON);
        glVertex2i(65, 72);
        glVertex2i(66, 69);
        glVertex2i(62, 50);
        glVertex2i(61, 50);
        glEnd();
        glBegin(GL_POLYGON);
        glVertex2i(54, 70);
        glVertex2i(55, 72);
        glVertex2i(59, 50);
        glVertex2i(58, 50);
        glEnd();
        glMatrixMode(GL_MODELVIEW);
        // rotate around(x0,y0)
        glTranslatef(+x0,+y0,0.0);
        glRotatef(a,0.0,0.0,1.0);
        glTranslatef(-x0,-y0,0.0);
        }
    glMatrixMode(GL_MODELVIEW); // restore matrix in case you need it later or
    glPopMatrix();

    glFlush();
    SwapBuffers(hdc);
    }
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner) // constructor of my window
    {
    gl_init(Handle);
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender) // destructor of my window
    {
    gl_exit();
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender) // OnPaint event
    {
    gl_draw();
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender) // OnTimer event
    {
    gl_draw();
    }
//---------------------------------------------------------------------------

gl_simple.h 仅用于创建 GL 上下文,因此您可以忽略 VAOGLSL 东西。这里是源文件:

//---------------------------------------------------------------------------
#define GLEW_STATIC
#include "glew.c"
#include <gl\gl.h>
#include <gl\glu.h>
//---------------------------------------------------------------------------
//--- OpenGL GL example -----------------------------------------------------
//---------------------------------------------------------------------------
int     xs,ys;      // screen size
HDC     hdc=NULL;   // device context
HGLRC   hrc=NULL;   // rendering context
int  gl_inicialized=0;
int  gl_init(HWND Handle);
void gl_exit();
void gl_draw();
void gl_resize(int _xs,int _ys);
//---------------------------------------------------------------------------
//--- OpenGL GLSL example ---------------------------------------------------
//---------------------------------------------------------------------------
GLint prog_id=0,    // whole program
      vert_id=0,    // vertex shader
      frag_id=0;    // fragment shader
char  glsl_log[4096];// compile/link GLSL log
int   glsl_logs=0;
void  glsl_init(char *vert,char *frag);     // create/compile/link GLSL program
void  glsl_exit();
//---------------------------------------------------------------------------
//--- OpenGL VAO example ----------------------------------------------------
//---------------------------------------------------------------------------
#pragma pack(1)
//#define vao_indices
GLuint vbo[4]={-1,-1,-1,-1};
GLuint vao[4]={-1,-1,-1,-1};
const GLfloat vao_pos[]=
    {
//  x    y    z     //ix
    -1.0,-1.0,-1.0, //0
    +1.0,-1.0,-1.0, //1
    +1.0,+1.0,-1.0, //2
    -1.0,+1.0,-1.0, //3
    -1.0,-1.0,+1.0, //4
    +1.0,-1.0,+1.0, //5
    +1.0,+1.0,+1.0, //6
    -1.0,+1.0,+1.0, //7

    #ifndef vao_indices
    -1.0,-1.0,-1.0, //0
    +1.0,-1.0,-1.0, //1
    +1.0,-1.0,+1.0, //5
    -1.0,-1.0,+1.0, //4

    +1.0,-1.0,-1.0, //1
    +1.0,+1.0,-1.0, //2
    +1.0,+1.0,+1.0, //6
    +1.0,-1.0,+1.0, //5

    +1.0,+1.0,-1.0, //2
    -1.0,+1.0,-1.0, //3
    -1.0,+1.0,+1.0, //7
    +1.0,+1.0,+1.0, //6

    -1.0,+1.0,-1.0, //3
    -1.0,-1.0,-1.0, //0
    -1.0,-1.0,+1.0, //4
    -1.0,+1.0,+1.0, //7
    #endif
    };

const GLfloat vao_col[]=
    {
//  r   g   b    //ix
    0.0,0.0,0.0, //0
    1.0,0.0,0.0, //1
    1.0,1.0,0.0, //2
    0.0,1.0,0.0, //3
    0.0,0.0,1.0, //4
    1.0,0.0,1.0, //5
    1.0,1.0,1.0, //6
    0.0,1.0,1.0, //7

    #ifndef vao_indices
    0.0,0.0,0.0, //0
    1.0,0.0,0.0, //1
    1.0,0.0,1.0, //5
    0.0,0.0,1.0, //4

    1.0,0.0,0.0, //1
    1.0,1.0,0.0, //2
    1.0,1.0,1.0, //6
    1.0,0.0,1.0, //5

    1.0,1.0,0.0, //2
    0.0,1.0,0.0, //3
    0.0,1.0,1.0, //7
    1.0,1.0,1.0, //6

    0.0,1.0,0.0, //3
    0.0,0.0,0.0, //0
    0.0,0.0,1.0, //4
    0.0,1.0,1.0, //7
    #endif
    };

#ifndef vao_indices
const GLfloat vao_nor[]=
    {
//   nx   ny   nz   //ix
     0.0, 0.0,-1.0, //0
     0.0, 0.0,-1.0, //1
     0.0, 0.0,-1.0, //2
     0.0, 0.0,-1.0, //3

     0.0, 0.0,+1.0, //4
     0.0, 0.0,+1.0, //5
     0.0, 0.0,+1.0, //6
     0.0, 0.0,+1.0, //7

     0.0,-1.0, 0.0, //0
     0.0,-1.0, 0.0, //1
     0.0,-1.0, 0.0, //5
     0.0,-1.0, 0.0, //4

    +1.0, 0.0, 0.0, //1
    +1.0, 0.0, 0.0, //2
    +1.0, 0.0, 0.0, //6
    +1.0, 0.0, 0.0, //5

     0.0,+1.0, 0.0, //2
     0.0,+1.0, 0.0, //3
     0.0,+1.0, 0.0, //7
     0.0,+1.0, 0.0, //6

    -1.0, 0.0, 0.0, //3
    -1.0, 0.0, 0.0, //0
    -1.0, 0.0, 0.0, //4
    -1.0, 0.0, 0.0, //7
    };
#endif

#ifdef vao_indices
const GLuint vao_ix[]=
    {
    0,1,2,3,
    4,5,6,7,
    0,1,5,4,
    1,2,6,5,
    2,3,7,6,
    3,0,4,7,
    };
#endif

#pragma pack()
void vao_init();
void vao_exit();
void vao_draw();
//---------------------------------------------------------------------------
//--- bodies: ---------------------------------------------------------------
//---------------------------------------------------------------------------
int gl_init(HWND Handle)
    {
    if (gl_inicialized) return 1;
    hdc = GetDC(Handle);            // get device context
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory( &pfd, sizeof( pfd ) );      // set the pixel format for the DC
    pfd.nSize = sizeof( pfd );
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cDepthBits = 24;
    pfd.iLayerType = PFD_MAIN_PLANE;
    SetPixelFormat(hdc,ChoosePixelFormat(hdc, &pfd),&pfd);
    hrc = wglCreateContext(hdc);            // create current rendering context
    if(hrc == NULL)
            {
            ShowMessage("Could not initialize OpenGL Rendering context !!!");
            gl_inicialized=0;
            return 0;
            }
    if(wglMakeCurrent(hdc, hrc) == false)
            {
            ShowMessage("Could not make current OpenGL Rendering context !!!");
            wglDeleteContext(hrc);          // destroy rendering context
            gl_inicialized=0;
            return 0;
            }
    gl_resize(1,1);
    glEnable(GL_DEPTH_TEST);                // Zbuf
    glDisable(GL_CULL_FACE);                // vynechavaj odvratene steny
    glDisable(GL_TEXTURE_2D);               // pouzivaj textury, farbu pouzivaj z textury
    glDisable(GL_BLEND);                    // priehladnost
    glShadeModel(GL_SMOOTH);                // gourard shading
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);   // background color
    gl_inicialized=1;
    glewInit();
    return 1;
    }
//---------------------------------------------------------------------------
void gl_exit()
    {
    if (!gl_inicialized) return;
    wglMakeCurrent(NULL, NULL);     // release current rendering context
    wglDeleteContext(hrc);          // destroy rendering context
    gl_inicialized=0;
    }
//---------------------------------------------------------------------------
void gl_resize(int _xs,int _ys)
    {
    xs=_xs;
    ys=_ys;
    if (xs<=0) xs = 1;                  // Prevent a divide by zero
    if (ys<=0) ys = 1;
    if (!gl_inicialized) return;
    glViewport(0,0,xs,ys);              // Set Viewport to window dimensions
    glMatrixMode(GL_PROJECTION);        // operacie s projekcnou maticou
    glLoadIdentity();                   // jednotkova matica projekcie
    gluPerspective(30,float(xs)/float(ys),0.1,100.0); // matica=perspektiva,120 stupnov premieta z viewsize do 0.1
    glMatrixMode(GL_TEXTURE);           // operacie s texturovou maticou
    glLoadIdentity();                   // jednotkova matica textury
    glMatrixMode(GL_MODELVIEW);         // operacie s modelovou maticou
    glLoadIdentity();                   // jednotkova matica modelu (objektu)
    }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void glsl_init(char *vert,char *frag)
    {
    const int _size=1024;
    GLint status,siz=0,i;
    const char * VS = vert;
    const char * FS = frag;
    glsl_logs=0;
    if (prog_id<=0) prog_id=glCreateProgram();

    if (vert_id<=0) vert_id=glCreateShader(GL_VERTEX_SHADER); else glDetachShader(prog_id,vert_id);
    if (vert)
        {
        glShaderSource(vert_id, 1, &VS,NULL);
        glCompileShader(vert_id);
        glAttachShader(prog_id,vert_id);
        glGetShaderiv(vert_id,GL_COMPILE_STATUS,&status);
        const char t[]="[Vertex]\r\n"; for (i=0;t[i];i++) { glsl_log[glsl_logs]=t[i]; glsl_logs++; }
        glGetShaderInfoLog(vert_id,_size,&siz,glsl_log+glsl_logs);
        glsl_logs+=siz;
        }
    if (frag_id<=0) frag_id=glCreateShader(GL_FRAGMENT_SHADER); else glDetachShader(prog_id,frag_id);
    if (frag)
        {
        glShaderSource(frag_id, 1, &FS,NULL);
        glCompileShader(frag_id);
        glAttachShader(prog_id,frag_id);
        glGetShaderiv(frag_id,GL_COMPILE_STATUS,&status);
        const char t[]="[Fragment]\r\n"; for (i=0;t[i];i++) { glsl_log[glsl_logs]=t[i]; glsl_logs++; }
        glGetShaderInfoLog(frag_id,_size,&siz,glsl_log+glsl_logs);
        glsl_logs+=siz;
        }

    glLinkProgram(prog_id);
    glGetProgramiv(prog_id,GL_LINK_STATUS,&status);
    const char t[]="[Program]\r\n"; for (i=0;t[i];i++) { glsl_log[glsl_logs]=t[i]; glsl_logs++; }
    glGetShaderInfoLog(prog_id,_size,&siz,glsl_log+glsl_logs);
    glsl_logs+=siz;

    glReleaseShaderCompiler();
    glsl_log[glsl_logs]=0;
    }
//------------------------------------------------------------------------------
void glsl_exit()
    {
    glUseProgram(0);
    if (vert_id>0) { glDetachShader(prog_id,vert_id); glDeleteShader(vert_id); }
    if (frag_id>0) { glDetachShader(prog_id,frag_id); glDeleteShader(frag_id); }
    if (prog_id>0) {                                  glDeleteShader(prog_id); }
    glsl_log[0]=0;
    }
//---------------------------------------------------------------------------
//------------------------------------------------------------------------------
void vao_init()
    {
    GLuint i;
    glGenVertexArrays(4,vao);
    glGenBuffers(4,vbo);
    glBindVertexArray(vao[0]);
    i=0; // vertex
    glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vao_pos),vao_pos,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,0,0);
    i=1; // indices
    #ifdef vao_indices
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(vao_ix),vao_ix,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,4,GL_UNSIGNED_INT,GL_FALSE,0,0);
    #endif
    i=2; // normal
    #ifndef vao_indices
    glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vao_nor),vao_nor,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,0,0);
    #endif
    i=3; // color
    glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vao_col),vao_col,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,0,0);

    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);
    glDisableVertexAttribArray(3);
    }
//---------------------------------------------------------------------------
void vao_exit()
    {
    glDeleteVertexArrays(4,vao);
    glDeleteBuffers(4,vbo);
    }
//---------------------------------------------------------------------------
void vao_draw()
    {
    glBindVertexArray(vao[0]);
    #ifndef vao_indices
    glDrawArrays(GL_QUADS,0,sizeof(vao_pos)/sizeof(GLfloat));                       // QUADS ... no indices
    #endif
    #ifdef vao_indices
    glDrawElements(GL_QUADS,sizeof(vao_idx)/sizeof(GLuint),GL_UNSIGNED_INT,0);  // indices (choose just one line not both !!!)
    #endif
    glBindVertexArray(0);
    }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------

btw 这个文件取自:

M_PI=3.1415926535897932384626433832795 是在

中定义的常量
#include <math.h> 

您应该已经包含其中,因为您正在使用其中的 sin,cos 函数。

GLEW.c 是 OpenGL 扩展的牧马人,当你只使用 OpenGL 1.0 时你不需要它.. .但是一旦你删除包含你需要从这个文件中删除所有 VAO/VBOGLSL 东西(这不是无论如何都用过)