OBJ文件格式

    OBJ文件格式是非常简单的。这种文件以纯文本的形式存储了模型的顶点、法线和纹理坐标和材质使用信息。OBJ文件的每一行,都有极其相似的格式。在OBJ文件中,每行的格式如下:

前缀 参数1 参数2 参数3 ...

    其中,前缀标识了这一行所存储的信息类型。参数则是具体的数据。OBJ文件的前缀可以有:

表7.2-1 OBJ文件中的前缀
前缀

说明

v表示本行指定一个顶点。
此前缀后跟着3个单精度浮点数,分别表示该定点的X、Y、Z坐标值
vt表示本行指定一个纹理坐标。
此前缀后跟着两个单精度浮点数。分别表示此纹理坐标的U、V值
vn表示本行指定一个法线向量。
此前缀后跟着3个单精度浮点数,分别表示该法向量的X、Y、Z坐标值
f表示本行指定一个表面(Face)。
一个表面实际上就是一个三角形图元。此前缀行的参数格式后面将详细介绍。
usemtl此前缀后只跟着一个参数。该参数指定了从此行之后到下一个以usemtl开头的行之间的所有表面所使用的材质名称。该材质可以在此OBJ文件所附属的MTL文件中找到具体信息。
mtllib此前缀后只跟着一个参数。该参数指定了此OBJ文件所使用的材质库文件(*.mtl)的文件路径

    我们使用3DS Max创建了一个长方体,并保存为OBJ格式。用写字板打开这个OBJ文件,可以看到如下内容:

# Max2Obj Version 4.0 Mar 10th, 2001
#
mtllib ./Box.mtl
g
# object (null) to come ...
#
v -46.508743 -45.052959 50.796341
v 49.442947 -45.052959 50.796341
v -46.508743 -45.052959 -48.019585
v 49.442947 -45.052959 -48.019585
v -46.508743 48.034504 50.796341
v 49.442947 48.034504 50.796341
v -46.508743 48.034504 -48.019585
v 49.442947 48.034504 -48.019585
# 8 vertices

vt 0.000000 0.000000 0.000000
vt 1.000000 0.000000 0.000000
vt 0.000000 1.000000 0.000000
vt 1.000000 1.000000 0.000000
vt 0.000000 0.000000 0.000000
vt 1.000000 0.000000 0.000000
vt 0.000000 1.000000 0.000000
vt 1.000000 1.000000 0.000000
vt 0.000000 0.000000 0.000000
vt 1.000000 0.000000 0.000000
vt 0.000000 1.000000 0.000000
vt 1.000000 1.000000 0.000000
# 12 texture vertices

g (null)
s 2
f 1/10 3/12 4/11
f 4/11 2/9 1/10
s 4
f 5/9 6/10 8/12
f 8/12 7/11 5/9
s 8
f 1/5 2/6 6/8
f 6/8 5/7 1/5
s 16
f 2/1 4/2 8/4
f 8/4 6/3 2/1
s 32
f 4/5 3/6 7/8
f 7/8 8/7 4/5
s 64
f 3/1 1/2 5/4
f 5/4 7/3 3/1
# 12 faces

g

    仔细观察,你会发现这个文件中包含了一些我们没有提到的前缀,如以“#”开头的注释,以g开头的表示组的前缀等等。但这些前缀并不影响模型的外观,因此我们可以忽略它们。

    在解释以f为前缀的行的格式之前,我们不得不提一个新的概念,这就是顶点索引(Vertex Indices)。我们知道,对于每一个三角形,都需要用3个顶点来表示。例如在上面的立方体模型中,一共有6×2×3=36个顶点。仔细想想就会知道,在这36个顶点中,又相当数量的顶点是重合的。如果把这些重合的顶点都一一表示出来,就太浪费存储空间了。于是,我们提出了顶点索引的想法,解决空间占用问题。顶点索引的思想是建立两个数组,一个数组用于存储模型中所有的顶点坐标值,另一个数组则存储每一个表面所对应的三个顶点在第一个数组中的索引。

    建立这样的顶点索引显然更加节约存储空间。

    假设Indices:array of Integer是顶点索引数组,Vertices:array of TVertex是顶点数组,使用下面的代码段就可以把整个顶点索引对应的所有三角形绘制出来:

procedure DrawIndex(Indices:array of Integer;Vertices:array of TVertex);

var i :Integer;

begin

   glBegin(GL_TRIANGLES);

   for i := 0 to (High(Vertices)+1) div 3 -1 do

   begin

     glVertex3fv(@Vertices[Indices[i*3]]);

     glVertex3fv(@Vertices[Indices[i*3+1]]);

     glVertex3fv(@Vertices[Indices[i*3+2]]);

   end;

   glEnd;

