Computer Graphics小记(一):输出图元(上)

Point、Line、Curve、Polygon Fill Areas、Vertex Arrays

一个简单的OpenGL程序

  • OS:Mac OS X 10.11
  • IDE:Xcode
  • LANG:C++

步骤:

  1. 打开Xcode创建新工程,左侧选择OS X/Application,右侧选择Command Line Tool,点击Next
  2. 输入Product Name,选择Language为C++,一路Next创建完成
  3. 导入OpenGL.frameworkGLUT.framework
  4. OS X Deployment Target设置为10.9
  5. 在main.cpp中添加如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <GLUT/glut.h>
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glVertex2f(-0.5, -0.5);
glVertex2f(-0.5, 0.5);
glVertex2f(0.5, 0.5);
glVertex2f(0.5, -0.5);
glEnd();
glFlush();
}
int main(int argc, char * argv[]) {
glutInit(&argc, argv);
glutCreateWindow("output_primitives");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}

注意:这里的坐标系中心为(0,0),右上角为(1,1)。

保存后运行即可,输出如下图所示:

display函数中包含主要的绘制代码,方便起见,之后仅给出display函数中的内容。

Point

一般写法

1
2
3
4
5
glBegin(GL_POINTS);
glVertex2f(0.1,0.1);
glVertex2f(0.2,0.2);
glVertex2f(0.3,0.3);
glEnd();

使用数组

1
2
3
4
5
6
7
8
9
float p1 = {0.1,0.1};
float p2 = {0.2,0.2};
float p3 = {0.3,0.3};
glBegin(GL_POINTS);
glVertex2fv(p1);
glVertex2fv(p2);
glVertex2fv(p3);
glEnd();

glVertex,\中的数字表示维度,字母表示数据类型:i-integer,f-float,s-short,d-double,v-vector

使用类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class wcPt2D
{
public:
GLfloat x, y;
}
void display()
{
wcPt2D p1,p2,p3;
p1.x = 0.1; p1.y = 0.1;
p2.x = 0.2; p2.y = 0.2;
p3.x = 0.3; p3.y = 0.3;
glBegin(GL_POINTS);
glVertex2f(p1.x,p1.y);
glVertex2f(p2.x,p2.y);
glVertex2f(p3.x,p3.y);
glEnd();
}

Line

1
2
3
4
5
6
7
8
9
10
11
12
13
float p1 = {0.5,0.5};
float p2 = {-0.5,-0.5};
float p3 = {0,0.8};
float p4 = {0.5,-0.5};
float p5 = {-0.5,0.5};
glBegin(**MODE**);
glVertex2fv(p1);
glVertex2fv(p2);
glVertex2fv(p3);
glVertex2fv(p4);
glVertex2fv(p5);
glEnd();

代码中的MODE为线函数的枚举值,有GL_LINESGL_LINE_STRIPGL_LINE_LOOP三种。

GL_LINES

GL_LINE_STRIP

GL_LINE_LOOP

Curve

OpenGL核心库中并没有绘制圆与椭圆等曲线的图元基本程序。一般有三种方法:

  1. GLU中包含一些绘制曲线的程序
  2. 使用polyline来近似
  3. 编写自己的曲线生成函数,之后会讲到。

Polygon Fill Areas

矩形

glRect*

1
2
3
//glRect*(x1, y1, x2, y2);
glRectf(-0.2, -0.2, 0.5, 0.5);

(x1,y1)为矩形左下角坐标,(x2,y2)为右上角坐标

效果如下图:

三角形与多边形

顶点设置如下:

1
2
3
4
5
6
float p1[] = {-0.5,0};
float p2[] = {-0.35,-0.35};
float p3[] = {0.35,-0.35};
float p4[] = {0.5,0};
float p5[] = {0.35,0.35};
float p6[] = {-0.35,0.35};

GL_POLYGON

1
2
3
4
5
6
7
8
glBegin(GL_POLYGON);
glVertex2fv(p1);
glVertex2fv(p2);
glVertex2fv(p3);
glVertex2fv(p4);
glVertex2fv(p5);
glVertex2fv(p6);
glEnd();

GL_TRIANGLES

1
2
3
4
5
6
7
8
glBegin(GL_TRIANGLES);
glVertex2fv(p1);
glVertex2fv(p2);
glVertex2fv(p6);
glVertex2fv(p3);
glVertex2fv(p4);
glVertex2fv(p5);
glEnd();

GL_TRIANGLE_STRIP

