谈谈Processing 3D世界 六

来源:互联网 发布:nginx和iis 编辑:程序博客网 时间:2024/05/13 02:14

六六大顺,都到六了嚯~

之前仅仅一个cube的顶点和UV就快把我们弄残了,这样下去肯定不是办法,更别说一些复杂的网格对象。

所以我们现在就来说说如何向Processing导入网格数据。


一般来说,我们不会一个点一个点的定义一个物体,这样做太辛苦,也太单调。好在米国人又开始拯救世界了,工业光魔、皮克斯那些鬼人已经发明了一批又一批的先进工具用来制作网格。据说程序猿喜欢用Blender,这是什么鬼不太懂。反正我用Maya。


怎么样,狂拽酷炫吊炸天!
当然你也可以用3DMax来建模。好了什么软件无所谓了,能建模就行。
神马?你妈没教过你建模?没关系,你也可以去网站上下载一些别人建好的模型。钢弹、Loli、御姐应有尽有。
我一会也会提供给你几个。


step1 建模

打开Maya。(咦为什么要打开Maya,我们不是在谈编程的吗?)

确保你在多边形模块下。
首先我们在maya中建一个cube。


菜单->创建->NURBS基本体->立方体(取消交互式创建,再点击立方体)



好啦一个cube就建好啦,囧。(为了一个cube我们前前后后忙乎了多久?有了工具,就是不一样!)


step2 展UV

NURBS对象需要转换成我们熟悉的多边形对象才能展UV。

菜单->修改->转化->NURBS到多边形 (点击后面的一个小方框,会弹出一个转化选项框)
选择转化类型:三角面 (我们的显卡喜欢三角面)
细分方法:计数
计数:2

点击应用,然后关闭选项框。

这样,这个cube就转化成和我们之前用程序写的那个cube一毛一样啦。并且这个cube系统已经自动帮我们布置好啦UV。

这就是王的力量...哦不,工业的力量呀!

想要查看UV,框选中cube对象,菜单->编辑UV->UV纹理编辑器


注意这里cube的6(一个12个三角面)个面的UV是重合的。迷糊的同学,请查看第三节知识。

step3 导出obj

我们的模型做好了。接下来就要把它导入Processing,这才是我们的最终目的。

那么如何导出数据呢? -- 我们可以使用obj这个格式。


obj文件是什么?

度娘为您解惑:
OBJ文件是Alias|Wavefront公司为它的一套基于工作站的3D建模和动画软件"Advanced Visualizer"开发的一种标准3D模型文件格式,很适合用于3D软件模型之间的互导,也可以通过Maya读写。比如你在3dsMax或LightWave中建了一个模型,想把它调到Maya里面渲染或动画,导出OBJ文件就是一种很好的选择。目前几乎所有知名的3D软件都支持OBJ文件的读写,不过其中很多需要通过插件才能实现。


度娘解释二:
OBJ文件是一种文本文件格式,比起二进制文件为主、连每个块的用途也得试探来试探去的3DS,文本文件为主的OBJ对我们更友好。与3DS文件的树状[块结构]不同,OBJ文件只是很单纯的字典状结构,没有块ID来表征名字而是简单地用易懂的表意字符来表示。总之看上去是赏心悦目的样子。。。 


好了,我们知道obj可以导出模型数据,而且结构简单。最重要的是他是文本文件,我们可以直接拿记事本、nodePad+查看编辑。同时Processing也有良好的外部文件编辑功能。

一切万事具备,我先来规划规划。
step4 研究obj文件格式
step5 将文本读入processing
step6 编写obj解码模块
step7 绘制obj模型对象


我们先将cube从Maya导出存储为obj文件。这里要注意导出obj文件前,先将要导出的网格三角化一下。还记得吗?我们之前选择的绘制模式是三角面(TRIANGLES)。我们的显卡喜欢三角面,欲罢不能。


在maya视口中选中我们的cube,准备放技能:

菜单->网格->三角化

好啦,现在我们的cube就跟我们之前劳心劳力定义的顶点数据一样啦,那可是湿湿的一大坨呢。


确保选中我们的cube

菜单->文件->导出当前选择

来到导出界面 

选择要导出的文件类型:OBJexport

替文件取个名字,保存在你喜欢的位置。

这里我们可以看到文件选项有

组     - 意味着可以一次导出多个网格对象 (本节空间有限,暂时不覆盖这一信息)

点组 - 顶点信息, 这里就包含着顶点的位置信息、UV纹理坐标信息及顶点索引

材质 - 生成一些mtl附属文件,里面记录了网格所用的材质,及贴图信息,极为便利。 (本节空间有限,暂时不覆盖这一信息)

平滑 - 记录每个顶点之间的平滑系数 (本节空间有限,暂时不覆盖这一信息)

法线 - 记录每个面的法线朝向,为灯光计算所需。


step4 研究OBJ文件格式


本来Processing到是有个obj导入插件的。可惜版本迟迟未被更新,感觉官方好像已经放弃了。。。所以3.x以后的Processing就不要想了。幸好obj文件本身不是很复杂,利用Processing的文件处理功能,我们是完全可以自己写一个导入模块的。悲催的是。。。偶的笔记找不到了。。笔记呀!!你死的好惨。。。咦又找到了一部分,虽然要重新开始推演,但也有了依据~


我们用Maya将cube导出后会得到两个文件:


cube.mtl // 这个就是用来记录材质贴图路径的附属文件了

cube.obj


随便用一个文本编辑器打开obj文件,我们便会看到以下内容:

# This file uses centimeters as units for non-parametric coordinates.mtllib cube.mtlg defaultv -0.500000 -0.500000 0.500000v 0.500000 -0.500000 0.500000v -0.500000 0.500000 0.500000v 0.500000 0.500000 0.500000v -0.500000 0.500000 -0.500000v 0.500000 0.500000 -0.500000v -0.500000 -0.500000 -0.500000v 0.500000 -0.500000 -0.500000vt 0.375000 0.000000vt 0.625000 0.000000vt 0.375000 0.250000vt 0.625000 0.250000vt 0.375000 0.500000vt 0.625000 0.500000vt 0.375000 0.750000vt 0.625000 0.750000vt 0.375000 1.000000vt 0.625000 1.000000vt 0.875000 0.000000vt 0.875000 0.250000vt 0.125000 0.000000vt 0.125000 0.250000vn 0.000000 0.000000 1.000000vn 0.000000 0.000000 1.000000vn 0.000000 0.000000 1.000000vn 0.000000 0.000000 1.000000vn 0.000000 1.000000 0.000000vn 0.000000 1.000000 0.000000vn 0.000000 1.000000 0.000000vn 0.000000 1.000000 0.000000vn 0.000000 0.000000 -1.000000vn 0.000000 0.000000 -1.000000vn 0.000000 0.000000 -1.000000vn 0.000000 0.000000 -1.000000vn 0.000000 -1.000000 0.000000vn 0.000000 -1.000000 0.000000vn 0.000000 -1.000000 0.000000vn 0.000000 -1.000000 0.000000vn 1.000000 0.000000 0.000000vn 1.000000 0.000000 0.000000vn 1.000000 0.000000 0.000000vn 1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000s 1g pCube1usemtl initialShadingGroupf 1/1/1 2/2/2 3/3/3f 3/3/3 2/2/2 4/4/4s 2f 3/3/5 4/4/6 5/5/7f 5/5/7 4/4/6 6/6/8s 3f 5/5/9 6/6/10 7/7/11f 7/7/11 6/6/10 8/8/12s 4f 7/7/13 8/8/14 1/9/15f 1/9/15 8/8/14 2/10/16s 5f 2/2/17 8/11/18 4/4/19f 4/4/19 8/11/18 6/12/20s 6f 7/13/21 1/1/22 5/14/23f 5/14/23 1/1/22 3/3/24

(⊙o⊙)哦,大致感觉上我们需要的顶点信息都有了,只不知道那些是那些。不要方!让我们细细来看一下。


OBJ文件一般以几行注释开头,注释行以一个“#”号为开头,空格和空行可以随意加到文件中以增加文件的可读性。


# This file uses centimeters as units for non-parametric coordinates. 

# 机翻大法就是说这个文件的单位是厘米,嗯咱们目前可以不考虑单位,忽略。

mtllib cube.mtl

# 指出文件包含那些附带的材质库,方便我们查找。


OBJ文件由一行行文本组成,有字的行都由一两个标记字母也就是关键字(Keyword)开头,关键字可以说明这一行是什么样的数据。多行可以逻辑地连接在一起表示一行,方法是在每一行最后添加一个连接符(\)。注意连接符(\)后面不能出现空格或tab格,否则将导致文件出错。

