OpenGL编程学习(3)-多边形填充函数和顶点数组

  • OpenGL多边形填充函数

矩形函数

  glRect* (x1, y1, x2, y2);

  星号(*)代表的后缀可以是i(整数)、s(短整数)、f(浮点型)、d(双精度浮点)、v(向量)。矩形的边平行于坐标轴,多边形的边按照顶点序列(x1, y1)、(x2, y1)、(x2, y2)、(x1,y2)来形成,然后返回到第一顶点(x1, y1)。

6种不同的符号常量下的图元填充函数
  GL_POLYGON可以产生单个多边形,一个多边形的顶点集至少包含三个顶点,否则什么也不显示。
  GL_TRIANGLES可以显示分开的三角形区域:最开始的3个坐标定义第一个三角形的三个顶点,之后3个顶点定义下一个三角形的顶点,以此类推。如果最后不足3个坐标则忽略多余的数据。
  GL_TRIANGLE_STRIP可以产生连续的三角形:最开始3个坐标定义第一个三角形的三个顶点,第2-4个坐标定义第二个三角形的顶点,以此类推。N个顶点可以产生N-2个三角形。
  GL_TRIANGLE_FAN可以产生“扇形”分布的三角形,其中第一个顶点坐标被所有的三角形共享,第2、3个顶点与它产生第一个三角形,第3、4个顶点与它产生第二个三角形,以此类推。N个顶点可以产生N-2个三角形。
  GL_QUADS可以产生单个四边形,至少输入4个顶点,与GL_TRIANGLES产生三角形的规律相同:从头至尾,每4个坐标一组。
  GL_QUAD_STRIP将产生连续的四边形。在N≥4时,N个顶点可以产生N/2-1个四边形。我们可以按n=1,n=2,…,n=N/2-1对填充多边形和顶点计数,这样,多边形表中第n个四边形的顶点次序为2n-1、2n、2n+2、2n+1。

  • OpenGL顶点数组

  顶点数组可以简化复杂场景渲染中多众多函数的重复调用,下面通过绘制单位立方体的例子说明。
  假设pt是包含坐标值的顶点数组:

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} };

  绘制单位立方体的代码为:

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);

  第一条命令激活了OpenGL顶点数组特性。也可以用下面的命令将该特性“关闭”:

  glDisableClientState(GL_VERTEX_ARRAY);

  glVertexPointer提供对象顶点坐标的位置和格式。此例中,第一个参数指出每个顶点描述中的坐标数目为3,第二个参数表示顶点坐标中的数据类型GL_INT,此外还有GL_BYTE、GL_SHORT、GL_FLOAT和GL_DOUBLE。第三个参数说明连续顶点之间的字节位移。最后一个参数指向包含坐标值的顶点数组。
  立方体顶点的所有索引放在数组vertIndex中,其中每一个索引是对应于该顶点值的数组pt的下标。glDrawElements的第一个参数表示绘制多边形的方式,第二个参数指定下标索引数组,也就是vertIndex中的元素数量,第三个参数指定索引值的类型,除例中的GL_UNSIGNED_BYTE之外,还有GL_UNSIGNED_SHORT和GL_UNSIGNED_INT两种。

  • 示例代码

  代码清单:

#include <GL/glut.h>

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} };

void init(){
  glClearColor(1.0, 1.0, 1.0, 0.0);
  glMatrixMode(GL_PROJECTION);
  gluOrtho2D(0.0, 200, 0.0, 150);
  //glOrtho(-1.0, 2.0, -1.0, 2.0, -1.0, 2.0);
}

void polygon(void){
  glClear(GL_COLOR_BUFFER_BIT);
  glColor3f(1.0, 0.0, 0.0);

  glRecti(10, 10, 40, 50);

  glColor3f(0.0, 1.0, 0.0);
  glBegin(GL_POLYGON);
  glVertex2i(10, 60);
  glVertex2i(40, 60);
  glVertex2i(30, 90);
  glVertex2i(20, 90);
  glEnd();

  glColor3f(0.0, 0.0, 1.0);
  glBegin(GL_TRIANGLES);
  glVertex2i(60, 30);
  glVertex2i(70, 10);
  glVertex2i(70, 50);
  glVertex2i(90, 10);
  glVertex2i(100, 30);
  glVertex2i(90, 50);
  glEnd();

  glColor3f(0.0, 1.0, 1.0);
  glBegin(GL_TRIANGLE_STRIP);
  glVertex2i(60, 80);
  glVertex2i(70, 60);
  glVertex2i(70, 100);
  glVertex2i(90, 60);
  glVertex2i(90, 100);
  glVertex2i(100, 80);
  glEnd();

  glColor3f(0.0, 0.50, 1.0);
  glBegin(GL_QUAD_STRIP);
  glVertex2i(110, 80);
  glVertex2i(120, 20);
  glVertex2i(130, 70);
  glVertex2i(140, 10);
  glVertex2i(160, 70);
  glVertex2i(160, 10);
  glVertex2i(190, 90);
  glVertex2i(180, 20);
  glEnd();
  
  glFlush();
}

void cube(void){
  glClear(GL_COLOR_BUFFER_BIT);

  glColor3f(1.0, 0.0, 0.0);
  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);

  glFlush();
}

int main(int argc, char *argv[])
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
  glutInitWindowSize(400, 300);
  glutCreateWindow("Draw Polygon");

  init();
  glutDisplayFunc(polygon);

  glutMainLoop();
}

  以polygon作为显示函数的运行结果:
Draw Polygon_026

发表评论

电子邮件地址不会被公开。 必填项已用*标注