end;

    以此类推,我们可以为模型中所有的法线、纹理坐标都建立起相应的索引,以节省更多的空间。而事实上,OBJ文件就是这么做的。

    现在,我们再来看一下OBJ文件的结构。在一个OBJ文件中,首先有一些以v、vt或vn前缀开头的行指定了所有的顶点、纹理坐标、法线的坐标。然后再由一些以f开头的行指定每一个三角形所对应的顶点、纹理坐标和法线的索引。在顶点、纹理坐标和法线的索引之间,使用符号“/”隔开的。一个f行可以以下面几种格式出现:

f 1 2 3

    这样的行表示以第1、2、3号顶点组成一个三角形。

f 1/3 2/5 3/4

    这样的行表示以第1、2、3号顶点组成一个三角形,其中第一个顶点的纹理坐标的索引值为3,第二个顶点的纹理坐标的索引值为5,第三个顶点的纹理坐标的索引值为4。

f 1/3/4 2/5/6 3/4/2

    这样的行表示以第1、2、3号顶点组成一个三角形,其中第一个顶点的纹理坐标的索引值为3,其法线的索引值是4;第二个顶点的纹理坐标的索引值为5,其法线的索引值是6;第三个顶点的纹理坐标的索引值为6,其法线的索引值是2。

f 1//4 2//6 3//2

    这样的行表示以第1、2、3号顶点组成一个三角形,且忽略纹理坐标。其中第一个顶点的法线的索引值是4;第二个顶点的法线的索引值是6;第三个顶点的法线的索引值是2。

    值得注意的是文件中的索引值是以1作为起点的,这一点与Delphi中以0作为起点有很大的不同。在渲染的时候应注意将从文件中读取的坐标值减去1。

增加阅读:

OBJ文件 -- 基本结构
OBJ文件不需要任何种文件头(File Header),尽管经常使用几行文件信息的注释作为文件的开头。
OBJ文件由一行行文本组成,注释行以一个“井”号(#)为开头,空格和空行可以随意加到文件中以增加文件的可读性。有字的行都由一两个标记字母也就是关键字(Keyword)开头,关键字可以说明这一行是什么样的数据。多行可以逻辑地连接在一起表示一行,方法是在每一行最后添加一个连接符(/)。
注意连接符(/)后面不能出现空格或tab格,否则将导致文件出错。

  下列关键字可以在OBJ文件使用。
  在这个列表中, 关键字根据数据类型排列,每个关键字有一段简短描述。
  顶点数据(Vertex data):
   v 几何体顶点 (Geometric vertices)
  vt 贴图坐标点 (Texture vertices)
  vn 顶点法线 (Vertex normals)
  vp 参数空格顶点 (Parameter space vertices)
  自由形态曲线(Free-form curve)/表面属性(surface attributes):
  deg 度 (Degree)
  bmat 基础矩阵 (Basis matrix)
  step 步尺寸 (Step size)
  cstype 曲线或表面类型 (Curve or surface type)
  元素(Elements):
  p 点 (Point)
  l 线 (Line)
  f 面 (Face)
  curv 曲线 (Curve)
  curv2 2D曲线 (2D curve)
  surf 表面 (Surface)
  自由形态曲线(Free-form curve)/表面主体陈述(surface body statements):

  parm 参数值 (Parameter values )
  trim 外部修剪循环 (Outer trimming loop)
  hole 内部整修循环 (Inner trimming loop)
  scrv 特殊曲线 (Special curve)
  sp 特殊的点 (Special point)
  end 结束陈述 (End statement)
  自由形态表面之间的连接(Connectivity between free-form surfaces):

  con 连接 (Connect)
-  成组(Grouping):
   g 组名称 (Group name)
  s 光滑组 (Smoothing group)
  mg 合并组 (Merging group)
  o 对象名称 (Object name)
-  显示(Display)/渲染属性(render attributes):

  bevel 导角插值 (Bevel interpolation)
  c_interp 颜色插值 (Color interpolation)
  d_interp 溶解插值 (Dissolve interpolation)
  lod 细节层次 (Level of detail)
  usemtl 材质名称 (Material name)
  mtllib 材质库 (Material library)
  shadow_obj 投射阴影 (Shadow casting)
  trace_obj 光线跟踪 (Ray tracing)
  ctech 曲线近似技术 (Curve approximation technique)
  stech 表面近似技术 (Surface approximation technique)


  的确挺难理解,所以要用实例来说明。
  OBJ文件 -- 实例:
  下面通过实例来具体讲解。
  OBJ文件记录一个四边形的代码:
  v -0.58 0.84 0
  v 2.68 1.17 0
  v 2.84 -2.03 0
  v -1.92 -2.89 0
  f 1 2 3 4

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值