首页 » 软件开发 » OpenGL基础图形编程(七)建模(顶点坐标多边形定义几何)

OpenGL基础图形编程(七)建模(顶点坐标多边形定义几何)

落叶飘零 2024-07-24 01:52:38 0

扫一扫用手机浏览

文章目录 [+]

  OpenGL基本库提供了大量绘制各种类型图元的方法,辅助库也提供了不少描述复杂三维图形的函数。
这一章主要介绍基本图元,如点、线、多边形,有了这些图元,就可以建立比较复杂的模型了。

OpenGL基础图形编程(二)OpenGL概念建立

7.1、描述图元

OpenGL基础图形编程(七)建模(顶点坐标多边形定义几何) 软件开发
(图片来自网络侵删)

  OpenGL是三维图形的函数库,它所定义的点、线、多边形等图元与一般的定义不太一样,存在一定的差别。
对编程者来说,能否理解二者之间的差别十分重要。
一种差别源于基于计算机计算的限制。
OpenGL中所有浮点计算精度有限,故点、线、多边形的坐标值存在一定的误差。
另一种差别源于位图显示的限制。
以这种方式显示图形,最小的显示图元是一个象素,尽管每个象素宽度很小,但它们仍然比数学上所定义的点或线宽要大得多。
当用OpenGL 进行计算时,虽然是用一系列浮点值定义点串,但每个点仍然是用单个象素显示,只是近似拟合。

  OpenGL图元是抽象的几何概念,不是真实世界中的物体,因此须用相关的数学模型来描述。

7.1.1 齐次坐标(Homogeneous Coordinate)

  在空间直角坐标系中,任意一点可用一个三维坐标矩阵[x y z]表示。
如果将该点用一个四维坐标的矩阵[Hx Hy Hz H]表示时,则称为齐次坐标表示方法。
在齐次坐标中,最后一维坐标H称为比例因子。

  在OpenGL中,二维坐标点全看作三维坐标点,所有的点都用齐次坐标来描述,统一作为三维齐次点来处理。
每个齐次点用一个向量(x, y, z, w)表示,其中四个元素全不为零。
齐次点具有下列几个性质:

  1)如果实数a非零,则(x, y, x, w)和(ax, ay, az, aw)表示同一个点,类似于x/y = (ax)/( ay)。

  2)三维空间点(x, y, z)的齐次点坐标为(x, y, z, 1.0),二维平面点(x,y)的齐次坐标为(x, y, 0.0, 1.0)。

  3)当w不为零时,齐次点坐标(x, y, z, w)即三维空间点坐标(x/w, y/w, z/w);当w为零时,齐次点(x, y, z, 0.0)表示此点位于某方向的无穷远处。

  注意:OpenGL中指定w大于或等于0.0。

7.1.2 点(Point)

  用浮点值表示的点称为顶点(Vertex)。
所有顶点在OpenGL内部计算时都作为三维点处理,用二维坐标(x, y)定义的点在OpenGL中默认z值为0。
所有顶点坐标用齐次坐标(x, y, z, w) 表示,如果w不为0.0,这些齐次坐标表示的顶点即为三维空间点(x/w, y/w, z/w)。
编程者可以自己指定w值,但很少这样做。
一般来说,w缺省为1.0。

7.1.3 线(Line)

  在OpenGL中,线代表线段(Line Segment),不是数学意义上的那种沿轴两个方向无限延伸的线。
这里的线由一系列顶点顺次连结而成,有闭合和不闭合两种。
见图7-1所示。

7.1.4 多边形(Polygon)  OpenGL中定义的多边形是由一系列线段依次连结而成的封闭区域。
这些线段不能交叉,区域内不能有空洞,多边形必须在凸多边形,否则不能被OpenGL函数接受。
合法和非法多边形图示见图7-2。

OpenGL多边形可以是平面多边形,即所有顶点在一个平面上,也可以是空间多边形。
更复杂的多边形将在提高篇中介绍。

7.2、绘制图元

7.2.1 定义顶点

  在OpenGL中,所有几何物体最终都由有一定顺序的顶点集来描述。

  函数glVertex{234}{sifd}[v](TYPE coords)可以用二维、三维或齐次坐标定义顶点。
举例如下:

glVertex2s(2,3);  glVertex3d(0.0,1.0,3.1414926535);  glVertex4f(2.4,1.0,-2.2,2.0);  GLfloat pp[3]={5.0,2.0,10.2};  glVertex3fv(pp);

第一例子表示一个空间顶点(2, 3, 0),第二个例子表示用双精度浮点数定义一个顶点,第三个例子表示用齐次坐标定义一个顶点,其真实坐标为(1.2, 0.5, -1.1),最后一个例子表示用一个指针(或数组)定义顶点。

