百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

OpenGL基础图形编程(七)建模

lipiwang 2024-11-27 17:20 8 浏览 0 评论

七、OpenGL建模

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

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

7.1、描述图元

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

相关推荐

前端入门——css 网格轨道详细介绍

上篇前端入门——cssGrid网格基础知识整体大概介绍了cssgrid的基本概念及使用方法,本文将介绍创建网格容器时会发生什么?以及在网格容器上使用行、列属性如何定位元素。在本文中,将介绍:...

Islands Architecture(孤岛架构)在携程新版首页的实践

一、项目背景2022,携程PC版首页终于迎来了首次改版,完成了用户体验与技术栈的全面升级。作为与用户连接的重要入口,旧版PC首页已经陪伴携程走过了22年,承担着重要使命的同时,也遇到了很多问题:维护/...

HTML中script标签中的那些属性

HTML中的<script>标签详解在HTML中,<script>标签用于包含或引用JavaScript代码,是前端开发中不可或缺的一部分。通过合理使用<scrip...

CSS 中各种居中你真的玩明白了么

页面布局中最常见的需求就是元素或者文字居中了,但是根据场景的不同,居中也有简单到复杂各种不同的实现方式,本篇就带大家一起了解下,各种场景下,该如何使用CSS实现居中前言页面布局中最常见的需求就是元...

CSS样式更改——列表、表格和轮廓

上篇文章主要介绍了CSS样式更改篇中的字体设置Font&边框Border设置,这篇文章分享列表、表格和轮廓,一起来看看吧。1.列表List1).列表的类型<ulstyle='list-...

一文吃透 CSS Flex 布局

原文链接:一文吃透CSSFlex布局教学游戏这里有两个小游戏,可用来练习flex布局。塔防游戏送小青蛙回家Flexbox概述Flexbox布局也叫Flex布局,弹性盒子布局。它决定了...

css实现多行文本的展开收起

背景在我们写需求时可能会遇到类似于这样的多行文本展开与收起的场景:那么,如何通过纯css实现这样的效果呢?实现的难点(1)位于多行文本右下角的展开收起按钮。(2)展开和收起两种状态的切换。(3)文本...

css 垂直居中的几种实现方式

前言设计是带有主观色彩的,同样网页设计中的css一样让人摸不头脑。网上列举的实现方式一大把,或许在这里你都看到过,但既然来到这里我希望这篇能让你看有所收获,毕竟这也是前端面试的基础。实现方式备注:...

WordPress固定链接设置

WordPress设置里的最后一项就是固定链接设置,固定链接设置是决定WordPress文章及静态页面URL的重要步骤,从站点的SEO角度来讲也是。固定链接设置决定网站URL,当页面数少的时候,可以一...

面试发愁!吃透 20 道 CSS 核心题,大厂 Offer 轻松拿

前端小伙伴们,是不是一想到面试里的CSS布局题就发愁?写代码时布局总是对不齐,面试官追问兼容性就卡壳,想跳槽却总被“多列等高”“响应式布局”这些问题难住——别担心!从今天起,咱们每天拆解一...

3种CSS清除浮动的方法

今天这篇文章给大家介绍3种CSS清除浮动的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。首先,这里就不讲为什么我们要清楚浮动,反正不清除浮动事多多。下面我就讲3种常用清除浮动的...

2025 年 CSS 终于要支持强大的自定义函数了?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!1.什么是CSS自定义属性CSS自...

css3属性(transform)的一个css3动画小应用

闲言碎语不多讲,咱们说说css3的transform属性:先上效果:效果说明:当鼠标移到a标签的时候,从右上角滑出二维码。实现方法:HTML代码如下:需要说明的一点是,a链接的跳转需要用javasc...

CSS基础知识(七)CSS背景

一、CSS背景属性1.背景颜色(background-color)属性值:transparent(透明的)或color(颜色)2.背景图片(background-image)属性值:none(没有)...

CSS 水平居中方式二

<divid="parent"><!--定义子级元素--><divid="child">居中布局</div>...

取消回复欢迎 发表评论: