




免费预览已结束,剩余34页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
厦门大学本科毕业论文本科毕业论文(科研训练、毕业设计)题 目:三维发型仿真姓 名:学 院:软件学院系:软件工程专 业:软件工程年 级: 学 号:指导教师(校内): 职称: 年 月 日摘要本文主要论述本人在2005年在软件学院做毕业设计期间对自己所负责的基OpenGL 的三维发型仿真软件的设计。OpenGL是个专业的3D程序接口,是一个功能强大,调用方便的底层3D图形库。目前已在各行各业得到广泛得应用。实习得目的就是探索OpenGL在三维仿真方面的应用。该程序基于OpenGL2.0,采用c+语言编写,运行效率较高。建模方面采用3dMAX7.0结合facegen,hairFX等插件。以及三维人物建模工具Poser.。三维模型细腻,仿真度良好。本人负责三维模型的建模,以及模型的读取和显示的类的设计工作。本文正是建模方面的分步骤描述,以及程序中具体三维数据的读取与显示的过程,采用的数据结构,算法的设计。阐明了程序的已有的功能和将来需要完善的地方。关键词三维仿真OpenGL三维建模三维仿真 three-dimensional human face emluatorAbstract:This thesis is mainly about the three-dimensional software base on OpenGL desigh by me when I was practice in xiamen university software department.OpenGL is a speciality software interface which is very powerful and convenience. OpenGL is using in every walk of life .The practice aim of me is to explore the feasibility of using OpenGL to design 3D application. This application is base on OpenGL2.0 and using the programming language of C+.,Run efficiency. Modeling by 3dmax7.0 facegen poser 5.0 and hairFX and so on. The models are exquisite and reality. Iam in the charge of modeling and design the classes in C+ which can make the mode display in the application . This these is about the modeling step by step the date structure and arithmetic using in the programe. Clarify the Function have come true and will come true in the future. Key Word: three-dimensional emulator OpenGL three-dimensional modeling three-dimensional emulator目录1引言 62总体设计 62.1实现目标 62.2软件结构 63建模 73.1建模软件 73.2建模步骤 73.2.1建立人头模型 83.2.2完善头部模型 83.2.3建立头发模型 93.3模型成品图 104数据结构 124.13ds文件的格式定义 124.1.1 3ds格式文件简介 124.1.2 3DS格式文件中的编辑程序块 134.1.3面信息中每一位的具体含义 174.2读取3ds文件的c+类的定义 184.2.1初始化存储3ds文件数据的结构体 184.2.2将文件的第一块读出并判断是否是3ds文件 194.2.3读出3ds文件的主要部分 204.2.4处理所有的文件中对象的信息 234.2.5处理所有的材质信息 264.2.6读入RGB颜色 284.2.7读入顶点索引 294.2.8读入对象的材质名称 305程序中OpenGL图形显示环境的设定 31 5.1初始化OpenGL绘图环境 335.1.1定义颜色格式 335.1.2定义缓冲模式 335.2设置光源 335.3设置材质 345.4 定义投影方式 356优化程序的性能 3661采用合适的读取方法优化程序的性能 366.2在建模过程中优化模型 367尚未解决的问题 378结论 379致谢语 38参考文献 38 1 引言OpenGL是个专业的3D程序接口,是一个功能强大,调用方便的底层3D图形库。OpenGL的前身是SGI公司为其图形工作站开发的IRIS GL。OpenGL是个与.硬件无关的软件接口,可以在不同的平台如Windows 95、Windows NT、Unix、Linux、MacOS、OS2之间进行移植。因此,支持OpenGL的软件具有很好的移植性,可以获得非常广泛的应用。由于OpenGL是3D图形的底层图形库,没有提供几何实体图元,不能直接用以描述场景。但是,通过一些转换程序,可以很方便地将AutoCAD、3DS等3D图形设计软件制作的DFX和3DS模型文件转换成OpenGL的顶点数组。本软件就是基于OpenGL的标准,采用在三维软件中建立3DS三维模型,在C+类中分析读取3DS模型中的数据,并转换为OpenGL顶点数组,进而利用OpenGL标准的画图函数在屏幕上将三维模型绘制出来。2 总体设计2.1实现目标建立一个三维的人头模型,能根据用户选择更改模型的发型,并能更改发型的颜色。光泽等参数。2.2软件结构 软件包括一个用户界面和对应的消息相应函数,一个发型模型库,一个发质模型库。一个读取3ds文件的类,一个初始化OpenGL环境的类,以及一个在屏幕上显示图形的主函数。当用户点击相应的发型,或发色的按钮时,调用发型库里的相应模型,当用户点击显示按钮时,能将相应的模型在屏幕上显示出来。 图1 软件抓图3 建模3.1建模软件程序中所用到的3D模型主要是用3dmax7.0,Facegen,poser5.0,以及3dmax的毛发插件hairFX。3.2建模步骤3.2.1 建立人头模型FaceGen是一个参数化的三维人头模型建立工具,首先启动FaceGen,并调节各项参数,建立一个初步的人头模型。并将其保存为3DS文件格式。 图2 用FaceGen制作头部模型3.2.2完善人头模型将建立的人头模型导入到3dmax7.0中,采用3dmax的建模工具和命令对模型进行调整使其更逼真,主要用到的命令有多边形挤压命令,多变形修改命令,镜像半边命令。并设置模型的皮肤纹理贴图。 图3 在3dmax中修改头部模型3.2.3 建立头发模型在3dmax7.0中在建好的人头模型的基础上进一步建立头发的三维模型。采用的命令主要有多边形挤压命令,多变形修改命令,创建命令,镜像半边命令等。并在建好的头发上加上初始化的纹理贴图。 图4 在3dmax中建立头发模型3.2.4 完善模型用3dmax7.0的hairFX插件进一步优化和完美头发的模型,使其数据量更小,材质更逼真。3.3模型成品图(部分)图5 模型成品抓图4数据结构41 3ds文件的格式定义411 3ds格式文件简介 3DStudio是Autodesk公司开发的一套用于在微机上制作三维动画的应用程序,它所生成的图形文件的格式是3DS文件格式。由于3DS是一种非常普遍的数据格式,以3DS格式保存的三维图形文件非常丰富。 本程序主要采用分析读取3ds格式模型数据,并利用OpenGL画图函数在windows窗口中绘制模型的方式。3DS文件由许多块组成,每个块首先描述其信息类别,即该块是如何组成的。块的信息类别用ID来标识,块还包含了下一个块的相对位置信息。因此,即使不理解一个块的含义,也可以很容易地跳过它,因为该块中指出了下一个块地相对于改块的起始位置地偏移字节数。与许多文件格式一样,3DS二进制文件中的数据也是按低位在前,高位在后的方式组织的。例如,2个十六进制字节4A 5C 3B 8F,表明5C 4A是低位字节,而8F 3B是高位字节。块的前两项信息分别是:块的ID和块的长度(也即下一个块相对于改块的字节偏移量),块的ID是一个整形数,而块的长度是一个长整形数。每个块实际上是一个层次结构,不同类型的块,其层次结构也不相同。3DS文件中有一个基本块,其ID是4D 4D,每一个3DS文件的开头都是由这样一个块构成。基本块内的块称为主块。下面给出具体的图表来说明不同类型(ID)的块及其各自在文件中的位置。 最先开始出现的主块是基本块,包含了整个文件。应此这个块的大小就是文件的大小建去主块的大小。还有两种主块:3D编辑程序块和关键帧块,前者的ID是3D3D,后者的ID是B000。3D编辑程序块表明编辑程序数据开始,也就是说物体的形体数据定义从此处开始。关键帧块表明即将开始定义关键帧信息。412 3DS格式文件中的编辑程序块表1 3D(编辑程序块)的子块ID含义0100配置的一部分1100未知1200背景色1201未知1300未知1400未知1420未知1450未知1500未知2100环境颜色块2200雾2210雾2300未知3000未知3D3E编辑程序配置主块4000一个物体的定义AFFF材质列表开始AFFF(材质列表块)的子块ID材质名称A000用于一个零结尾的字符串定义表2 3D3E(编程程序配置块)的子块ID定义7001视口指示器7011视口定义(类型1)7012视口定义(类型2)7020视口定义(类型3)3D3E块中包含了许多冗余数据,其中较重要的块是7020块,这个块定义编辑程序中4个活动的视口。假设在编辑程序布局中使用了4个视口,编辑程序配置中包含5个7020视口和5个7011视口定义块。但事实上只有开始的4个7020块对用户的视口外观有影响,其他视口中只包含一些附加信息。该块的第6,7字节表明视图的类型,合法的ID及其对应的视图如下所示:表3 合法的ID及其对应的视图ID含义0001顶视图0002底视图0003左视图0004右视图0005前视图0006后视图0007用户视图FFFF相机视图0009光源视图0010无效4000(物体描述块)的子块第一项是物体名称,为一个零结尾串,这里所指的物体可以是一个相机或一个光源,也可以是物体的形状。表4 4000(物体描述块)的子块ID含义4010未知4012阴影块4100三角形列表块4600光源块4700相机块表5 4100(三角形列表)的子块ID含义4110顶点列表4111顶点选项4120面列表4130面材质4140纹理映射坐标4150面平滑组4160平移矩阵4165物体可见性4170标准映射表6 4110(顶点列表块)的子块起始位置结束位置大小数据类型名称012无符号整数物体的顶点数目254浮点数X坐标值694浮点数Y坐标10134浮点数Z坐标值从第2个字节到第13个字节定义了一个顶点的坐标,重复这项定义VertexNum次,便得到了所有顶点的坐标。4111(顶点选项块)的子块该子块由一些整形数组成,第一个整形数表明顶点个数,然后对每个顶点用一个整形数表示一些位置信息。其中,07位和1112位影响物体的可见性,810位是随即信息,1315位表明该顶点是否在某个选择集中被选中。顶点选项块不是很重要,即使将其删除,3DS也能正确地将物体装入。表7 4120面列表块起始位置结束位置大小数据类型名称012无符号整数物体中地三角形数232无符号整数顶点A的序号452无符号整数顶点B的序号672无符号整数顶点C的序号892无符号整数面信息重复29定义PolyNum次,就给出了所有的三角形。27所给出的3个整形数是三角形面的三个顶点序号,序号为0的顶点表示顶点列表中定义的第一个顶点。顶点的顺序影响着面的法向量方向。一般情况下三角形应按逆时针方向定义,但有些3DS文件使用顺时针方向,这时就需要在程序中将其调整过来。面信息是一个整型数,其中前3个二进制位给出了三角形每条边的顺序,可以根据它们判断三角形是以逆时针还是顺时针顺序给出的。这3个数字要么全是0,要么全是1。若这3位全为1,其二进制方式为111,意味着ABC给出的就是逆时针方向。4.1.3 面信息中每一位的具体含义Bit0 AC边顺序, 1:A-C 0: CABit1 BC边顺序, 1: B-C 0: CBBit2 AB边顺序, 1:AB 0:BABit3 纹理映射(如果有)Bit48 保留(0)Bit910 随即数Bit1112 保留(0)Bit13 面在第三选择集中被选Bit14 面在第三选择集中被选Bit15 面在第三选择集中被选4143面材质块 材质块给出了物体中使用的每一种材质,但并不是每个物体都有材质块,只使用默认材质的物体就没有材质块。每一个4130面材质块以一个0结尾的材质名称字符串开始,接着跟一个由数字表示的与该材质相关的面的数目,然后就是一个一个的面。0000表示4120面列表中的第一个面。 4140纹理映射坐标 前2个字节表示定义的顶点数,然后为每个顶点定义2个浮点型的纹理映射坐标,也就是说,如果一个顶点的纹理映射在纹理平面的中心,那么其映射坐标为(0。5,0。5)。 4145面平滑块块的大小为面的个数4B,即每个基本数据是一个长整形数字,第n个数字表示该面是否属于第n个平滑组。 4160局部坐标轴块开始的3个浮点数定义了物体的局部坐标轴在绝对坐标系内的位置坐标,最后的3个浮点数是物体的局部中心 4170标准映射前两个字节表明映射的类型,其中,0表示平明映射或制定映射,当制定映射时,与这个块中的信息就无关了,1表示圆柱映射,2表示球映射。接着用21个浮点数来描述这个映射。4.2读取3ds文件的c+类的定义 4.2.1初始化存储3ds文件数据的结构体CLoad3DS函数用来初始化存储3ds文件数据的结构体CLoad3DS:CLoad3DS()m_CurrentChunk = new tChunk;/ 初始化并为当前的块分配空间m_TempChunk = new tChunk;/ 初始化一个临时块并分配空间/ 打开一个3ds文件,读出其中的内容,并释放内存bool CLoad3DS:Import3DS(t3DModel *pModel, char *strFileName)char strMessage255 = 0;/ 打开一个3ds文件m_FilePointer = fopen(strFileName, rb);/ 确保所获得的文件指针合法if(!m_FilePointer) sprintf(strMessage, Unable to find the file: %s!, strFileName);MessageBox(NULL, strMessage, Error, MB_OK);return false;/ 当文件打开之后,首先应该将文件最开始的数据块读出以判断是否是一个3ds文件/ 如果是3ds文件的话,第一个块ID应该是PRIMARY4.2.2将文件的第一块读出并判断是否是3ds文件ReadChunk(m_CurrentChunk);/ 确保是3ds文件if (m_CurrentChunk-ID != PRIMARY)sprintf(strMessage, Unable to load PRIMARY chuck from file: %s!, strFileName);MessageBox(NULL, strMessage, Error, MB_OK);return false;/ 现在开始读入数据,ProcessNextChunk()是一个递归函数/ 通过调用下面的递归函数,将对象读出ProcessNextChunk(pModel, m_CurrentChunk);/ 在读完整个3ds文件之后,计算顶点的法线ComputeNormals(pModel);/ 释放内存空间CleanUp();return true;4.2.3读出3ds文件的主要部分ProcessNextChunk函数读出3ds文件的主要部分void CLoad3DS:ProcessNextChunk(t3DModel *pModel, tChunk *pPreviousChunk)t3DObject newObject = 0;/ 用来添加到对象链表tMaterialInfo newTexture = 0;/ 用来添加到材质链表unsigned int version = 0;/ 保存文件版本int buffer50000 = 0;/ 用来跳过不需要的数据m_CurrentChunk = new tChunk;/ 为新的块分配空间/ 下面每读一个新块,都要判断一下块的ID,如果该块是需要的读入的,则继续进行/ 如果是不需要读入的块,则略过/ 继续读入子块,直到达到预定的长度while (pPreviousChunk-bytesRead length)/ 读入下一个块ReadChunk(m_CurrentChunk);/ 判断块的ID号switch (m_CurrentChunk-ID)case VERSION:/ 文件版本号/ 在该块中有一个无符号短整型数保存了文件的版本/ 读入文件的版本号,并将字节数添加到bytesRead变量中m_CurrentChunk-bytesRead += fread(&version, 1, m_CurrentChunk-length - m_CurrentChunk-bytesRead, m_FilePointer);/ 如果文件版本号大于3,给出一个警告信息if (version 0x03)MessageBox(NULL, This 3DS file is over version 3 so it may load incorrectly, Warning, MB_OK);break;case OBJECTINFO:/ 网格版本信息/ 读入下一个块ReadChunk(m_TempChunk);/ 获得网格的版本号m_TempChunk-bytesRead += fread(&version, 1, m_TempChunk-length - m_TempChunk-bytesRead, m_FilePointer);/ 增加读入的字节数m_CurrentChunk-bytesRead += m_TempChunk-bytesRead;/ 进入下一个块ProcessNextChunk(pModel, m_CurrentChunk);break;case MATERIAL:/ 材质信息/ 材质的数目递增pModel-numOfMaterials+;/ 在纹理链表中添加一个空白纹理结构pModel-pMaterials.push_back(newTexture);/ 进入材质装入函数ProcessNextMaterialChunk(pModel, m_CurrentChunk);break;case OBJECT:/ 对象的名称/ 该块是对象信息块的头部,保存了对象了名称/ 对象数递增pModel-numOfObjects+;/ 添加一个新的tObject节点到对象链表中pModel-pObject.push_back(newObject);/ 初始化对象和它的所有数据成员memset(&(pModel-pObjectpModel-numOfObjects - 1), 0, sizeof(t3DObject);/ 获得并保存对象的名称,然后增加读入的字节数m_CurrentChunk-bytesRead += GetString(pModel-pObjectpModel-numOfObjects - 1.strName);/ 进入其余的对象信息的读入ProcessNextObjectChunk(pModel, &(pModel-pObjectpModel-numOfObjects - 1), m_CurrentChunk);break;case EDITKEYFRAME:/ 跳过关键帧块的读入,增加需要读入的字节数m_CurrentChunk-bytesRead += fread(buffer, 1, m_CurrentChunk-length - m_CurrentChunk-bytesRead, m_FilePointer);break;default: / 跳过所有忽略的块的内容的读入,增加需要读入的字节数m_CurrentChunk-bytesRead += fread(buffer, 1, m_CurrentChunk-length - m_CurrentChunk-bytesRead, m_FilePointer);break;/ 增加从最后块读入的字节数pPreviousChunk-bytesRead += m_CurrentChunk-bytesRead;/ 释放当前块的内存空间delete m_CurrentChunk;m_CurrentChunk = pPreviousChunk;4.2.4处理所有的文件中对象的信息ProcessNextObjectChunk函数处理所有的文件中对象的信息void CLoad3DS:ProcessNextObjectChunk(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk)int buffer50000 = 0;/ 用于读入不需要的数据/ 对新的块分配存储空间m_CurrentChunk = new tChunk;/ 继续读入块的内容直至本子块结束while (pPreviousChunk-bytesRead length)/ 读入下一个块ReadChunk(m_CurrentChunk);/ 区别读入是哪种块switch (m_CurrentChunk-ID)case OBJECT_MESH:/ 正读入的是一个新块/ 使用递归函数调用,处理该新块ProcessNextObjectChunk(pModel, pObject, m_CurrentChunk);break;case OBJECT_VERTICES:/ 读入是对象顶点ReadVertices(pObject, m_CurrentChunk);break;case OBJECT_FACES:/ 读入的是对象的面ReadVertexIndices(pObject, m_CurrentChunk);break;case OBJECT_MATERIAL:/ 读入的是对象的材质名称/ 该块保存了对象材质的名称,可能是一个颜色,也可能是一个纹理映射。同时在该块中也保存了/ 纹理对象所赋予的面/ 下面读入对象的材质名称ReadObjectMaterial(pModel, pObject, m_CurrentChunk);break;case OBJECT_UV:/ 读入对象的UV纹理坐标/ 读入对象的UV纹理坐标ReadUVCoordinates(pObject, m_CurrentChunk);break;default: / 略过不需要读入的块m_CurrentChunk-bytesRead += fread(buffer, 1, m_CurrentChunk-length - m_CurrentChunk-bytesRead, m_FilePointer);break;/ 添加从最后块中读入的字节数到前面的读入的字节中pPreviousChunk-bytesRead += m_CurrentChunk-bytesRead;/ 释放当前块的内存空间,并把当前块设置为前面块delete m_CurrentChunk;m_CurrentChunk = pPreviousChunk;425处理所有的材质信息ProcessNextMaterialChunk函数处理所有的材质信息void CLoad3DS:ProcessNextMaterialChunk(t3DModel *pModel, tChunk *pPreviousChunk)int buffer50000 = 0;/ 用于读入不需要的数据/ 给当前块分配存储空间m_CurrentChunk = new tChunk;/ 继续读入这些块,知道该子块结束while (pPreviousChunk-bytesRead length)/ 读入下一块ReadChunk(m_CurrentChunk);/ 判断读入的是什么块switch (m_CurrentChunk-ID)case MATNAME:/ 材质的名称/ 读入材质的名称m_CurrentChunk-bytesRead += fread(pModel-pMaterialspModel-numOfMaterials - 1.strName, 1, m_CurrentChunk-length - m_CurrentChunk-bytesRead, m_FilePointer);break;case MATDIFFUSE:/ 对象的R G B颜色ReadColorChunk(&(pModel-pMaterialspModel-numOfMaterials - 1), m_CurrentChunk);break;case MATMAP:/ 纹理信息的头部/ 进入下一个材质块信息ProcessNextMaterialChunk(pModel, m_CurrentChunk);break;case MATMAPFILE:/ 材质文件的名称/ 读入材质的文件名称m_CurrentChunk-bytesRead += fread(pModel-pMaterialspModel-numOfMaterials - 1.strFile, 1, m_CurrentChunk-length - m_CurrentChunk-bytesRead, m_FilePointer);break;default: / 掠过不需要读入的块m_CurrentChunk-bytesRead += fread(buffer, 1, m_CurrentChunk-length - m_CurrentChunk-bytesRead, m_FilePointer);break;/ 添加从最后块中读入的字节数pPreviousChunk-bytesRead += m_CurrentChunk-bytesRead;/ 删除当前块,并将当前块设置为前面的块delete m_CurrentChunk;m_CurrentChunk = pPreviousChunk;/ 下面函数读入块的ID号和它的字节长度void CLoad3DS:ReadChunk(tChunk *pChunk)/ 读入块的ID号,占用了2个字节。块的ID号象OBJECT或MATERIAL一样,说明了在块中所包含的内容pChunk-bytesRead = fread(&pChunk-ID, 1, 2, m_FilePointer);/ 然后读入块占用的长度,包含了四个字节pChunk-bytesRead += fread(&pChunk-length, 1, 4, m_FilePointer);4.2.6 读入RGB颜色ReadColorChunk函数读入RGB颜色void CLoad3DS:ReadColorChunk(tMaterialInfo *pMaterial, tChunk *pChunk)/ 读入颜色块信息ReadChunk(m_TempChunk);/ 读入RGB颜色m_TempChunk-bytesRead += fread(pMaterial-color, 1, m_TempChunk-length - m_TempChunk-bytesRead, m_FilePointer);/ 增加读入的字节数pChunk-bytesRead += m_TempChunk-bytesRead;4.2.7读入顶点索引ReadVertexIndices函数读入顶点索引void CLoad3DS:ReadVertexIndices(t3DObject *pObject, tChunk *pPreviousChunk)unsigned short index = 0;/ 用于读入当前面的索引/ 读入该对象中面的数目pPreviousChunk-bytesRead += fread(&pObject-numOfFaces, 1, 2, m_FilePointer);/ 分配所有面的存储空间,并初始化结构pObject-pFaces = new tFace pObject-numOfFaces;memset(pObject-pFaces, 0, sizeof(tFace) * pObject-numOfFaces);/ 遍历对象中所有的面for(int i = 0; i numOfFaces; i+)for(int j = 0; j bytesRead += fread(&index, 1, sizeof(index), m_FilePointer);if(j pFacesi.vertIndexj = index;4.2.7读入对象的UV坐标ReadUVCoordinates函数读入对象的UV坐标void CLoad3DS:ReadUVCoordinates(t3DObject *pObject, tChunk *pPreviousChunk)/ 为了读入对象的UV坐标,首先需要读入UV坐标的数量,然后才读入具体的数据/ 读入UV坐标的数量pPreviousChunk-bytesRead += fread(&pObject-numTexVertex, 1, 2, m_FilePointer);/ 分配保存UV坐标的内存空间pObject-pTexVerts = new CVector2 pObject-numTexVertex;/ 读入纹理坐标pPreviousChunk-bytesRead += fread(pObject-pTexVerts, 1, pPreviousChunk-length - pPreviousChunk-bytesRead, m_FilePointer);/ 读入对象的顶点void CLoad3DS:ReadVertices(t3DObject *pObject, tChunk *pPreviousChunk)/ 在读入实际的顶点之前,首先必须确定需要读入多少个顶点。/ 读入顶点的数目pPreviousChunk-bytesRead += fread(&(pObject-numOfVerts), 1, 2, m_FilePointer);/ 分配顶点的存储空间,然后初始化结构体pObject-pVerts = new CVector3 pObject-numOfVerts;memset(pObject-pVerts, 0, sizeof(CVector3) * pObject-numOfVerts);/ 读入顶点序列pPreviousChunk-bytesRead += fread(pObject-pVerts, 1, pPreviousChunk-length - pPreviousChunk-bytesRead, m_FilePointer);/ 现在已经读入了所有的顶点。/ 因为3D Studio Max的模型的Z轴是指向上的,因此需要将y轴和z轴翻转过来。/ 具体的做法是将Y轴和Z轴交换,然后将Z轴反向。/ 遍历所有的顶点for(int i = 0; i numOfVerts; i+)/ 保存Y轴的值float fTempY = pObject-pVertsi.y;/ 设置Y轴的值等于Z轴的值pObject-pVertsi.y = pObject-pVertsi.z;/ 设置Z轴的值等于-Y轴的值 pObject-pVertsi.z = -fTempY;4.2.8 读入对象的材质名称ReadObjectMaterial函数读入对象的材质名称void CLoad3DS:ReadObjectMaterial(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk)char strMaterial255 = 0;/ 用来保存对象的材质名称int buffer50000 = 0;/ 用来读入不需要的数据/ 材质或者是颜色,或者是对象的纹理,也可能保存了象明亮度、发光度等信息。/ 下面读入赋予当前对象的材质名称pPreviousChunk-bytesRead += GetString(strMaterial);/ 遍历所有的纹理for(int i = 0; i numOfMaterials; i+)/如果读入的纹理与当前的纹理名称匹配if(strcmp(strMaterial, pModel-pMaterialsi.strName) = 0)/ 设置材质IDpObject-materialID = i;/ 判断是否是纹理映射,如果strFile是一个长度大于1的字符串,则是纹理if(strlen(pModel-pMaterialsi.strFile) 0) / 设置对象的纹理映射标志pObject-bHasTexture = true;break;else/ 如果该对象没有材质,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 旅游安全管理报告
- 2025浙江省金华成泰农商银行社会招聘考试备考试题及答案解析
- 2025浙江金华市市场监督管理局窗口招聘1人笔试备考题库及答案解析
- 油井液面监测规范
- 2025榆林煤化消防员和消防驾驶员招聘(20人)笔试参考题库附带答案详解
- UML钞栏图规定和操作手册
- 2025西安光环电子科技有限公司招聘(3-5人)笔试备考试题及答案解析
- 心理治疗理论及方法制度手册制定方案制定
- 土地使用权许可审批管理规定细则
- 2025四川绵阳市中级人民法院招聘合同制审判辅助人员19人笔试参考题库附答案解析
- (完整版)水利部考试历年真题-水利基础知识试题集
- 医院客服主管年终总结
- 软件系统集成方案
- 幼儿园饮用水突发污染事故应急处理预案
- 联通技能竞赛考试题及答案(5G核心网知识部分)
- 政治-中国特色社会主义教材探究与分享参考答案高中政治统编版必修一
- 恶性贫血的动物模型构建和研究
- “余香萦绕”-2024年中考语文作文押题分析+学生习作+素材积累+金句积累
- 2024年秋新北师大版一年级上册数学教学课件 我上学啦 第5课时 收获的季节
- 2024年全国期货从业资格之期货投资分析考试高频题(附答案)
- 拨叉加工工艺及夹具设计毕业设计
评论
0/150
提交评论