7.2.2 构造几何图元

  在实际应用中,通常用一组相关的顶点序列以一定的方式组织起来定义某个几何图元,而不采用单独定义多个顶点来构造几何图元。
在OpenGL中,所有被定义的顶点必须放在glBegain()和glEnd()两个函数之间才能正确表达一个几何图元或物体,否则,glVertex()不完成任何操作。
如:  

glBegin(GL_POLYGON);    glVertex2f(0.0,0.0);    glVertex2f(0.0,3.0);    glVertex2f(3.0,3.0);    glVertex2f(4.0,1.5);    glVertex2f(3.0,0.0);  glEnd();

以上这段程序定义了一个多边形,如果将glBegin()中的参数GL_POLYGON改为GL_POINTS,则图形变为一组顶点(5个),见图7-3所示。

点函数glBegin(GLenum mode)标志描述一个几何图元的顶点列表的开始,其参数mode表示几何图元的描述类型。
所有类型及说明见表7-1所示,相应的图示见图7-4。

函数glEnd()标志顶点列表的结束。

  从图7-4中可看出,可以采用许多方法构造几何图元,这些方法仅仅依赖于所给的顶点数据。

  在glBegin()和glEnd()之间最重要的信息就是由函数glVertex()定义的顶点,必要时也可为每个顶点指定颜色、法向、纹理坐标或其他,即调用相关的函数,见表7-2所示,具体用法以后会逐步介绍。

看如下几句: 

glBegin(GL_POINTS);    glColor3f(1.0,0.0,0.0); / red color /    glVertex(...);    glColor3f(0.0,1.0,0.0); / green color /    glColor3f(0.0,0.0,1.0); / blue color /    glVertex(...);    glVertex(...);  glEnd();

颜色等的设置只对当前点或后续点有效。
上一例中第一个点是红色,第二个点和第三个点都是蓝色。
其中设置绿色时,之后没有顶点操作,而是设置蓝色,故只有当前蓝色对紧跟其后的两个顶点有效。

  为了更好地理解构造几何图元函数的用法,下面举一个简单的例子:

例7-3 几何图元构造例程(drawgeom.c)  

