使用OpenGl库在C ++中实现2D形状 [英] 2D shape in C++ by using the OpenGl library
问题描述
我正在尝试使用OpenGl库在C ++中绘制形状 我已经编写了以下代码,但是我所获得的只是以下形状):
I am trying to draw a shape in C++ by using the OpenGl library I've written the following code , but all what I achieved is the following shape ):
但是我需要使用glRotatef来获得这个形状吗?以及如何使用它?
but do I need to use glRotatef to get this shape :? and how can I use it ?
这是我的代码:)
#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();
}
推荐答案
我对您的代码做了一些修改:
I adapted your code a bit:
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
循环和围绕形状中心的旋转.结果如下:
So I added for
loop and the rotation around shape center to it. Here result:
xs,ys
是我的透视相机设置窗口的分辨率,而hdc
是我的上下文.我还发现您在交换缓冲区后调用了flush
,而我以前会调用它.
The xs,ys
is resolution of my window for the perspective camera settings and hdc
is my context. Also I spotted that you call flush
after swapping buffers I would call it before.
[Edit1]完整代码
我使用的是 BDS2006 C ++ ,因此代码使用的是 VCL (仅用于创建窗口和事件),没有GLUT或其他任何您必须更改以匹配您的平台的部分. ..该应用程序只是一个带有单个计时器的纯净表单.
I am using BDS2006 C++ so the code uses VCL (just for creating window and events) no GLUT or anything That part you have to change to match your platform... The app is just single clean Form with single timer on it.
//---------------------------------------------------------------------------
#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 上下文,因此您可以忽略 VAO 和 GLSL 东西.这里是源文件:
The gl_simple.h is just used for creating GL context so you can ignore the VAO and GLSL stuff. Here the source file:
//---------------------------------------------------------------------------
#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);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
顺便说一句,该文件来自:
M_PI=3.1415926535897932384626433832795
是在
#include <math.h>
在使用其中的sin,cos
功能时,您应该已经包括了.
Which you should have already included as you are using sin,cos
functions from it.
GLEW.c 是OpenGL扩展程序的争吵者,而当您仅使用 OpenGL 1.0 时就不需要它了……但是一旦删除了include,就变得很粗糙了.还需要从该文件中删除所有 VAO/VBO 和 GLSL 内容(无论如何都不会使用)
The GLEW.c is wrangler for OpenGL extensions and as you using just OpenGL 1.0 you do not need it ... but of coarse once you remove the include you need to delete also all VAO/VBO and GLSL stuff from this file (which is not used anyway)
这篇关于使用OpenGl库在C ++中实现2D形状的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!