3d引用
引用:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=67201&extra=page%3D1&page=1
原文:http://www.javaworld.com.tw/jute/post/view?bid=26&id=282225
一、 在Android显示3D模型,用obj文件
利用网络上找到的obj文件,自行写了一个objLoader类,并分析他的obj文件和结构,最后解析出data文件。
必须确认obj文件的f
参数下必须有
f 1137/1/1 1212/2/2 1115/3/3
对应顶点座标、材质座标、法向量座标
大部分的obj文件可能只有对应的顶点座标
这样的模型就没有材质跟灯光可以使用
附档有范例
objLoader一般java专案用于分析出OPGL需要的vertices、texture、normals、indices
OpglTest3模型测试 :源码:
OpglTest.rar (847.1 KB, 下载次数: 585)
二、 OBJ文件格式(转http://www.ategpu.com/2009/06/25/%E4%BD%BF%E7%94%A83d%E6%A8%A1%E5%9E%8B.html)
1. 使用建模工具创建模型并导出obj文件
要渲染一个模型,首先要有一个模型文件。目前绝大多数流行的建模软件都支持将模型输出为OBJ文件。这里以3DS
Max为例,介绍创建OBJ模型的方法。
首先,启动3DS
Max,并向往常一样创建模型。如图
所示。
模型创建完后,执行文件(File)菜单->导出(Export)命令。在弹出的保存对话框中,输入文件名,并在”保存类型”项中,选则”Wavefront Object (*.obj)”项。
如图
所示。
单击”保存”按钮后,会弹出如图
所示的选项对话框。
在这里,请注意在Faces栏中,选择Triangles以使用三角形作为基本图元。还要注意钩去Relative Vertex一项,禁止使用相对顶点索引。这是因为在后面的程序中,我们将不考虑相对顶点索引以简化代码。
单击”OK”按钮后,会紧接着弹出另一个选项对话框,如图
所示。
这一步是在设置与此OBJ文件对应的MTL文件(用于保存材质信息),注意要选择”Scene”并勾选”Export”复选框。然后单击”OK”按钮完成设置。这样,在指定的文件夹下,我们得到了两个文件:一个*.OBJ文件,存储了模型的顶点、法线和纹理坐标信息;一个*.MTL文件,存储了该模型所用的材质信息。
2
.OBJ文件格式OBJ文件格式是非常简单的。这种文件以纯文本的形式存储了模型的顶点、法线和纹理坐标和材质使用信息。OBJ文件的每一行,都有极其相似的格式。在OBJ文件中,每行的格式如下:
前缀 参数1 参数2 参数3 … |
其中,前缀标识了这一行所存储的信息类型。参数则是具体的数据。OBJ文件的前缀可以有:
表7.2-1 OBJ文件中的前缀 |
|
前缀 |
说明 |
v |
表示本行指定一个顶点。
|
vt |
表示本行指定一个纹理坐标。
|
vn |
表示本行指定一个法线向量。
|
f |
表示本行指定一个表面(Face)。
|
usemtl |
此前缀后只跟着一个参数。该参数指定了从此行之后到下一个以usemtl开头的行之间的所有表面所使用的材质名称。该材质可以在此OBJ文件所附属的MTL文件中找到具体信息。 |
mtllib |
此前缀后只跟着一个参数。该参数指定了此OBJ文件所使用的材质库文件(*.mtl)的文件路径 |
我们使用3DS Max创建了一个长方体,并保存为OBJ格式。用写字板打开这个OBJ文件,可以看到如下内容:
# Max2Obj Version 4.0 Mar 10th,
2001 |
仔细观察,你会发现这个文件中包含了一些我们没有提到的前缀,如以”#”开头的注释,以g开头的表示组的前缀等等。但这些前缀并不影响模型的外观,因此我们可以忽略它们。在解释以f为前缀的行的格式之前,我们不得不提一个新的概念,这就是顶点索引(Vertex
Indices)。我们知道,对于每一个三角形,都需要用3个顶点来表示。例如在上面的立方体模型中,一共有6×2×3=36个顶点。仔细想想就会知道,在这36个顶点中,又相当数量的顶点是重合的。如果把这些重合的顶点都一一表示出来,就太浪费存储空间了。于是,我们提出了顶点索引的想法,解决空间占用问题。顶点索引的思想是建立两个数组,一个数组用于存储模型中所有的顶点坐标值,另一个数组则存储每一个表面所对应的三个顶点在第一个数组中的索引。图
7.2-1显示了这种一一对应的关系。
建立这样的顶点索引显然更加节约存储空间。假设Indices:array of
Integer是顶点索引数组,Vertices:array of
TVertex是顶点数组,使用下面的代码段就可以把整个顶点索引对应的所有三角形绘制出来:procedure
DrawIndex(Indices:array of Integer;Vertices:array of TVertex);var i
:Integer;beginglBegin(GL_TRIANGLES);for i := 0 to (High(Vertices)+1) div 3 -1
dobeginglVertex3fv(@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。7.3 用于存储材质信息的MTL文件MTL文件与OBJ文件极其相似。只是用于标识行的前缀有所不同。这些前缀的意义如表7.3-1所示。
表7.3-1 MTL文件中的前缀 |
|
前缀 |
说明 |
newmtl |
表示新建一个材质。 |
Ka |
指定最后建立的材质的环境光成分。此行包含3个单精度浮点参数。 |
Kd |
指定最后建立的材质的漫射光成分。此行包含3个单精度浮点参数。 |
Ks |
指定最后建立的材质的镜面光成分。此行包含3个单精度浮点参数。 |
map_Kd |
指定最后建立的材质的反射贴图。如果此行的第一个参数为字符串”-s”,则此行将包括5个参数。其中第二、第三和第四个参数为此纹理贴图在U、V、W方向的缩放值,第五个参数为纹理图片的文件名。如果第一个字符串不是”-s”,那么第一个参数就是此纹理图片的文件名。 |
map_Ks |
指定最后建立的材质的镜面贴图。如果此行的第一个参数为字符串”-s”,则此行将包括5个参数。其中第二、第三和第四个参数为此纹理贴图在U、V、W方向的缩放值,第五个参数为纹理图片的文件名。如果第一个字符串不是”-s”,那么第一个参数就是此纹理图片的文件名。 |
由这些信息,我们就足以写一个类,用于读取和渲染OBJ模型了。