#include "glos.h"  #include<GL/gl.h>  #include<GL/glaux.h>   void myinit(void);  void DrawMyObjects(void);  void CALLBACK myReshape(GLsizei w,GLsizei h);  void CALLBACK display(void);   void myinit(void)  {    glClearColor(0.0,0.0,0.0,0.0);    glClear(GL_COLOR_BUFFER_BIT);    glShadeModel(GL_FLAT);  }   void CALLBACK myReshape(GLsizei w,GLsizei h)  {    glViewport(0,0,w,h);    glMatrixMode(GL_PROJECTION);    glLoadIdentity();     if(w<=h)      glOrtho(-20.0,20.0,-20.0(GLfloat)h/(GLfloat)w, 20.0(GLfloat)h/(GLfloat)w,-50.0,50.0);    else      glOrtho(-20.0(GLfloat)h/(GLfloat)w, 20.0(GLfloat)h/(GLfloat)w,-20.0,20.0,-50.0,50.0);    glMatrixMode(GL_MODELVIEW);    glLoadIdentity();  }   void CALLBACK display(void)  {    glColor3f(1.0,1.0,0.0);    DrawMyObjects();    glFlush();  }   void DrawMyObjects(void)  {    / draw some points /    glBegin(GL_POINTS);      glColor3f(1.0,0.0,0.0);      glVertex2f(-10.0,11.0);      glColor3f(1.0,1.0,0.0);      glVertex2f(-9.0,10.0);      glColor3f(0.0,1.0,1.0);      glVertex2f(-8.0,12.0);    glEnd();     / draw some line_segments /    glBegin(GL_LINES);      glColor3f(1.0,1.0,0.0);      glVertex2f(-11.0,8.0);      glVertex2f(-7.0,7.0);      glColor3f(1.0,0.0,1.0);      glVertex2f(-11.0,9.0);      glVertex2f(-8.0,6.0);    glEnd();     / draw one opened_line /    glBegin(GL_LINE_STRIP);      glColor3f(0.0,1.0,0.0);      glVertex2f(-3.0,9.0);      glVertex2f(2.0,6.0);      glVertex2f(3.0,8.0);      glVertex2f(-2.5,6.5);    glEnd();     / draw one closed_line /    glBegin(GL_LINE_LOOP);      glColor3f(0.0,1.0,1.0);      glVertex2f(7.0,7.0);      glVertex2f(8.0,8.0);      glVertex2f(9.0,6.5);      glVertex2f(10.3,7.5);      glVertex2f(11.5,6.0);      glVertex2f(7.5,6.0);    glEnd();     / draw one filled_polygon /    glBegin(GL_POLYGON);      glColor3f(0.5,0.3,0.7);      glVertex2f(-7.0,2.0);      glVertex2f(-8.0,3.0);      glVertex2f(-10.3,0.5);      glVertex2f(-7.5,-2.0);      glVertex2f(-6.0,-1.0);    glEnd();     / draw some filled_quandrangles /    glBegin(GL_QUADS);      glColor3f(0.7,0.5,0.2);      glVertex2f(0.0,2.0);      glVertex2f(-1.0,3.0);      glVertex2f(-3.3,0.5);      glVertex2f(-0.5,-1.0);      glColor3f(0.5,0.7,0.2);      glVertex2f(3.0,2.0);      glVertex2f(2.0,3.0);      glVertex2f(0.0,0.5);      glVertex2f(2.5,-1.0);    glEnd();     / draw some filled_strip_quandrangles /    glBegin(GL_QUAD_STRIP);      glVertex2f(6.0,-2.0);      glVertex2f(5.5,1.0);      glVertex2f(8.0,-1.0);      glColor3f(0.8,0.0,0.0);      glVertex2f(9.0,2.0);      glVertex2f(11.0,-2.0);      glColor3f(0.0,0.0,0.8);      glVertex2f(11.0,2.0);      glVertex2f(13.0,-1.0);      glColor3f(0.0,0.8,0.0);      glVertex2f(14.0,1.0);    glEnd();     / draw some filled_triangles /    glBegin(GL_TRIANGLES);      glColor3f(0.2,0.5,0.7);      glVertex2f(-10.0,-5.0);      glVertex2f(-12.3,-7.5);      glVertex2f(-8.5,-6.0);      glColor3f(0.2,0.7,0.5);      glVertex2f(-8.0,-7.0);      glVertex2f(-7.0,-4.5);      glVertex2f(-5.5,-9.0);    glEnd();     / draw some filled_strip_triangles /    glBegin(GL_TRIANGLE_STRIP);      glVertex2f(-1.0,-8.0);      glVertex2f(-2.5,-5.0);      glColor3f(0.8,0.8,0.0);      glVertex2f(1.0,-7.0);      glColor3f(0.0,0.8,0.8);      glVertex2f(2.0,-4.0);      glColor3f(0.8,0.0,0.8);      glVertex2f(4.0,-6.0);    glEnd();     / draw some filled_fan_triangles /    glBegin(GL_TRIANGLE_FAN);      glVertex2f(8.0,-6.0);      glVertex2f(10.0,-3.0);      glColor3f(0.8,0.2,0.5);      glVertex2f(12.5,-4.5);      glColor3f(0.2,0.5,0.8);      glVertex2f(13.0,-7.5);      glColor3f(0.8,0.5,0.2);      glVertex2f(10.5,-9.0);    glEnd();  }   void main(void)  {    auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);    auxInitPosition(0,0,500,500);    auxInitWindow("Geometric Primitive Types");    myinit();    auxReshapeFunc(myReshape);    auxMainLoop(display);  }

以上程序运行结果就是图7-4所示的内容,这个例子很好地说明了几何图元的类型及颜色等函数的用法。
希望读者自己仔细分析每个物体的绘制方法,体会其中的关键之处,达到举一反三的效果。
当然,还可利用上一章辅助库中提供的基本三维图元构造比较复杂的物体,你不妨也试一试。

相关文章

语言中的借用,文化交融的桥梁

自古以来,人类社会的交流与发展离不开语言的传播。在漫长的历史长河中,各民族、各地区之间的文化相互碰撞、交融,产生了许多独特的语言现...

软件开发 2025-01-01 阅读1 评论0

机顶盒协议,守护数字生活的新卫士

随着科技的飞速发展,数字家庭逐渐走进千家万户。在这个时代,机顶盒成为了连接我们与丰富多彩的数字世界的重要桥梁。而机顶盒协议,作为保...

软件开发 2025-01-01 阅读1 评论0

语言基础在现代社会的重要性及方法步骤

语言是人类沟通的桥梁,是社会发展的基础。语言基础作为语言学习的基石,对于个人、社会乃至国家的发展具有重要意义。本文将从语言基础在现...

软件开发 2025-01-01 阅读2 评论0

粤语电影,传承文化,点亮时代之光

粤语电影,作为中国电影产业的一朵奇葩,以其独特的地域特色、丰富的文化内涵和鲜明的艺术风格,赢得了广大观众的喜爱。本文将从粤语电影的...

软件开发 2025-01-01 阅读3 评论0

苹果游戏语言,塑造未来娱乐体验的基石

随着科技的飞速发展,游戏产业逐渐成为全球娱乐市场的重要支柱。在我国,游戏产业更是蓬勃发展,吸引了无数玩家和投资者的目光。而在这其中...

软件开发 2025-01-01 阅读1 评论0