土地一级开发项成目本核算.ppt
10/11/2023,山东大学 HCI&VR Lab.,1,第二章 图形学(OpenGL)编程,10/11/2023,山东大学 HCI&VR Lab.,2,一.基本内容,OpenGL API的发展历史OpenGL 体现结构OpenGL 作为一个状态机(state machine)函数 Functions 类型 Types格式Formats简单程序,10/11/2023,山东大学 HCI&VR Lab.,3,API的早期历史,IFIPS(1973)组织了两个委员会建立图形 API标准图形核心系统(Graphical Kernel System GKS)二维,但包含很好的工作站模型Core:同时应用于二维和三维GKS 成为 IS0标准,后来成为 ANSI 标准(1980s)GKS 很难推广到 3D(GKS-3D)远远落后于硬件的发展,10/11/2023,山东大学 HCI&VR Lab.,4,PHIGS and X,程序员层次交互式图形系统PHIGS(Programmers Hierarchical Graphics System)来自于 CAD业界保存图形的数据库模型X Window 系统DEC/MIT 的成果提出了应用图形系统的客户-服务器体现(Client-server)PEX 把两者结合在一起不易应用(也是两者的缺陷),10/11/2023,山东大学 HCI&VR Lab.,5,SGI 和 GL,Silicon Graphics(SGI)通过实现流水线体系改良了图形工作站(1982)源程序通过一个图形库(GL)与系统通讯借助于 GL,可以非常简单地设计出三维交互图形应用程序,10/11/2023,山东大学 HCI&VR Lab.,6,OpenGL,GL 的成功导致了 OpenGL的出现(1992),这是一个与平台无关的图形 API:使用方便与硬件非常贴近,从而能充分发挥其功能注重渲染和绘制(rendering)没有提供窗口和输入接口,从而避免依赖与窗口系统,10/11/2023,山东大学 HCI&VR Lab.,7,OpenGL 的演化,由 Architectural Review Board(ARB)控制成员包括 SGI,Microsoft,Nvidia,HP,3DLabs,IBM,.相对稳定(目前版本 version 2.0)演化反映了新的硬件能力3D 纹理映射和纹理对象基于顶点的编程通过扩展可以指定具体平台相应的功能,10/11/2023,山东大学 HCI&VR Lab.,8,OpenGL 库,OpenGL 核心库Windows:OpenGL32大多数 unix/linux 系统:GL库OpenGL 实用库(GLU)利用 OpenGL核心库提供一些功能,从而避免重复编写代码 与窗口系统的连接GLX for X window systemsWGL for WindowsAGL for Macintosh,10/11/2023,山东大学 HCI&VR Lab.,9,GLUT,OpenGL 实用工具库(GLUT:OpenGL Utility Toolkit Library)提供所有窗口系统的共同功能打开窗口 Open a window从鼠标和键盘获得输入Get input from mouse and keyboard菜单 Menus事件驱动 Event-driven代码可以在平台之间移植,但是GLUT 缺乏在确定平台上优秀工具包所具有的功能没有滚动条,10/11/2023,山东大学 HCI&VR Lab.,10,软件组织,GLUT,GLU,GL,GLX,AGLor WGL,X,Win32,Mac O/S,软 件or 硬 件,应用程序,OpenGL 图形工具条等,10/11/2023,山东大学 HCI&VR Lab.,11,OpenGL 体系结构,快速模式,显示列表,多项式求值器,逐顶点操作&基本图元集成,光栅化,逐片操作,纹理内存,CPU,像素操作,帧缓存,geometry pipeline,10/11/2023,山东大学 HCI&VR Lab.,12,OpenGL 函数类型,基本图形元素(Primitives)定义图形系统可以显示的低级对象或原子实体,典型的如:点 Points线段 Line Segments多边形Polygons像素 Pixel字符 Character属性函数(Attributes)线段颜色的设置多边形内部团填充图形标题文字的字体选择变换(Transformations)视图 Viewing:定义了各种不同的视域建模 Modeling:虚拟照相机模型等控制(GLUT):多窗口环境下的多进程之间的通信输入(GLUT):处理键盘、鼠标等设备的输入响应查询Query:获得诸如照相机参数、帧缓存里的数据等内在信息,10/11/2023,山东大学 HCI&VR Lab.,13,OpenGL 状态,OpenGL 是一个状态机(state machine)OpenGL 函数有两种基本类型基本图元的生成(Primitive generating)如果图元可见,可以得到输出顶点如何处理,基本形状的外观由状态控制改变状态(State changing)变换函数属性函数,10/11/2023,山东大学 HCI&VR Lab.,14,面向对象方面的缺憾,OpenGL 不是面向对象的,因此逻辑上的一个函数却对应着多个OpenGL函数glVertex3f glVertex2i glVertex3dv内在存储模式是相同的在C+可以很容易地创建重载函数,但是效率却成为主要问题,10/11/2023,山东大学 HCI&VR Lab.,15,OpenGL 接口,核心库GL:OpenGL 中所有函数的名字都以gl开头Windows:OpenGL32大多数 unix/linux 系统:GL库实用库 GLU只引用 OpenGL核心库GL中的函数,但还包括了球体等这些常用对象的建模代码以及其他的一些功能,从而避免重复编写代码 实用工具性GLUT提供了任何窗口操作系统所需要的最小功能集GLX:把:OpenGL与 X Window操作系统“粘合”起来,10/11/2023,山东大学 HCI&VR Lab.,16,OpenGL 函数名称格式,glVertex3f(x,y,z),属于 GL 库,函数名,x,y,z 为 float数据类型,glVertex3fv(p),p 为指向float的指针,维数(参数个数),注意每一部分的大小写,10/11/2023,山东大学 HCI&VR Lab.,17,OpenGL 中的#defines,大多数常数采用预定义方式#defines在头文件 gl.h,glu.h 和 glut.h定义注意#include 会自动包含另外两个头文件例如:glBegin(GL_POLYGON)glClear(GL_COLOR_BUFFER_BIT)包含文件也定义 OpenGL 的数据类型:GLfloat,GLdouble,.,常数,10/11/2023,山东大学 HCI&VR Lab.,18,一个简单的程序,在黑色背景上画一个矩形,10/11/2023,山东大学 HCI&VR Lab.,19,simple.c,#include/包含GL头文件void mydisplay()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(/主函数循环,10/11/2023,山东大学 HCI&VR Lab.,20,事件循环,在程序中定义了一个显示回调函数(display callback function):mydisplay每个 glut 程序必须有一个显示回调函数只要OpenGL确定显示内容要被刷新时,显示回调函数就会被调用:例如,当窗口被打开的时候 main()函数以程序进入事件循环作为结束,10/11/2023,山东大学 HCI&VR Lab.,21,默认值,simple.c 是个很简单的程序大量使用了状态变量的默认值视图模式 Viewing色彩设置 Colors窗口参数 Window parameters后续的程序将改变一下默认值,10/11/2023,山东大学 HCI&VR Lab.,22,如何在VC+6.0环境下使用进行OPENGL环境设置,下载 有关的GLUT软件库:如glutdlls37beta 压缩包(1)将下载的压缩包解开,将得到5个文件:glut.h,glut.lib,glut32.lib,glut.dll和glut32.dll,并按如下要求进行设置(1)“找到 盘符(d:)Program FilesMicrosoft Visual StudioVC98includeGL文件夹”。把解压得到的glut.h放到这个GL文件夹里。没有GL文件夹可以自己建一个,一般都有的。(2)把解压得到的glut.lib和glut32.lib放到静态函数库所在文件夹,即lib文件夹。如“盘符(d:)Program FilesMicrosoft Visual StudioVC98lib文件夹”)。(3)把解压得到的glut.dll和glut32.dll放到操作系统目录下面的system32文件夹内。(典型的位置为:C:WindowsSystem32)这是非常重要的动态链接库设置!,10/11/2023,山东大学 HCI&VR Lab.,23,如何在VC+6.0环境编辑和运行OpenGL程序,WINDOWS环境设置创建一个Win32 console application 类型的workspace 文件创建一个C/C+文件,包含simple.c的代码,并把这个文件插入到创建好的workspace 文件中直接进行编译 CTRL+F7,进行函数库的链接 F7执行 编译好的可执行文件F5(080311讲完),10/11/2023,山东大学 HCI&VR Lab.,24,图元与属性,OpenGL基本库:很小的基本图元集在GLU中包含从基本库里推导而来的其他类型的基本对象OpenGL支持两类基本图元几何型图元在问题(用户)域里定义,具有空间和几何属性:点、线段、多边形、曲线、曲面等经过几何处理流水线,经过光栅化后变成帧缓存里的像素几何处理处理:决定图元是否可见、计算在屏幕上的显示位置等在问题域进行几何对象的建模和几何变换旋转、平移等光栅型图元把对象看作是像素的集合,缺少几何属性,不能在问题空间中对其进行处理,经过另一条平行流水线到达帧缓存,10/11/2023,山东大学 HCI&VR Lab.,25,图元和属性的定义与设置,OpenGL中的基本图元都是用空间中的点或顶点定义的,采用 glBigin()glEnd()之间来定义glBing(type);/type参数决定定义的几何对象类型glVertex*();glVertex*();glEnd();,10/11/2023,山东大学 HCI&VR Lab.,26,OpenGL基本图元-点、线段(P33),点(GL_POINT):每个顶点至少是一个像素大小线段(GL_LINE):线段类型把两个相邻的顶点当作线段的两个端点多段线(GL_LINE_STRIP,GL_LINE_LOOP):封闭和不封闭,10/11/2023,山东大学 HCI&VR Lab.,27,OpenGL 基本图形元素,GL_QUAD_STRIP,GL_POLYGON,GL_TRIANGLE_STRIP,GL_TRIANGLE_FAN(扇面),GL_POINTS,GL_LINES,GL_LINE_LOOP,GL_LINE_STRIP(缺口),GL_TRIANGLES,10/11/2023,山东大学 HCI&VR Lab.,28,OpenGL基本图元-多边形,多边形:带边界的、封闭的、具有内部区域的对象(GL_POLYGON)多边形的边界与采用GL_LINE_LOOP的类型一样,相邻两个顶点定义边界线,其中那个一条线段连接最后一个顶点和第一个顶点三角形和四边形是多边形的特例(P35,图2.13)(GL_TRIANGLES)(GL_QUADS)带状和扇形:由一组三角形或四边形组成,共享部分顶点和边界线(P35,图2.14)(GL_TRIANGLE_STRIP)(GL_QUAD_STRIP)(GL_TRIANGLE_FAN),10/11/2023,山东大学 HCI&VR Lab.,29,多边形的限制条件,OpenGL 只能显示满足下述条件的多边形简单多边形:边除顶点外不相交凸多边形:对于多边形中的任意两点,连接这两点的线段完全在多边形中平面多边形:所有顶点都在同一个平面内用户自己确保上述条件的满足OpenGL 将报错,如果上述条件不满足三角形满足上述所有限制条件,nonsimple polygon,nonconvex polygon,10/11/2023,山东大学 HCI&VR Lab.,30,曲线和曲面,用图元来逼近曲线或曲面可以用一个正N多边形来逼近一个圆弧可以用正多面体来逼近球体用数学的方法来定义曲线和曲面,推导出这些对象的图形函数,再利用这些函数来创建对象四次曲面参数多项式曲线和曲面,10/11/2023,山东大学 HCI&VR Lab.,31,属性,属性是 OpenGL状态的一部分确定对象的外观颜色(点,线,多边形)大小和宽度(points,lines)宽度和虚实形式(lines,polygons)多边形填充显示:颜色和模式显示边界显示顶点,10/11/2023,山东大学 HCI&VR Lab.,32,RGB 色彩,每个颜色组件分别存储在帧缓存中一般在帧缓存中每个组件为8位注意在 glColor3f中,颜色值的范围从0.0到1.0,而在 glColor3ub中,值的范围在 0 255,10/11/2023,山东大学 HCI&VR Lab.,33,索引颜色(颜色查找表),颜色值指向颜色查找表需要更少的存储量一般为8位现在不是很重要了存储器很便宜了需要更多的颜色做渲染,10/11/2023,山东大学 HCI&VR Lab.,34,颜色和状态,颜色通过 glColor 来设置,成为状态机的一部分,直到被改变为止,一直保持这种状态颜色与其他属性不是对象的一部分,但是在渲染时要把这些属性赋给对象可以按下述方法创建顶点的颜色 glColor glVertex glColor glVertex,10/11/2023,山东大学 HCI&VR Lab.,35,颜色的光滑过渡,默认状态是光滑过渡OpenGL 根据多边形顶点的颜色插值出来内部的颜色函数:glShadeModel(GL_SMOOTH),10/11/2023,山东大学 HCI&VR Lab.,36,颜色的平坦过渡,另外一种状态是平坦过渡第一个顶点的颜色确定填充颜色函数:glShadeModel(GL_FLAT),10/11/2023,山东大学 HCI&VR Lab.,37,OpenGL编程第二节 完整的程序(080318),10/11/2023,山东大学 HCI&VR Lab.,38,主要内容,修改第一个程序改变默认值定义标准程序结构简单视图二维视图:作为三维视图的特例基本的OpenGL 图形元素属性,10/11/2023,山东大学 HCI&VR Lab.,39,程序结构,大多数 OpenGL 程序有类似的结构,包含以下函数:main():主函数定义回调函数 打开一个或多个具有指定属性的窗口进入事件循环(最后一条可执行语句)init():设置状态变量视图:Viewing属性:AttributesCallbacks 回调函数显示函数输入和窗口函数,10/11/2023,山东大学 HCI&VR Lab.,40,对simple.c 的修改,在这一版本的程序中,会得到同样的输出,但是所有具有默认值的相应状态值都通过函数调用显式指定特别地,设置了颜色 Colors视图条件 Viewing conditions窗口属性 Window properties,10/11/2023,山东大学 HCI&VR Lab.,41,main.c,#include int main(int argc,char*argv)glutInit(,includes gl.h,define window properties,set OpenGL state,enter event loop,display callback,自动包含了gl.h,定义窗口属性,显示回调函数,设置OpenGL状态,进入事件循环,(500,500)像素大小,10/11/2023,山东大学 HCI&VR Lab.,42,GLUT 函数,glutInit 使得应用程序可以获得命令行参数并初始化系统gluInitDisplayMode 设置窗口的属性(渲染上下文the rendering context)RGB 颜色单缓冲区 Single buffering属性按逻辑“或”组合在一起glutWindowSize 以像素为单位定义窗口的尺寸glutWindowPosition 定义窗口左上角在显示器的位置glutCreateWindow 创建窗口,标题为“simple”,来自参数glutDisplayFunc 定义显示回调函数glutMainLoop 进入无穷的事件循环,10/11/2023,山东大学 HCI&VR Lab.,43,Init(),void init()glClearColor(0.0,0.0,0.0,1.0);glColor3f(1.0,1.0,1.0);glMatrixMode(GL_PROJECTION);glLoadIdentity();glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);,清除色(背景色)为黑色,不透明窗口,矩形填充色彩值设置白色,矩阵模式设置为投影模式,视景体设置(物体各个顶点的坐标值经过坐标变换后必须介于调用glOrtho()函数中提供参数的范围内),将当前的矩阵清零,不可再恢复,10/11/2023,山东大学 HCI&VR Lab.,44,坐标系,在 glVertex 中的单位是由应用程序确定的,称为世界坐标系(也叫对象或问题坐标系object or problem coordinates)视景体(viewing volume)也是相对于世界坐标系指定的,视景体确定出现在图像空间中的对象 在 OpenGL内部,会把世界坐标系转化为照相机坐标系(camera(eye)coordinates),稍后再转化为屏幕坐标系(screen coordinates)OpenGL 也常用某些内部表示法,这些内部表示法对应用程序并不可见,10/11/2023,山东大学 HCI&VR Lab.,45,OpenGL 照相机,OpenGL 照相机被放置在坐标原点,指向Z轴负方向默认的视景体是一个中心在原点,边长为2的立方体,10/11/2023,山东大学 HCI&VR Lab.,46,正交视图(Orthographic Viewing),在默认的正交视图中,点沿着Z轴投影到Z=0的平面上plane z=0,10/11/2023,山东大学 HCI&VR Lab.,47,变换与视图,在 OpenGL中,投影是利用投影矩阵乘法进行的 由于只存在一个变换函数系列,因此必须先设置矩阵模式 glMatrixMode(GL_PROJECTION)变换函数是累加在一起的所以需要从单位矩阵开始,然后把它改变为一个投影矩阵以定义视景体 glLoadIdentity();,10/11/2023,山东大学 HCI&VR Lab.,48,二维与三维视图,在 glOrtho(left,right,bottom,top,near,far)中,近与远是相对于与照相机的距离而言的glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);二维顶点命令把所有的顶点放在z=0的盘面上如果应用程序处于二维状态,那么可以使用下述函数设置正交视景体:gluOrtho2D(left,right,bottom,top)对二维情形,视景体或裁剪体退化为裁剪窗口(clipping window),10/11/2023,山东大学 HCI&VR Lab.,49,mydisplay.c,void mydisplay()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();,10/11/2023,山东大学 HCI&VR Lab.,50,视窗,并不需要把整个当前窗口用来显示图像:可以在窗口中设置视窗,函数为:glViewport(x,y,w,h)/x,y,w,h的含义见下图参数值以像素为单位(屏幕坐标系),10/11/2023,山东大学 HCI&VR Lab.,51,OpenGL 编程Part 3:三维图形,10/11/2023,山东大学 HCI&VR Lab.,52,主要内容,提供一个更复杂的三维图形实例分形:Sierpinski 鏤垫l隐藏面消除,10/11/2023,山东大学 HCI&VR Lab.,53,三维图形应用程序,在OpenGL中,二维应用程序是三维应用程序的特殊情形要得到三维图形应用程序只对前面程序做很小的修改使用 glVertex3*()必须考虑多边形绘制的顺序或者启用隐藏面消除功能只考虑平面的简单图多边形,10/11/2023,山东大学 HCI&VR Lab.,54,Sierpinski Gasket(2D),从一个三角形开始连接三边的中点并去掉中间的三角形Repeat,10/11/2023,山东大学 HCI&VR Lab.,55,示例,五次细分后的结果,10/11/2023,山东大学 HCI&VR Lab.,56,作为分形的鏤垫,考虑黑色填充区域的面积与周长(即包含填充区域的所有线段总长)当持续细分时面积趋向于零但周长趋向于无穷因此无穷细分后的结果不是通常的几何形状它的维数既不是一维的,也不是二维的称之为分形(fractional dimension)对象,10/11/2023,山东大学 HCI&VR Lab.,57,Gasket Program,#include/initial triangle typedef GLfloat point22;/initial trianglepoint2 v=-1.0,-0.58,1.0,-0.58,0.0,1.15;int n;/递归步数,10/11/2023,山东大学 HCI&VR Lab.,58,绘制三角形,void triangle(point2 a,point2 b,point2 c)/display one triangleglBegin(GL_TRIANGLES);glVertex2fv(a);glVertex2fv(b);glVertex2fv(c);glEnd();,10/11/2023,山东大学 HCI&VR Lab.,59,三角形细分,void divide_triangle(point2 a,point2 b,point2 c,int m)/*triangle subdivision using vertex numbers*/point2 v0,v1,v2;int j;if(m0)for(j=0;j2;j+)v0j=(aj+bj)/2;for(j=0;j2;j+)v1j=(aj+cj)/2;for(j=0;j2;j+)v2j=(bj+cj)/2;divide_triangle(a,v0,v1,m-1);divide_triangle(c,v1,v2,m-1);divide_triangle(b,v2,v0,m-1);else(triangle(a,b,c);/*draw triangle at end of recursion*/,10/11/2023,山东大学 HCI&VR Lab.,60,显示和初始化函数,void display(void)glClear(GL_COLOR_BUFFER_BIT);glBegin(GL_TRIANGLES);divide_triangle(v0,v1,v2,n);glEnd();glFlush();void myinit()glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(-2.0,2.0,-2.0,2.0);glMatrixMode(GL_MODELVIEW);glClearColor(1.0,1.0,1.0,1.0)glColor3f(0.0,0.0,0.0);,10/11/2023,山东大学 HCI&VR Lab.,61,Main()函数,Void main(int argc,char*argv)n=4;glutInit(,10/11/2023,山东大学 HCI&VR Lab.,62,三维的情形,通过下述修改,可以很容易地把程序生成三维图形 typedef GLfloat point33glVertex3fglOrtho但这并不没有多大实质性改变下面从四面体开始迭代,10/11/2023,山东大学 HCI&VR Lab.,63,3D Gasket,细分四面体的四个面好像我们从这个达到四面体中抠去了四个小一点的四面体,10/11/2023,山东大学 HCI&VR Lab.,64,示例,5次迭代后的结果,10/11/2023,山东大学 HCI&VR Lab.,65,生成三角形的代码,void triangle(point a,point b,point c)glBegin(GL_POLYGON);glVertex3fv(a);glVertex3fv(b);glVertex3fv(c);glEnd();,10/11/2023,山东大学 HCI&VR Lab.,66,细分代码,void divide_triangle(point a,point b,point c,int m)point v1,v2,v3;int j;if(m0)for(j=0;j3;j+)v1j=(aj+bj)/2;for(j=0;j3;j+)v2j=(aj+cj)/2;for(j=0;j3;j+)v3j=(bj+cj)/2;divide_triangle(a,v1,v2,m-1);divide_triangle(c,v2,v3,m-1);divide_triangle(b,v3,v1,m-1);else(triangle(a,b,c);,10/11/2023,山东大学 HCI&VR Lab.,67,生成四面体的代码,void tetrahedron(int m)glColor3f(1.0,0.0,0.0);divide_triangle(v0,v1,v2,m);glColor3f(0.0,1.0,0.0);divide_triangle(v3,v2,v1,m);glColor3f(0.0,0.0,1.0);divide_triangle(v0,v3,v1,m);glColor3f(0.0,0.0,0.0);divide_triangle(v0,v2,v3,m);,10/11/2023,山东大学 HCI&VR Lab.,68,问题,由于三角形是按照在程序中定义的顺序画出的,本来在前面的三角形并不是显示在位于它后面的三角形的前面,get this,want this,10/11/2023,山东大学 HCI&VR Lab.,69,隐藏面的消除,只想见到那些位于其它面前面的曲面或平面片OpenGL采用称为z缓冲区的算法进行隐藏面消除,在z缓冲区中存贮着对象的深度信息,从而只有前面的对象出现在图像中,10/11/2023,山东大学 HCI&VR Lab.,70,Z缓冲区算法,在该算法中创建专门的缓冲区(称为z缓冲区),当几何体经过流水线各步骤时,存贮着该几何体的深度信息启用该算法的要素在 main()中 glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH)在init()中启用glEnable(GL_DEPTH_TEST)在显示回调函数中glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT),10/11/2023,山东大学 HCI&VR Lab.,71,二维细分 vs 三维细分,在我们的例子中,对每个二维面进行细分我们也可以使用相同的中点来细分三维的图形中点定义了四个小一些的四面体,每一个四面体对应一个顶点在中点移除一个体,仅保持这些四面体,10/11/2023,山东大学 HCI&VR Lab.,72,体的细分形式,