哦,那我们就知道这些v啊vt啊vn啊都是说明数据的关键字。


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文本了。但我们对于obj的数据为何要这样堆砌,以及描述一个面'f 3/3/5 4/4/6 5/5/7'的语法仍然不太理解其含义。没关系,让伟大的度娘来给你解惑:

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"表示面(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。一个面出现两个相同顶点,可能造成程序的内存分配错误。

经过这个基本例子,我们似乎了解了一些,obj的堆砌方式。再看看一个复杂一点的obj文件内容:

*注意这个用于演示的cube文件跟我们的cube.obj文件不一样,这个是四角面,这个文件更简单一些。

# 这个文件以厘米为单位非参数坐标# This file uses centimeters as units for non-parametric coordinates.g default# 'v'代表顶点位置v -0.500000 -0.500000 0.500000v 0.500000 -0.500000 0.500000v -0.500000 0.500000 0.500000v 0.500000 0.500000 0.500000v -0.500000 0.500000 -0.500000v 0.500000 0.500000 -0.500000v -0.500000 -0.500000 -0.500000v 0.500000 -0.500000 -0.500000# 'vt'代表顶点贴图UVvt 0.375000 0.000000vt 0.625000 0.000000vt 0.375000 0.250000vt 0.625000 0.250000vt 0.375000 0.500000vt 0.625000 0.500000vt 0.375000 0.750000vt 0.625000 0.750000vt 0.375000 1.000000vt 0.625000 1.000000vt 0.875000 0.000000vt 0.875000 0.250000vt 0.125000 0.000000vt 0.125000 0.250000# 'vn'代表顶点法向量vn 0.000000 0.000000 1.000000vn 0.000000 0.000000 1.000000vn 0.000000 0.000000 1.000000vn 0.000000 0.000000 1.000000vn 0.000000 1.000000 0.000000vn 0.000000 1.000000 0.000000vn 0.000000 1.000000 0.000000vn 0.000000 1.000000 0.000000vn 0.000000 0.000000 -1.000000vn 0.000000 0.000000 -1.000000vn 0.000000 0.000000 -1.000000vn 0.000000 0.000000 -1.000000vn 0.000000 -1.000000 0.000000vn 0.000000 -1.000000 0.000000vn 0.000000 -1.000000 0.000000vn 0.000000 -1.000000 0.000000vn 1.000000 0.000000 0.000000vn 1.000000 0.000000 0.000000vn 1.000000 0.000000 0.000000vn 1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000# 's'代表光滑组,这里两个三角面组成一个光滑组# 光滑组决定一坨面的边缘是锐利还是平滑过渡到另一个光滑组的面# 这里's off'表示关闭光滑组s off# 'g'表示组,这里的成组与Maya中的成组不一样,这里的成组是指把# "g pCube1"后出现的面都结合到一起,组成一个整的多边形网格。# 'pCube1'是组名g pCube1# 使用材质usemtl initialShadingGroup# 这是在面的数据中多了贴图坐标uv点和法线的索引号,索引号分别用左斜线(/)隔开。# 格式:"f 顶点索引/uv点索引/法线索引"。f 1/1/1 2/2/2 4/4/3 3/3/4f 3/3/5 4/4/6 6/6/7 5/5/8f 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
这个文件看起来稍复杂一些,用到了许多关键词,你可以对照前面的列表查看一下每个关键词的意思。  
把"cube.obj"文件修改一下就知道成组的意思了。把"s off"这句后面的代码替换成以下代码: 
  usemtl 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)",可见组的名称其实就是单独几何体的名称。

obj文件格式总结

好,不得不说obj文件确实“博大精深”,很多深入的资料我就不贴出来分大家的心了。经过一番囫囵吞枣式的研究,我们总算知道了obj的堆叠式的结构。以g()和f(面)为总指导调用各个信息。倘若是三角面模型,f便有3组数据;倘若是四角面,f便有4组数据。每组数据分别按顺序引用顶点位置索引/顶点UV索引/顶点法向量索引。

目前我们先剥离复杂的信息,尽力简化工程,只关心模型的面和点的数据传递。

受限空间限制,那么这一节就先说都这里。我们下一节接着从'step5 - 将obj读入processing'开始,一步步现实processing obj解码模块的制作。


0 0