[iTyran原创]iPhone中OpenGL ES显示3DS MAX模型之一:OBJ文件格式分析
作者:yuezang - iTyran

    在iOS的3D开发中常常需要导入通过3DS MAX之类的3D设计软件生成的模型。因为OpenGL ES是不能直接读取这些文件的,所以常常需要开发人员增加接口来导入。通常的做法是在建模软件中建立3D模型之后在OpenGL ES中导入并进行控制。
    3DS MAX通常的保存格式有*.max(现在生成的版本的格式),*.3ds(低版本的3ds Max生成的格式),*.ASC(ASC File Explorer),*.ASE(ASCII Scene Explorer),*.OBJ等文件格式。其他的软件保存的格式也是不尽相同的,同样的,这些软件和格式在保存数据方面也是各有各的不同。为了通用,我们选择比较通用的OBJ格式来作为讲解的例子,如果其他格式大家有需要的话,可以自己去研究数据保存的格式,至于读取的方式都是大同小异的。

1.    从3DS Max中导出OBJ文件
首先,咱们打开3DS Max并且随便创建一个模型,比如下面这个(简单的有点简陋了……)

画完以后,将文件导出为.obj格式,注意这里说的是导出,如果是选保存的话是找不到.obj格式的。导出的步骤是:
1)    打开“文件”菜单,选中里面的“导出”选项;
2)    在“导出”对话框中选择“Wavefront Object(*.OBJ)”,输入文件名后选“保存”,这里比如“test.obj”;

3)    在点击“保存”以后会弹出一个名叫“对象导出器”对话框,一般按下面这样选就可以了,其中要注意的就是“面”选项中要选择“Triangles”选项,这样的话将选择三角形作为基本图元;

4)    点击“确定”后打开“导出MTL”对话框,这个对话框是用来设置和OBJ文件配合使用的.MTL文件的,MTL文件主要用来保存材质信息,一般按下面的样子勾选就可以了;

5)    点击“确定”后生成了两个文件分别为“test.obj”和“test.mtl”。

2.    OBJ文件格式分析
    直接用记事本或者其他文本编辑工具打开test.obj文件,在开头可以看到这样的一些字符串:

# Max2Obj Version 4.0 Mar 10th, 2001
#
mtllib ./test.mtl
g
# object (null) to come ...
#

这里要注意的是在.obj文件中”#”号是作为注释符的(类似于bash等脚本)。Mtlib语句声明了引用的mtl文件的相对路径。接下来的行中得字符”g”在obj文件中表示的是组。
再往下看可以看到类似的内容

v  7.268521 0.000000 -2.808495
v  43.775921 3.692307 -11.804825
v  40.087490 4.896347 -20.872227
……
vt  0.500000 0.000000 0.000000
vt  0.750000 0.000000 1.000000
vt  0.791667 0.000000 1.000000
……
vn  0.061305 -0.985877 -0.155850
vn  0.176545 -2.839121 -0.448815
vn  0.176545 -2.839120 -0.448815
……
g (null)
s 1
f 1/1/1 3/3/3 2/2/2
f 1/1/1 4/4/4 3/3/3
f 1/1/1 5/5/5 4/4/4
……

从上面可以看出一般的obj文件中数据的格式是这样的:
     前缀    参数1    参数2    参数3 …
     前缀标识了这一行所存储的信息类型。参数则是具体的数据。OBJ文件数据类型的前缀一般有:

  • v    表示本行指定一个顶点。 此前缀后跟着3个单精度浮点数,分别表示该定点的X、Y、Z坐标值
  • vt    表示本行指定一个纹理坐标。此前缀后跟着两个单精度浮点数。分别表示此纹理坐标的U、V值
  • vn    表示本行指定一个法线向量。此前缀后跟着3个单精度浮点数,分别表示该法向量的X、Y、Z坐标值
  • f    表示本行指定一个表面(Face)。一个表面实际上就是一个三角形图元。

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

以此类推,我们可以为模型中所有的法线、纹理坐标都建立起相应的索引,以节省更多的空间。而事实上,OBJ文件就是这么做的。接下来可以看看f类型的数据。f类型的数据一般有以下几种格式:

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

第一种类型表示以顶点1,2,3作为索引建立三角形;
第二种类型表示以顶点1,2,3作为索引建立三角形,并且顶点1的纹理坐标为3,第二个顶点的纹理坐标为5,第三个顶点的纹理坐标为4;
第三种类型表示以顶点1,2,3作为索引建立三角形,并且顶点1的纹理坐标为3,法理坐标为4,第二个顶点的纹理坐标为5,法理坐标为6,第三个顶点的纹理坐标为4,法理坐标为2。

3.    MTL文件格式分析
MTL文件与OBJ文件极其相似。只是用于标识行的前缀有所不同。这些前缀的意义如下表所示:
前缀                                                   说明

  • newmtl    表示新建一个材质。此前缀后跟一个字符串,表示此材质的名称。 此行之后的信息都是对这个材质进行设定。
  • Ka    指定最后建立的材质的环境光成分。此行包含3个单精度浮点参数。
  • Kd    指定最后建立的材质的漫射光成分。此行包含3个单精度浮点参数。
  • Ks    指定最后建立的材质的镜面光成分。此行包含3个单精度浮点参数。
  • map_Kd    指定最后建立的材质的反射贴图。如果此行的第一个参数为字符串”-s”,则此行将包括5个参数。其中第二、第三和第四个参数为此纹理贴图在U、V、W方向的缩放值,第五个参数为纹理图片的文件名。如果第一个字符串不是”-s”,那么第一个参数就是此纹理图片的文件名。
  • map_Ks    指定最后建立的材质的镜面贴图。如果此行的第一个参数为字符串”-s”,则此行将包括5个参数。其中第二、第三和第四个参数为此纹理贴图在U、V、W方向的缩放值,第五个参数为纹理图片的文件名。如果第一个字符串不是”-s”,那么第一个参数就是此纹理图片的文件名。

