http://www.cnblogs.com/kex1n/archive/2011/09/23/2186351.html
接下来要介绍的模型文件格式是OBJ格式。该格式非常流行,而且可以使用大量3D建模软件导出。OBJ是一种简单的格式,它是可以用任何文本编辑器打开和保存的文本文件。准确的说,OBJ文件并不是设计用于处理与动画相关的信息,但如果有一个需要快速加载到场景中的静态对象,OBJ也许会有用。已经被导出OBJ格式的模型由顶点、法线、纹理坐标和三角形索引(外观)组成。因此,在OBJ格式中将不为除了简单静态网格之外的任何对象使用模型。
【注意】
使用由不同类型软件导出的OBJ文件时一定要慎重。例如,用Lightwave7.5创建的OBJ文件就不同于3D Studio Max导出的OBJ文件。试着用为稍有不同类型文件编写的代码打开用Lightwave7.5创建的OBJ文件会产生错误。为了避免出现错误,这里只加载文件开始处包含Wavefront的OBJ文件。
12.3.1 OBJ文件格式介绍
诚如所知,OBJ格式是基于文本的格式。在OBJ文件中每行开始处的单词将决定这一行所代表的信息。如果该行是以字母v开头,那么跟随它后面的将是三个不同的浮点值以代表顶点位置。如果该行以字母vt开头,那么跟随它后面的将是两个不同的浮点值以代表纹理坐标。跟随在vn后面的将是代表法线的三个浮点值。通常,跟随在f后面的是三对索引值。每组索引代表一个三角形,由三个索引索引构成,一个代表顶点,一个代表该顶点的纹理坐标,最后一个代表该顶点使用的法线。例如,1/1/1,2/3/2,3/1/2。第一组意味着三角形的第一个顶点使用顶点数组中的第一个顶点,纹理坐标数组中的第一个纹理坐标,法线数组中的第一个法线。第二组意味着该三角形的第二个顶点使用顶点数组中的第二个顶点,纹理坐标数组中的第三个纹理坐标,法线数组中的第二个法线。所以这三对中的每一对都是用索引描述顶点、纹理坐标和法线数组。由于有三组数值,所以每个顶点用一个,每个顶点都有自己的位置、纹理坐标和法线。某些点也许会共用位置、纹理坐标和/或法线,这样可以重用数据。
除了提到的这些字符之外,还有一些其他字符,如mtllib,它指的是为模型保存材质信息的文件名,#号和C语言中的注释符号“//”的功能一样。程序清单12.12给出了MilkShape3D导出的OBJ模型文件示例。
程序清单12.2 OBJ格式的纹理立方体示例
# Wavefront OBJ exported by MilkShape 3D
mtllib test.mtl
v -21.000000 20.750000 20.750000
v -21.000000 -21.250000 20.750000
v -21.000000 20.750000 20.750000
v -21.000000 -21.250000 20.750000
v -21.000000 20.750000 -19.000000
v -21.000000 -21.250000 -19.000000
v -21.000000 20.750000 -19.000000
v -21.000000 -21.250000 -19.000000
# 8 vertices
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 1.000000
vt 1.000000 0.000000
# 4 texture coordinates
vn 0.000000 0.000000 1.000000
vn 1.000000 0.000000 0.000000
vn 0.000000 0.000000 -1.000000
vn -1.000000 0.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 -1.000000 1.000000
# 6 normals
g Box01
usemtl Material01
s 1
f 1/1/1 2/2/1 3/3/1
f 2/2/1 4/4/1 3/3/1
s 2
f 3/1/2 4/2/2 5/3/2
f 4/2/2 6/4/2 5/3/2
s1
f 5/1/3 6/2/3 7/3/3
f 6/2/3 8/4/3 7/3/3
s2
f 7/1/4 8/2/4 1/3/4
f 8/2/4 2/4/4 1/3/4
s3
f 7/1/5 1/2/5 5/3/5
f 1/2/5 3/4/5 5/3/5
f 2/1/6 8/2/6 4/3/6
f 8/2/6 6/4/6 4/3/6
# 12 triangles in group
# 12 triangles total
由程序清单12.12可以看到,一旦定义完所有的顶点、纹理坐标和法线,接下来就是定义每个对象。开始先是对象名称、对象使用的从文件中得到的文件名以及构成该对象的多边形。一旦读取完最后一个外观,要么是在文件结尾处,要么就是准备开始读取另一个对象。如果读取的内容既不是注释,也不是文件结尾标识符,那么可以假定还有要读取的对象。一直读取直到所有的对象都被读取出来为止。在定义对象时,文件在顶点、纹理坐标和法线的数组中使用索引。有共同边、纹理坐标和法线的对象就可以让文件比平常的要小一些。然而,在Direct3D中创建对象时,不得不查找所有的数据而不是像这样一样可以直接使用的索引。
和OBJ文件自身一起,同样还要材质文件。材质文件通常包含了.MTL扩展名,以及为对象添加纹理所需的全部信息。像OBJ文件一样,.MTL文件每行包含了一些其后跟随数据的字符。这包括代表环境属性的Ka、代表漫反射的Kd、代表镜面反射的Ks以及代表反射能量的Ns。如果在材质文件中见到newmtl这样的单词,就意味要定义一种新材质。map_Kd表示材质包含与它关联的纹理图像,而且这一行后面就是纹理图像的文件名。MilkShape3D导出的.MTL材质文件示例如程序清单12.13所示。
程序清单12.13 OBJ模型使用的材质文件示例
#
# test.mtl
#
newmtl Material01
Ka 0.200000 0.200000 0.200000
Ka 0.800000 0.800000 0.800000
Ks 0.000000 0.000000 0.000000
Ns 0.000000
map_Kd .\decal.tga
导出到OBJ的模型基于文本,它们是易于分析。大量不同的建模软件可以导出为Wavefront OBJ文件格式,当与静态对象打交道时,或是如果需要在将其转换成自定义的类型之前将模型转换成中间格式,这非常有用。使用不同类型的软件导出OBJ文件一定要慎重。回忆一下,LightWave 7.5并不能导出Wavefront OBJ文件,如果不作为一些预防措施,就会产生大量的错误。当为加载OBJ文件的演示程序编写代码时,一定要添加检查语句,以查看Wavefront单词是否出现在文件顶部的某个位置。如果出现了这个单词,就可以假定软件导粗豪的OBJ文件使用的是Wavefront格式。