写在前面
OBJ格式是一种简单的文本格式,用于描述三维模型的几何形状和材质信息,因为其文本格式的属性,学习OBJ格式能够很好理解在3D图形中是如何描述一个3D对象的。OBJ通常由顶点、法线、纹理坐标和面片组成,可以包含多个对象和材质。OBJ格式通常用于编辑器和渲染器之间的数据交换,以便在不同的软件中共享和处理三维模型数据。由于其简单易读的特性,OBJ格式在计算机图形学领域中被广泛应用,目前几乎所有知名的3D软件都支持OBJ文件的读写。
如果大家需要可用的OBJ格式3D模型,点这里。
OBJ格式解析
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文件示例
# Blender v2.64 (sub 0) OBJ File: 'nanosuit.blend'
# www.blender.org
mtllib nanosuit.mtl
o Visor
v 0.320384 14.057541 0.507779
v 0.385196 13.984534 0.445066
v 0.416643 14.114325 0.462461
......
......
v -0.216001 14.187331 0.577817
v -0.397356 14.114325 0.462461
v -0.365670 13.984534 0.445066
vt 0.439941 0.453613
vt 0.541992 0.372070
vt 0.564941 0.521973
......
......
vt 0.046417 0.900818
vt 0.447510 0.627197
vt 0.446777 0.559082
vn 0.496902 -0.240822 0.833674
vn 0.524613 -0.236702 0.817743
vn 0.581713 -0.161901 0.797082
......
......
vn -0.421766 -0.127873 0.897610
vn -0.571764 -0.123020 0.811121
vn -0.523911 -0.237526 0.817957
usemtl Glass
s 1
f 1/1/1 2/2/2 3/3/3
f 4/4/4 5/5/5 6/6/6
f 6/6/6 7/7/7 4/4/4
......
......
f 37/14/37 51/3/51 47/28/47
f 48/1/48 47/28/47 51/3/51
f 51/3/51 52/2/52 48/1/48
上面给出了一个obj对象内容节选,可以看到用到的关键字并不多,一般情况只需要掌握这些基本关键字。
#
后面的内容表示注释。mtllib
关键字后参数为文件名称,指定了obj文件所使用的材质库文件(mtl文件)的文件名称。o
关键字表示开始一个对象,一个对象包含顶点、纹理坐标、法向量、材质等信息。v
关键字表示对象中的顶点坐标信息,依次为x、y、z分量。vt
关键字表示纹理坐标,依次为x、y两个分量。值大小一般在0~1之间。vn
关键字表示法向量信息,依次为x、y、z分量。usemtl
关键字后参数为材质名称,指定了从此行之后到下一个以usemtl开头的行之间的所有表面所使用的材质名称,该材质可以在此obj文件所附属的mtl文件中找到具体信息。f
关键字后跟的是面信息,有以下几种格式:- 顶点索引:以f v1 v2 v3的格式分配的面片。v1、v2、v3等是顶点序号,以文件中第一个v标志行为1,逐个递增。一个面片至少分配3个顶点,但可以分配超过3个顶点,即obj格式不保证三角面。面中顶点的声明顺序一般按逆时针方向,即遵循右手螺旋定则。
- 顶点纹理坐标索引:以f v1/vt1 v2/vt2 v3/vt3的格式分配的面片。v1、v2、v3等是顶点序号,vt1、vt2、vt3等是对应顶点的纹理坐标序号,序号分配方式和v类似。
- 顶点法线索引:以f v1//vn1 v2//vn2 v3//vn3的格式分配的面片。v1、v2、v3等是顶点序号,vn1、vn2、vn3等是对应顶点的法线方向序号,序号分配方式和v类似。
- 顶点纹理法线索引:以f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3的格式分配的面片。v1、v2、v3等是顶点序号,vt1、vt2、vt3等是对应顶点的纹理坐标序号,vn1、vn2、vn3等是对应顶点的法线方向序号。
MTL文件
obj文件不包含面的颜色定义信息,不过可以引用材质库,材质库信息储存在一个后缀是".mtl"的独立文件中。mtl文件是obj文件附属的材质库文件,材质库中包含材质的漫射(diffuse),环境(ambient),光泽(specular)的RGB的定义值,以及反射(specularity),折射(refraction),透明度(transparency)等其它特征。
mtl文件关键字:
- newmtl: 定义新的材质组,后面参数为材质组名称
- Ka: 材质的环境光颜色(ambient color)
- Kd: 材质的散射光颜色(diffuse color)
- Ks: 材质的镜面光颜色(specular color)
- Ke: 材质的放射光颜色(emissive color)
- Ns: 材质的光亮度
- d,Tr 均可用于定义材质的Alpha透明度
- sharpness:材质的锐度(sharpness)
- illum: 照明度(illumination)后面可接0~10范围内的数字参数
- 0 Color on and Ambient off
- 1 Color on and Ambient on
- 2 Highlight on
- 3 Reflection on and Ray trace on
- 4 Transparency: Glass on
Reflection: Ray trace on - 5 Reflection: Fresnel on and Ray trace on
- 6 Transparency: Refraction on
Reflection: Fresnel off and Ray trace on - 7 Transparency: Refraction on
Reflection: Fresnel on and Ray trace on - 8 Reflection on and Ray trace off
- 9 Transparency: Glass on ,Reflection: Ray trace off
- 10 Casts shadows onto invisible surfaces
- Ni : 材质的光密度(optical density)
- Tf: 材质的透射滤波(transmission filter),对应数据为r,g,b值
- map_Ka、map_Kd、map_Ks、map_Bump表示材质的环境,散射、镜面和凹凸贴图,对应数据为贴图文件名称
- refl: 材质的反射属性
下面节选了部分mtl文件。当描述一个模型时,如果材质颜色单一,可以直接使用Ka、Kd和Ks来描述材质的环境光颜色、散射光颜色和镜面光颜色。当材质颜色丰富的时候,如果要描述则需要大量的数据,这种情况更适合通过map_Ka、map_Kd和map_Ks来描述材质的环境光颜色、散射光颜色和镜面光颜色。这样渲染过程中结合模型的纹理坐标vt
就能通过颜色采样获取各个点的材质颜色。
# Blender MTL File: 'nanosuit.blend'
# Material Count: 6
newmtl Arm
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
map_Kd arm_dif.png
map_Bump arm_showroom_ddn.png
map_Ks arm_showroom_spec.png
......
......
OBJ渲染简述
以OpenGL渲染为例,首先需要的是模型的顶点信息v
,顶点信息决定了几何形状。其次渲染过程还需要得到模型的颜色信息。为了模拟现实场景中的光照,采用冯氏光照模型计算颜色信息。obj格式提供关于颜色计算的相关参数也是和冯氏光照基本对应的。冯氏光照中将光照分为环境光、散射光(漫反射光)和镜面反射光。obj对应的mtl文件中提供了map_Ka
、map_Kd
和map_Ks
贴图,结合obj文件中的纹理坐标vt
对这些贴图进行采样,获取采样值后结合法向量vn
和光源信息用冯氏光照模型计算就能得到每个顶点环境光、散射光颜色和镜面反射光颜色。由于结合了光源信息,这样计算出来的颜色会随着光源变化而变化,模拟了现实场景。
注意并不是所有mtl文件中都包含map_Ka、map_Kd和map_Ks贴图,有的可能只有一个或者两个贴图。另外贴图是以路径的形式给出,如果路径没有前缀信息,需要在加载模型时将贴图、obj和mtl文件放在同级目录。如果mtl文件中没有光照贴图,那就只能通过Ka
、Kd
和Ks
作为环境光、散射光和镜面反射光,一般用于模型颜色单一的场景。
欢迎留言讨论,创作不易,感谢点赞、关注和收藏~