根据这些信息,我们就可以在Opengl ES中实现obj和mtl文件的读取并显示了。至于代码实现和分析,下一篇文章中将会细细道来。

附录1  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)
参考的文章
1.   3D中的OBJ文件格式详解
2.   使用3D模型

[iTyran原创]iPhone中OpenGL ES显示3DS MAX模型之一:OBJ格式分析的更多相关文章

  1. [iTyran原创]iPhone中OpenGL ES显示3DS MAX模型之二:lib3ds加载模型

    [iTyran原创]iPhone中OpenGL ES显示3DS MAX模型之二:lib3ds加载模型 作者:u0u0 - iTyran 在上一节中,我们分析了OBJ格式.OBJ格式优点是文本形式,可读 ...

  2. iphone中button按钮显示为圆形解决

    iphone中button按钮显示为圆形解决: 添加样式: -webkit-appearance:button; 如果需要为直角: border-radius:0 在源码中添加如:style=&quo ...

  3. WebGL 在 OpenGL ES 指令 iOS 在 C 分歧版指令分析

    WebGL 中 OpenGL ES 指令与 iOS 中 C 版指令的差异简析 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途 ...

  4. 【Unity】3.4 将现有的3ds Max模型导入到Unity

    分类:Unity.C#.VS2015 创建日期:2016-04-05 一.简介 这一节我们用一个带有"装子弹和上膛"动画的"枪"模型,介绍在3ds Max 20 ...

  5. iOS 中OpenGL ES 优化 笔记 1

    1,避免同步和Flushing操作 OpenGL ES的命令执行通常是在command buffer中积累一定量的命令后,再做批处理执行,这样效率会更高:但是一些OpenGL ES命令必须flush ...

  6. Unity3d / 3ds max 模型分享站点

    http://www.cgrealm.org/model/ 王国3D模型库 http://www.cgjoy.com/ 游戏特效论坛

  7. OpenGL ES教程系列(经典合集)

    为了搞透播放器的开发,花了些时间收集这些资料,虽然我已经搞定opengles渲染视频的内容,但是想玩玩opengles,往深里玩,图像处理这块是个好的方向,所以opengles是值得好好学的.   O ...

  8. obj2opengl:转换OBJ 3D模型到iPhone OpenGL ES兼容的数组中

    原文如下:obj2opengl: convert obj 3D models to arrays compatible with iPhone OpenGL ES obj2opengl在GitHub中 ...

  9. 一步步实现windows版ijkplayer系列文章之六——SDL2源码分析之OpenGL ES在windows上的渲染过程

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

随机推荐

  1. c#值类型引用类型第一章

    概要 本篇文章主要简单扼要的讲述值类型和引用类型更进阶的理解和使用.如果希望更多的了解和技术讨论请记得看文章末尾,望各位看官多多支持多多关注,关注和支持是我更新文章的最大动力.在这里谢谢大家.温馨提示 ...

  2. RPC的入门应用

    一.什么是RPC RPC 的全称是 Remote Procedure Call ,是一种进程间通信方式.它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这 ...

  3. 【原】“Error getting 'android:label' attribute”

    项目上线过程中遇到“Error getting 'android:label' attribute: attribute is not a string value”这个错误. 备忘下:是因为有act ...

  4. 《神经网络的梯度推导与代码验证》之vanilla RNN的前向传播和反向梯度推导

    在本篇章,我们将专门针对vanilla RNN,也就是所谓的原始RNN这种网络结构进行前向传播介绍和反向梯度推导.更多相关内容请见<神经网络的梯度推导与代码验证>系列介绍. 注意: 本系列 ...

  5. java初探(1)之登录补充

    在登录之后,可能服务器是分布式的,因此不能通过一个本地的session来管理登录信息,导致登录的信息不能传递,即在这台服务器上可以得到用户登录信息,但在那台就得不到.因此,需要设置分布式的sessio ...

  6. Solon详解(三)- Solon的web开发

    Solon详解系列文章: Solon详解(一)- 快速入门 Solon详解(二)- Solon的核心 Solon详解(三)- Solon的web开发 Solon详解(四)- Solon的事务传播机制 ...

  7. Zookeeper高级

    1.1. 一致性协议概述 前面已经讨论过,在分布式环境下,有很多不确定性因素,故障随时都回发生,也讲了CAP理论,BASE理论 我们希望达到,在分布式环境下能搭建一个高可用的,且数据高一致性的服务,目 ...

  8. 让document.write的广告无阻塞的加载

    广告代码分析 很多第三方的广告系统都是使用document.write来加载广告,如下面的一个javascript的广告链接. 1 <script type="text/javascr ...

  9. Odoo10.0中的工作流

    Odoo10.0中可以通过两种方式来实现工作流(workflow) 一种的官网API中给出的方式,链接:https://www.odoo.com/documentation/10.0/referenc ...

  10. Georgia and Bob(POJ 1704)

    原题如下: Georgia and Bob Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12712   Accepted: ...