[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. 贪心思想之区间贪心 关联洛谷P1803

    力扣上也有一道类似的题 几乎是一样 输出不同 → 力扣leetcode 435. 无重叠区间 区间贪心是比较经典的 就拿洛谷P1803来举例 题目大意 n个比赛 [开始时间,结束时间] 问一个人最多能 ...

  2. e3mall商城的归纳总结5之修改商品分类、e3mall—content的搭建

    说在前面的话 本节基本上没有用到新的知识点.主要还是对数据库的增删改查以及创建了一个新的内容模块. 新增商品分类 由于easyUI的Tree需要三个字段(Id.state.text), [{ &quo ...

  3. Zigzags CodeForces - 1400D

    给出一组数: 寻找四元组的个数 (i,j,k,l)其中a[i]=a[k],并且a[j]=a[l] 刚看到这个题的时候想到了记录每个数的个数,然后求前缀和以及后缀和.先枚举i和k,当a[i]和a[k]相 ...

  4. Linux文件描述符与重定向

    文件描述符可以理解为linux跟踪打开文件,而分配的一个数字,这个数字有点类似c语言操作文件时候的句柄,通过句柄就可以实现文件的读写操作. 当Linux启动的时候会默认打开三个文件描述符,分别是: 标 ...

  5. nginx server_name 多个

    nginx server_name 多个 nginx server_name 多个的话,空格隔开就行 server_name baidu.com baidu.me; 如果很多的话可以用正则,我的需求, ...

  6. HDU-4417-Super Mario(主席树解法)

    Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory ...

  7. [BUUOJ记录] [BJDCTF2020]Easy MD5

    各种关于md5的Bypass操作,都是基本操作,考察数组绕过.弱类型比较绕过以及md5($password,true) ByPass 1.利用md5($password,true)实现SQL注入 F1 ...

  8. oracle无法通过ip地址连接

    问题描述:使用plsql可以连接本地oracle实例,但telnet 192.168.130.71 (内网ip)不通. 其实在11g安装完成后,默认网络配置 listener.ora中 host = ...

  9. TonWeb6.1Linux安装文档

    东方通部署文档   东方通安装部署文档 准备文件:开始安装:警告:在安装之前先安装JDK,JDK要求JDK5以上Linux安装:运行安装包sh Install_TW6.1.5.15_Standard_ ...

  10. 转载 深入理解Nginx及使用Nginx实现负载均衡

    转载:https://developer.51cto.com/art/202001/609322.htm 正向代理是代理客户端,也就是客户端能真正接触到的,比如访问外网时需要使用VPN软件,在这个软件 ...