Obj文件解析相关bug心得

在优诺科技实习的期间,修改了Emp项目中几个关于解析Obj文件的bug,记录下来当作实习的回忆吧。

1.Obj文件简介

    Obj文件是Alias|Wavefront公司为3D建模和动画软件“Advanced Visualizer”开发的一种标准,适用于3D软件模型之间的互导,也可以通过Maya读写,其不需要文件头

2.Obj文件格式

2.1 项目中涉及的Obj文件行头定义

    Obj文件几乎都是以行为单位进行排列的,每一行可以认为有两部分,第一部分我们不妨定义为“行头”(又可以称为关键字),另外的一个部分,我们不妨定义为“行数据”,举例来说有这么一行数据的话:

        f 10026/10026/10026 10027/10027/100279553/9553/9553

        “f”即为我们定义的行头,剩下的部分则代表行数据。

        在EMP项目中所涉及到的行头如下:

            关于顶点的行头如下:

                  v:几何体顶点(vertices),一般是3个数据,xyz

                              vt:贴图坐标点(texcoords),也成为纹理坐标,一般两个数据,xy

                          vn:顶点法线(normals),一般3个数据,xyz

          关于面的行头如下:

                     f:面(face,代码中以triangle的形式表现

          关于成组的行头如下:

                     g:组名称 group

2.2 项目中涉及的行数据形式

2.2.1点形式

       v -0.798343598843.2453789791 20.8864974975

        vt 1.669923126 0.089159741(对于Emaspro模型导入无实际意义)

            vn0.19151529 0.9378334879 -0.2894653677

        每一个点都由其对应的顶点坐标(v),贴图坐标(vt),vn(法线坐标)组成 

2.2.2面形式

     首先,我们需要明白,面其实是由点组成的,至少3个顶点就可以确定一个面,在Obj文件中,面也是由点进行索引。所谓索引的意思,是存入点的时候,Obj文件就为点隐式建立索引,举例来说:

                v xx xx xx

                v yy yy yy

                v zz zz zz

         则第一个点的索引值为1,第二个点的索引值为2,第三个点索引值为3,贴图坐标索引和法线坐标索引类似。

         Emaspro导入的obj文件中主要为三角形面(当面为多边形面的时候转化为三角形面存入),所以以三角形面为例,讲述面在OBJ文件中存在的三种形式:

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

            这种形式表示有一个面,其由三个点组成,三个点的坐标索引值是1,2,3(红色标注),即取第一个点,第二个点,第三个点的坐标为面上的三个点的坐标,同理,贴图索引为2,3,4(蓝色标注),法线坐标索引为3,4,5(紫色标注)。

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

            这种形式表示这个面也有三个点,其中1,2,3为点索引值,3,5,4为贴图索引值。

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

             这种形式表示的1,2,3为点索引值,3,5,4为法线索引

值得一提的是:面的索引值可以不为证书,当索引值为负数的时候(假设为-n),表示的意思是这个索引值为f上面的最后一个点(v或者vt或者vn)倒数n的那个点。

              举例来说:

            v 1 2 3

            v  2 3 4

            v  3 4 5

            ……(假设后面vt,vn也是3个)

    f -1/-1/-1 -2/-2/-2 -3/-3/-3 

     这样的一组数据,我们可以得到三个坐标点,其索引值为1,2,3,三个贴图坐标,其索引值为1,2,3,三个法线坐标,其索引值为1,2,3。这里的索引明显是按照不同类型进行分类的索引。

      则f所代表的第一个点,其点索引为点中倒着数的第一个点,也就是索引为3;其贴图坐标为贴图坐标中倒着数的第一个,索引也为3;法线索引也为法线中倒着数的第一个,索引也为3。之所以用负数相对索引,是因为有些时候(例如在点数目很多并频繁取倒数的几个点时)表达起来容易。

3.遇到的BUG以及解决方式

3.1Obj文件无法导入的问题

表现:导入obj文件,程序直接关闭

原因:obj文件虽然不支持对颜色的表示,但是支持导入材质库,在obj文件中以xxx.mtl形式出现,源代码中遇到mtl会去寻找这个mtl文件,如果找不到的话,会直接exit(1)。

修改:因为Obj文件中的mtl所需要的材质,在导入进EmasPro里面并不会涉及,所以直接将exit(1)改为return 即可。

3.2Obj文件导入部分部件缺失

表现:导入部分obj文件,部件缺失(tank.obj,su-37.obj)

原因:源代码中的ReadObjFile函数中,会判断当前部件中的面元数,如果为0,则会跳出while循环,因为存入部件的时候是以逆序链表存入的,也就是说,取部件是倒序取的,当obj部件中部存在空部件的时候,会跳出while循环而不是继续去读下一个部件直到全部部件读完。

修改:将while循环改为一直读到第一个部件为止(第一个部件的->next为空,不会继续读),遇到空部件的时候不是退出while循环,而是continue

3.3部分OBJ文件导入之后程序崩溃

表现:导入部分obj文件后,程序崩溃(F117.obj,m1a2.obj)

原因:源代码不支持相对坐标的obj文件,遇到索引为负数时崩溃

修改:添加当读到负数索引之后转换为正索引的代码

3.4部分obj文件读入之后面元丢失

表现:导入部分obj文件,部件不缺,但是部件中的部分面元丢失(tu-154.obj)

原因:部分obj文件中,在行末中有“\”符号,代表的是此行未完,原代码中没有进行处理,读到“\”直接就跳过了,由于下一行开始的时候读到的还是为1个数据,也就是数字开头,根据原代码,每行数据开头要为字母,所以也不会处理进行跳过,于是这个部件中的点没有读取完,面也没有读取完。

修改:添加了支持“\”相关的代码。

PS.因为”\”的出现情况相对复杂,另外一个合理的办法是用文字编辑软件打开OBJ文件,直接将其中的”\”替换成”\0”(替换时查找对象为\,替换对象为空),或者”\n”(替换时查找对象为\,替换对象为回车)。这种方法只针对Emaspro项目代码有效,并不代表一定有效。

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值