2010在 工程图学学报 2010 第4期 J0URNAL OF ENGINEERING GRAPHICS NO.4 OpenGL显示3DS模型若干问题的研究 平 , 刘建明2, 王晶杰 (1.北京信息科技大学,北京100192;2.国息通信有限公司,北京100761) 摘 要:根据OpenGL进行三维显示的处理过程和3DS文件中三维模型的数据组 织结构,说明了如何从3DS文件得到OpenGL显示所需的数据。讨论了OpenGL显示三维 物体时法线向量的作用,给出了一种高效的法线向量求解方法,该方法比现有方法的速度快 一至两个数量级。最后讨论了如何利用3DS文件中的关键帧数据正确地显示带动画信息的 模型。 关键词:计算机应用;OpenGL显示3DS模型;法线向量求解;数据转换 中图分类号:TP 391 文献标识码:A 文章编号:1003—0158(2010)04—0189.05 Research on Some Problems in Displaying 3DS Model with OpenGL HU Ping—ping ,LIU Jian.ming ,WANG Jing-jie (1.Beijing University ofInformation Technology,Beijing 100192,China; 2.Information and Communication Corporation ofState Grid,Beijing 100761,China) Abstract:The way to get OpenGL data from 3DS file is introduced based on OpenGL display process and 3DS file data organization.After discussing the function of normal vector in OpenGL,a new method to find normal vectors from 3DS data is given,and this new method is tenfold faster than existing one.The usage of key frame data in 3DS file is given SO that the objects in 3DS file can be displayed on their right positions. Key words:computer application;display 3DS model with OpenGL;normal vector solving; data仃ansform OpenGL是一个著名的开放式三维图形开发 3DS是Autodesk公司存储3D模型数据的一种文 函数库,它提供的函数不仅可以创建基本的3D 件格式,许多流行的3D建模软件和图形格式转 物体原形还能够很方便地对3D物体进行各种操 换工具都能够生成3D模型的3DS文件,将 作和变换,得到逼真的3D显示效果,这使它成 OpenGL技术和3DS模型数据结合实现对3D物 为一个非常流行的3D图形浏览开发工具。但 体的浏览便成为一种广泛使用的方法。 OpenGL却不适于创建复杂的不规则3D物体。 由于3DS文件的数据格式没有官方的正式说 收稿日期:2008—11-21 基金项目:北京市教委科技发展资助项目(KM200711232008);国家电网公司科技资助项目(SGKJ[20074241) 作者简介:平(1963一),男,湖南嘉禾人,副教授,硕士,主要研究方向为计算机信息处理。 .Y-程图学学报 2010年 明文档,尽管很多文献[1-3]对用OpenGL读取、显 示和控制3DS模型数据的方法进行了介绍,但都 侧重于OpenGL编程实现方法,只涉及了基本的 若该物体不同面有不同的纹理则glEndO; 若该物体没有纹理或各面有相同纹理映射glEnd0 ̄ 在上面的过程中,以面为单位的法线向量设 静态3DS模型数据的使用。各种资源上能够得到 置和以顶点为单位的法线向量设置是两种不同的 的读取3DS数据的方法基本上一样,都没有对动 方式,下文将详细介绍。如果物体没有纹理映射 态数据进行处理,也没有考虑数据转换的性能。 用这些方法显示含动画信息的3DS模型时会出现 或各面的纹理映射相同,则glBegin0和glEnd() 以物体为单位,否则应该以每一个面为单位,这 物体位置错位的现象,即使是静态数据,当模型 样不同的面才能显示不同的纹理。 复杂且数据量较大时,其处理速度常常慢到不能 实用的地步。 本文从OpenGL显示3D模型的数据处理过 程出发,结合3DS文件数据的组织结构,扼要介 绍了如何由3DS文件构造OpenGL显示数据的方 法。重点讨论了法线向量在OpenGL显示中的两 种应用效果和由3DS数据生成法线向量的方法, 给出了一种高效的法线向量求解算法,该算法的 速度比现有方法快一至两个数量级,极大地提高 了数据转换的性能。本文还介绍了3DS模型中和 动画有关的关键帧数据的使用方法,解决了现有 方法在显示带动画信息的3DS模型时物体位置不 正确的问题。 1 OpenGL和3DS数据的关系 1.1 OpenGL的数据处理过程 OpenGL显示三维物体的一般过程是:保存 当前变换矩阵、设置新的视景体和新的变换矩阵、 设置每一个三维物体的数据、恢复当前变换矩阵。 设置三维物体数据的过程是由一系列嵌入在 glBegin(): ̄H glEndO调用之间的OpenGL函数调用 构成的,其过程如下所示: 对每一个三维物体: 若该物体没有纹理或各面有相同纹理映射则 glBegin(); 对物体的每一个面: 若该面有纹理映射则设置纹理: 若该物体不同面有不同的纹理则glBegin(); 设置以面为单位的面法线向量; 设置纹理或材质的颜色; 对每一个面的所有顶点: 设置以顶点为单位的顶点法线向量; 若该面有纹理则设置顶点的纹理坐标; 设置顶点坐标: 1.2 3DS文件数据的组织结构 关于3DS文件的格式,文献[4]和文献[5]有较 详细的介绍,此处仅列出和OpenGL显示数据有 关部分的组织结构: 3DS文件数据: 文件版本数据(ID=0x0002); 编辑数据(ID=0x3D3D): . 材质数据(ID=0xAFFF); . . 材质名称数据(ID=0xAFFF); . . 材质颜色数据(ID=0xA010/20/30); . . 材质纹理数据(ID=0xA300); . 物体数据(ID=0x4000): . 物体名称数据; . 物体顶点数据(ID=0x41lO); . 物体面数据(ID=0x4120); . . 面材质数据(ID=0x4130); . . 面材质名称; . . 同材质面索引数据; . 物体转换矩阵数据(ID=0x4160); 关键帧数据(ID=0xB000): 关键帧名称(ID=0xB00A); 关键帧起止帧数据(ID=0xB008); 物体关键帧数据(ID=0xB002); 物体关键帧标识数据(ID=0xB030); 物体关键帧名称和层次数据 (ID=0xB0l 0/11): 物体关键帧支点坐标数据(ID=0xB013); 物体关键帧移动数据(ID=OxB020); 物体关键帧转动数据(ID=OxB02 1); 物体关键帧缩放数据(ID=0xB022): 1.3 OpenGL显示数据和3DS数据的关系 从上面的介绍可知,OpenGL显示处理是以 物体为单位进行的,3DS的数据则按照类型组织, 对应于OpenGL中同一个物体的数据要从3DS文 件中不同类型的数据获得,具体方法是: 第4期 平等:0penGL显示3DS模型若干问题的研究 物体的顶点和面数据:直接来自3DS的物体 顶点数据( ,Y,Z坐标值)和物体面数据(该面 所用顶点的索引号和方向)。 物体的材质数据:由3DS物体面数据的面材 质名称数据得到材质名称,再由该材质名称到 3DS材质数据中找到对应的材质颜色和纹理数 据。而物体面数据的同材质面索引数据则指出哪 些面使用这个材质。 物体的位置数据:该数据由物体顶点数据、 物体转换矩阵数据和关键帧数据共同决定,前两 种数据从物体数据中直接得到,后一个则来自物 体对应的关键帧数据。具体生成方法,在本文后 面介绍。 物体的法线向量数据:由上述得到的物体顶 点和面数据通过计算得到,具体方法见下文。 2 OpenGL中法线向量的作用和求 解方法 2.1法向量的作用和效果 OpenGL显示三维物体时,需要为每一个顶 点设置法线向量,法线向量不仅为OpenGL光照 处理确定每一个面的正反提供依据,而且还影响 到物体的显示效果 J。OpenGL法向量的设置有 两种方法:以面为单位和以顶点为单位,前一种 方法每个面的所有顶点使用相同的法向量,后一 种方法每个面的不同顶点有不同的法向量(又称 平均法向量)。图1和图2是同一个3D模型用两 种法向量设置方法的显示效果图。 从上面的效果图可以看出,以顶点为单位的 法向量方法显示的物体比较平滑,这也是OpenGL 显示3DS模型时最常用的方法。 图1法向量以面为单位的显示效果 图2法向量以顶点为单位的显示效果 2.2现有的法向量求解方法 3DS模型并没有直接提供OpenGL显示用的 法向量数据,这些数据要从3DS模型的面数据中 求解得到。3DS模型的面是由3个顶点和一个方 向码构成的三角面片,读入3DS模型的面数据后, 首先要统一各个面的方向(必要时要根据方向码 调整3个顶点的顺序),然后按特点顺序由三角形 的两个边向量的叉积求出该三角形的法向量。如 果采用以面为单位的法向量方法,则构成三角形 的3个顶点的法向量就是该三角形的法向量;如 果采用以顶点为单位的法向量方法,由于同一个 顶点可能为不同的三角形共用,此时一个顶点的 法向量就是使用该顶点的所有三角形法向量的平 均向量。现有的顶点法向量求解方法如下所示: 对每一个三维物体: 对物体的每一个面: 计算该面的法向量并归一化; 对物体的每一个顶点: 在物体所有面中寻找用到该顶点的面并将该面 的法向量叠加; 叠加法向量平均并归一化后作为该顶点的法向 量; 该方法在求某一个顶点的法向量时,要遍历 物体所有面的3个顶点,其运算量是:顶点数量 面数量X3,由于是先求出所有面的法向量然后 再使用,因此,计算过程中还要为每一个面设置 一个法向量存储空间。 2-3改进的法向量求解方法 3D物体模型中,一个顶点可能被多个面使 用,但用到某一个顶点的面占全部面的比例往往 很小。一般情况下,简单模型的比例最大约10%, 复杂大型模型的比例最大约1%,可见现有算法为 工程图学学报 201 0年 求某一个顶点的法向量而遍历所有面的处理大部 变量空间最多是现有方法的1/2。 分是不必要的。鉴于此,可以对顶点法向量的求 2.4两种法向量求解方法的比较 解方法改进为如下所示: 新顶点法向量的求解方法在使用变量空间上 对每一个三维物体: 至少节省一半,而计算量的节省情况则和3D模 型的具体情况有关。只有当使用每一个顶点的面 的数量和面的总数量相等时,现有算法才不存在 无用的处理,此时两种算法的处理量几乎相等, 但该情况意味着每一个顶点被所有的面共用,这 是不可能存在的,因此新算法的处理量总是小于 现有方法。 将该物体所有顶点的法向量设置为0; 对物体的每一个面: 计算该面的法向量; 将该面的法向量叠加到该面3个顶点的法向量 中: 对物体的每一个顶点: 将顶点的法向量除以其叠加次数并归一化; 表1是两种处理方法对几种典型模型的实际 上述新方法在求顶点的法向量时避免了对不 处理时问对比,可以看出,模型的数据量越大, 使用该顶点的面的判断处理,且新方法不用为每 尤其是顶点被共用的面的数量相对于面的总数量 一个面设置一个法向量存储空间,只需为每一个 越小,新方法的改进效果就越明显。对于一般模 顶点设置一个叠加计数器变量,由于计数器变量 型数据,新方法的速度平均是现有方法的几倍至 所使用的空间只是法向量的1/6[计数器为两字节 几十倍,而对大型模型,速度提高的效果非常明 整数,法向量为3个浮点数,用12字节),而顶 显,约为几百倍。 点的数量最多是面数量的3倍,故新方法使用的 表1 两种法向量求解方法的计算时间比较 I司决定。 3 3DS模型关键帧数据的使用方法 3DS模型中各种关键帧数据块的结构在文献 [4]和文献【5】中有一定的介绍,但这些数据的具体 不带动画信息的3DS模型中各物体的顶点数 含义和使用方法都没有介绍。下面仅对与物体位 置有关的关键帧数据含义和使用方法做一个简单 据可以直接作为这些物体的实际位置坐标数据, 但当3DS模型带动画信息时,模型中各物体的实 介绍,至于如何利用关键帧数据在OpenGL环境 际位置一般由顶点数据和关键帧数据共同决定, 能会显示在错误的位置上。 中显示可以运动的3DS模型,由于篇幅所限,此 3.1物体关键帧数据的确定方法 3DS模型中每一个关键帧数据都有自己的名 如果仅按顶点数据显示物体,则模型中的物体可 处不做介绍。3DS模型中每一个物体的关键帧信息由物体 的名称或关键帧的层次结构决定。关键帧的层次 称,该名称在名称层次块(0xB010)中,如果其中 关系是一个树状结构,当某一个物体是根节点或 的名称不是“DUMMY”,则该关键帧数据就属于 根节点的叶节点时,其位置信息仅由它自己的关 名称与之匹配的物体,否则,该关键帧数据属于 键帧数据决定;否则该物体的位置信息要由它自 一个虚物体,该物体是一个父节点,它的实际名 0xB01 11中,而该父节点的 己的关键帧数据和它所有父节点的关键帧数据共 称在后面的虚名称块(第4期 平等:OpenGL显示3DS模型若干问题的研究 关键帧数据为其所有子节点共用,它所含子节点 当前位置的平移量,因此,为了显示物体正确的 的关键帧数据位于其后,由子节点关键帧数据的 当前位置,应该将物体的顶点坐标进行调整,方 层次号决定。 法是:将物体各顶点坐标减去其关键帧数据的支 点坐标。 在关键帧数据中,每一个物体的关键帧数据 f0xB002)都有一个位于名称层次块(0xB010)中的 层次号,层次号是由该关键帧的层次关系和它在 4结 论 本文给出的由3DS模型数据求解顶点法向量 关键帧数据中出现的位置决定的,其编排方法是: 根关键帧的层次号为一1,其它关键帧的层次号由 0开始递增或保持不变。层次号保持不变,说明 这些关键帧属于同一个层次;层次号增加则表示 该关键帧是上一个节点的子节点;层次号减小, 则说明该关键帧是一个新的父节点,该节点的层 次同前面与之层次号相同的节点一样,每一个父 节点之后新子节点关键帧的层次号就是该关键帧 数据出现的实际位置的顺序号(新子节点关键帧 的层次号一定是一个没有出现过的值)。以后各关 键帧的层次号依上述规律编排,直到所有的关键 帧数据编排完毕。 3.2物体位置和关键帧数据的关系 3DS模型中物体的位置由以下数据决定:物 体的顶点坐标数据(Ox4110)、转换矩阵数据 (0x4160)中的源点坐标和物体关键帧数据中的支 点坐标数据(0xB013)、移动数据(0xB020)、旋转数 据(0xB021)及缩放数据(ID=0xB022)。 3DS模型中不带动画信息的物体也有一帧关 键帧数据,只不过其关键帧数据的支点坐标和旋 转关键帧数据都是0,缩放数据是1。带动画信息 的物体则按它具有关键帧的多少带有指定数量的 关键帧数据。物体转换矩阵数据中的源点坐标表 示该物体当前位置和它被创建时原始位置的位 移,该数据和物体关键帧数据第0帧的移动数据 相同。物体的顶点坐标实际上就是由物体被创建 时的初始位置和大小按照其第0帧关键帧数据做 变换(平移、旋转和缩放)生成的。而物体关键 帧数据中的支点坐标则是顶点坐标表示的位置到 的新方法和关键帧数据的使用均成功地应用到作 者开发的多屏同步3D显示系统中,不仅实现了 大型3DS模型的快速装入和带动画信息的3DS模 型物体位置的正确显示,还实现了带动画信息的 3DS模型物体的运动显示,效果良好。 参考文献 【1] 赵文广,李仲学,李翠平.面向工程可视化仿真的 VC++,OpenGL与3DS集成技术[J].北京科技大学 学报,2001,23(6):563~565. [2】殷素峰,高雪强,杨胜强.在OpenGL环境下开发 3DS文件浏览器[J].工程图学学报,2005,26(6) 22—25. [3】尹士伟,张光年,郭新宇.一种控制3DS模型的新方 法的研究与实现[J].微计算机信息,2007,23(3—2): 307—308. [4】Martin van Velsen.3D—Studi0 File Format(.3ds)[EB/OL]. http://www.the・labs.com/Blender/3dsspec.html,1998.10.5. 【5】Jeff Lewis.The Unofifcial 3DStudio 3DS File Format [EB/OL].http://www.the-labs.com/Blender/3DS—details. html,1998.10.5. 【6】乔林,费广正,林杜,等.OpenGL程序设计[M】. 北京:清华大学出版社,2000.194-202. [7】[美]Dave Shrieiner,Mason Woo等.OpenGL编程指 南(第4版)[M].邓郑祥译.北京:人民邮电出版社, 2005.44-45