1
2
3
4
5
6
7
8
glBegin(GL_TRIANGLE_STRIP);
glVertex2fv(p1);
glVertex2fv(p2);
glVertex2fv(p6);
glVertex2fv(p3);
glVertex2fv(p5);
glVertex2fv(p4);
glEnd();

GL_TRIANGLE_FAN

1
2
3
4
5
6
7
8
glBegin(GL_TRIANGLE_FAN);
glVertex2fv(p1);
glVertex2fv(p2);
glVertex2fv(p3);
glVertex2fv(p4);
glVertex2fv(p5);
glVertex2fv(p6);
glEnd();

四边形

顶点设置如下:

1
2
3
4
5
6
7
8
float p1[] = {-0.8,0.8};
float p2[] = {-0.6,-0.4};
float p3[] = {-0.3,-0.4};
float p4[] = {-0.4,0.4};
float p5[] = {0.4,0.45};
float p6[] = {0.45,-0.3};
float p7[] = {0.8,-0.6};
float p8[] = {0.7,0.9};

GL_QUADS

1
2
3
4
5
6
7
8
9
10
glBegin(GL_QUADS);
glVertex2fv(p1);
glVertex2fv(p2);
glVertex2fv(p3);
glVertex2fv(p4);
glVertex2fv(p5);
glVertex2fv(p6);
glVertex2fv(p7);
glVertex2fv(p8);
glEnd();

GL_QUAD_STRIP

1
2
3
4
5
6
7
8
9
10
glBegin(GL_QUAD_STRIP);
glVertex2fv(p1);
glVertex2fv(p2);
glVertex2fv(p4);
glVertex2fv(p3);
glVertex2fv(p5);
glVertex2fv(p6);
glVertex2fv(p8);
glVertex2fv(p7);
glEnd();

Vertex Arrays

要绘制一个立方体,首先需要定义它的所有顶点,可以使用一个二位数组来实现:

1
GLint points [8][3] = { {0,0,0}, {0,1,0}, {1,0,0}, {1,1,0}, {0,0,1}, {0,1,1}, {1,0,1}, {1,1,1}};

也可以通过定义一个特殊的数据类型来实现:

1
2
3
4
typedef GLint vertex3 [3];
vertex3 pt[8] = { {0,0,0}, {0,1,0}, {1,0,0}, {1,1,0}, {0,0,1}, {0,1,1}, {1,0,1}, {1,1,1}
};

通过如下代码绘制一个立方体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void quad(GLint n1, GLint n2, GLint n3, GLint n4)
{
glBegin(GL_QUADS);
glVertex3iv(pt [n1]);
glVertex3iv(pt [n2]);
glVertex3iv(pt [n3]);
glVertex3iv(pt [n4]);
glEnd();
}
void draw()
{
quad(6, 2, 3, 7);
quad(5, 1, 0, 4);
quad(7, 3, 1, 5);
quad(4, 0, 2, 6);
quad(2, 0, 1, 3);
quad(7, 5, 4, 6);
}

如此绘制的话需要多次调用面绘制方法,冗余代码未免有点多。

使用Vertex Array

启用GL_VERTEX_ARRAY功能:

1
2
3
4
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_INT, 0, pt);
GLubyte vertIndex[] = {6, 2, 3, 7, 5, 1, 0, 4, 7, 3, 1, 5, 4, 0, 2, 6, 2, 0, 1, 3, 7, 5, 4, 6};
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, vertIndex);

这样就简洁多了。

文章目录
  1. 1. 一个简单的OpenGL程序
  2. 2. Point
    1. 2.1. 一般写法
    2. 2.2. 使用数组
    3. 2.3. 使用类
  3. 3. Line
    1. 3.1. GL_LINES
    2. 3.2. GL_LINE_STRIP
    3. 3.3. GL_LINE_LOOP
  4. 4. Curve
  5. 5. Polygon Fill Areas
    1. 5.1. 矩形
      1. 5.1.1. glRect*
    2. 5.2. 三角形与多边形
      1. 5.2.1. GL_POLYGON
      2. 5.2.2. GL_TRIANGLES
      3. 5.2.3. GL_TRIANGLE_STRIP
      4. 5.2.4. GL_TRIANGLE_FAN
    3. 5.3. 四边形
      1. 5.3.1. GL_QUADS
      2. 5.3.2. GL_QUAD_STRIP
  6. 6. Vertex Arrays
    1. 6.1. 使用Vertex Array
|