3D中的OBJ⽂件格式详解(转载)
OBJ⽂件是Alias|Wavefront公司为它的⼀套基于⼯作站的3D建模和动画软件"Advanced Visualizer"开发的⼀种标准3D模型⽂件格式,很适合⽤于3D软件模型之间的互导,也可以通过Maya读写。⽐如你在3dsMax或LightWave中建了⼀个模型,想把它调到Maya⾥⾯渲染或动画,导出OBJ⽂件就是⼀种很好的选择。⽬前⼏乎所有知名的3D软件都⽀持OBJ⽂件的读写,不过其中很多需要通过插件才能实现。
OBJ⽂件是⼀种⽂本⽂件,可以直接⽤写字板打开进⾏查看和编辑修改。另外,有⼀种与此相关⼆进制⽂件格式(*.MOD),其作为专利未公开,因此这⾥不作讨论。
1、OBJ⽂件的特点
OBJ3.0⽂件格式⽀持直线(Line)、多边形(Polygon)、表⾯(Surface)和⾃由形态曲线(Free-form Curve)。直线和多⾓形通过它们的点来描述,曲线和表⾯则根据它们的控制点和依附于曲线类型的额外信息来定义,这些信息⽀持规则和不规则的曲线,包括那些基于贝塞尔曲线(Bezier)、B样条(B-spline)、基数(Cardinal/Catmull-Rom)和泰勒⽅程(Taylor equations)的曲线。其他特点如下:
(1)OBJ⽂件是⼀种3D模型⽂件。不包含动画、材质特性、贴图路径、动⼒学、粒⼦等信息。
(2)OBJ⽂件主要⽀持多边形(Polygons)模型。虽然也⽀持曲线(Curves)、表⾯(Surfaces)、点组材质(Poi
nt Group Materials),但Maya导出的OBJ⽂件并不包括这些信息。
(3)OBJ⽂件⽀持三个点以上的⾯,这⼀点很有⽤。很多其它的模型⽂件格式只⽀持三个点的⾯,所以导⼊Maya的模型经常被三⾓化了,这对于我们对模型进⾏再加⼯甚为不利。
(4)OBJ⽂件⽀持法线和贴图坐标。在其它软件中调整好贴图后,贴图坐标信息可以存⼊OBJ⽂件中,这样⽂件导⼊Maya后只需指定⼀下贴图⽂件路径就⾏了,不需要再调整贴图坐标。
2、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) umtl 材质名称(Material name) mtllib 材质库(Material library) shadow_obj 投射阴影(Shadow casting) trace_obj 光线跟踪(Ray tracing) ctech 曲线近似技术(Curve approximation technique) stech 表⾯近似技术 (Surface approximation technique)
3、OBJ⽂件实例
的确挺难理解,下⾯通过实例来具体讲解。让我们来创建⼀个OBJ⽂件,内容为⼀个四边形,不过这⼀回我们不⽤3D软件,⽽是⽤写字板来创建。打开写字板,把下⾯的5⾏代码写⼊,可以适当加⼀点注释。保存⽂件为⽂本格式,⽂件名为"myObj.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
注意:代码最后⼀定要按⼀下回车把光标切换到下⼀⾏,就是说加⼀个换⾏符(/n)。否则会看到如下错误信息: // Error: line 1: OBJ file line 5: index out of range. // // Error: line 1: Error reading file. //
在Maya中导⼊"myObj.obj"⽂件,看见了吧,导⼊了⼀个四边形。这个四边形的形状是完全由前⾯的那5⾏代码决定的。(图⽚暂⽆)
我们来分析⼀下这些代码。v -0.58 0.84 0武汉两日游
画⼀个四边形需要四个顶点,这是第⼀个顶点,"v"表⽰顶点(vertex),"-0.58"为这个顶点的X轴坐标值,"0.84"为Y轴坐标值,"0"为Z轴坐标值。它的索引号是1。索引号是画⾯时要⽤到的。 v 2.68 1.17 0 v 2.84 -2.03 0 v -1.92 -2.89 0 这分别是第⼆、三、四个顶点,它们的索引号分别是2,3,4。
f 1 2 3 4 现在开始画⾯,"f"表⽰⾯(face),1,2,3,4是前⾯那四个顶点的索引号。请注意画这个⾯连接点的顺序,是从第⼀个点出发,依次连接第⼆、三、四个点。
如果连接的顺序不同所⽣成的⾯也会截然不同,例如"f 1 2 4 3"会产⽣⼀个交迭的⾯,如上图。
社交礼仪论文⾯的连接点是按顺时针排列或逆时针排列,将决定⾯的法线⽅向(⾯的反正)。例如:"f 1 2 3 4"⾯的法线向外,"f 4 3 2 1"⾯的法线向⾥。⾯的连接点顺序错误,是导致导⼊模型产⽣碎⾯的⼀个重要原因。⼀个⾯不能出现两个以上相同的顶点,这也是检查OBJ⽂件出错的⼀个要点。例如:"f 1 2 3 4 3",有两个相同的顶点,索引号是3。⼀个⾯出现两个相同顶点,可能造成程序的内存分配错误。
下⾯来研究⼀下Maya导出的OBJ⽂件。
在Maya中创建⼀个多边形⽴⽅体,选中这个⽴⽅体,选择菜单"File -> "导出格式为OBJ,⽂件名为"cube.obj",如果没有此格式,请在Plug-in Manager中载⼊"objExport.mll"。⽤写字板打开"cube.obj",可以看到如下代码:
# The units ud in this file are centimeters. g default v -0.500000 -0.500000 0.500000 v 0.500000 -0.500000 0.500000 v -0.500000
0.500000 0.500000 v 0.500000 0.500000 0.500000 v -0.500000 0.500000 -0.500000 v 0.500000 0.5
00000 -0.500000 v -0.500000 -
梦见包子但没吃
0.500000 -0.500000 v 0.500000 -0.500000 -0.500000 vt 0.000000 0.000000 vt 1.000000 0.000000 vt 0.000000 1.000000 vt 1.000000
1.000000 vt 0.000000
2.000000 vt 1.000000 2.000000 vt 0.000000
3.000000 vt 1.000000 3.000000 vt 0.000000
4.000000 vt 1.000000
红焖羊肉的做法
4.000000 vt 2.000000 0.000000 vt 2.000000 1.000000 vt -1.000000 0.000000 vt -1.000000 1.000000 vn 0.000000 0.000000 1.000000 vn 0.000000 0.000000 1.000000 vn 0.000000 0.000000 1.000000 vn 0.000000 0.000000 1.000000 vn 0.000000 1.000000 0.000000 vn
0.000000 1.000000 0.000000 vn 0.000000 1.000000 0.000000 vn 0.000000 1.000000 0.000000 vn 0.000000 0.000000 -1.000000 vn
0.000000 0.000000 -1.000000 vn 0.000000 0.000000 -1.000000 vn 0.000000 0.000000 -1.000000 vn 0.000000 -1.000000 0.000000 vn
0.000000 -1.000000 0.000000 vn 0.000000 -1.000000 0.000000 vn 0.000000 -1.000000 0.000000 vn 1.000000 0.000000 0.000000 vn
1.000000 0.000000 0.000000 vn 1.000000 0.000000 0.000000 vn 1.000000 0.000000 0.000000 vn -1.000000 0.000000 0.000000 vn -1.000000 0.000000 0.000000 vn -1.000000 0.000000 0.000000 vn -1.000000 0.000000 0.000000 s off g pCube1 umtl initialShadingGroup f 1/1/1 2/2/2 4/4/3 3/3/4 f 3/3/5 4/4/6 6/6/7 5/5/8 f 5/5/9 6/6/10 8/8/11 7/7/12 f 7/7/13 8/8/14 2/10/15 1/9/16 f 2/2/17
8/11/18 6/12/19 4/4/20 f 7/13/21 1/1/22 3/3/23 5/14/24 这个⽂件看起来稍复杂⼀些,⽤到了许多关键词,你可以对照前⾯的列表查看⼀下每个关键词的意思。我来解释⼀下: "vt 1.000000 0.000000"这句"vt"代表点的贴图坐标。 "vn 0.000000 0.000000 -1.000000"这句"vn"代表点的法线。 "s off"表⽰关闭光滑组。 "umtl initialShadingGroup"表⽰使⽤的材质。 "f 7/13/21"这时在⾯的数据中多了贴图坐标uv点和法线的索引号,索引号分别⽤左斜线(/)隔开。格式:"f 顶点索引/uv点索引/法线索引"。
"g pCube1"表⽰组,这⾥的成组与Maya中的成组不⼀样,这⾥的成组是指把"g pCube1"后出现的⾯都结合到⼀起,组成⼀个整的多边形⼏何体。
把"cube.obj"⽂件修改⼀下就知道成组的意思了。把"s off"这句后⾯的代码替换成以下代码: umtl initialShadingGroup g pCube_Face1 f 1/1/1 2/2/2 4/4/3 3/3/4 g pCube_Face2 f 3/3/5 4/4/6 6/6/7 5/5/8 g pCube_Face3 f 5/5/9 6/6/10 8/8/11 7/7/12 g pCube_Face4 f 7/7/13 8/8/14 2/10/15 1/9/16 g pCube_Face5 f 2/2/17 8/11/18 6/12/19 4/4/20 g pCube_Face6 f 7/13/21 1/1/22 3/3/23 5/14/24 导⼊Maya后可以看到,⽴⽅体的每个⾯是分离的,每个⾯的名称分别是"pCube_Face(1~6)",可见组的名称其实就是单独⼏何体的名称。
可不可以⽤中⽂命名⼏何体(组)呢?试试就知道了,把前⾯的代码改成: umtl initialShadingGroup g ⽴⽅体⾯1 f 1/1/1 2/2/2 4/4/3 3/3/4 g ⽴⽅体⾯2 f 3/3/5 4/4/6 6/6/7 5/5/8 g ⽴⽅体⾯3 f 5/5/9 6/6/10 8/8/11 7/7/12 g ⽴⽅体⾯4 f 7/7/13 8/8/14 2/10/15 1/9/16 g ⽴⽅体⾯5 f 2/2/17
8/11/18 6/12/19 4/4/20 g ⽴⽅体⾯6 f 7/13/21 1/1/22 3/3/23 5/14/24
试⼀下,会发现模型顺利的导⼊了。虽然物体的名称都变乱码了,可这并不是很严重的事。不过使⽤中⽂名并不总是这么顺利,把"g ⽴⽅体⾯1"这⾏改为"g 选择"再试试看,这回导⼊时模型根本⽆法出现,只会出现如下的错误信息: // Error: line 1: Your OBJ file contains a line which is too long to be pard. Plea edit your obj file. // // Error: line 1: Error reading file. // 由此可见,物体命名的不规范也是导致OBJ⽂件出错的原因之⼀。关于Maya的物体命名,英⽂名是很保险的,标点符号中只有下划
线(_)可⽤,数字不能⽤放到名称的开头,尽量不要⽤中、⽇、韩等双字节⽂字。 OBJ⽂件不⽀持有孔的多边形⾯。举个例⼦说明⼀下:选择Maya的创建多边形⼯具(Polygons -> Create Polyon Tool),在视图中画⼀个四边形,不要按回车,按Ctrl在四边形中间点⼀下,可以继续在四边形中挖⼀个洞。把这个有孔的多边形存成OBJ格式,在导⼊Maya时,会发现多边形少了⼀块。如果你把这也看成错误,现在⾄少你已经知道错误的原因了,就是OBJ⽂件不⽀持有孔的多边形⾯。
转⾃:
4、OBJ⽂件的实际问题:
现在来讨论⼀点⽐较实际的问题吧,就是⼀旦你遇到了⼀个出错的OBJ⽂件,倒底该怎么办?
当你打开OBJ⽂件后,往往会看到有⼏万⾏的代码,你恐怕还没本事情⼀眼看出错误所在⾏,除⾮程序的错误信息中已经告诉你错误⾏。如果你不知道错误在哪⾥,可以⽤排除法,弄清楚肯定正确的代码范围,通过缩减错误代码范围定位错误。例如,你先新建⼀个空的OBJ⽂件,把有错的OBJ⽂件代码粘贴⼀半过来,然后把这个只有⼀半代码的新OBJ⽂件导⼊Maya。如果这时没有错误信息,说明错误⾏是在另⼀半代码中,可以从另⼀半代码中再粘贴⼀部分代码试试看;如果这时出现错误,说明错误⾏就在粘贴的代码中,可以把粘贴过来的代码删去⼀部分再试试看。就这样,逐步缩减范围直到找到错误⾏为⽌。
这种⽅法虽然很⿇烦,不过颇为有效。如果你不会编程,⼜遇到⾮常紧急的情况,这种⽅法还是值得⼀试的。
5、OBJ⽂件的更多细节:
简单的OBJ格式写法。 # Simple Wavefront file v 0.0 0.0 0.0 v 0.0 1.0 0.0 v 1.0 0.0 0.0 f 1 2 3
⾯可以使⽤负值索引,有时⽤负值索引描述⾯更为简便。
v -0.500000 0.000000 0.400000 v -0.500000 0.000000 -0.800000 v -0.500000 1.000000 -0.800000 v -0.500000 1.000000 0.400000 f -4 -3 -2 -1
"f -4 -3 -2 -1"这句索引值"-3"表⽰从"f"这⾏往上数第3个顶点,就是"v -0.500000 0.000000 -0.800000",其它的索引值以此类推。因此与这⼀⾏等效的正值索引写法为:"f 1 2 3 4"
OBJ⽂件不包含⾯的颜⾊定义信息,不过可以引⽤材质库,材质库信息储存在⼀个后缀是".mtl"的独⽴⽂件中。关键字"mtllib"即材质库的意思。材质库中包含材质的漫射(diffu),环境(ambient),光泽(specular)的RGB(红绿蓝)的定义值,以及反射(specularity),折射(refraction),透明度(transparency)等其它特征。"umtl"指定了材质之后,以后的⾯都是使⽤这⼀材质,直到遇到下⼀个"umtl"来指定新的材质。
指定材质的⽅法: Cube with Materials: # This cube has a different material # applied to each of its faces. l v 0.000000 2.000000 2.000000 v 0.000000 0.000000 2.000000 v 2.000000 0.000000 2.000000 v 2.000000 2.000000 2.000000 v 0.000000 2.000000 0.000000 v 0.000000 0.000000 0.000000 v 2.000000 0.000000 0.000000 v 2.000000 2.000000 0.000000 # 8 vertices g front umtl red f 1
2 3 4 g back umtl blue f 8 7 6 5 g right umtl green f 4 3 7 8 g top umtl gold f 5 1 4 8 g left umtl orange f 5 6 2 1 g bottom umtl purple f 2 6 7 3 # 6 elements
贝塞尔⽚⾯(Bezier Patch): Maya不能导出OBJ格式的贝塞尔⽚⾯,却能够导⼊它。导⼊的贝塞尔⽚⾯⾃动转换为Nurbs表⾯。 # 3.0 Bezier patch v -5.000000 -5.000000 0.000000 v -5.000000 -1.666667 0.000000 v -5.000000 1.666667 0.000000 v -5.000000 5.000000 0.000000 v -1.666667 -5.000000 0.000000 v -1.666667 -1.666667 0.000000 v -1.666667 1.666667 0.000000 v -1.666667 5.000000 0.000000 v
1.666667 -5.000000 0.000000 v 1.666667 -1.666667 0.000000 v 1.666667 1.666667 0.000000 v 1.666667 5.000000 0.000000 v 5.000000 -5.000000 0.000000 v 5.000000 -1.666667 0.000000 v 5.000000 1.666667 0.000000 v 5.000000 5.000000 0.000000 # 16 vertices cstype bezier deg 3 3 #
Example of line continuation surf 0.000000 1.000000 0.000000 1.000000 13 14 / 15 16 9 10 11 12 5 6 7 8 1 2 3 4 parm u 0.000000 1.000000 parm v 0.000000 1.000000 end # 1 element
项目副经理岗位职责基数曲线(Cardinal Curve): Maya好像不⽀持OBJ格式的曲线,导⼊时不会出现错误信息,却也不会出现曲线。 # 3.0 Cardinal curve v
0.940000 1.340000 0.000000 v -0.670000 0.820000 0.000000 v -0.770000 -0.940000 0.000000 v 1.030000 -1.350000 0.000000 v
3.070000 -1.310000 0.000000 # 6 vertices cstype cardinal deg 3 curv 0.000000 3.000000 1 2 3 4 5 6 parm u 0.000000 1.000000 2.000000 3.000000 end # 1 element
贴图映射(Texture-Mapped): # A 2 x 2 square mapped with a 1 x 1 square # texture stretched to fit the square exactly. l v
0.000000 2.000000 0.000000 v 0.000000 0.000000 0.000000 v 2.000000 0.000000 0.000000 v 2.000000 2.000000 0.000000 vt 0.000000
毕业证书丢失怎么补1.000000 0.000000 vt 0.000000 0.000000 0.000000 vt 1.000000 0.000000 0.000000 vt 1.000000 1.000000 0.000000 # 4 vertices umtl wood # The first number is the point, # then the slash, # and
the cond is the texture point f 1/1 2/2 3/3 4/4 # 1 element